Construir e Executar uma Imagem de Aplicação Local

DockerBeginner
Pratique Agora

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.