Déployer l’image conteneur dans Azure Kubernetes Service
Dans cette unité, vous déployez une image conteneur sur Azure Kubernetes Service (AKS). Avec AKS, vous configurez votre cluster Kubernetes pour qu’il s’exécute dans un état souhaité via un déploiement, qui est le processus de fourniture de mises à jour déclaratives pour les pods et les ReplicaSets. Cette déclaration d’état est administrée dans le fichier YAML du manifeste, et le contrôleur Kubernetes remplace l’état actuel par l’état déclaré lorsqu’il est indiqué. Vous créez ce fichier manifeste deployment.yml et demandez à votre instance AKS de s’exécuter dans un état souhaité avec des pods configurés pour extraire et exécuter l’image flightbookingsystemsample conteneur contenue dans le registre de conteneurs Azure que vous avez envoyé (push) dans l’unité précédente. Ce manifeste définit de façon déclarative un Deployment et un Service. Kubernetes utilise le contrôleur Deployment pour gérer les pods de l’application ; vous pouvez également créer un Deployment de manière impérative avec kubectl create deployment.
Remarque
Si votre session est inactive ou que vous effectuez cette étape à un autre moment ou à partir d’une autre interface CLI, vous devrez peut-être réinitialiser vos variables d’environnement et réauthentifier à l’aide des commandes suivantes :
Restaurez les valeurs des variables de ressources utilisées lors de l’installation. Remplacez <your-subscription-ID> ci-dessous par l’ID de l’abonnement que vous avez utilisé pour ce module. Si la connexion présente un sélecteur d’abonnement, choisissez ce même abonnement. Exécutez les commandes d’authentification une par une. Après az account show, vérifiez que l’abonnement actif correspond à la configuration avant de continuer. Si une commande échoue, arrêtez et résolvez l’erreur.
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"
Déployer une image conteneur
Désormais, vous déployez l'image de conteneur flightbookingsystemsample sur votre cluster AKS. Dans containerize-and-deploy-Java-app-to-Azure/Project/Airlines, utilisez un éditeur de texte installé pour créer un fichier nommé deployment.yml. Ce chemin d’accès est relatif au répertoire parent où vous avez cloné le référentiel. Si vous êtes déjà dans Project/Airlines, restez là plutôt que de passer à nouveau au chemin absolu complet. Créez le fichier et exécutez ensuite la commande kubectl apply -f deployment.yml à partir de ce répertoire.
Ajoutez le contenu suivant à deployment.yml, puis enregistrez le fichier. Remplacez le texte de remplacement <AZ_CONTAINER_REGISTRY> par la valeur de la variable d’environnement AZ_CONTAINER_REGISTRY que vous avez définie précédemment.
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
Remarque
Si vous utilisez le fichier deployment_solution.yml dans le dossier racine de votre projet comme point de départ, mettez à jour son image avec la même image de registre et :latest la même balise affichée ici. Ajoutez également le même nodeSelector Linux AMD64 sous le spec.template.spec du déploiement, aux côtés de containers. N’utilisez pas l’alternative inchangée : son image et son sélecteur de nœud doivent correspondre à la plateforme de génération de ce module.
Dans la deployment.yml précédente, le fichier contient un déploiement et un service. Le déploiement est utilisé pour administrer un ensemble de pods, et le service est utilisé pour autoriser l’accès réseau aux pods. Les pods sont configurés pour extraire une seule image, <AZ_CONTAINER_REGISTRY>.azurecr.io/flightbookingsystemsample:latestà partir d’Azure Container Registry. Le service est configuré pour autoriser le trafic de pod HTTP entrant vers le port 8080, similaire à la façon dont vous avez exécuté l’image conteneur localement avec l’argument -p de port.
Le sélecteur de nœuds limite les pods aux nœuds AMD64 Linux, correspondant à l’image linux/amd64 créée précédemment. Il appartient au Deployment, et non au Service. Un sélecteur limite la planification ; cela ne permet pas d’exécuter une image incompatible sur une autre architecture.
Avant de configurer l’accès au cluster, vérifiez que la création du cluster AKS dans l’unité d’installation s’est terminée correctement. Vérifiez son état de provisionnement et sa version actuelle de Kubernetes :
az aks show \
--resource-group "$AZ_RESOURCE_GROUP" \
--name "$AZ_KUBERNETES_CLUSTER" \
--query '{provisioningState:provisioningState,currentKubernetesVersion:currentKubernetesVersion}' \
--output table
Ne continuez pas si la commande échoue, provisioningState n’est pas Succeeded, ou currentKubernetesVersion n’est pas une version non vide au format major.minor.patch.
Les instructions d’outil suivantes s’appliquent à la session Linux, macOS ou WSL Bash locale établie lors de la configuration, et non à l’invite de commandes ou PowerShell native. Si vous avez déjà des installations kubectl et kubelogin fonctionnelles dans cette session, conservez-les au lieu de les réinstaller. Vérifiez-les avec kubectl version --client et kubelogin --version, puis assurez-vous qu’elle kubectl répond the à la stratégie d’asymétrie de version prise en charge pour le cluster.
Sinon, remplacez <control-plane-version> par la valeur renvoyée currentKubernetesVersion. Installez cette version correspondante kubectl et kubelogin dans des emplacements accessibles en écriture par l’utilisateur :
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
Les deux chemins d’installation incluent le nom de fichier exécutable. La commande export PATH s’applique uniquement à l’interpréteur de commandes actuel ; répétez-la dans une nouvelle session ou ajoutez-la à la configuration de démarrage Bash appropriée. Résolvez tout échec d’installation ou de vérification de version avant de continuer.
Une fois les deux outils disponibles et vérifiés, configurez kubectl pour qu'il se connecte à votre cluster AKS :
az aks get-credentials \
--resource-group $AZ_RESOURCE_GROUP \
--name $AZ_KUBERNETES_CLUSTER
La sortie suivante est classique :
Merged AZ_KUBERNETES_CLUSTER as current context in ~/.kube/config
Vérifiez les systèmes d’exploitation et les architectures de nœud réels avant d’appliquer le manifeste :
kubectl get nodes \
-o custom-columns='NAME:.metadata.name,OS:.status.nodeInfo.operatingSystem,ARCH:.status.nodeInfo.architecture'
Le chemin de génération de ce module linux/amd64 nécessite des nœuds Linux AMD64. S’il n’existe aucun nœud correspondant, arrêtez et résolvez l’incompatibilité avant de continuer. Utilisez un pool de nœuds AMD64 pris en charge, ou régénérez, exécutez et envoyez (push) l’image pour une autre architecture de nœud Linux prise en charge et mettez à jour le sélecteur d’architecture du déploiement pour qu’il corresponde. L’option Docker --platform ne crée pas ou ne modifie pas un pool de nœuds AKS.
À partir de containerize-and-deploy-Java-app-to-Azure/Project/Airlines, appliquez deployment.yml à votre cluster :
kubectl apply -f deployment.yml
La sortie suivante est classique :
deployment.apps/flightbookingsystemsample created
service/flightbookingsystemsample created
Surveillez l’état du déploiement à l’aide de la commande suivante :
kubectl get all
La sortie suivante est classique :
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
L’état d’un pod Running ne confirme pas que Tomcat a terminé le déploiement de l’application ou que les requêtes HTTP réussissent. Attendez l’opération de déploiement, puis suivez les journaux de démarrage de l’application :
kubectl rollout status deployment/flightbookingsystemsample --timeout=300s &&
kubectl logs deployment/flightbookingsystemsample --tail=100 --follow
Un déploiement réussi suppose la disponibilité de Kubernetes. Étant donné que ce manifeste n’a pas de probe readiness de l’application, le déploiement n’est pas un test d’intégrité HTTP. Suivez les journaux jusqu’à ce que Tomcat signale que le démarrage du serveur et le déploiement de AirlinesReservationSample.war se sont terminés sans erreurs. Appuyez ensuite sur Ctrl+C pour arrêter de suivre les journaux. Cela arrête uniquement le flux de journal, et non le conteneur. Si le lancement ou le démarrage de l’application échoue ou ne se termine pas, inspectez les journaux et les événements de pod au lieu de passer à la vérification du navigateur.
La sortie historique suivante illustre les messages de démarrage d’une image Tomcat 10.1.33 antérieure. Ce n’est pas la sortie générée par l’image mise à jour dans ce module ; utilisez vos propres journaux pour vérifier le démarrage plutôt que d’attendre les mêmes versions, horodatages ou détails de l’environnement :
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
Surveillez le service pour connaître son adresse externe :
kubectl get service flightbookingsystemsample --watch
La EXTERNAL-IP valeur peut initialement être <pending> pendant que Azure provisionne l’équilibreur de charge. Cela peut prendre plusieurs minutes et n’est pas une preuve d’un déploiement ayant échoué par lui-même. Lorsqu’une adresse s’affiche, appuyez sur Ctrl+C pour stopper votre observation. Si le provisionnement n’est pas terminé, stoppez l’observation et inspectez les événements de service avec kubectl describe service flightbookingsystemsample.
La sortie d’illustration suivante montre où l’adresse affectée s’affiche :
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
flightbookingsystemsample LoadBalancer 10.0.62.153 <external-IP> 8080:30534/TCP 3m28s
Remarque
Remplacez l’adresse <external-IP> IP dans l’URL suivante par votre EXTERNAL-IP valeur à partir de la commande que vous avez exécutée précédemment :
Ouvrez un navigateur et visitez la page d’accueil de l’exemple de système de réservation de vol à l’adresse http://<external-IP>:8080/AirlinesReservationSample/. Vérifiez que la page de l’application répond ; un Running pod ou une adresse IP affectée seule ne prouve pas la préparation de l’application. Votre navigateur doit ressembler à la capture d’écran suivante :
Vous pouvez éventuellement vous connecter avec n’importe quel utilisateur à partir de tomcat-users.xml , par exemple. someuser@azure.com: password
Résoudre les problèmes liés à une incompatibilité entre l’image et la plateforme
Pour les échecs de démarrage des pods, inspectez kubectl describe pods -l app=flightbookingsystemsample, kubectl logs deployment/flightbookingsystemsample --tail=100et kubectl get events --sort-by=.metadata.creationTimestamp. Un CrashLoopBackOff état peut avoir plusieurs causes, y compris les erreurs d’application ; ne supposez pas que chaque échec est une incompatibilité d’architecture.
Si vous confirmez qu’une image déjà déployée a une plateforme incorrecte, répétez d’abord le build, l’exécution locale, l’inspection de l’image, l’étiquetage du registre et les étapes push avec les paramètres de plateforme correspondants. Une fois l’image corrigée reconstruite, retaguée et envoyée avec la même balise :latest, remplacez explicitement les pods en cours d’exécution :
kubectl rollout restart deployment/flightbookingsystemsample &&
kubectl rollout status deployment/flightbookingsystemsample --timeout=300s
Pour ce manifeste, :latest est défini par défaut sur imagePullPolicy: Always, de sorte que les pods de remplacement résolvent la balise de registre actuelle. L’application d’un manifeste inchangé seul ne déclenche pas de déploiement. Si vous avez personnalisé la stratégie d’extraction, utilisez une balise d’image ou un digest mis à jour et mettez à jour le déploiement. Répétez les vérifications du journal de démarrage et de l’URL de l’application après le déploiement.
Nettoyer les ressources
Les ressources que vous avez créées dans ce module peuvent entraîner des coûts continus. Pour nettoyer les ressources, supprimez le groupe de ressources qui les contient à l’aide de la commande suivante :
az group delete --name $AZ_RESOURCE_GROUP