[JAVA] 4. Creating a manifest and running a web module

Introduction

This article is a continuation of 3 below.

  1. Quickly run Java web module with Google Kubernetes Engine (GKE)
  2. Create Docker image and register registry
  3. Create a database to access from the Web module
  4. Create Manifest and Run Web Module (https://qiita.com/Turtle-child-No2/items/23982059d188e44618df)

4-1. Creating a manifest and running a web module

Step 4-1.1

Create the manifest file required to place the app (this time the web module) in GKE. Start vi and create sample-app_dev.yaml with the following contents.

[userid]@cloudshell:~ ([project_id])$ vi sample-app_dev.yaml
apiVersion: apps/v1beta2
kind: Deployment
metadata:
  #The name of the Deployment. Must be unique within namespace
  name: sample-app
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: sample-app
  #Specifies the waiting time from when the pod is ready to when it is ready for use.
  #The default is 0 seconds. Therefore, if you do not specify it, it will be treated as immediately usable.
  minReadySeconds: 5
  
  #Specify the maximum processing time for Deployment processing.
  #When the processing time of Deployment exceeds this time
  #It fails the process, sets ProgressDeadlineExceeded to status, and rolls back automatically.
  #The default is 600 seconds.
  progressDeadlineSeconds: 600
  
  strategy:
    #Perform rolling update
    type: RollingUpdate
    
    rollingUpdate:
      #How much reduction (scale-in) is allowed at the time of update for the number of pods currently running.
      #For example, two pods are currently running and maxUnavailable=50%(Or 1)If you set
      #Allows 1 out of 2 pods to be unavailable due to the update.
      maxUnavailable: 50%
    
      #How much increase (scale out) is allowed for the number of pods currently running at the time of update.
      #For example, two pods are currently running and maxSurge=50%(Or 1)If is set, scale-out of up to 1 pod is allowed due to the update.
      #In other words, during the update, up to a total of 3 units including the old version will be allowed to start the pod.
      maxSurge: 50%
  
  #This part is the Temlate of Pod. Rolling update occurs when there is a change in the description here
  template:
    metadata:
      labels:
        #Labeling required spec.selector.Need to match with 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
          
          #Check if it has started normally. If the health check fails, the pod will be restarted.
          #initialDelaySeconds shows how many seconds after launching the app the health check will start.
          #For example, it is convenient to specify this setting for applications that take a long time to start.
          #timeoutSeconds indicates how many seconds to wait for the health check response. In the case of livenessProbe, it is faster to detect it if it is made as short as possible, so the recovery is quick.
          #But there is something to be aware of and you have to set an appropriate timeout even under load.
          #The app is restarted even though it is the busiest time, and the performance is affected. So it's important to specify the appropriate timeoutSeconds.
          #If you cannot connect to the application's livenessProbe or an HTTP error code is returned
          #periodSeconds is a scheduled execution schedule.
          #failureThreshold restarts the container when the specified value fails.
          livenessProbe:
            httpGet:
              scheme: HTTP
              path: /sample-app/views/NewFile.jsp
              port: api-port
            
            initialDelaySeconds: 10
            timeoutSeconds: 5
            periodSeconds: 30
            failureThreshold: 20
          
          #Check if the pod is in service. Do not send traffic when health check fails(Does not restart the pod).
          #If the readinessProbe fails, the pod is removed from the service endpoint.
          #For example, when I was rolling updates or when I scaled up, the new pod was working.
          #If a request comes in when you can't receive traffic yet, you'll be in trouble, so readiness Probe will prevent that.
          readinessProbe:
            httpGet:
              scheme: HTTP
              path: /sample-app/servlet/MyServlet
              port: api-port
            
            initialDelaySeconds: 10
            timeoutSeconds: 5
            periodSeconds: 60
            failureThreshold: 5
          
          resources:
            #Resources needed when deploying a pod(CPU/memory)To specify.
            #However, the pod can use more resources than the specified resource requests.(Use limit to limit resource usage)
            #The point is that when deploying a pod, the deployment is done by looking at resource requests without looking at the resource usage of node.
            #cpu 200m is an abbreviation for 200 milli cores, which is 1 cpu for 1000 milli cores.
            #1 at 200 mill core/5 CPU is used.(By the way, cpu:If you specify 1, cpu:Interpreted as 1000m)
            #500Mi is 500mebibytes.
            requests:
              memory: "500Mi"
            
            #Resources used by pods(CPU/memory)Can be restricted.
            #Even if there are free resources in node, resources above the specified resource limits cannot be used.
            #If you do not specify resource limits, you can use unlimited resources.
            #If resource requests are not specified, a value similar to the limit value is set in resource requests.
            limits:
              memory: "600Mi"
          
          #Environment variables for database host and PostgreSQL instance
          #Set the user and password to connect.
          #Since the database is connected via cloud sql proxy, the loopback address is specified for the database host.
          env:
            - name: POSTGRES_DB_HOST
              value: 127.0.0.1:5432
            # [START cloudsql_secrets]
            #Use the secret username and password created in 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
          #Start proxying with the database with the secret service account created in 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]
          #Mount the secret service account created in article 3
          volumeMounts:
            - name: cloudsql-instance-credentials
              mountPath: /secrets/cloudsql
              readOnly: true
        # [END proxy_container]
      
      #The time between the start of the pod shutdown process and the sending of the SIGKILL.
      #If preStop is set, SIGTERM is sent after preStop processing is completed.
      #A SIGLKILL is sent if the process has not completed within the number of seconds specified by terminationGracePeriodSeconds since the shutdown process started.
      #The default should be 30 seconds.
      terminationGracePeriodSeconds: 30
      
      # [START volumes]
      volumes:
        - name: cloudsql-instance-credentials
          secret:
            secretName: cloudsql-instance-credentials
      # [END volumes]

Step 4-1.2

Execute the created manifest file. It was created successfully.

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

Step 4-1.3

After a while, check if the pod is started normally with the following command. If READY is 2/2, the two containers are running normally.

[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]

Step 4-1.4

If it is not started normally, check the container log with the following command. The following is the log when the sample-app-container and cloudsql-proxy container are started normally.

[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

Step 4-1.5

Create a manifest that defines the Service so that you can access the pod you just started from the Internet side.

[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

Step 4-1.6

Immediately execute the manifest that defines Service.

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

Step 4-1.7

After a while, check the EXTERNAL-IP of sample-app-svc with the following command.

[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

Step 4-1.8

Start another browser and display the following URL with the EXTERNAL-IP mentioned earlier. The current date and time and the contents of the table are displayed.

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

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

in conclusion

References are below. Kubernetes Complete Guide-Shinya Aoyama (Author) Docker / Kubernetes Introduction to Practical Container Development --Akinori Yamada (Author) that's all

Recommended Posts

4. Creating a manifest and running a web module
Creating a Payjp Customer and setting default_card
I built a Java EE environment on AWS and tried running a web application
The road to creating a Web service (Part 1)
3. Create a database to access from the web module
Create a JAVA WEB application and try OMC APM
Creating a local repository
Creating a test case
Socket communication with a web browser using Java and JavaScript ②
Socket communication with a web browser using Java and JavaScript ①