非 root ユーザーが NFS ファイル・ストレージのマウント・パスを所有しているとアプリが失敗するのはなぜですか?
クラシック・インフラストラクチャー
デプロイメントに NFS ストレージを追加した後に、コンテナーのデプロイメントが失敗します。 コンテナーのログを取得すると、以下のようなエラーが表示されることがあります。 ポッドが失敗し、再ロードが繰り返されます。
write-permission
don't have required permission
can't create directory '/bitnami/mariadb/data': Permission denied
デフォルトでは、非 root ユーザーには、NFS 補助ストレージのボリューム・マウント・パスに対する書き込み権限がありません。 一部の一般的なアプリのイメージ (Jenkins や Nexus3 など) は、マウント・パスを所有する非 root ユーザーを Dockerfile に指定しています。
この Dockerfile からコンテナーを作成すると、マウント・パスに対する非 root ユーザーの権限が不十分なために、コンテナーの作成は失敗します。 書き込み権限を付与するには、Dockerfile を変更して、マウント・パス権限を変更する前に root ユーザー・グループに非 root ユーザーを一時的に追加するか、 init コンテナーを使用します。
Helm チャートを使用してイメージをデプロイする場合は、 init コンテナーを使用するように Helm デプロイメントを編集します。
デプロイメントに init コンテナー を含めると、Dockerfile に指定されている非 root ユーザーに、コンテナー内のボリューム・マウント・パスに対する書き込み権限を付与できます。
init コンテナーは、アプリ・コンテナーが開始する前に開始します。 init コンテナーは、コンテナー内にボリューム・マウント・パスを作成し、正しい (非 root) ユーザーが所有するようにマウント・パスを変更し、クローズします。 その後、マウント・パスに書き込む必要がある非 root ユーザーでアプリ・コンテナーが開始されます。 パスは既に非 root ユーザーによって所有されているため、マウント・パスへの書き込みは成功します。
init コンテナーを使用しない場合は、Dockerfile を変更して、 NFS ファイル・ストレージへの非 root ユーザー・アクセスを追加することができます。
始めに: アカウントにログインします。 該当する場合は、適切なリソース・グループをターゲットにします。 クラスターのコンテキストを設定します。
-
アプリの Dockerfile を開き、ボリューム・マウント・パスに対する書き込み権限を付与するユーザーのユーザー ID (UID) とグループ ID (GID) を取得します。 Jenkins Dockerfile の例では、情報は以下のとおりです。
- UID:
1000 - GID:
1000
Dockerfile の例
FROM openjdk:8-jdk RUN apt-get update && apt-get install -y git curl && rm -rf /var/lib/apt/lists/* ARG user=jenkins ARG group=jenkins ARG uid=1000 ARG gid=1000 ARG http_port=8080 ARG agent_port=50000 ENV JENKINS_HOME /var/jenkins_home ENV JENKINS_SLAVE_AGENT_PORT ${agent_port} ... - UID:
-
永続ボリューム請求 (PVC) を作成して、アプリに永続ストレージを追加します。 この例では、
ibmc-file-bronzeストレージ・クラスを使用します。 使用可能なストレージ・クラスを確認するには、kubectl get scを実行します。apiVersion: v1 kind: PersistentVolumeClaim metadata: name: mypvc annotations: volume.beta.kubernetes.io/storage-class: "ibmc-file-bronze" spec: accessModes: - ReadWriteMany resources: requests: storage: 20Gi -
PVC を作成します。
kubectl apply -f mypvc.yaml -
デプロイメントの
.yamlファイルで、initコンテナーを追加します。 先ほど取得した UID と GID を指定します。initContainers: - name: initcontainer # Or replace the name image: alpine:latest command: ["/bin/sh", "-c"] args: - chown <UID>:<GID> /mount; # Replace UID and GID with values from the Dockerfile volumeMounts: - name: volume # Or you can replace with any name mountPath: /mount # Must match the mount path in the args line以下の Jenkins デプロイメントの例を検討します。
apiVersion: apps/v1 kind: Deployment metadata: name: my-pod spec: replicas: 1 selector: matchLabels: app: jenkins template: metadata: labels: app: jenkins spec: containers: - name: jenkins image: jenkins volumeMounts: - mountPath: /var/jenkins_home name: volume volumes: - name: volume persistentVolumeClaim: claimName: mypvc initContainers: - name: permissionsfix image: alpine:latest command: ["/bin/sh", "-c"] args: - chown 1000:1000 /mount; volumeMounts: - name: volume mountPath: /mount -
ポッドを作成して、PVC をポッドにマウントします。
kubectl apply -f my-pod.yaml -
ボリュームがポッドに正常にマウントされたことを確認します。 ポッド名と Containers/Mounts パスをメモします。
kubectl describe pod <my-pod>出力例
Name: mypod-123456789 Namespace: default ... Init Containers: ... Mounts: /mount from volume (rw) /var/run/secrets/kubernetes.io/serviceaccount from default-token-cp9f0 (ro) ... Containers: jenkins: Container ID: Image: jenkins Image ID: Port: <none> State: Waiting Reason: PodInitializing Ready: False Restart Count: 0 Environment: <none> Mounts: /var/jenkins_home from volume (rw) /var/run/secrets/kubernetes.io/serviceaccount from default-token-cp9f0 (ro) ... Volumes: myvol: Type: PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace) ClaimName: mypvc ReadOnly: false -
前にメモしたポッド名を使用して、ポッドにログインします。
kubectl exec -it <my-pod-123456789> /bin/bash -
コンテナーのマウント・パスの権限を確認します。 この例では、マウント・パスは
/var/jenkins_homeです。ls -ln /var/jenkins_home出力例
jenkins@mypod-123456789:/$ ls -ln /var/jenkins_home total 12 -rw-r--r-- 1 1000 1000 102 Mar 9 19:58 copy_reference_file.log drwxr-xr-x 2 1000 1000 4096 Mar 9 19:58 init.groovy.d drwxr-xr-x 9 1000 1000 4096 Mar 9 20:16 warこの出力は、Dockerfile の GID と UID (この例では
1000と1000) がコンテナー内部のマウント・パスを所有していることを示しています。