Introdução
Os laboratórios de deploy anteriores utilizaram imagens que já existiam em um registro ou no cache do cluster. Desenvolvedores de aplicações também precisam entender o fluxo de trabalho de imagens locais: construir uma imagem a partir de arquivos da aplicação, disponibilizar essa imagem para o nó do Kubernetes e instruir um Deployment a utilizá-la.
Neste laboratório, você construirá uma pequena imagem de aplicação web localmente com o Minikube, fará o deploy dela com imagePullPolicy: Never e, em seguida, reconstruirá a aplicação como uma segunda tag de imagem para realizar uma atualização gradual (rolling update). Isso reflete uma tarefa comum no estilo CKAD: conectar o artefato da aplicação à carga de trabalho do Kubernetes que a executa.
Preparar um Espaço de Trabalho para Imagem Local
Nesta etapa, você preparará um namespace limpo e confirmará que o caminho de build da imagem está disponível.
Comece em /home/labex/project. Você criará os arquivos da aplicação, arquivos de build da imagem e manifestos do Kubernetes 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...
Aguarde até que o Pod de rede do cluster esteja pronto (Ready). A aplicação será testada através de um Service, portanto, a rede precisa estar funcional.
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-local-image e defina-o como o namespace atual:
kubectl create namespace ckad-prep-local-image
kubectl config set-context --current --namespace=ckad-prep-local-image
Confirme o namespace e verifique o comando de imagem do Minikube. O comando minikube image build constrói uma imagem diretamente para o perfil do Minikube, para que os Pods possam utilizá-la sem a necessidade de enviá-la (push) para um registro.
kubectl config view --minify --output 'jsonpath={..namespace}'; echo
minikube image build --help | sed -n '1,4p'
A saída esperada inclui:
ckad-prep-local-image
Build a container image...
Construir a Primeira Imagem Local
Nesta etapa, você criará uma pequena aplicação web e a construirá como local-message-app:v1.
A imagem usará o httpd do BusyBox para servir um arquivo estático. O conteúdo do arquivo é a versão visível da aplicação, para que você possa provar posteriormente qual tag de imagem está sendo executada no Kubernetes.
Crie o diretório da aplicação e a primeira página web:
mkdir -p local-message-app/www
cat > local-message-app/www/index.html <<'EOF'
local-image-v1
EOF
Crie um Dockerfile. A instrução COPY coloca seu arquivo local www/index.html na imagem, e o CMD inicia o servidor web do BusyBox na porta 8080 quando um container é executado a partir da imagem.
cat > local-message-app/Dockerfile <<'EOF'
FROM busybox:1.36
COPY www/index.html /www/index.html
EXPOSE 8080
CMD ["httpd", "-f", "-p", "8080", "-h", "/www"]
EOF
Construa a imagem para o perfil ativo do Minikube. A opção -t atribui uma tag local à imagem, e o caminho final é o diretório de contexto do build.
minikube image build --profile labex-v135 -t local-message-app:v1 ./local-message-app
A saída esperada inclui:
naming to docker.io/library/local-message-app:v1 done
Liste as imagens conhecidas pelo Minikube e procure pela sua nova tag:
minikube image ls --profile labex-v135 | grep local-message-app
Saída esperada:
docker.io/library/local-message-app:v1
Fazer o Deploy da Imagem Local
Nesta etapa, você executará a imagem local no Kubernetes.
Como a local-message-app:v1 não foi enviada para um registro remoto, o Deployment utiliza imagePullPolicy: Never. Isso instrui o kubelet a usar uma imagem que já existe no nó, em vez de tentar baixá-la da rede.
Crie o arquivo local-image-app.yaml:
cat > local-image-app.yaml <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
name: local-message-app
spec:
replicas: 2
selector:
matchLabels:
app: local-message-app
template:
metadata:
labels:
app: local-message-app
spec:
terminationGracePeriodSeconds: 0
containers:
- name: web
image: local-message-app:v1
imagePullPolicy: Never
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /
port: 8080
initialDelaySeconds: 1
periodSeconds: 2
---
apiVersion: v1
kind: Service
metadata:
name: local-message-app
spec:
selector:
app: local-message-app
ports:
- port: 80
targetPort: 8080
EOF
Aplique o manifesto e aguarde o Deployment:
kubectl apply -f local-image-app.yaml
kubectl rollout status deployment/local-message-app --timeout=120s
A saída esperada inclui:
deployment.apps/local-message-app created
service/local-message-app created
deployment "local-message-app" successfully rolled out
Crie um Pod cliente e teste o Service:
kubectl run image-client --image=busybox:1.36 --restart=Never --command -- sleep 3600
kubectl wait --for=condition=Ready pod/image-client --timeout=120s
kubectl exec image-client -- wget -qO- http://local-message-app
Saída esperada:
local-image-v1
Reconstruir e Atualizar para uma Nova Imagem Local
Nesta etapa, você reconstruirá a aplicação como uma segunda tag de imagem e atualizará o Deployment para essa tag.
Alterar um arquivo no disco não altera uma imagem em execução. Você deve construir uma nova tag de imagem e atualizar o Deployment para que o Kubernetes inicie novos Pods a partir dessa tag. Isso mantém a alteração de versão visível e evita depender de conteúdos de imagem locais mutáveis.
Substitua o conteúdo da página web pela versão dois:
cat > local-message-app/www/index.html <<'EOF'
local-image-v2
EOF
Construa a segunda tag de imagem:
minikube image build --profile labex-v135 -t local-message-app:v2 ./local-message-app
A saída esperada inclui:
naming to docker.io/library/local-message-app:v2 done
Atualize a imagem do Deployment e aguarde a atualização (rollout):
kubectl set image deployment/local-message-app web=local-message-app:v2
kubectl rollout status deployment/local-message-app --timeout=120s
A saída esperada inclui:
deployment.apps/local-message-app image updated
deployment "local-message-app" successfully rolled out
Confirme tanto a tag da imagem quanto a resposta da aplicação:
kubectl get deployment local-message-app -o jsonpath='{.spec.template.spec.containers[0].image}'; echo
kubectl exec image-client -- wget -qO- http://local-message-app
Saída esperada:
local-message-app:v2
local-image-v2
Resumo
Você construiu uma pequena imagem de aplicação para o perfil do Minikube, fez o deploy dela com imagePullPolicy: Never, testou-a através de um Service do Kubernetes, reconstruiu a aplicação como uma nova tag de imagem e atualizou o Deployment. O fluxo de trabalho principal consiste em disponibilizar a imagem para o nó antes de esperar que os Pods a executem.



