Por que não é possível incluir o acesso de usuário não raiz ao armazenamento persistente?

Infraestrutura clássica

Os usuários não raiz não podem gravar no armazenamento de arquivos, mesmo depois de configurar as permissões de acesso.

Após você incluir acesso de usuário não raiz no armazenamento persistente ou implementar um gráfico do Helm com um ID de usuário não raiz especificado, o usuário não pode gravar no armazenamento montado.

A implementação do app ou configuração do gráfico do Helm especifica o contexto de segurança para o fsGroup (ID do grupo) e runAsUser (ID do usuário) do pod. Geralmente, o contexto de segurança padrão de um pod configura runAsNonRoot para que o pod não possa executar como o usuário raiz. Como a configuração fsGroup não foi projetada para o armazenamento compartilhado, como o armazenamento de arquivo NFS, a configuração de fsGroup não é suportada e a configuração de runAsUser é configurada automaticamente como 2020. Essas configurações padrão não permitem que outros usuários não raiz gravem no armazenamento montado.

Resolvendo o problema

Para permitir que um usuário não raiz tenha acesso de leitura e gravação a um dispositivo de armazenamento de arquivos, deve-se alocar um ID do grupo suplementar em uma classe de armazenamento, referir-se a essa classe de armazenamento na PVC e configurar o contexto de segurança do pod com um valor runAsUser que é incluído automaticamente no ID do grupo suplementar. Ao conceder ao ID do grupo suplementar o acesso de leitura e gravação ao armazenamento de arquivo, qualquer usuário não raiz que pertença ao ID do grupo, incluindo seu pod, tem o acesso ao armazenamento de arquivo concedido.

Você pode usar um dos sites fornecidos gid classes de armazenamento ou criar sua própria classe de armazenamento para definir sua própria ID de grupo suplementar.

A alocação de um ID de grupo suplementar para um usuário não raiz de um dispositivo File Storage é suportada apenas para clusters de zona única e não pode ser usada em clusters multizona.

  1. Selecione uma das classes de armazenamento gid fornecidas para designar o ID do grupo padrão 65531 ao seu usuário não raiz que você deseja que leia e grave em seu armazenamento de arquivo. Para designar um ID de grupo customizado, crie um arquivo YAML para uma classe de armazenamento customizado. Em seu arquivo YAML de classe de armazenamento customizado, inclua o parâmetro gidAllocate: "true" e defina o ID do grupo no parâmetro gidFixed.

    Exemplo de classes de armazenamento para atribuir a ID de grupo padrão 65531:

    • ibmc-file-bronze-gid
    • ibmc-file-silver-gid
    • ibmc-file-gold-gid

    Exemplo de classe de armazenamento personalizada para especificar uma ID de grupo diferente:

    apiVersion: storage.k8s.io/v1beta1
    kind: StorageClass
    metadata:
      name: ibmc-file-bronze-gid-custom
      labels:
        kubernetes.io/cluster-service: "true"
    provisioner: ibm.io/ibmc-file
    parameters:
      type: "Endurance"
      iopsPerGB: "2"
      sizeRange: "[1-12000]Gi"
      mountOptions: nfsvers=4.1,hard
      billingType: "hourly"
      reclaimPolicy: "Delete"
      classVersion: "2"
      gidAllocate: "true"
      gidFixed: "65165"
    

    Para criar a classe de armazenamento em seu cluster, execute kubectl apply -f storageclass.yaml.

  2. Crie um arquivo YAML para o seu PVC que use a classe de armazenamento que você criou.

    kind: PersistentVolumeClaim
    apiVersion: v1
    metadata:
      name: gid-pvc
      labels:
        billingType: "monthly"
    spec:
      accessModes:
        - ReadWriteMany
      resources:
        requests:
          storage: 20Gi
      storageClassName: ibmc-file-bronze-gid
    
  3. Crie o PVC em seu cluster.

    kubectl apply -f pvc.yaml
    
  4. Aguarde alguns minutos para que o armazenamento de arquivo seja provisionado e a PVC mude para um status Bound.

    Se você criou o PVC em um cluster de várias zonas, o PVC permanecerá em um estado pending.

    kubectl get pvc
    

    Saída de exemplo:

    NAME      STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS           AGE
    gid-pvc   Bound    pvc-5e4acab4-9b6f-4278-b53c-22e1d3ffa123   20Gi       RWX            ibmc-file-bronze-gid   2m54s
    
  5. Crie um arquivo YAML para a sua implementação que monta a PVC que você criou. No campo spec.template.spec.securityContext.runAsUser, especifique o ID do usuário não raiz que você deseja usar. Esse ID do usuário é incluído automaticamente no ID do grupo suplementar que é definido na classe de armazenamento para obter acesso de leitura e gravação no armazenamento de arquivo.

    Exemplo de criação de uma implantação node-hello:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: gid-deployment
      labels:
        app: gid
    spec:
      selector:
        matchLabels:
          app: gid
      template:
        metadata:
          labels:
            app: gid
        spec:
          containers:
          - image: gcr.io/google-samples/node-hello:1.0
            name: gid-container
            volumeMounts:
            - name: gid-vol
              mountPath: /myvol
          securityContext:
            runAsUser: 2020
          volumes:
          - name: gid-vol
            persistentVolumeClaim:
              claimName: gid-pvc
    
  6. Crie a implementação em seu cluster.

    kubectl apply -f deployment.yaml
    
  7. Verifique se o seu pod está em um status Em execução.

    kubectl get pods
    

    Saída de exemplo:

    NAME                              READY   STATUS    RESTARTS   AGE
    gid-deployment-5dc86db4c4-5hbts   2/2     Running   0          69s
    
  8. Efetue login em seu pod.

    kubectl exec <pod_name> -it -- bash
    

Verificando as permissões de leitura e gravação para o usuário não raiz

  1. Liste o ID do usuário e os IDs do grupo para o usuário atual dentro do pod. A configuração estará correta se o seu ID de usuário não raiz estiver listado como uid e o ID do grupo suplementar que você definiu em sua classe de armazenamento estiver listado sob groups.

    id
    

    Saída de exemplo:

    uid=2020 gid=0(root) groups=0(root), 65531
    
  2. Liste as permissões para o seu diretório de montagem de volume que você definiu em sua implementação. A configuração estará correta se o ID do grupo suplementar que você definiu em sua classe de armazenamento estiver listado com permissões de leitura e gravação em seu diretório de montagem do volume.

    ls -l /<volume_mount_path>
    

    Saída de exemplo:

    drwxrwxr-x 2 nobody 65531 4096 Dec 11 07:40 .
    drwxr-xr-x 1 root   root  4096 Dec 11 07:30 ..
    
  3. Crie um arquivo em seu diretório de montagem.

    echo "Able to write to file storage with my non-root user." > /myvol/gidtest.txt
    
  4. Liste as permissões para os arquivos em seu diretório de montagem de volume.

    ls -al /myvol/
    

    Saída de exemplo:

    drwxrwxr-x 2 nobody      65531 4096 Dec 11 07:40 .
    drwxr-xr-x 1 root        root  4096 Dec 11 07:30 ..
    -rw-r--r-- 1 2020   4294967294   42 Dec 11 07:40 gidtest.txt .
    

    Em sua saída da CLI, o ID do usuário não raiz é listado com acesso de leitura e gravação ao arquivo que você criou.

  5. Saia do pod.

    exit
    

Se você precisar mudar a propriedade do caminho de montagem de nobody, veja O app falha quando um usuário não raiz possui o caminho de montagem do armazenamento de arquivo NFS.