GolangのアプリケーションをGKEで実行する

基本的には前回と同じです。

リポジトリを作成します。

1
2
3
4
5
6
gcloud source repos create cocotola-app
gcloud source repos clone cocotola-app
gcloud source repos create cocotola-env
gcloud source repos clone cocotola-env
cd cocotola-app
go mod init github.com/kujilabo/cocotola

cocotola-app/main.go

ヘルスチェック用のエンドポイントを用意します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package main

import (
"net/http"

"github.com/gin-gonic/gin"
)

func main() {
r := gin.Default()
r.GET("/healthcheck", func(c *gin.Context) {
c.Status(http.StatusOK)
})
r.GET("/ping", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "pong",
})
})
r.Run() // listen and serve on 0.0.0.0:8080 (for windows "localhost:8080")
}

cocotola-app/Dockerfile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
FROM golang:1.15-alpine as builder

WORKDIR /go/src/app
ADD . .
COPY main.go .

RUN go build -o cocotola

# Application image.
FROM alpine:latest

COPY --from=builder /go/src/app/cocotola .

CMD ["./cocotola"]

動作確認をするにはこちらのコマンドです。

1
2
sudo docker build -t cocotola-app:latest .
sudo docker run --rm -p 8080:8080 cocotola-app:latest

トリガーを作成

GCP のコンソールからトリガーを作成しておきます。設定内容は前回と同じです。

  • cocotola-app
  • cocotola-env

cocotola-app/cloudbuild.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
steps:
- name: "gcr.io/cloud-builders/docker"
id: Build
args:
- "build"
- "-t"
- "gcr.io/$PROJECT_ID/cocotola-app:$SHORT_SHA"
- "."

- name: "gcr.io/cloud-builders/docker"
id: Push
args:
- "push"
- "gcr.io/$PROJECT_ID/cocotola-app:$SHORT_SHA"

- name: "gcr.io/cloud-builders/gcloud"
id: Clone env repository
entrypoint: /bin/sh
args:
- "-c"
- |
gcloud source repos clone cocotola-env && \
cd cocotola-env && \
git checkout candidate && \
git config user.email $(gcloud auth list --filter=status:ACTIVE --format='value(account)')

- name: "gcr.io/cloud-builders/gcloud"
id: Generate manifest
entrypoint: /bin/sh
args:
- "-c"
- |
sed "s/GOOGLE_CLOUD_PROJECT/${PROJECT_ID}/g" k8s/kubernetes.yaml.tpl | \
sed "s/COMMIT_SHA/${SHORT_SHA}/g" > cocotola-env/kubernetes.yaml

- name: "gcr.io/cloud-builders/gcloud"
id: Push manifest
entrypoint: /bin/sh
args:
- "-c"
- |
set -x && \
cd cocotola-env && \
git add kubernetes.yaml && \
git commit -m "Deploying image gcr.io/${PROJECT_ID}/cocotola:${SHORT_SHA}
Built from commit ${COMMIT_SHA} of repository cocotola-app
Author: $(git log --format='%an <%ae>' -n 1 HEAD)" && \
git push origin candidate

cocotola-app/k8s/kubernetes.yaml.tpl

こちらも基本は同じですが、ヘルスチェックの設定を追加します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
apiVersion: apps/v1
kind: Deployment
metadata:
name: cocotola
namespace: default
spec:
selector:
matchLabels:
run: cocotola
template:
metadata:
labels:
run: cocotola
spec:
containers:
- image: gcr.io/cocotola/cocotola-app:COMMIT_SHA
imagePullPolicy: IfNotPresent
name: cocotola
ports:
- containerPort: 8080
protocol: TCP
readinessProbe:
httpGet:
path: /healthcheck
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
name: cocotola
namespace: default
spec:
ports:
- port: 8080
protocol: TCP
targetPort: 8080
selector:
run: cocotola
type: NodePort

IP アドレスを予約します。

1
2
gcloud compute addresses create cocotola --global
gcloud compute addresses list

cocotola-env/cloudbuild.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
steps:
- name: "gcr.io/cloud-builders/kubectl"
id: Deploy
args:
- "apply"
- "-f"
- "kubernetes.yaml"
env:
- "CLOUDSDK_COMPUTE_ZONE=asia-northeast1-c"
- "CLOUDSDK_CONTAINER_CLUSTER=k8s-cluster"

- name: "gcr.io/cloud-builders/git"
id: Copy to production branch
entrypoint: /bin/sh
args:
- "-c"
- |
set -x && \
# Configure Git to create commits with Cloud Build's service account
git config user.email $(gcloud auth list --filter=status:ACTIVE --format='value(account)') && \
# Switch to the production branch and copy the kubernetes.yaml file from the candidate branch
git fetch origin production && git checkout production && \
git checkout $COMMIT_SHA kubernetes.yaml && \
# Commit the kubernetes.yaml file with a descriptive commit message
git commit -m "Manifest from commit $COMMIT_SHA
$(git log --format=%B -n 1 $COMMIT_SHA)" && \
# Push the changes back to Cloud Source Repository
git push origin production
1
2
3
4
5
6
7
cd cocotola-env
git checkout -b candidate
git add .
git commit -m "Add cloudbuild.yaml"
git push origin candidate
git checkout -b production
git push origin production

ここでトリガーによるビルドが実行されますが失敗します。

以下のコマンドを実行して、Cloud Build 上で Push できるようにします。

1
2
3
4
5
6
7
8
9
10
11
PROJECT_ID=$(gcloud config get-value project)
PROJECT_NUMBER="$(gcloud projects describe ${PROJECT_ID} \
--format='get(projectNumber)')"
cat >/tmp/cocotola-env-policy.yaml <<EOF
bindings:
- members:
- serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com
role: roles/source.writer
EOF
gcloud source repos set-iam-policy \
cocotola-env /tmp/cocotola-env-policy.yaml

一旦ここでビルドします。ここでは、app と env の両方のビルドの実行に成功します。

1
2
3
4
cd ../cocotola-app
git add .
git commit -m "Initial commit"
git push origin master

cocotola-app/k8s/ingress.yaml

1
2
3
4
5
6
7
8
9
10
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: cocotola
annotations:
kubernetes.io/ingress.global-static-ip-name: cocotola
spec:
backend:
serviceName: cocotola
servicePort: 8080
1
kubectl apply -f k8s/ingress.yaml

ここまでで、IP アドレスでアクセスできるようになっているはずです。
ただし、設定してから反映されるまでに時間がかかります。

cocotola-app/k8s/cert.yaml

1
2
3
4
5
6
7
apiVersion: networking.gke.io/v1beta1
kind: ManagedCertificate
metadata:
name: cocotola-certificate
spec:
domains:
- cocotola.com
1
kubectl apply -f k8s/cert.yaml

この結果が出るまでに時間がかかります。また失敗したときの具体的な原因がよくわからないです。DNS の設定をいじっていると解消したりします。
進捗を確認するコマンドはこちら。

1
kubectl describe managedcertificate

ingress.yamlを更新して、SSL 証明書を関連付けます。(7 行目)

1
2
3
4
5
6
7
8
9
10
11
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: cocotola
annotations:
kubernetes.io/ingress.global-static-ip-name: cocotola
networking.gke.io/managed-certificates: cocotola-certificate
spec:
backend:
serviceName: cocotola
servicePort: 8080

以上です。