This article is a continuation of 3 below.
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]
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
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]
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
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
Immediately execute the manifest that defines Service.
[userid]@cloudshell:~ ([project_id])$ kubectl apply -f sample-app_svc.yaml
service "sample-app-svc" created
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
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
http://zzz.zzz.zzz.zzz/sample-app/servlet/MyServlet
References are below. Kubernetes Complete Guide-Shinya Aoyama (Author) Docker / Kubernetes Introduction to Practical Container Development --Akinori Yamada (Author) that's all
Recommended Posts