Pular para o conteúdo principal

Volumes

Sabemos que a função do container é processar dados e morrer e o que segura ele vivo é o processo com ID 1. Se esse processo morrer o container para. Somente é destruído os dados quando o container é destruído.

datalost

No mundo dos containers para persistir os dados usamos os volumes.

retain

Os containers dentro de um pod rodam em suas respectivas camadas read-write como falamos anteriormente. O pod controla os containers dentro dele e quando um pod é finalizado ele destrói seus respectivos containers levando junto os dados.

poddata

Para persistir os dados é necessário também o uso de volumes.

poddata

Se criamos um pod normalmente os dados são perdidos quando o pod morrer

alt text

Para criar um volume usando um driver Local precisamos declarar um volume. Seria o mesmo processo quando um container cria o volume automaticamente. No cenário abaixo criamos um volume dentro do host, mas o volume ainda não está sendo usado.

alt text

É necessário mapear que o /opt do container corresponda ao volume no /data.

alt text

Se esse pod for destruído e criado novamente e subir em um node diferente, o dado estará lá? Não.

Dois pontos que devemos levar em consideração aqui.

  1. Esse volume esta passando um path no node logo esse diretório precisa existir previamente com permissão adequada.

  2. Isso funcionaria para um cluster com um único nó.

  3. Em um cluster com múltiplos o pod pode subir em qualquer node que passe pela filtragem do scheduler. O dados não estariam disponíveis se ele subisse em um node diferente do que subiu antes.

Ter réplicas para o mesmo pod necessita que todos os pods vejam o mesmo diretório para que os dados façam sentido.

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: "ramdon-number-generator"
spec:
containers:
- name: alpine
image: "alpine"

command: ["/bin/sh", "-c"]
args: ["shuf -i 0-100 -n 1 >> /opt/number.out;"]
volumeMounts:
- name: data-volume
mountPath: /opt
volumes:
- name: data-volume
hostPath:
path: /data
type: Directory
EOF

# Observe que o pod não esta ready.
kubectl get pods
NAME READY STATUS RESTARTS AGE
ramdon-number-generator 0/1 ContainerCreating 0 22s

kubectl describe pod ramdon-number-generator
## Removido para facilitar a leitura
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 28s default-scheduler Successfully assigned default/ramdon-number-generator to kind-cluster-worker2
# Não conseguiu montar como esperado
Warning FailedMount 13s (x6 over 29s) kubelet MountVolume.SetUp failed for volume "data-volume" : hostPath type check failed: /data is not a directory

Se você trocasse por /tmp funcionaria.

Mas esta é uma solução específica para alguns e não para a grande maioria. O ideal não é guardar os dados das aplicações dentro dos nodes, mas ter uma solução externa para esse propósito.

Kubernetes suporta diferentes tipos de soluções de armazenamento.

  • NFS
  • GlusterFS
  • Flocker
  • Ceph
  • Scaleio
  • vSphere
  • Outras

E também muitas soluções de cloud como:

  • AWS
  • Azure
  • GCP
  • outros

Por exemplo na AWS poderíamos usar o EBS.

  volumes:
- name: data-volume
awsElasticBlockStore:
volumeID: <volume-id>
fsType: ext4

Vamos criar um container do nginx e um volume compartilhado entre ele e outro. O segundo container deverá colocar a hora no index.html do nginx.

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: pod-com-dois-containers
spec:
containers:
- name: nginx-container
image: nginx
ports:
- containerPort: 80
volumeMounts:
- name: html-volume
mountPath: /usr/share/nginx/html
- name: hora-container
image: alpine
command: ["/bin/sh", "-c"]
args:
- while true; do echo "$(date '+%Y-%m-%d %H:%M:%S')" > /mnt/html/index.html; sleep 1; done
volumeMounts:
- name: html-volume
mountPath: /mnt/html
volumes:
- name: html-volume
emptyDir: {}
EOF
notification icon
Would you like to be notified about new content?