Implementación de la imagen de contenedor en Azure Kubernetes Service
En esta unidad, implementará una imagen de contenedor en Azure Kubernetes Service (AKS). Con AKS, configurará el clúster de Kubernetes para que se ejecute en un estado deseado a través de una implementación, que es el proceso de proporcionar actualizaciones declarativas a pods y ReplicaSets. Esta declaración de estado se administra en el archivo YAML del manifiesto y el controlador de Kubernetes cambia el estado actual al estado declarado cuando se indica. Cree este deployment.yml archivo de manifiesto e indique a la instancia de AKS que se ejecute en un estado deseado con pods configurados para extraer y ejecutar la flightbookingsystemsample imagen de contenedor contenida en el registro de contenedor de Azure que insertó en la unidad anterior. Este manifiesto define declarativamente un Deployment y un servicio. Kubernetes usa el controlador de implementación para administrar los pods de la aplicación; También puede crear una implementación de forma imperativa con kubectl create deployment.
Nota:
Si la sesión se ha inactivo o está realizando este paso en otro momento o desde otra CLI, es posible que tenga que reinicializar las variables de entorno y volver a autenticarse mediante los siguientes comandos:
Restaure los valores de las variables de recurso que se usan en la instalación. Reemplace <your-subscription-ID> a continuación por el identificador de la suscripción que usó para este módulo. Si el inicio de sesión presenta un selector de suscripción, elija esa misma suscripción. Ejecute los comandos de autenticación de uno en uno. Después de az account show, confirme que la suscripción activa coincide con la configuración antes de continuar. Si un comando falla, detenga y resuelva el error.
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"
Desplegar una imagen de contenedor
Ahora implementará la imagen de flightbookingsystemsample contenedor en el clúster de AKS. En containerize-and-deploy-Java-app-to-Azure/Project/Airlines, usa un editor de texto instalado para crear un archivo denominado deployment.yml. Esta ruta de acceso es relativa al directorio padre donde ha clonado el repositorio. Si ya está en Project/Airlines, permanezca allí en lugar de cambiar de nuevo a la ruta relativa completa. Cree el archivo y ejecute el comando que aparece más adelante kubectl apply -f deployment.yml desde este directorio.
Agregue el siguiente contenido a deployment.yml y guarde el archivo. Reemplace el <AZ_CONTAINER_REGISTRY> marcador de posición por el valor de la AZ_CONTAINER_REGISTRY variable de entorno que estableció 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
Nota:
Si usa el archivo deployment_solution.yml en la carpeta raíz del proyecto como punto de partida, actualice su imagen a la misma imagen del registro y la etiqueta :latest que se muestran aquí. Agregue también el mismo Linux AMD64 nodeSelector en el despliegue spec.template.spec, junto con containers. No use la alternativa sin cambios: su selector de imagen y su selector de nodo deben coincidir con la plataforma de compilación de este módulo.
En el deployment.yml anterior, el archivo contiene una implementación y un servicio. La implementación se usa para administrar un conjunto de pods, y el servicio se usa para permitir el acceso de red a los pods. Los pods están configurados para extraer una sola imagen, <AZ_CONTAINER_REGISTRY>.azurecr.io/flightbookingsystemsample:latest, de Azure Container Registry. El servicio está configurado para permitir el tráfico entrante del pod HTTP al puerto 8080, similar a la forma en que ejecutó la imagen de contenedor localmente con el argumento de puerto -p.
El selector de nodos restringe los pods a los nodos Linux AMD64 que coincidan con la imagen linux/amd64 compilada anteriormente. Pertenece al despliegue, no al servicio. Un selector restringe la programación; no hace que una imagen incompatible se ejecute en otra arquitectura.
Antes de configurar el acceso al clúster, asegúrese de que la creación del clúster de AKS en la unidad de instalación se completó correctamente. Compruebe su estado de aprovisionamiento y la versión actual de Kubernetes:
az aks show \
--resource-group "$AZ_RESOURCE_GROUP" \
--name "$AZ_KUBERNETES_CLUSTER" \
--query '{provisioningState:provisioningState,currentKubernetesVersion:currentKubernetesVersion}' \
--output table
No continúe si se produce un error en el comando, provisioningState no es Succeeded o currentKubernetesVersion no es una versión no vacía en formato major.minor.patch.
Las siguientes instrucciones de herramienta se aplican a la sesión local de Linux, macOS o Bash de WSL establecida en la configuración, no a PowerShell nativo ni al Símbolo del sistema. Si ya tiene instalaciones funcionales de kubelogin y kubectl en esa sesión, consérvelas en lugar de reinstalarlas. Compruébelos con kubectl version --client y kubelogin --version, y asegúrese de que kubectl cumple la directiva de asimetría de versiones admitida para el clúster.
De lo contrario, reemplace <control-plane-version> por el currentKubernetesVersion devuelto. Instale esa versión correspondiente kubectl y kubelogin en ubicaciones grabables por el usuario:
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
Ambas rutas de instalación incluyen el nombre de archivo ejecutable. El comando PATH export solo se aplica al shell actual; repítelo en una nueva sesión o añádelo a la configuración de inicio de Bash adecuada. Resuelva cualquier error de instalación o comprobación de versiones antes de continuar.
Después de que ambas herramientas estén disponibles y comprobadas, configure kubectl para conectarse al clúster de AKS:
az aks get-credentials \
--resource-group $AZ_RESOURCE_GROUP \
--name $AZ_KUBERNETES_CLUSTER
La salida siguiente es típica:
Merged AZ_KUBERNETES_CLUSTER as current context in ~/.kube/config
Compruebe los sistemas operativos y arquitecturas reales del nodo antes de aplicar el manifiesto:
kubectl get nodes \
-o custom-columns='NAME:.metadata.name,OS:.status.nodeInfo.operatingSystem,ARCH:.status.nodeInfo.architecture'
La ruta de acceso de compilación de este módulo linux/amd64 requiere nodos AMD64 de Linux. Si no hay nodos coincidentes, detenga y resuelva el error de coincidencia antes de continuar. Utilice un grupo de nodos AMD64 compatible, o recompile, ejecute y publique la imagen para otra arquitectura de nodo Linux compatible y actualice el selector de arquitectura de la implementación para que coincida. La opción docker --platform no crea ni cambia un grupo de nodos de AKS.
Desde containerize-and-deploy-Java-app-to-Azure/Project/Airlines, aplique deployment.yml al clúster:
kubectl apply -f deployment.yml
La salida siguiente es típica:
deployment.apps/flightbookingsystemsample created
service/flightbookingsystemsample created
Supervise el estado de la implementación mediante el comando siguiente:
kubectl get all
La salida siguiente es 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
El estado de un pod Running no confirma que Tomcat haya terminado de desplegar la aplicación o que las solicitudes HTTP se realicen correctamente. Espere a que finalice el despliegue y siga los registros de inicio de la aplicación:
kubectl rollout status deployment/flightbookingsystemsample --timeout=300s &&
kubectl logs deployment/flightbookingsystemsample --tail=100 --follow
Una implementación correcta indica la disponibilidad de Kubernetes. Dado que este manifiesto no tiene ningún sondeo de preparación de la aplicación, la implementación no constituye una comprobación de estado HTTP. Siga los registros hasta que Tomcat informe de que se completó el inicio del servidor y la implementación de AirlinesReservationSample.war se haya completado sin errores. A continuación, presione Ctrl+C para detener el seguimiento de los registros. Esto detiene solo el flujo de registros, no el contenedor. Si el despliegue o el inicio de la aplicación fallan o no se completan, inspeccione los registros y los eventos del pod en lugar de continuar con la comprobación del explorador.
La siguiente salida histórica muestra los mensajes de inicio de una imagen anterior de Tomcat 10.1.33. No es la salida de la imagen actualizada en este módulo; use sus propios registros para comprobar el arranque en lugar de esperar las mismas versiones, marcas de tiempo o detalles del entorno:
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
Observe el servicio para su dirección externa:
kubectl get service flightbookingsystemsample --watch
El EXTERNAL-IP valor puede ser <pending> inicialmente mientras Azure aprovisiona el equilibrador de carga. Esto puede tardar varios minutos y no es evidencia de una implementación con errores por sí misma. Cuando aparezca una dirección, presione Ctrl+C para dejar de vigilar. Si el aprovisionamiento no se completa, detenga la supervisión e inspeccione los eventos del servicio con kubectl describe service flightbookingsystemsample.
En la siguiente salida ilustrativa se muestra dónde aparece la dirección asignada:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
flightbookingsystemsample LoadBalancer 10.0.62.153 <external-IP> 8080:30534/TCP 3m28s
Nota:
Sustituya la dirección IP <external-IP> en la siguiente URL por el valor EXTERNAL-IP del comando que ejecutó anteriormente.
Abra un navegador y visite la página de inicio de ejemplo del sistema de reservas de vuelos en http://<external-IP>:8080/AirlinesReservationSample/. Confirme que la página de la aplicación responde; un Running pod o una dirección IP asignada por sí solos no demuestra la preparación de la aplicación. El explorador debe tener un aspecto similar al de la captura de pantalla siguiente:
Opcionalmente, puede iniciar sesión con cualquier usuario desde tomcat-users.xml , por ejemplo, someuser@azure.com: password.
Solución de problemas de incompatibilidad entre una imagen y una plataforma
En el caso de los errores de inicio del pod, inspeccione kubectl describe pods -l app=flightbookingsystemsample, kubectl logs deployment/flightbookingsystemsample --tail=100y kubectl get events --sort-by=.metadata.creationTimestamp. Un CrashLoopBackOff estado puede tener varias causas, incluidos los errores de aplicación; no suponga que todos los fallos son una falta de coincidencia de arquitectura.
Si confirma que una imagen ya implementada tiene la plataforma incorrecta, repita primero la compilación, la ejecución local, la inspección de imágenes, el etiquetado del registro y los pasos de envío con la configuración de plataforma coincidente. Una vez que la imagen corregida se ha recompilado correctamente, se ha vuelto a etiquetar y publicado bajo la misma etiqueta :latest, reemplace explícitamente los pods en ejecución:
kubectl rollout restart deployment/flightbookingsystemsample &&
kubectl rollout status deployment/flightbookingsystemsample --timeout=300s
Para este manifiesto, :latest se establece de forma predeterminada en imagePullPolicy: Always, por lo que los pods de reemplazo resuelven la etiqueta actual del registro. Volver a aplicar un manifiesto sin cambios por sí solo no desencadena un despliegue. Si personalizó la directiva de extracción, use una etiqueta de imagen actualizada o un resumen y actualice el Deployment en su lugar. Repita las comprobaciones del registro de inicio y la dirección URL de la aplicación después del despliegue.
Limpieza de recursos
Los recursos creados en este módulo pueden incurrir en costos continuos. Para limpiar los recursos, elimine el grupo de recursos que los contiene mediante el siguiente comando:
az group delete --name $AZ_RESOURCE_GROUP