Implantar a imagem de contêiner no Serviço de Kubernetes do Azure
Nesta unidade, você implantará uma imagem de contêiner no AKS (Serviço de Kubernetes do Azure). Com o AKS, você configura o cluster kubernetes para ser executado em um estado desejado por meio de um Deployment, que é o processo de fornecer atualizações declarativas para pods e ReplicaSets. Essa declaração de estado é administrada no arquivo YAML do manifesto e o controlador kubernetes altera o estado atual para o estado declarado quando instruído. Você cria este arquivo de manifesto deployment.yml e instrui sua instância do AKS a operar em um estado desejado, com pods configurados para buscar e executar a imagem de contêiner flightbookingsystemsample — armazenada no Registro de Contêiner do Azure — que você enviou na unidade anterior. Esse manifesto define declarativamente um Deployment e um serviço. O Kubernetes usa o controlador de implantação para gerenciar os pods do aplicativo; você também pode criar uma implantação imperativamente com kubectl create deployment.
Observação
Se a sua sessão tiver expirado por inatividade ou você estiver fazendo essa etapa em outro momento ou em outra CLI, talvez seja necessário reinicializar as variáveis de ambiente e se reautenticar usando os seguintes comandos:
Restaure os valores das variáveis de recurso usados na configuração. Substitua <your-subscription-ID> abaixo pela ID da assinatura que você usou para este módulo. Se o login apresentar um seletor de assinatura, escolha a mesma assinatura. Execute os comandos de autenticação um de cada vez. Depois de az account show, confirme se a assinatura ativa corresponde à configuração antes de continuar. Se um comando falhar, pare e resolva o erro.
export AZ_RESOURCE_GROUP=java-containerization-demo-rg
export AZ_CONTAINER_REGISTRY=<your-container-registry>
export AZ_KUBERNETES_CLUSTER=java-containerization-demo-aks
export AZ_LOCATION=<your-Azure-region>
export AZ_KUBERNETES_CLUSTER_DNS_PREFIX=<your-unique-DNS-prefix-to-access-your-AKS-cluster>
az login
az account set --subscription "<your-subscription-ID>"
az account show --output table
az acr login --name "$AZ_CONTAINER_REGISTRY"
Fazer deploy de uma imagem de contêiner
Agora você implanta a imagem de flightbookingsystemsample contêiner no cluster do AKS. Em containerize-and-deploy-Java-app-to-Azure/Project/Airlines, use um editor de texto instalado para criar um arquivo chamado deployment.yml. Esse caminho é relativo ao diretório pai em que você clonou o repositório. Se você já estiver em Project/Airlines, permaneça lá, em vez de navegar novamente pelo caminho relativo completo. Crie o arquivo e execute o comando kubectl apply -f deployment.yml (mencionado posteriormente) a partir deste diretório.
Adicione o conteúdo a seguir para deployment.yml e salve o arquivo. Substitua o <AZ_CONTAINER_REGISTRY> placeholder pelo valor da variável de ambiente AZ_CONTAINER_REGISTRY definida anteriormente.
apiVersion: apps/v1
kind: Deployment
metadata:
name: flightbookingsystemsample
spec:
replicas: 1
selector:
matchLabels:
app: flightbookingsystemsample
template:
metadata:
labels:
app: flightbookingsystemsample
spec:
nodeSelector:
kubernetes.io/os: linux
kubernetes.io/arch: amd64
containers:
- name: flightbookingsystemsample
image: <AZ_CONTAINER_REGISTRY>.azurecr.io/flightbookingsystemsample:latest
resources:
requests:
cpu: "1"
memory: "1Gi"
limits:
cpu: "2"
memory: "2Gi"
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: flightbookingsystemsample
spec:
type: LoadBalancer
ports:
- port: 8080
targetPort: 8080
selector:
app: flightbookingsystemsample
Observação
Se você usar o arquivo deployment_solution.yml na pasta raiz do projeto como ponto de partida, atualize sua imagem para a mesma imagem do registro e a tag :latest mostrada aqui. Adicione também a mesma configuração para Linux AMD64 nodeSelector na seção spec.template.spec, do Deployment, ao lado de containers. Não utilize a alternativa original sem alterações: a imagem e o seletor de nós (node selector) devem corresponder à plataforma de compilação deste módulo.
No deployment.yml anterior, o arquivo contém um Deployment e um serviço. A implantação é usada para administrar um conjunto de pods e o serviço é usado para permitir o acesso à rede aos pods. Os pods são configurados para efetuar pull de uma única imagem, <AZ_CONTAINER_REGISTRY>.azurecr.io/flightbookingsystemsample:latestdo Registro de Contêiner do Azure. O serviço está configurado para permitir tráfego HTTP de entrada para os pods na porta 8080, de forma semelhante a como você executou a imagem de contêiner localmente usando o argumento de porta -p.
O seletor de nó restringe os pods a nós AMD64 do Linux, correspondendo à linux/amd64 imagem criada anteriormente. Isso pertence ao Deployment, não ao Service. Um seletor restringe o agendamento; não faz com que uma imagem incompatível seja executada em outra arquitetura.
Antes de configurar o acesso ao cluster, verifique se a criação do cluster do AKS na unidade de instalação foi concluída com êxito. Verifique o estado de provisionamento e a versão atual do Kubernetes:
az aks show \
--resource-group "$AZ_RESOURCE_GROUP" \
--name "$AZ_KUBERNETES_CLUSTER" \
--query '{provisioningState:provisioningState,currentKubernetesVersion:currentKubernetesVersion}' \
--output table
Não continue se o comando falhar, provisioningState não for currentKubernetesVersion ou major.minor.patch não for uma versão não vazia no formato Succeeded.
As instruções da ferramenta a seguir se aplicam à sessão local de Bash no Linux, macOS ou WSL estabelecida na configuração, não ao PowerShell nativo nem ao Prompt de Comando. Se você já tiver instalações funcionais de kubectl e kubelogin nessa sessão, mantenha-as em vez de reinstalá-las. Verifique-as usando kubectl version --client e kubelogin --version e certifique-se de que kubectl atenda à política de discrepância de versão compatível para o cluster.
Caso contrário, substitua <control-plane-version> pelo retornado currentKubernetesVersion. Instale essa versão correspondente kubectl e kubelogin em locais com permissão de gravação para o usuário:
KUBECTL_VERSION="<control-plane-version>"
if [[ "$KUBECTL_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
mkdir -p "$HOME/.local/bin" &&
az aks install-cli \
--client-version "$KUBECTL_VERSION" \
--install-location "$HOME/.local/bin/kubectl" \
--kubelogin-install-location "$HOME/.local/bin/kubelogin" &&
export PATH="$HOME/.local/bin:$PATH" &&
kubectl version --client &&
kubelogin --version
else
printf 'Stop: set KUBECTL_VERSION to the returned major.minor.patch version.\n' >&2
false
fi
Ambos os caminhos de instalação incluem o nome do arquivo executável. O comando PATH export aplica-se somente ao shell atual; repita-o em uma nova sessão ou adicione-o à configuração de inicialização do Bash apropriada. Resolva qualquer falha de instalação ou verificação de versão antes de continuar.
Depois que ambas as ferramentas estiverem disponíveis e verificadas, configure kubectl para se conectar ao cluster do AKS:
az aks get-credentials \
--resource-group $AZ_RESOURCE_GROUP \
--name $AZ_KUBERNETES_CLUSTER
A saída a seguir é típica:
Merged AZ_KUBERNETES_CLUSTER as current context in ~/.kube/config
Verifique os sistemas operacionais e as arquiteturas reais do nó antes de aplicar o manifesto:
kubectl get nodes \
-o custom-columns='NAME:.metadata.name,OS:.status.nodeInfo.operatingSystem,ARCH:.status.nodeInfo.architecture'
O caminho de build deste linux/amd64 módulo requer nós AMD64 do Linux. Se não houver nós correspondentes, pare e resolva a incompatibilidade antes de continuar. Use um pool de nós AMD64 com suporte ou recompile, execute e envie por push a imagem para outra arquitetura de nó do Linux com suporte e atualize o seletor de arquitetura do Deployment para corresponder. A opção Docker --platform não cria ou altera um pool de nós do AKS.
De containerize-and-deploy-Java-app-to-Azure/Project/Airlines, aplique deployment.yml ao cluster:
kubectl apply -f deployment.yml
A saída a seguir é típica:
deployment.apps/flightbookingsystemsample created
service/flightbookingsystemsample created
Monitore o status da implantação usando o seguinte comando:
kubectl get all
A saída a seguir é típica:
kubectl get all
NAME READY STATUS RESTARTS AGE
pod/flightbookingsystemsample-b7fd6684f-4j8vf 1/1 Running 0 37s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/flightbookingsystemsample LoadBalancer 10.0.62.153 <external-IP> 8080:30534/TCP 37s
service/kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 11h
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/flightbookingsystemsample 1/1 1 1 37s
NAME DESIRED CURRENT READY AGE
replicaset.apps/flightbookingsystemsample-b7fd6684f 1 1 1 37s
O status de Running um pod não confirma se o Tomcat terminou de implantar o aplicativo ou se as solicitações HTTP são bem-sucedidas. Aguarde o rollout da implantação e siga os logs de inicialização do aplicativo:
kubectl rollout status deployment/flightbookingsystemsample --timeout=300s &&
kubectl logs deployment/flightbookingsystemsample --tail=100 --follow
Um rollout bem-sucedido verifica a disponibilidade do Kubernetes. Como este manifesto não inclui uma investigação de preparação da aplicação, o processo de implantação (rollout) não envolve um teste de integridade HTTP. Siga os logs até que o Tomcat reporte a inicialização do servidor concluída e que a implantação de AirlinesReservationSample.war tenha sido concluída sem erros. Em seguida, pressione Ctrl+C para parar de seguir os logs. Isso interrompe apenas o fluxo de log, não o contêiner. Se a implantação ou a inicialização do aplicativo falhar ou não for concluída, inspecione os logs e os eventos de pod em vez de continuar para a verificação do navegador.
A saída histórica a seguir ilustra as mensagens de inicialização de uma imagem anterior do Tomcat 10.1.33. Isto não é a saída da imagem atualizada neste módulo; use seus próprios logs para verificar a inicialização em vez de esperar as mesmas versões, carimbos de data/hora ou detalhes do ambiente:
kubectl logs pod/flightbookingsystemsample-b7fd6684f-4j8vf
15-Nov-2024 12:31:51.208 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version name: Apache Tomcat/10.1.33
15-Nov-2024 12:31:51.211 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server built: Nov 7 2024 22:28:55 UTC
15-Nov-2024 12:31:51.212 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version number: 10.1.33.0
15-Nov-2024 12:31:51.212 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Name: Linux
15-Nov-2024 12:31:51.212 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Version: 5.15.0-1074-azure
15-Nov-2024 12:31:51.212 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Architecture: amd64
15-Nov-2024 12:31:51.216 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Java Home: /usr/lib/jvm/msopenjdk-17
15-Nov-2024 12:31:51.216 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Version: 17.0.13+11-LTS
15-Nov-2024 12:31:51.216 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Vendor: Microsoft
15-Nov-2024 12:31:51.216 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_BASE: /usr/local/tomcat
15-Nov-2024 12:31:51.216 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_HOME: /usr/local/tomcat
15-Nov-2024 12:31:51.226 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties
15-Nov-2024 12:31:51.226 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
15-Nov-2024 12:31:51.227 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djdk.tls.ephemeralDHKeySize=2048
15-Nov-2024 12:31:51.227 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.protocol.handler.pkgs=org.apache.catalina.webresources
15-Nov-2024 12:31:51.227 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dorg.apache.catalina.security.SecurityListener.UMASK=0027
15-Nov-2024 12:31:51.227 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: --add-opens=java.base/java.lang=ALL-UNNAMED
15-Nov-2024 12:31:51.228 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: --add-opens=java.base/java.io=ALL-UNNAMED
15-Nov-2024 12:31:51.228 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: --add-opens=java.base/java.util=ALL-UNNAMED
15-Nov-2024 12:31:51.228 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: --add-opens=java.base/java.util.concurrent=ALL-UNNAMED
15-Nov-2024 12:31:51.229 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED
15-Nov-2024 12:31:51.229 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dcatalina.base=/usr/local/tomcat
15-Nov-2024 12:31:51.229 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dcatalina.home=/usr/local/tomcat
15-Nov-2024 12:31:51.229 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.io.tmpdir=/usr/local/tomcat/temp
15-Nov-2024 12:31:51.231 INFO [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent The Apache Tomcat Native library which allows using OpenSSL was not found on the java.library.path: [/usr/java/packages/lib:/usr/lib64:/lib64:/lib:/usr/lib]
15-Nov-2024 12:31:51.565 INFO [main] org.apache.coyote.AbstractProtocol.init Initializing ProtocolHandler ["http-nio-8080"]
15-Nov-2024 12:31:51.602 INFO [main] org.apache.catalina.startup.Catalina.load Server initialization in [616] milliseconds
15-Nov-2024 12:31:51.658 INFO [main] org.apache.catalina.core.StandardService.startInternal Starting service [Catalina]
15-Nov-2024 12:31:51.659 INFO [main] org.apache.catalina.core.StandardEngine.startInternal Starting Servlet engine: [Apache Tomcat/10.1.33]
15-Nov-2024 12:31:51.689 INFO [main] org.apache.catalina.startup.HostConfig.deployWAR Deploying web application archive [/usr/local/tomcat/webapps/AirlinesReservationSample.war]
15-Nov-2024 12:31:53.264 INFO [main] org.apache.jasper.servlet.TldScanner.scanJars At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
15-Nov-2024 12:31:55.155 INFO [main] com.sun.xml.ws.server.MonitorBase.createRoot Metro monitoring rootname successfully set to: com.sun.metro:pp=/,type=WSEndpoint,name=/AirlinesReservationSample-PriceAndSeats-PriceAndSeatsPort
15-Nov-2024 12:31:55.347 INFO [main] com.sun.xml.ws.transport.http.servlet.WSServletDelegate.<init> WSSERVLET14: XML-WS servlet initializing
WARNING:Error in the metadata of the table SEATS: table's row count in the metadata is 5 but 6 records have been found and loaded by UCanAccess. All will work fine, but it's better to repair your database.
15-Nov-2024 12:31:56.248 INFO [main] com.sun.xml.ws.transport.http.servlet.WSServletContextListener.contextInitialized WSSERVLET12: XML-WS context listener initializing
15-Nov-2024 12:31:56.249 INFO [main] com.sun.xml.ws.transport.http.servlet.WSServletContextListener.contextInitialized WSSERVLET12: XML-WS context listener initializing
15-Nov-2024 12:31:56.284 INFO [main] org.apache.catalina.startup.HostConfig.deployWAR Deployment of web application archive [/usr/local/tomcat/webapps/AirlinesReservationSample.war] has finished in [4,595] ms
15-Nov-2024 12:31:56.285 INFO [main] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [/usr/local/tomcat/webapps/docs]
15-Nov-2024 12:31:56.315 INFO [main] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [/usr/local/tomcat/webapps/docs] has finished in [30] ms
15-Nov-2024 12:31:56.316 INFO [main] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [/usr/local/tomcat/webapps/examples]
15-Nov-2024 12:31:56.439 INFO [main] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [/usr/local/tomcat/webapps/examples] has finished in [123] ms
15-Nov-2024 12:31:56.440 INFO [main] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [/usr/local/tomcat/webapps/manager]
15-Nov-2024 12:31:56.456 INFO [main] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [/usr/local/tomcat/webapps/manager] has finished in [16] ms
15-Nov-2024 12:31:56.457 INFO [main] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [/usr/local/tomcat/webapps/ROOT]
15-Nov-2024 12:31:56.468 INFO [main] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [/usr/local/tomcat/webapps/ROOT] has finished in [11] ms
15-Nov-2024 12:31:56.468 INFO [main] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [/usr/local/tomcat/webapps/host-manager]
15-Nov-2024 12:31:56.481 INFO [main] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [/usr/local/tomcat/webapps/host-manager] has finished in [13] ms
15-Nov-2024 12:31:56.484 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-nio-8080"]
15-Nov-2024 12:31:56.501 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in [4897] milliseconds
Monitore o serviço para obter seu endereço externo:
kubectl get service flightbookingsystemsample --watch
O EXTERNAL-IP valor pode ser <pending> inicialmente enquanto Azure provisiona o balanceador de carga. Isso pode levar vários minutos e não é evidência de uma implantação com falha por si só. Quando um endereço aparecer, pressione Ctrl+C para interromper o monitoramento. Se o provisionamento não for concluído, interrompa o monitoramento e inspecione os eventos do serviço usando kubectl describe service flightbookingsystemsample.
A seguinte saída ilustrativa mostra onde o endereço atribuído é exibido:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
flightbookingsystemsample LoadBalancer 10.0.62.153 <external-IP> 8080:30534/TCP 3m28s
Observação
Substitua o endereço IP <external-IP> na seguinte URL pelo valor EXTERNAL-IP do comando executado anteriormente:
Abra um navegador e visite a página inicial do exemplo Sistema de Reservas de Voo em http://<external-IP>:8080/AirlinesReservationSample/. Confirme se a página do aplicativo responde; um Running pod ou um IP atribuído sozinho não prova a preparação do aplicativo. Seu navegador deve ser semelhante à seguinte captura de tela:
Opcionalmente, você pode fazer login com qualquer usuário de tomcat-users.xml – por exemplo, someuser@azure.com: password.
Solução de problemas: incompatibilidade de plataforma da imagem
Para falhas de inicialização de pod, inspecione kubectl describe pods -l app=flightbookingsystemsamplee kubectl logs deployment/flightbookingsystemsample --tail=100kubectl get events --sort-by=.metadata.creationTimestamp. Um CrashLoopBackOff estado pode ter várias causas, incluindo erros de aplicativo; não suponha que cada falha seja uma incompatibilidade de arquitetura.
Se você confirmar que uma imagem já implantada tem a plataforma errada, primeiro repita o build, a execução local, a inspeção de imagem, a marcação do Registro e as etapas de push com as configurações de plataforma correspondentes. Após a imagem corrigida ser reconstruída, renomeada e enviada com a mesma marcação :latest, substitua explicitamente os pods em execução:
kubectl rollout restart deployment/flightbookingsystemsample &&
kubectl rollout status deployment/flightbookingsystemsample --timeout=300s
Para esse manifesto, :latest é definido por padrão como imagePullPolicy: Always, portanto, os pods de substituição resolvem a tag atual do registro. Reaplicar um manifesto inalterado por si só não dispara um rollout. Se você personalizou a política de busca, utilize uma marcação ou um digest de imagem atualizado e, em vez disso, atualize o Deployment. Repita as verificações de URL do aplicativo e do log de inicialização após a implantação.
Limpar os recursos
Os recursos criados neste módulo podem gerar custos contínuos. Para limpar os recursos, exclua o grupo de recursos que os contém usando o seguinte comando:
az group delete --name $AZ_RESOURCE_GROUP