Pourquoi mon application échoue-t-elle si un utilisateur non root détient le chemin de montage du stockage de fichiers NFS ?
Infrastructure classique
Une fois que vous ajoutez du stockage NFS dans votre déploiement, le conteneur ne parvient pas à se déployer. Lorsque vous extrayez les journaux de votre conteneur, vous pourrez voir les messages d'erreur suivants. On observer l'échec du pod qui est bloqué dans un cycle de rechargement.
write-permission
don't have required permission
can't create directory '/bitnami/mariadb/data': Permission denied
Par défaut, les utilisateurs non root n'ont pas le droit d'écriture sur le chemin de montage du volume pour le stockage sauvegardé par NFS. Certaines images d'application courantes, telles que Jenkins et Nexus3, spécifient un utilisateur non root qui est le propriétaire du chemin de montage dans le fichier Dockerfile.
Lorsque vous créez un conteneur à partir de ce fichier Dockerfile, la création échoue car l'utilisateur non root ne dispose pas des droits nécessaires pour accéder au chemin de montage. Pour accorder l'autorisation d'écriture, vous pouvez modifier
le fichier Docker pour ajouter temporairement l'utilisateur non root au groupe d'utilisateurs root avant de modifier les autorisations du chemin de montage, ou utiliser un conteneur 'init
Si vous utilisez un diagramme Helm pour déployer l'image, modifiez le déploiement Helm pour utiliser un conteneur 'init
Lorsque vous incluez un conteneur 'init
dans votre déploiement, vous pouvez donner à un utilisateur non root spécifié
dans votre Dockerfile des droits d'écriture sur le chemin de montage du volume à l'intérieur du conteneur.
Le conteneur 'init
démarre avant le conteneur de votre application. Le conteneur " init
crée le chemin de montage du volume à l'intérieur du conteneur, modifie le chemin de montage pour qu'il appartienne à l'utilisateur
correct (non root) et se ferme. Ensuite, le conteneur de votre application avec l'utilisateur non root qui doit écrire dans le chemin de montage démarre. Comme le chemin est déjà détenu par l'utilisateur non root, l'écriture dans le chemin de
montage aboutit. Si vous ne souhaitez pas utiliser un conteneur 'init
, vous pouvez modifier le fichier Docker pour ajouter l'accès d'un utilisateur non root au stockage de fichiers NFS.
Avant de commencer :
- Accédez à votre cluster Red Hat OpenShift.
- Sélectionnez une contrainte de contexte de sécurité (SCC) permettant à votre déploiement de réaliser des opérations
chown
.
Pour utiliser un conteneur 'init
afin de donner à un utilisateur non root des droits d'écriture sur le chemin de montage du volume :
-
Ouvrez le fichier Dockerfile de votre application et récupérez l'ID utilisateur (UID) et l'ID du groupe (GID) de l'utilisateur auquel vous voulez accorder les droits en écriture sur le chemin de montage du volume. Dans l'exemple d'un fichier Dockerfile Jenkins, les informations sont :
- ID utilisateur :
1000
- ID groupe :
1000
Exemple de document 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} ...
- ID utilisateur :
-
Ajoutez du stockage persistant à votre application en créant une réservation de volume persistant (PVC). Cet exemple utilise la classe de stockage
ibmc-file-bronze
. Pour passer en revue les classes de stockage disponibles, exécutez 'oc 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
-
Créez le PVC (circuit virtuel permanent).
oc apply -f mypvc.yaml
-
Dans votre fichier de déploiement "
.yaml
, ajoutez le conteneur "init
Insérez les identificateurs UID et GID que vous avez récupérés précédemment.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
Consultez l'exemple de déploiement de Jenkins suivant.
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
-
Créez le pod et montez la PVC dessus.
oc apply -f my-pod.yaml
Le conteneur "
init
est-il défaillant ? Etant donné qu'Red Hat OpenShift définit des contraintes de contexte de sécurité restreintes, vous pouvez obtenir une erreur de ce type :chown: /opt/ibm-ucd/server/ext_lib: Operation not permitted
. Pour votre déploiement, utilisez une contrainte de contexte de sécurité qui autorise des opérationschown
et renouvelez votre demande. -
Vérifiez que le montage du volume sur votre pod a réussi. Notez le nom du pod et le chemin Containers/Mounts.
oc describe pod <my-pod>
Exemple de sortie
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
-
Connectez-vous au pod en utilisant le nom du pod que vous avez noté précédemment.
oc exec -it <my-pod-123456789> /bin/bash
-
Vérifiez les droits octroyés pour le chemin de montage de votre conteneur. Dans l'exemple, le chemin de montage est
/var/jenkins_home
.ls -ln /var/jenkins_home
Exemple de sortie
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
Cette sortie montre que les identificateurs GID et UID de votre fichier Dockerfile (dans cet exemple,
1000
et1000
) sont propriétaires du chemin de montage à l'intérieur du conteneur.