Introdução
Um init container é executado antes dos containers de aplicação principais em um Pod. Cada init container deve ser concluído com sucesso antes que o Kubernetes inicie o próximo init container ou qualquer container regular. Isso torna os init containers úteis para preparar arquivos, verificar dependências ou realizar pequenas tarefas de configuração que não precisam permanecer em execução junto com a aplicação.
Neste laboratório, você adicionará um init container que grava um arquivo de inicialização em um volume emptyDir compartilhado, confirmará que o container da aplicação consegue ler o arquivo, inspecionará o status de conclusão e os logs do init container e, em seguida, usará o mesmo padrão em um template de Deployment.
Preparar um Namespace para Init Containers
Nesta etapa, você preparará um namespace limpo para praticar com init containers.
Comece em /home/labex/project. Você escreverá os manifestos de Pod e Deployment neste diretório.
mkdir -p /home/labex/project
cd /home/labex/project
Verifique se o servidor da API do Kubernetes está acessível. Se a VM acabou de iniciar e o nó ainda não está pronto, aguarde alguns segundos e execute o comando novamente.
kubectl get nodes --request-timeout=5s
A saída esperada inclui:
NAME STATUS ROLES AGE VERSION
labex-v135 Ready control-plane ... v1.35...
Os init containers são executados dentro de Pods, portanto, aguarde até que o Pod de rede do cluster esteja pronto (Ready) antes de criar as cargas de trabalho.
kubectl wait --namespace kube-system --for=condition=Ready pod -l k8s-app=calico-node --timeout=120s
Saída esperada:
pod/calico-node-... condition met
Crie um namespace chamado ckad-prep-init:
kubectl create namespace ckad-prep-init
Defina este namespace como o namespace do contexto atual:
kubectl config set-context --current --namespace=ckad-prep-init
Confirme o namespace atual:
kubectl config view --minify --output 'jsonpath={..namespace}'; echo
Saída esperada:
ckad-prep-init
Preparar Dados Compartilhados Antes da Inicialização da Aplicação
Nesta etapa, você criará um Pod onde um init container prepara um arquivo antes que o container da aplicação seja iniciado.
O volume emptyDir é criado quando o Pod é atribuído a um nó e é compartilhado pelos containers no mesmo Pod. Tanto o init container quanto o container da aplicação montam este volume em /work. O init container grava em /work/startup.txt e, em seguida, encerra. Somente após a conclusão bem-sucedida, o Kubernetes inicia o container da aplicação.
Crie o arquivo init-file-pod.yaml:
cat > init-file-pod.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:
name: init-file-demo
labels:
app: init-file-demo
spec:
terminationGracePeriodSeconds: 0
volumes:
- name: shared-work
emptyDir: {}
initContainers:
- name: prepare-startup-file
image: busybox:1.36
command:
- /bin/sh
- -c
- 'echo init-started; echo prepared-by-init > /work/startup.txt; echo init-finished'
volumeMounts:
- name: shared-work
mountPath: /work
containers:
- name: app
image: busybox:1.36
command:
- /bin/sh
- -c
- 'echo app-started; cat /work/startup.txt; sleep 3600'
volumeMounts:
- name: shared-work
mountPath: /work
EOF
Aplique o manifesto:
kubectl apply -f init-file-pod.yaml
Saída esperada:
pod/init-file-demo created
Aguarde até que o Pod esteja pronto (Ready):
kubectl wait --for=condition=Ready pod/init-file-demo --timeout=120s
Saída esperada:
pod/init-file-demo condition met
Leia o arquivo de dentro do container da aplicação. Isso prova que o init container preparou os dados no volume compartilhado antes que a aplicação fosse iniciada.
kubectl exec init-file-demo -c app -- cat /work/startup.txt
Saída esperada:
prepared-by-init
Inspecionar o Status e os Logs do Init Container
Nesta etapa, você inspecionará as evidências de que o init container foi concluído antes que o container da aplicação continuasse em execução.
Os init containers aparecem em .status.initContainerStatuses, enquanto os containers regulares aparecem em .status.containerStatuses. O init container deve ter um motivo (reason) Completed porque foi encerrado com sucesso.
kubectl get pod init-file-demo -o 'jsonpath={.status.initContainerStatuses[0].name}{" "}{.status.initContainerStatuses[0].state.terminated.reason}{"\n"}'
Saída esperada:
prepare-startup-file Completed
Agora, inspecione o status do container da aplicação regular. Ele deve estar pronto e em execução.
kubectl get pod init-file-demo -o 'jsonpath={.status.containerStatuses[0].name}{" "}{.status.containerStatuses[0].ready}{" "}{.status.containerStatuses[0].state.running.startedAt}{"\n"}'
A saída esperada inclui:
app true ...
Leia os logs do init container. Mesmo que o init container tenha terminado, seus logs permanecem disponíveis através do comando kubectl logs -c.
kubectl logs init-file-demo -c prepare-startup-file
Saída esperada:
init-started
init-finished
Leia os logs do container da aplicação. A aplicação inicia após o init container gravar o arquivo, portanto, seus logs incluem o valor preparado.
kubectl logs init-file-demo -c app
A saída esperada inclui:
app-started
prepared-by-init
Adicionar um Init Container a um Deployment
Nesta etapa, você usará o mesmo padrão de init container dentro de um template de Deployment.
Para cargas de trabalho de aplicação, você geralmente coloca init containers no template de Pod de um controlador, em vez de criar Pods isolados. Quando o Deployment cria um Pod, o Kubernetes executa o init container primeiro para cada Pod criado a partir desse template.
Crie o arquivo init-deployment.yaml:
cat > init-deployment.yaml <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
name: init-web
spec:
replicas: 1
selector:
matchLabels:
app: init-web
template:
metadata:
labels:
app: init-web
spec:
terminationGracePeriodSeconds: 0
volumes:
- name: web-content
emptyDir: {}
initContainers:
- name: render-index
image: busybox:1.36
command:
- /bin/sh
- -c
- 'echo deployment-init > /site/index.txt'
volumeMounts:
- name: web-content
mountPath: /site
containers:
- name: web
image: busybox:1.36
command:
- /bin/sh
- -c
- 'cat /site/index.txt; sleep 3600'
volumeMounts:
- name: web-content
mountPath: /site
EOF
Aplique o Deployment:
kubectl apply -f init-deployment.yaml
Saída esperada:
deployment.apps/init-web created
Aguarde até que o Deployment esteja disponível:
kubectl wait --for=condition=Available deployment/init-web --timeout=120s
Saída esperada:
deployment.apps/init-web condition met
Encontre o Pod criado pelo Deployment:
web_pod="$(kubectl get pods -l app=init-web -o 'jsonpath={.items[0].metadata.name}')"
echo "$web_pod"
A saída esperada mostra um nome de Pod gerado:
init-web-...
Leia os logs do container da aplicação a partir desse Pod:
kubectl logs "$web_pod" -c web
Saída esperada:
deployment-init
Inspecione o status de conclusão do init container dentro do Pod criado pelo Deployment:
kubectl get pod "$web_pod" -o 'jsonpath={.status.initContainerStatuses[0].name}{" "}{.status.initContainerStatuses[0].state.terminated.reason}{"\n"}'
Saída esperada:
render-index Completed
Resumo
Você adicionou init containers a um Pod e a um template de Deployment. Você usou um volume emptyDir para compartilhar arquivos preparados com o container da aplicação, inspecionou o status de conclusão do init container, leu os logs do init e da aplicação e confirmou que o mesmo padrão funciona para Pods de aplicação gerenciados por controladores.


