Perché la mia app non funziona quando il percorso di montaggio dello spazio di archiviazione file NFS appartiene a un utente non root?
Risoluzione dei problemi relativi al montaggio di NFS senza privilegi di root per l'archiviazione dei file.
Infrastrutture classiche
Dopo aver aggiunto l'archiviazione NFS alla tua distribuzione, la distribuzione del tuo contenitore ha esito negativo. Quando richiami i log per il tuo contenitore, potresti vedere degli errori simili ai seguenti. Il pod genera un errore e si blocca in un ciclo di ricaricamento.
write-permission
don't have required permission
can't create directory '/bitnami/mariadb/data': Permission denied
Per impostazione predefinita, gli utenti non root non dispongono dei permessi di scrittura sul percorso di montaggio del volume per lo spazio di archiviazione basato su NFS. Alcune immagini comuni dell'applicazione, come Jenkins e Nexus3, specificano un utente non root che possiede il percorso di montaggio nel Dockerfile.
Quando crei un contenitore da questo Dockerfile, la creazione del contenitore non riesce a causa di autorizzazioni insufficienti dell'utente non root sul percorso di montaggio. Per concedere i permessi di scrittura, è possibile modificare il Dockerfile
in modo da aggiungere temporaneamente l'utente non root al gruppo root prima che modifichi i permessi del percorso di mount, oppure utilizzare un container init.
Se utilizzi un grafico " Helm " per distribuire l'immagine, modifica la distribuzione " Helm " in modo da utilizzare un container " init ".
Quando si include un container init nella propria distribuzione, è possibile assegnare a un utente non root specificato
nel Dockerfile i permessi di scrittura per il percorso di montaggio del volume all'interno del container.
Il container " init " viene avviato prima dell'avvio del container dell'applicazione. Il container " init " crea il percorso di montaggio del volume all'interno del container, modifica il percorso
di montaggio in modo che sia di proprietà dell'utente corretto (non root) e si chiude. Quindi, viene avviato il contenitore dell'applicazione con l'utente non root che deve scrivere sul percorso di montaggio. Poiché il percorso è già di proprietà
dell'utente non root, la scrittura sul percorso di montaggio ha esito positivo. Se non si desidera utilizzare un container init, è possibile modificare il Dockerfile per consentire l'accesso da parte di un utente non root all'archivio
file NFS.
Prima di iniziare:
- Accedi al tuo cluster Red Hat OpenShift.
- Scegli un vincolo del contesto di sicurezza (o SCC, security context constraint) che consente alla tua distribuzione di eseguire operazioni
chown.
Per utilizzare un container init e assegnare a un utente non root i permessi di scrittura sul percorso di montaggio del volume:
-
Apri il Dockerfile per la tua applicazione e ottieni l'ID utente (UID) e l'ID di gruppo (GID) dell'utente a cui desideri concedere l'autorizzazione di scrittore sul percorso di montaggio del volume. Nell'esempio di un Dockerfile Jenkins, le informazioni sono:
- UID:
1000 - GID:
1000
Esempio di 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:
-
Aggiungi l'archiviazione persistente alla tua applicazione creando un'attestazione del volume persistente (PVC, persistent volume claim). Questo esempio utilizza la classe di archiviazione
ibmc-file-bronze. Per visualizzare le classi di archiviazione disponibili, eseguire il comandooc 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 -
Crea la PVC.
oc apply -f mypvc.yaml -
Nel file
.yamldella tua distribuzione, aggiungi il contenitoreinit. Includi l'UID e il GID che hai richiamato in precedenza.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 lineEsamina il seguente esempio di distribuzione 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 -
Crea il pod e monta la PVC nel tuo pod.
oc apply -f my-pod.yamlIl contenitore "
init" presenta un errore? PoichéRed Hat OpenShiftimposta dei vincoli relativi al contesto di sicurezza limitato, è possibile che venga visualizzato un errore del tipo "chown: /opt/ibm-ucd/server/ext_lib: Operation not permitted". Per la tua distribuzione, utilizza un SCC che consente le operazionichowne riprova. -
Verifica che il volume sia stato correttamente montato nel tuo pod. Prendi nota del nome del pod e del percorso Containers/Mounts.
oc describe pod <my-pod>Output di esempio
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 -
Accedi al pod utilizzando il nome pod di cui hai preso nota precedentemente.
oc exec -it <my-pod-123456789> /bin/bash -
Verifica le autorizzazioni del percorso di montaggio del tuo contenitore. Nell'esempio, il percorso di montaggio è
/var/jenkins_home.ls -ln /var/jenkins_homeOutput di esempio
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 warQuesto output mostra che il GID e l'UID dal tuo Dockerfile (in questo esempio,
1000e1000) possiedono il percorso di montaggio all'interno del contenitore.