Wie der Titel schon sagt. Ich wollte nur sicherstellen, dass es der eigentliche Schritt war.
gcloud
ist einsatzbereit.)kubectl
ist einsatzbereit.
--GKE-Cluster erstellt.$ cat /etc/os-release
NAME="Ubuntu"
VERSION="18.04.5 LTS (Bionic Beaver)"
$ gcloud version
Google Cloud SDK 312.0.0
$ 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"}
$ go version
go version go1.15.2 linux/amd64
https://github.com/sky0621/study-k8sOnGKE/tree/v0.1.0/try01
Golang Richten Sie einen Webserver entsprechend ein, und wenn er ein Betriebssystemsignal ("SIGTERM") empfängt, spuckt er ein Protokoll ("GOT_NOTIFY") aus. Bereiten Sie auch ein Protokoll für "Zurückstellen" vor und stellen Sie sicher, dass das Verzögerungsprotokoll nicht angezeigt wird, wenn das Betriebssystemsignal empfangen wird.
main.go
package main
import (
"fmt"
"net/http"
"os"
"os/signal"
"syscall"
)
func main() {
fmt.Println("APP_START")
defer fmt.Println("DEFER")
//Goroutine wartet auf OS-Signal (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)
}()
//Starten Sie einen HTTP-Server ordnungsgemäß
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 Eine gewöhnliche mehrstufige Docker-Datei.
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"]
Das Docker-Image verwendet 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'
Die Hülle für den Bau mit den oben genannten ist unten.
build.sh
#!/usr/bin/env bash
set -euox pipefail
SCRIPT_DIR=$(dirname "$0")
cd "${SCRIPT_DIR}"
gcloud builds submit --config cloudbuild.yaml .
Rufen Sie das Docker-Image aus der Container-Registrierung ab. Es gibt drei Hülsen. Der Container-Port ist 8080 (obwohl ich ihn diesmal nicht verwenden werde).
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
Die Shell, die mithilfe der oben genannten Informationen bereitgestellt werden soll, befindet sich unten.
Ich benötige die ID des von mir verwendeten GCP-Projekts, die selbst über den Befehl gcloud
in meiner lokalen Umgebung abgerufen werden kann.
Es war schwierig herauszufinden, wie die GCP-Projekt-ID angegeben werden kann, ohne sie direkt in Yaml von k8s zu schreiben (* Möglicherweise über ConfigMap oder Secret, aber wenn möglich, ist dies einfach). Schreiben Sie sie daher mit sed
neu.
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
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}"
$ ./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
$ ./deploy.sh
++ dirname ./deploy.sh
+ SCRIPT_DIR=.
+ echo .
.
+ cd .
・
・
・
+ kubectl apply -f deployment.yaml
deployment.apps/golang-app-try01 created
・
・
・
Es gibt 3 Hülsen.
$ kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
golang-app-try01 3/3 3 3 4m19s
Wenn Sie sich das Containerprotokoll an dieser Stelle ansehen, können Sie sehen, dass jeder der drei Pods ein Protokoll darüber enthält, wann die App gestartet wird und wann der Betriebssystem-Signal-Standby startet.
$ ./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
Das Protokoll (GOT_NOTIFY
), als das Betriebssystemsignal empfangen wurde, wurde als Protokoll jedes Pods ausgegeben.
Das Protokoll (DEFER
) der Person, die mit defer
erstellt hat, wird nicht angezeigt.
Wenn Sie es auf GKE setzen, ist der Inhalt, den Sie sicher verarbeiten möchten, wenn die Anwendung gestoppt wird, nicht "verzögern", sondern Goroutine zum Empfangen des Betriebssystemsignals ("SIGTERM") wird separat eingerichtet.