はじめてのGKE

ブログに GKE を使う

このブログはHexoを使って VPS 上に構築していましたが、
今回、 VPS をやめて GKS を使うようにしました。

目標

  • リポジトリに push したら自動でブログの内容が更新される
  • https で通信できる
  • そんなに費用がかからない

手順概要

  1. GKE の使い方を勉強する
  2. Kubernetes クラスタを作る
  3. Hexo 用の Docker イメージを作る
  4. Cloud Build の設定をする
  5. https で通信できるように設定する

手順詳細

1. GKE の使い方を勉強する

Cloud Build を利用すると GCP で CI/CD の環境を構築できます。次のドキュメントがわかりやすいです。

https://cloud.google.com/kubernetes-engine/docs/tutorials/gitops-cloud-build?hl=ja

途中、リポジトリに Push できない箇所がありましたが、hello-cloudbuild-env/.git/configファイルの[credential]部分をコピーすれば Push できるようになります。
また、最後までいったら忘れずにクラスをを削除して余計な課金がされないようにしましょう。

2. Kubernetes クラスタを作る

ブログ用のクラスタを作成します。
クラスタを作る前にリージョンを設定しておきます。日本を指定すると若干費用が高いです。

1
2
gcloud config set compute/zone asia-northeast1-c
gcloud config set compute/region asia-northeast1

現在の設定値は以下のコマンドで確認できます。

1
gcloud config list

クラスタを作成します。f1-micro ではメモリ不足でクラスタを作成できないので、今回はe2-microを指定しました。

1
gcloud container clusters create k8s-cluster --preemptible --machine-type=e2-micro --num-nodes=3 --disk-size=10

asia-northeast1でプリエンプティブルのe2-microが 3 台だと 1 ヶ月あたりUSD 7.06らしいです。
費用はこちらで計算できます。
https://cloud.google.com/products/calculator?hl=ja

3. Hexo 用の Docker イメージを作る

hello-cloudbuild-app と同じように app と env の 2 つのリポジトリを用意します。
app にDockerfileを用意します。

1
2
3
4
5
6
7
8
9
10
FROM node:slim as builder
WORKDIR /app
ADD . .
RUN npm install
RUN npm install -g hexo-cli
RUN hexo clean
RUN hexo generate

FROM nginx
COPY --from=builder /app/public /usr/share/nginx/html

Docker イメージで作成した場合、何故か hexo generate したときに出力されるファイルのサイズが 0 になりました。
この問題は npm のライブラリ のバージョンを最新にすると解消しました。

4. Cloud Build の設定をする

hello-cloudbuild-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/kujilabo-blog-app:$SHORT_SHA"
- "."

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

- name: "gcr.io/cloud-builders/gcloud"
id: Clone env repository
entrypoint: /bin/sh
args:
- "-c"
- |
gcloud source repos clone kujilabo-blog-env && \
cd kujilabo-blog-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" > kujilabo-blog-env/kubernetes.yaml

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

続いて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
apiVersion: apps/v1
kind: Deployment
metadata:
name: kujilabo-blog
namespace: default
spec:
selector:
matchLabels:
run: kujilabo-blog
template:
metadata:
labels:
run: kujilabo-blog
spec:
containers:
- image: gcr.io/cocotola/kujilabo-blog-app:COMMIT_SHA
imagePullPolicy: IfNotPresent
name: kujilabo-blog
ports:
- containerPort: 80
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
name: kujilabo-blog
namespace: default
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
run: kujilabo-blog
type: NodePort

Service はLoadBalancerではなくNodePortを指定しています。

1
gcloud compute addresses create kujilabo --global

IP アドレスの確認コマンドはこちら。

1
gcloud compute addresses list

トリガーも GCP のコンソールから作成しておきます。
ここまでで、app に Push したらビルドが実行されるところまで動作します。

5. https で通信できるように設定する

ドメインは Google Domains で取得済みです。
SSL の設定については以下のドキュメントがわかりやすいです。

https://cloud.google.com/kubernetes-engine/docs/how-to/managed-certs?hl=ja

このドキュメントに書かれていることの一部は、すでに Kubernetes で構築した部分もあるので適宜置き換えて読んでください。

k8s/ingress.yamlにファイルを用意します。

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

以下のコマンドで適用します。

1
kubectl apply -f k8s/ingress.yaml

k8s/cert.yamlにファイルを用意します。

1
2
3
4
5
6
7
apiVersion: networking.gke.io/v1beta1
kind: ManagedCertificate
metadata:
name: kujilabo-certificate
spec:
domains:
- kujilabo.com

以下のコマンドで適用します。

1
kubectl apply -f k8s/cert.yaml

SSL の進捗状況は以下のコマンドで確認できます。

1
kubectl describe managedcertificate