[JAVA] 4. Création d'un manifeste et exécution d'un module Web

introduction

Cet article est une suite de 3 ci-dessous.

  1. Exécuter rapidement le module Web Java avec Google Kubernetes Engine (GKE)
  2. Créer une image Docker et enregistrer le registre
  3. Créer une base de données accessible à partir du module Web
  4. Créez le manifeste et exécutez le module Web (https://qiita.com/Turtle-child-No2/items/23982059d188e44618df)

4-1. Création d'un manifeste et exécution d'un module Web

Étape 4-1.1

Créez le fichier manifeste requis pour placer l'application (cette fois le module Web) dans GKE. Démarrez vi et créez sample-app_dev.yaml avec le contenu suivant.

[userid]@cloudshell:~ ([project_id])$ vi sample-app_dev.yaml
apiVersion: apps/v1beta2
kind: Deployment
metadata:
  #Le nom du déploiement. Doit être unique dans l'espace de noms
  name: sample-app
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: sample-app
  #Spécifie le temps d'attente entre le moment où un pod est prêt et celui où il est prêt à être utilisé.
  #La valeur par défaut est de 0 seconde. Par conséquent, si vous ne le spécifiez pas, il sera traité comme immédiatement utilisable.
  minReadySeconds: 5
  
  #Spécifie le temps de traitement maximal pour le traitement du déploiement.
  #Lorsque le temps de traitement du déploiement dépasse ce délai
  #Il échoue le processus, définit ProgressDeadlineExceeded sur status et annule automatiquement.
  #La valeur par défaut est de 600 secondes.
  progressDeadlineSeconds: 600
  
  strategy:
    #Effectuer une mise à jour continue
    type: RollingUpdate
    
    rollingUpdate:
      #Quelle est la réduction (mise à l'échelle) autorisée au moment de la mise à jour pour le nombre de pods en cours d'exécution?
      #Par exemple, deux pods sont actuellement en cours d'exécution et maxUnavailable=50%(Ou 1)Si vous définissez
      #Permet à 1 pod sur 2 d'être indisponible en raison de la mise à jour.
      maxUnavailable: 50%
    
      #L'augmentation (mise à l'échelle) autorisée pour le nombre de pods en cours d'exécution au moment de la mise à jour.
      #Par exemple, deux pods sont actuellement en cours d'exécution et maxSurge=50%(Ou 1)Si est défini, la mise à l'échelle jusqu'à 1 pod est autorisée en raison de la mise à jour.
      #En d'autres termes, pendant la mise à jour, jusqu'à un total de 3 unités, y compris l'ancienne version, seront autorisées à démarrer le pod.
      maxSurge: 50%
  
  #Cette partie est le Temlate de Pod. Une mise à jour continue se produit lorsqu'il y a un changement dans la description ici
  template:
    metadata:
      labels:
        #Spécification d'étiquette Spécification requise.selector.Besoin de correspondre avec matchLabels
        app: sample-app
    spec:
      containers:
        - name: sample-app-container
          image: gcr.io/[project_id]/sample-app:latest
          
          ports:
            - containerPort: 8080
              name: api-port
              protocol: TCP
          
          #Vérifiez s'il a démarré normalement. Si la vérification de l'état échoue, le pod sera redémarré.
          #initialDelaySeconds indique combien de secondes après le lancement de l'application la vérification de l'état commencera.
          #Par exemple, il est pratique de spécifier ce paramètre pour les applications dont le démarrage est long.
          #timeoutSeconds indique le nombre de secondes à attendre la réponse de vérification de l'état. Dans le cas de livenessProbe, plus il est court, plus il sera détecté rapidement, donc la récupération sera plus rapide.
          #Mais il y a quelque chose à savoir et vous devez définir un délai d'attente approprié, même sous charge.
          #L'application est redémarrée même si c'est la période la plus chargée et les performances sont affectées. Il est donc important de spécifier le timeoutSeconds approprié.
          #Si vous ne pouvez pas vous connecter à la sonde de vivacité de votre application ou si vous obtenez un code d'erreur HTTP
          #periodSeconds est un programme d'exécution planifié.
          #failureThreshold redémarre le conteneur lorsque la valeur spécifiée échoue.
          livenessProbe:
            httpGet:
              scheme: HTTP
              path: /sample-app/views/NewFile.jsp
              port: api-port
            
            initialDelaySeconds: 10
            timeoutSeconds: 5
            periodSeconds: 30
            failureThreshold: 20
          
          #Vérifiez si le pod est en service. N'envoyez pas de trafic lorsque la vérification de l'état échoue(Ne redémarre pas le pod).
          #Si le readinessProbe échoue, le pod est supprimé du point de terminaison de service.
          #Par exemple, lorsque je déplaçais des mises à jour ou lorsque j'ai mis à l'échelle, le nouveau pod fonctionnait.
          #Si une demande arrive alors que vous ne pouvez pas encore recevoir de trafic, vous aurez des problèmes, alors la sonde de disponibilité l'empêchera.
          readinessProbe:
            httpGet:
              scheme: HTTP
              path: /sample-app/servlet/MyServlet
              port: api-port
            
            initialDelaySeconds: 10
            timeoutSeconds: 5
            periodSeconds: 60
            failureThreshold: 5
          
          resources:
            #Ressources nécessaires lors du déploiement d'un pod(CPU/Mémoire)Spécifier.
            #Cependant, le pod peut utiliser plus de ressources que les demandes de ressources spécifiées.(Utiliser la limite pour limiter l'utilisation des ressources)
            #Le fait est que lors du déploiement d'un pod, le déploiement est effectué en examinant les demandes de ressources sans regarder l'utilisation des ressources du nœud.
            #cpu 200m est une abréviation pour 200 milli cœurs, soit 1 cpu pour 1000 milli cœurs.
            #1 à 200 mill core/5 CPU est utilisé.(Au fait, cpu:Si vous spécifiez 1, cpu:Interprété comme 1000m)
            #500Mi équivaut à 500 mégaoctets.
            requests:
              memory: "500Mi"
            
            #Ressources utilisées par les pods(CPU/Mémoire)Peut être restreint.
            #Même si le nœud dispose de ressources libres, les ressources supérieures aux limites de ressources spécifiées ne peuvent pas être utilisées.
            #Si vous ne spécifiez pas de limites de ressources, vous pouvez utiliser des ressources illimitées.
            #Si les demandes de ressources ne sont pas spécifiées, une valeur similaire à la valeur limite est définie dans les demandes de ressources.
            limits:
              memory: "600Mi"
          
          #Variables d'environnement pour l'hôte de base de données et l'instance PostgreSQL
          #Définissez l'utilisateur et le mot de passe pour vous connecter.
          #Une adresse de bouclage est spécifiée pour l'hôte de la base de données car il se connecte à la base de données via le proxy cloud sql.
          env:
            - name: POSTGRES_DB_HOST
              value: 127.0.0.1:5432
            # [START cloudsql_secrets]
            #Utilisez le nom d'utilisateur et le mot de passe secrets créés à l'article 3
            - name: POSTGRES_DB_USER
              valueFrom:
                secretKeyRef:
                  name: cloudsql-db-credentials
                  key: username
            - name: POSTGRES_DB_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: cloudsql-db-credentials
                  key: password
            # [END cloudsql_secrets]
        
        # [START proxy_container]
        - name: cloudsql-proxy
          image: gcr.io/cloudsql-docker/gce-proxy:1.13
          #Démarrez le proxy avec la base de données avec le compte des services secrets créé à l'article 3
          command: ["/cloud_sql_proxy",
                    "-instances=[project_id]:us-central1:sample-app-ist=tcp:5432",
                    "-credential_file=/secrets/cloudsql/credentials.json"]
          # [START cloudsql_security_context]
          securityContext:
            runAsUser: 2  # non-root user
            allowPrivilegeEscalation: false
          # [END cloudsql_security_context]
          #Montez le compte des services secrets créé à l'article 3
          volumeMounts:
            - name: cloudsql-instance-credentials
              mountPath: /secrets/cloudsql
              readOnly: true
        # [END proxy_container]
      
      #Le temps entre le début du processus d'arrêt du pod et l'envoi de SIGKILL.
      #Si preStop est défini, SIGTERM sera envoyé une fois le traitement preStop terminé.
      #SIGLKILL est envoyé si le processus ne s'est pas terminé dans le nombre de secondes spécifié dans terminerGracePeriodSeconds depuis le début du processus d'arrêt.
      #La valeur par défaut doit être de 30 secondes.
      terminationGracePeriodSeconds: 30
      
      # [START volumes]
      volumes:
        - name: cloudsql-instance-credentials
          secret:
            secretName: cloudsql-instance-credentials
      # [END volumes]

Étape 4-1.2

Exécutez le fichier manifeste créé. Il a été créé avec succès.

[userid]@cloudshell:~ ([project_id])$ kubectl apply -f sample-app_dev.yaml --record
deployment.apps "sample-app" created

Étape 4-1.3

Après un certain temps, vérifiez si le pod démarre normalement avec la commande suivante. Si READY est 2/2, les deux conteneurs ont démarré normalement.

[userid]@cloudshell:~ ([project_id])$ kubectl get pods -o wide
NAME                       READY     STATUS    RESTARTS   AGE       IP           NODE
[pod_name]                 2/2       Running   0          40s       10.40.1.10   [node_name]

Étape 4-1.4

S'il n'est pas démarré normalement, vérifiez le journal du conteneur avec la commande suivante. Ce qui suit est un journal lorsque le conteneur sample-app-container et le conteneur cloudsql-proxy sont démarrés normalement.

[userid]@cloudshell:~ ([project_id])$ kubectl logs [pod_name] -c sample-app-container
・
・
・
12-Mar-2019 12:02:50.933 INFO [main] org.apache.catalina.core.StandardService.startInternal Starting service [Catalina]
12-Mar-2019 12:02:50.935 INFO [main] org.apache.catalina.core.StandardEngine.startInternal Starting Servlet engine: [Apache Tomcat/9.0.16]
12-Mar-2019 12:02:50.960 INFO [main] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [/opt/apache-tomcat-9.0.16/webapps/sample-app]
12-Mar-2019 12:02:52.609 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.
12-Mar-2019 12:02:52.705 INFO [main] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [/opt/apache-tomcat-9.0.16/webapps/sample-app] has finished in [1,744] ms
12-Mar-2019 12:02:52.714 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-nio-8080"]
12-Mar-2019 12:02:52.786 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["ajp-nio-8009"]
12-Mar-2019 12:02:52.817 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in [2,069] milliseconds
[userid]@cloudshell:~ ([project_id])$ kubectl logs [pod_name] -c cloudsql-proxy
2019/03/12 11:55:17 current FDs rlimit set to 1048576, wanted limit is 8500. Nothing to do here.
2019/03/12 11:55:17 using credential file for authentication; email=sample-app-db-client@[project_id].iam.gserviceaccount.com
2019/03/12 11:55:17 Listening on 127.0.0.1:5432 for [project_id]:us-central1:sample-app-ist
2019/03/12 11:55:17 Ready for new connections

Étape 4-1.5

Créez un manifeste qui définit le service afin que vous puissiez accéder au pod que vous venez de démarrer depuis Internet.

[userid]@cloudshell:~ ([project_id])$ vi sample-app_svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: sample-app-svc
  namespace: default
spec:
  selector:
    app: sample-app
  type:
    LoadBalancer
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080

Étape 4-1.6

Exécutez immédiatement le manifeste qui définit le service.

[userid]@cloudshell:~ ([project_id])$ kubectl apply -f sample-app_svc.yaml
service "sample-app-svc" created

Étape 4-1.7

Après un certain temps, vérifiez l'adresse IP EXTERNE de sample-app-svc avec la commande suivante.

[userid]@cloudshell:~ ([project_id])$ kubectl get service
NAME             TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
kubernetes       ClusterIP      xxx.xxx.xxx.xxx     <none>        443/TCP        3d
sample-app-svc   LoadBalancer   yyy.yyy.yyy.yyy   zzz.zzz.zzz.zzz   80:31004/TCP   3m

Étape 4-1.8

Démarrez un autre navigateur et affichez l'URL suivante avec l'IP EXTERNE. La date et l'heure actuelles et le contenu du tableau sont affichés.

http://zzz.zzz.zzz.zzz/sample-app/views/NewFile.jsp 44.png

http://zzz.zzz.zzz.zzz/sample-app/servlet/MyServlet 45.png

en conclusion

Les références sont ci-dessous. Guide complet de Kubernetes-Shinya Aoyama (Auteur) Docker / Kubernetes Introduction au développement pratique de conteneurs --Akinori Yamada (Auteur) c'est tout

Recommended Posts

4. Création d'un manifeste et exécution d'un module Web
Créer un client Payjp et paramétrer default_card
J'ai créé un environnement Java EE sur AWS et essayé d'exécuter une application Web
La voie de la création d'un service Web (partie 1)
3. Créez une base de données à laquelle accéder à partir du module Web
Créez une application JAVA WEB et essayez OMC APM
Créer un référentiel local
Créer un cas de test
Communication socket avec un navigateur Web utilisant Java et JavaScript ②
Communication socket avec un navigateur Web utilisant Java et JavaScript ①