Pourquoi mon application échoue-t-elle si un utilisateur non root détient le chemin de montage du stockage de fichiers NFS ?
Dépannage des problèmes de montage d' NFS s non-root pour le stockage de fichiers.
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 des droits d'écriture, vous pouvez modifier
le fichier Dockerfile afin d'ajouter temporairement l'utilisateur non-root au groupe de l'utilisateur root avant qu'il ne modifie les droits d'accès au chemin de montage, ou utiliser un conteneur init.
Si vous utilisez un diagramme Helm pour déployer l'image, modifiez le déploiement Helm afin d'utiliser un conteneur init.
Lorsque vous incluez un dans init conteneur votre déploiement, vous pouvez attribuer à 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 init conteneur crée le chemin de montage du volume à l'intérieur du conteneur, modifie le chemin de montage pour qu'il appartienne à l'utilisateur
approprié (autre que root), puis 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 de conteneur init, vous pouvez modifier le fichier Dockerfile afin d’ajouter un accès 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 d'accorder à 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 consulter les classes de stockage disponibles, exécutezoc 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
.yamlde déploiement, ajoutez le conteneurinit. 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 lineConsultez 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.yamlLe conteneur
initprésente-t-il un dysfonctionnement? 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érationschownet 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_homeExemple 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 warCette sortie montre que les identificateurs GID et UID de votre fichier Dockerfile (dans cet exemple,
1000et1000) sont propriétaires du chemin de montage à l'intérieur du conteneur.