[GKE] Définissez les réplicas de déploiement sur 0 et informez l'application Go du signal du système d'exploitation SIGTERM

thème

Comme le dit le titre. Je voulais juste m'assurer que c'était le mouvement réel.

supposition

Environnement de développement

OS - Linux(Ubuntu)

$ cat /etc/os-release 
NAME="Ubuntu"
VERSION="18.04.5 LTS (Bionic Beaver)"

gcloud

$ gcloud version
Google Cloud SDK 312.0.0

kubectl

$ kubectl version
Client Version: version.Info{Major:"1", Minor:"17", GitVersion:"v1.17.9", GitCommit:"4fb7ed12476d57b8437ada90b4f93b17ffaeed99", GitTreeState:"clean", BuildDate:"2020-07-15T16:18:16Z", GoVersion:"go1.13.9", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"17+", GitVersion:"v1.17.12-gke.2502", GitCommit:"974eff7a63e05b7eb05c9aded92fae8a3ce14521", GitTreeState:"clean", BuildDate:"2020-10-19T17:01:32Z", GoVersion:"go1.13.15b4", Compiler:"gc", Platform:"linux/amd64"}

#Backend

#Langue --Golang

$ go version
go version go1.15.2 linux/amd64

Entraine toi

Ensemble de sources

https://github.com/sky0621/study-k8sOnGKE/tree/v0.1.0/try01

La source

Golang Configurez correctement un serveur Web et lorsqu'il reçoit un signal OS (SIGTERM), il crache un journal ( GOT_NOTIFY). Préparez également un journal pour «différer» et vérifiez que le journal de différé n'apparaît pas lorsque le signal du système d'exploitation est reçu.

main.go


package main

import (
	"fmt"
	"net/http"
	"os"
	"os/signal"
	"syscall"
)

func main() {
	fmt.Println("APP_START")
	defer fmt.Println("DEFER")

	//Goroutine en attente du signal du système d'exploitation (SIGTERM)
	go func() {
		fmt.Println("BEFORE_NOTIFY")
		q := make(chan os.Signal, 1)
		signal.Notify(q, syscall.SIGTERM)
		<-q
		fmt.Println("GOT_NOTIFY")

		os.Exit(-1)
	}()

	//Démarrez correctement un serveur HTTP
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		if _, err := fmt.Fprint(w, "Hello"); err != nil {
			fmt.Printf("HANDLE_ERROR_OCCURRED: %+v", err)
		}
	})
	if err := http.ListenAndServe(":8080", nil); err != nil {
		fmt.Printf("SERVE_ERROR_OCCURRED: %+v", err)
	}

	fmt.Println("APP_END")
}

Dockerfile Un Dockerfile de construction en plusieurs étapes ordinaire.

FROM golang:1.15 as builder
WORKDIR /app
COPY . .
RUN go mod download
RUN CGO_ENABLED=0 GOOS=linux go build -mod=readonly -v -o server

FROM gcr.io/distroless/base
COPY --from=builder /app/server /server
CMD ["/server"]

Paramètres de Cloud Build

L'image Docker utilise Container Registry.

cloudbuild.yaml


steps:
  - name: 'gcr.io/cloud-builders/docker'
    args: [ 'build', '-t', 'gcr.io/$PROJECT_ID/golang-app-try01', '.' ]
images:
  - 'gcr.io/$PROJECT_ID/golang-app-try01'

La coque pour la construction utilisant ce qui précède est ci-dessous.

build.sh


#!/usr/bin/env bash
set -euox pipefail
SCRIPT_DIR=$(dirname "$0")
cd "${SCRIPT_DIR}"

gcloud builds submit --config cloudbuild.yaml .

Paramètres de déploiement

Obtenez l'image Docker du Container Registry. Il y a trois pods. Le port de conteneurs est 8080 (bien que je ne l'utilise pas cette fois).

deployment.yaml


apiVersion: apps/v1
kind: Deployment
metadata:
  name: golang-app-try01
spec:
  replicas: 3
  selector:
    matchLabels:
      app: golang-app-try01
  template:
    metadata:
      labels:
        app: golang-app-try01
    spec:
      containers:
        - name: golang-app-try01
          image: gcr.io/MY_GCP_PROJECT_ID/golang-app-try01
          ports:
            - containerPort: 8080

Le shell à déployer en utilisant ce qui précède est ci-dessous. J'ai besoin de l'ID du projet GCP que j'utilise, qui lui-même peut être récupéré à partir de la commande gcloud dans mon environnement local. Il était difficile de savoir comment spécifier l'ID du projet GCP sans l'écrire directement dans Yaml de k8s (* Cela peut être possible via ConfigMap ou Secret, mais si possible, c'est facile), alors réécrivez-le avec sed.

deploy.sh


#!/usr/bin/env bash
set -euox pipefail
SCRIPT_DIR=$(dirname "$0")
cd "${SCRIPT_DIR}"

project=$(gcloud config get-value project)
if [[ -z "${project}" ]]; then
  echo -n "need project"
  exit 1
fi
echo "${project}"

sed -i -e "s/MY_GCP_PROJECT_ID/${project}/" deployment.yaml

kubectl apply -f deployment.yaml

sed -i -e "s/${project}/MY_GCP_PROJECT_ID/" deployment.yaml

Shell pour réécrire le nombre de pods

replica_n.sh


#!/usr/bin/env bash
set -euox pipefail
SCRIPT_DIR=$(dirname "$0")
cd "${SCRIPT_DIR}"

num=${1:-}

if [ -z "${num}" ]; then
  echo -n "input replicas number: "
  read num
fi

kubectl scale deployment golang-app-try01 --replicas="${num}"

Contrôle de fonctionnement

Construisez l'application (créez une image Docker et stockez-la dans Container Registry)

$ ./build.sh 
++ dirname ./build.sh
+ SCRIPT_DIR=.
+ echo .
.
+ cd .
+ gcloud builds submit --config cloudbuild.yaml .
Creating temporary tarball archive of 6 file(s) totalling 1.7 KiB before compression.
・
・
・
DONE
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

ID                                    CREATE_TIME                DURATION  SOURCE                                                                                   IMAGES                                        STATUS
6452c516-cfbf-4497-b536-378023cbc34d  2020-11-03T19:29:14+00:00  29S       gs://XXXXXXXX_cloudbuild/source/1604431752.38075-ccb069fbb0d0413382dc79d42e5c618a.tgz  gcr.io/XXXXXXXX/golang-app-try01 (+1 more)  SUCCESS

screenshot-console.cloud.google.com-2020.11.04-05_33_09.png

Déployer sur GKE

$ ./deploy.sh 
++ dirname ./deploy.sh
+ SCRIPT_DIR=.
+ echo .
.
+ cd .
・
・
・
+ kubectl apply -f deployment.yaml
deployment.apps/golang-app-try01 created
・
・
・

Il y a 3 pods.

$ kubectl get deployment
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
golang-app-try01   3/3     3            3           4m19s

Si vous regardez le journal du conteneur à ce stade, vous pouvez voir que chacun des trois pods a un journal lorsque l'application démarre et lorsque la mise en veille du signal du système d'exploitation démarre.

screenshot-console.cloud.google.com-2020.11.04-04_52_58.png

Changer le nombre de pods à 0

$ ./replica_n.sh 0
++ dirname ./replica_n.sh
+ SCRIPT_DIR=.
+ echo .
.
+ cd .
+ num=0
+ '[' -z 0 ']'
+ kubectl scale deployment golang-app-try01 --replicas=0
deployment.apps/golang-app-try01 scaled

Le journal (GOT_NOTIFY) lorsque le signal du système d'exploitation a été reçu est sorti comme journal de chaque pod. Le journal («DEFER») de la personne qui a préparé avec «différer» n'apparaît pas.

screenshot-console.cloud.google.com-2020.11.04-04_53_28.png

Sommaire

Si vous le mettez sur GKE, le contenu que vous souhaitez sûrement traiter lorsque l'application est arrêtée n'est pas «différer», mais Goroutine pour la réception du signal du système d'exploitation («SIGTERM») est configuré séparément.

Recommended Posts

[GKE] Définissez les réplicas de déploiement sur 0 et informez l'application Go du signal du système d'exploitation SIGTERM
[Introduction à cx_Oracle] (Partie 4) Récupération et défilement du jeu de résultats