"Google Kubernetes Engine(GKE)"を使って"Kubernetes"について勉強した際の内容を自分用のメモとしてまとめました
"Kubernetesクラスタ"内のノード
について
"Kubernetesクラスタ"は大きく2種類のノード
で構成されます
- Control Planeとなる**
マスターノード
** - コンテナ実行環境となる**
ワーカーノード
**
"Google Kubernetes Engine(GKE)"では、マスターノード
側はフルマネージド提供され課金対象にもなりません。そのためワーカーノード
のみ作成すれば、すぐに"Kubernetesクラスタ"環境を利用することが可能です。
"Kubernetesクラスタ"内のオブジェクトについて
"Kubernetesクラスタ"上のオブジェクトは、Ingress
、Service
、Pod
の3つのレイヤーに別けることができます
出典: Kubernetes NodePort vs LoadBalancer vs Ingress? When should I use what?
https://medium.com/google-cloud/kubernetes-nodeport-vs-loadbalancer-vs-ingress-when-should-i-use-what-922f010849e0
種類 | 説明 |
---|---|
Ingress | ”Kubernetesクラスタの外部からのトラフィック”を制御する**"L7アプリケーションデリバリーコントローラー(ADC)"**です。”Ingress”は”ワーカーノード”とは別の場所に、"Google Kubernetes Engine(GKE)"環境においては、"Google Cloud Load Balancing"ベースのソフトウェア定義として作成されます。 |
Service | ”Ingressからのトラフィック”もしくは”同一Kubernetesクラスタ内部からのトラフィック”を制御する**”L4ロードバランサー”**です。 |
Pod | ”ワーカーノード”上に作成する**”コンテナ”と”ボリューム”**です。”Pod”のデプロイ方式を管理するためのオブジェクト(ワークロード)として別途”Deployment”、”StatefulSet”、”DaemonSet”、”CronJob”といったオブジェクトがありますが、これらの説明については後述します。”Pod”内の永続的ボリュームを管理するオブジェクトとして”PersistentVolumeClaim”がありますが、こちらの説明についても後述します。 |
"GKE"を使って次の3つを実施し"Kubernetesクラスタ"上にWordpressのシステムを構築することを通じて"Kubernetesクラスタ"の仕組みを理解することを目指します
- スタティックなグローバルIPアドレスを1つ割り当てた**
Ingress
**の作成 -
HorizontalPodAutoscaler(HPA)
を使った**オートスケールするWebサーバーのPod
とService
**の作成 -
StatefulSet
を使った**永続的なDBMS(MySQL)のPod
とService
**の作成
1. "Google Kubernetes Engine(GKE)"上にワーカーノード
のクラスタを作成する
まず、ワーカーノード
のクラスタの作成を"Google Cloud Platform(GCP)"のWebコンソールから行います。
□手順1-1: "Google Cloud Platform(GCP)"のWebコンソールにログインします
□手順1-2: ナビゲーションメニュー
からGoogle Kubernetes Engine
>クラスタ
を選択します
□手順1-3: 画面右上のCloud Shell
アイコンをクリックします
□手順1-4: 画面下にCloud Shell
が表示されるまでしばらく待ちます
□手順1-5: gcloud config set
コマンドでregion
の設定を行います
asia-northeast1(東京リージョン)
を指定します
$ gcloud config set compute/region "asia-northeast1"
Updated property [compute/region].
□手順1-6: 続けてgcloud config set
コマンドでzone
の設定を行います
$ gcloud config set compute/zone "asia-northeast1-a"
Updated property [compute/zone].
□手順1-6: cloud container clusters create
コマンドでワーカーノード
のクラスタを作成します
my-worker-node-cluseter
という名前で作成します
$ gcloud container clusters create "my-worker-node-cluseter"
□手順1-7: ワーカーノード
のクラスタが作成されるまでしばく待ちます
□手順1-8: kubectl get all
コマンドを実行してワーカーノード
のクラスタが作成されたことを確認します
$ kubectl get all
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.15.240.1 <none> 443/TCP 91s
上記のように表示されれば、ワーカーノード
のクラスタ作成は完了です
参考: gcloud compute instances list
コマンドで個別のワーカーノード
の情報を確認することができます
$ gcloud compute instances list
NAME ZONE MACHINE_TYPE PREEMPTIBLE INTERNAL_IP EXTERNAL_IP STATUS
gke-my-worker-node-cluse-default-pool-924284ce-bm6s asia-northeast1-a n1-standard-1 10.146.0.15 35.243.112.157 RUNNING
gke-my-worker-node-cluse-default-pool-924284ce-kpcs asia-northeast1-a n1-standard-1 10.146.0.16 104.198.83.208 RUNNING
gke-my-worker-node-cluse-default-pool-924284ce-td1m asia-northeast1-a n1-standard-1 10.146.0.17 104.198.120.68 RUNNING
2. Manifest
の作成と適用
"Kubernetesクラスタ"上に作成する各種オブジェクトについては、コマンドで個別に作成することも可能ですがManifest
と呼ばれるYAML形式のファイルを作成することにより一括した管理が可能になります
このManifest
の作成単位についてはいろいろ考え方があると思いますが、ここでは、ワーカーノード
の外に作成されるIngress
については独立して1つ作成し、ワーカーノード
上に作成されるその他のオブジェクトについてはService
の単位で作成したいと思います
□手順2-1: gcloud compute address create
コマンドでGCP上にIngress
に割り当てるためのスタティックなグローバルIPアドレス
を1つ作成します
$ gcloud compute addresses create "my-ingress-address" --global
Created [https://www.googleapis.com/compute/v1/projects/proud-command-246805/global/addresses/my-ingress-address].
□手順2-2: gcloud compute address list
コマンドで割り当てられたスタティックなグローバルIPアドレス
を確認します
$ gcloud compute addresses list
NAME ADDRESS/RANGE TYPE PURPOSE NETWORK REGION SUBNET STATUS
my-ingress-address XXX.XXX.XXX.XXX EXTERNAL RESERVED
□手順2-3: Manifest
を配置するためのディレクトリを作成してカレントディレクトリを移動します
$ export MANIFESTS_PATH=$HOME/my-manifests
$ mkdir -p $MANIFESTS_PATH
$ cd $MANIFESTS_PATH
$ pwd
□手順2-4: kubectl create namespace
コマンドでnamespace
を作成します
my-wordpress
という名前でnamespace
を作成します
$ kubectl create namespace "my-wordpress"
namespace/my-wordpress created
$ kubectl get namespace
NAME STATUS AGE
default Active 24m
kube-public Active 24m
kube-system Active 24m
my-wordpress Active 22s
□手順2-5: この後のコマンドの実行を簡略化するためにkubectl config set-context
コマンドでデフォルトで使用するnamespace
を設定します
$ kubectl config set-context $(kubectl config current-context) --namespace="my-wordpress"
Context "gke_proud-command-246805_asia-northeast1-a_my-worker-node-cluseter" modified.
□手順2-6: まずnamespace
名のディレクトリを作成します
$ mkdir -p $MANIFESTS_PATH/my-wordpress
□手順2-7: 作成したディレクトリ下にIngress
のManifest(my-ingress.yaml)
を作成します
このManifest
では、Ingress
のオブジェクトのみを定義しています
$ vi $MANIFESTS_PATH/my-wordpress/my-ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: my-ingress # このIngressの名前を定義します
namespace: my-wordpress
annotations:
kubernetes.io/ingress.global-static-ip-name: my-ingress-address # 割り当てるスタティックIPアドレスを定義します
spec:
rules:
- http:
paths:
- path: /*
backend: # バックエンドのServiceとポート番号を定義します
serviceName: web-service
servicePort: 80
□手順2-8: 続いて、Webサーバー側のService
のManifest(web-service.yaml)
を作成します
このManifest
では、Service
とDeployment
、HorizontalPodAutoscaler
の3種類のオブジェクトを定義しています
Deployment
はステートレス(非永続的)なPod
を管理するためのオブジェクトです
HorizontalPodAutoscaler
はPod
のオートスケールを定義するためのオブジェクトです
HorizontalPodAutoscaler
は指定したメトリックを30秒間隔で監視し、targetAverageValue
で指定した値未満になるようPod
数をminReplicas
およびmaxReplicas
の間で自動調整します
$ vi $MANIFESTS_PATH/my-wordpress/web-service.yaml
apiVersion: v1
kind: Service
metadata:
name: web-service # このServiceの名前を定義します
namespace: my-wordpress
labels: # このServiceに付与するラベルを定義します
ServiceName: web-service
Environment: development
spec:
type: NodePort # Kubernetesクラスタ外部からのトラフィックも許可する場合はNodePortを設定します
ports: # Serviceが使用するポート番号(port)と紐づけを行うPod側のポート番号(targetPort)、Node側のポート番号(nodePort)を定義します
- port: 80
targetPort: 80
nodePort: 30080
protocol: TCP
selector: # このServiceに紐づけるPodをPodに付与したラベルで定義します
ServiceName: web-service
Environment: development
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-deployment # このDeploymentの名前を定義します
namespace: my-wordpress
labels: # このDeploymentに付与するラベルを定義します
ServiceName: web-service
Environment: development
spec:
replicas: 3 # 作成するPod数を定義します
selector:
matchLabels: # 作成するPodに付与するラベルを定義します
ServiceName: web-service
Environment: development
template:
metadata:
labels: # spec: -> selector: -> matchLabels: と同じ内容を記載する必要があります
ServiceName: web-service
Environment: development
spec:
containers:
- name: web-container # 作成するPodのコンテナ名を定義します
ports: # 作成するPodのコンテナで開放するポート情報を定義します
- name: http
containerPort: 80
protocol: TCP
resources:
requests: # コンテナデプロイ時に必要とするリソースを定義します(リソースが足りない場合デプロイはエラーになります)
cpu: 100m # 1vCPU = 1,000m を意味します
memory: 256Mi
limits: # コンテナリソースの上限を定義します(ノードのメモリが枯渇しないようにrequestsと同値を設定します)
memory: 256Mi
image: wordpress:5.2-apache # 作成するPodのコンテナ作成時に使用するDockerイメージを定義します
env: # 作成するPodのコンテナに設定する環境変数を定義します
- name: WORDPRESS_DB_HOST
value: "db-service:3306"
- name: WORDPRESS_DB_USER
value: "wordpress"
- name: WORDPRESS_DB_PASSWORD
value: "wordpress!"
- name: WORDPRESS_DB_NAME
value: "wordpress"
livenessProbe: # ヘルスチェックに使用する情報を定義します
httpGet:
path: /readme.html
port: 80
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 3
readinessProbe: # ヘルスチェックに使用する情報を定義します
httpGet:
path: /readme.html
port: 80
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 3
---
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
name: web-deployment-horizontal-pod-autoscaler
namespace: my-wordpress
spec:
scaleTargetRef: # オートスケールの対象とするDeploymentの名前を定義します
apiVersion: apps/v1
kind: Deployment
name: web-deployment
minReplicas: 3
maxReplicas: 10
metrics: # オートスケールのトリガーとするメトリックを定義します
- type: Pods
pods: # Pod 1台あたり 100 HTTP Requests per Second 以下になるよう調整します
metricName: http_requests
targetAverageValue: 100
参考: HorizontalPodAutoscaler
で監視対象として設定するメトリックについて
監視対象として指定するメトリックの種類については、"HTTP Requests per Second"などRED Method
に基づいたものの方が良いと個人的に考えています
コンテナの性質上、CPU使用率/メモリ使用率などUSE Method
に基づいた監視対象メトリックのリソースが不足する場合は、ワーカーノード
をオートスケールするように設定した方が良いと考えます
The RED Method: How to Instrument Your Services
https://grafana.com/blog/2018/08/02/the-red-method-how-to-instrument-your-services/
The USE Method
http://www.brendangregg.com/usemethod.html
□手順2-9: DB(MySQL)側のService
のManifest(db-service.yaml)
を作成します
このManifest
では、``Serviceと
StatefulSet`、`PersistentVolumeClaim`の3種類のオブジェクトを定義します
StatefulSet
はDeployment
とは異なりステートフル(永続的)なPod
を管理するためのオブジェクトです
永続化を行う際に使用するストレージ領域についてはPersistentVolumeClaim
というオブジェクトで定義します
$ vi $MANIFESTS_PATH/my-wordpress/db-service.yaml
apiVersion: v1
kind: Service
metadata:
name: db-service # このServiceの名前を定義します
namespace: my-wordpress
labels: # このServiceに付与するラベルを定義します
ServiceName: db-service
Environment: development
spec:
type: ClusterIP # Kubernetesクラスタ内のトラフィックのみ許可する場合はClusterIPを設定します
ports: # Serviceが使用するポート番号(port)と紐づけを行うPod側のポート番号(targetPort)を定義します
- port: 3306
targetPort: 3306
protocol: TCP
selector: # このServiceに紐づけるPodをPodに付与したラベルで定義します
ServiceName: db-service
Environment: development
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: db-statefulset # このStatefulSetの名前を定義します
namespace: my-wordpress
labels: # このStatefulSetに付与するラベルを定義します
ServiceName: db-service
Environment: development
spec:
replicas: 1 # 作成するPod数を定義します
serviceName: db-service # このStatefulSetに紐付けるServiceを定義します
selector:
matchLabels: # 作成するPodに付与するラベルを定義します
ServiceName: db-service
Environment: development
template:
metadata:
labels: # spec: -> selector: -> matchLabels: に記載した内容と同じ内容を記載する必要があります
ServiceName: db-service
Environment: development
spec:
volumes:
- name: db-persistent-volume # このPodのボリューム名を定義します
persistentVolumeClaim:
claimName: db-persistent-volume-claim # このPodのボリュームに紐づけるPersistentVolumeClaimを定義します
containers:
- name: db-container # 作成するPodのコンテナ名を定義します
ports: # 作成するPodのコンテナで開放するポート情報を定義します
- name: mysql
containerPort: 3306
protocol: TCP
resources:
requests: # コンテナデプロイ時に必要とするリソースを定義します(リソースが足りない場合デプロイはエラーになります)
cpu: 100m # 1vCPU = 1,000m を意味します
memory: 512Mi
limits: # コンテナリソースの上限を定義します(ノードのメモリが枯渇しないようにrequestsと同値を設定します)
memory: 512Mi
image: mysql:5.6 # 作成するPodのコンテナ作成時に使用するDockerイメージを定義します
env: # 作成するPodのコンテナに設定する環境変数を定義します
- name: MYSQL_ROOT_PASSWORD
value: "somewordpress"
- name: MYSQL_DATABASE
value: "wordpress"
- name: MYSQL_USER
value: "wordpress"
- name: MYSQL_PASSWORD
value: "wordpress!"
volumeMounts: # このPodのコンテナが使用するボリューム名とマウントポイントを定義します
- name: db-persistent-volume
mountPath: /var/lib/mysql
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: db-persistent-volume-claim # このPersistentVolumeClaimの名前を定義します
namespace: my-wordpress
labels: # このPersistentVolumeClaimに付与するラベルを定義します
ServiceName: db-service
Environment: development
spec:
accessModes:
- ReadWriteOnce # Read/Writeは単一Podからのみ許可することを意味します
resources:
requests:
storage: 20Gi # 作成するボリュームのサイズを定義します
□手順2-10: kubectl apply
コマンドで、db-service
関連のオブジェクトから作成します
$ kubectl apply -f $MANIFESTS_PATH/my-wordpress/db-service.yaml
□手順2-11: kubectl get all
コマンドでオブジェクトが作成されたことを確認します
$ kubectl get all
NAME READY STATUS RESTARTS AGE
pod/db-statefulset-0 1/1 Running 0 46s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/db-service ClusterIP 10.15.241.248 <none> 3306/TCP 47s
NAME DESIRED CURRENT AGE
statefulset.apps/db-statefulset 1 1 47s
参考: StatefulSet
は、ナビゲーションメニュー
のGoogle Kubernetes Engine
>ワークロード
から確認することができます
参考: Service
は、ナビゲーションメニュー
のGoogle Kubernetes Engine
>ServiceとIngress
から確認することができます
参考: PersistentVolumeClaim
は、ナビゲーションメニュー
のGoogle Kubernetes Engine
>ストレージ
から確認することができます
□手順2-12: kubectl run
コマンドを使ってテンポラリのPod
を作成しService
との接続確認を行います
Service
に割り当てられているClusterIP
へは"Kubernetesクラスタ"内部からのみ疎通可能です
kubectl run
コマンドを使えばテンポラリのPod
を簡単に作成できるので、これを用いて接続確認を行います
$ kubectl run "mysql-client-pod" --image=mysql:5.6 --rm --restart=Never -it -- mysql -h "db-service" -u "wordpress" -p'wordpress!'
If you don't see a command prompt, try pressing enter.
mysql> quit
Bye
pod "mysql-client-pod" deleted
□手順2-13: 続いて、web-service
関連のオブジェクトを作成します
$ kubectl apply -f $MANIFESTS_PATH/my-wordpress/web-service.yaml
□手順2-14: kubectl get all
コマンドでオブジェクトが作成されたことを確認します
$ kubectl get all
NAME READY STATUS RESTARTS AGE
pod/db-statefulset-0 1/1 Running 0 29m
pod/web-deployment-5f4f68bf87-4vvnx 1/1 Running 0 16m
pod/web-deployment-5f4f68bf87-h2pr4 1/1 Running 0 16m
pod/web-deployment-5f4f68bf87-r5kjt 1/1 Running 0 16m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/db-service ClusterIP 10.15.241.248 <none> 3306/TCP 29m
service/web-service NodePort 10.15.249.35 <none> 80:30080/TCP 16m
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
deployment.apps/web-deployment 3 3 3 3 16m
NAME DESIRED CURRENT READY AGE
replicaset.apps/web-deployment-5f4f68bf87 3 3 3 16m
NAME DESIRED CURRENT AGE
statefulset.apps/db-statefulset 1 1 29m
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
horizontalpodautoscaler.autoscaling/web-deployment-horizontal-pod-autoscaler Deployment/web-deployment <unknown>/10 3 10 3 43s
参考: Deployment
は、ナビゲーションメニュー
のGoogle Kubernetes Engine
>ワークロード
からが確認することができます
参考: Service
は、ナビゲーションメニュー
のGoogle Kubernetes Engine
>ServiceとIngress
から確認することができます
□手順2-15: kubectl run
コマンドを使ってテンポラリのPod
を作成しService
との接続確認を行います
Webサーバー側についても同様にkubectl run
コマンドを使ってテンポラリのPod
を作成して接続確認を行います
$ kubectl run "curl-pod" --image=amazonlinux:2 --rm --restart=Never -it -- curl -I -Ss "http://web-service.my-wordpress.svc.cluster.local/readme.html"
HTTP/1.1 200 OK
Date: Fri, 09 Aug 2019 08:50:50 GMT
Server: Apache/2.4.38 (Debian)
Last-Modified: Mon, 08 Apr 2019 22:59:56 GMT
ETag: "1d17-5860ccb887300"
Accept-Ranges: bytes
Content-Length: 7447
Vary: Accept-Encoding
Content-Type: text/html
pod "curl-pod" deleted
□手順2-16: kubectl apply
コマンドでIngress(my-ingress)
を作成します
$ kubectl apply -f $MANIFESTS_PATH/my-wordpress/my-ingress.yaml
ingress.extensions/my-ingress created
□手順2-17: kubectl get ingress
コマンドでIngress
が作成されたことを確認します
"Google Kubernetes Engine(GKE)"環境において、Ingress
の実体は、"Google Cloud Load Balancing"ベースのソフトウェア定義です
そのため、Ingress
の作成には5分ほど要します
次に示すようにIPアドレスが割りてられるまで待つ必要があります
$ kubectl get ingress
NAME HOSTS ADDRESS PORTS AGE
my-ingress * 35.244.156.32 80 4m39s
参考: Ingress
は、ナビゲーションメニュー
のGoogle Kubernetes Engine
>ServiceとIngress
から確認することができます
□手順2-18: ナビゲーションメニュー
からKubernetes Engine
>Service と Ingress
を選択します
□手順2-19: my-ingress
列のエンドポイント
欄部分をクリックして"Wordpress"の初期設定画面が表示されれば成功です
以上、Google Kubernetes Engine(GKE)上を使って "Wordpress" のシステムを構築するまでの手順でした
ここまでの手順が上手くいかなかった場合のトラブルシューティングの方法をいくつか記載しておきますので、参考にしてください
参考: kubectl port-forward
コマンドを使ったトラブルシューティング
Service
に割り当てられたClusterIP
へは"Kubernetesクラスタ"内部からのみしか接続できませんので、Ingress
側の問題との切り分けを行う際はポートフォワーディングの設定が有効です
kubectl port-forward
コマンドでService
に対してポートフォワーディングを設定します
$ kubectl port-forward service/web-service 8080:80
Cloud Shell
の右上にあるウェブでプレビュー
アイコンをクリック後プレビューのポート:8080
を選択します
"ポートフォワーディング"によりWebブラウザから直接Service
のClusterIP
に対してアクセスが可能になりました
参考: Pod
のトラブルシューティング
kubectl logs
コマンドを使用することでPod
個別のログメッセージを確認できます
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE
db-statefulset-0 1/1 Running 0 159m 10.12.2.7 gke-my-worker-node-cluse-default-pool-924284ce-kpcs <none>
web-deployment-5f4f68bf87-4vvnx 1/1 Running 0 146m 10.12.2.15 gke-my-worker-node-cluse-default-pool-924284ce-kpcs <none>
web-deployment-5f4f68bf87-h2pr4 1/1 Running 0 146m 10.12.2.14 gke-my-worker-node-cluse-default-pool-924284ce-kpcs <none>
web-deployment-5f4f68bf87-r5kjt 1/1 Running 0 146m 10.12.1.5 gke-my-worker-node-cluse-default-pool-924284ce-td1m <none>
$ kubectl logs <Pod Name>
:
中略
:
より詳細な調査が必要な場合は、kubectl excec
コマンドを使用することでPod
に直接bash
でログインすることができます
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE
db-statefulset-0 1/1 Running 0 159m 10.12.2.7 gke-my-worker-node-cluse-default-pool-924284ce-kpcs <none>
web-deployment-5f4f68bf87-4vvnx 1/1 Running 0 146m 10.12.2.15 gke-my-worker-node-cluse-default-pool-924284ce-kpcs <none>
web-deployment-5f4f68bf87-h2pr4 1/1 Running 0 146m 10.12.2.14 gke-my-worker-node-cluse-default-pool-924284ce-kpcs <none>
web-deployment-5f4f68bf87-r5kjt 1/1 Running 0 146m 10.12.1.5 gke-my-worker-node-cluse-default-pool-924284ce-td1m <none>
$ kubectl exec <Pod Name> -it -- bash
root@<Pod Name>:/#h
3. Podのアップデートとロールバック
"Kubernetes"では、各Pod
の"Dockerイメージ"を簡単にアップデートしたりロールバックしたりすることが可能です
□手順3-1: sed
コマンドを使ってManifest
上のDockerイメージの値をwordpress:5.2-apache
からwordpress:5.2.2-apache
に書き換えます
sed -i -e "s/wordpress:5.2-apache/wordpress:5.2.2-apache/g" $MANIFESTS_PATH/my-wordpress/web-service.yaml
□手順3-2: kubectl apply
コマンドで修正したManifest
を上書き適用します
$ kubectl apply -f $MANIFESTS_PATH/my-wordpress/web-service.yaml
service/web-service unchanged
deployment.apps/web-deployment configured
horizontalpodautoscaler.autoscaling/web-deployment-horizontal-pod-autoscaler configured
□手順3-3: kubectl get pods
コマンドでPod
の状態を確認します
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE
db-statefulset-0 1/1 Running 0 3h24m 10.12.2.7 gke-my-worker-node-cluse-default-pool-924284ce-kpcs <none>
web-deployment-5b7f866c47-c4b6w 0/1 ContainerCreating 0 24s <none> gke-my-worker-node-cluse-default-pool-924284ce-bm6s <none>
web-deployment-5b7f866c47-swvvb 1/1 Running 0 41s 10.12.2.24 gke-my-worker-node-cluse-default-pool-924284ce-kpcs <none>
web-deployment-5f4f68bf87-h2pr4 1/1 Running 0 3h11m 10.12.2.14 gke-my-worker-node-cluse-default-pool-924284ce-kpcs <none>
web-deployment-5f4f68bf87-r5kjt 1/1 Running 0 3h11m 10.12.1.5 gke-my-worker-node-cluse-default-pool-924284ce-td1m <none>
元々あった3つのPod
はそのままで4つめのPod
が作成されています
□手順3-4: しばらく待って、もう一度kubectl get pods
コマンドでPod
の状態を確認します
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE
db-statefulset-0 1/1 Running 0 3h26m 10.12.2.7 gke-my-worker-node-cluse-default-pool-924284ce-kpcs <none>
web-deployment-5b7f866c47-c4b6w 1/1 Running 0 2m29s 10.12.0.7 gke-my-worker-node-cluse-default-pool-924284ce-bm6s <none>
web-deployment-5b7f866c47-qjg84 1/1 Running 0 112s 10.12.2.25 gke-my-worker-node-cluse-default-pool-924284ce-kpcs <none>
web-deployment-5b7f866c47-swvvb 1/1 Running 0 2m46s 10.12.2.24 gke-my-worker-node-cluse-default-pool-924284ce-kpcs <none>
Pod
の名前を確認するとすべてのPod
が差し替えられた事がわかります
□手順3-5: kubectl rollout history
コマンドを実行します
$ kubectl rollout history deployment web-deployment
deployment.extensions/web-deployment
REVISION CHANGE-CAUSE
1 <none>
2 <none>
□手順3-5: kubectl rollout history
コマンドで1つ目のRevision
の情報を確認します
$ kubectl rollout history deployment web-deployment --revision 1
deployment.extensions/web-deployment with revision #1
Pod Template:
Labels: Environment=development
ServiceName=web-service
pod-template-hash=5f4f68bf87
Containers:
web-container:
Image: wordpress:5.2-apache
Port: 80/TCP
Host Port: 0/TCP
Limits:
memory: 256Mi
Requests:
cpu: 100m
memory: 256Mi
Liveness: http-get http://:80/readme.html delay=10s timeout=1s period=3s #success=1 #failure=3
Readiness: http-get http://:80/readme.html delay=10s timeout=1s period=3s #success=1 #failure=3
Environment:
WORDPRESS_DB_HOST: db-service:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress!
WORDPRESS_DB_NAME: wordpress
Mounts: <none>
Volumes: <none>
Dockerイメージとしてwordpress:5.2-apache
を使用していたことが確認できます
□手順3-6: 同様に2つ目のRevision
の詳細を確認します
$ kubectl rollout history deployment web-deployment --revision 2
deployment.extensions/web-deployment with revision #2
Pod Template:
Labels: Environment=development
ServiceName=web-service
pod-template-hash=5b7f866c47
Containers:
web-container:
Image: wordpress:5.2.2-apache
Port: 80/TCP
Host Port: 0/TCP
Limits:
memory: 256Mi
Requests:
cpu: 100m
memory: 256Mi
Liveness: http-get http://:80/readme.html delay=10s timeout=1s period=3s #success=1 #failure=3
Readiness: http-get http://:80/readme.html delay=10s timeout=1s period=3s #success=1 #failure=3
Environment:
WORDPRESS_DB_HOST: db-service:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress!
WORDPRESS_DB_NAME: wordpress
Mounts: <none>
Volumes: <none>
使用しているDockerイメージがwordpress:5.2.2-apache
に変更されていることが確認できます
□手順3-7: kubectl rollout undo
コマンドを実行しロールバックを行います
$ kubectl rollout undo deployment web-deployment --to-revision 1
deployment.extensions/web-deployment
□手順3-8: kubectl rollout history
コマンドを実行します
$ kubectl rollout history deployment web-deployment
deployment.extensions/web-deployment
REVISION CHANGE-CAUSE
2 <none>
3 <none>
Revision 1
が無くなってRevision 3
が追加されています
□手順3-9: kubectl get pods
コマンドでPod
の状態を確認します
kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE
db-statefulset-0 1/1 Running 0 3h40m 10.12.2.7 gke-my-worker-node-cluse-default-pool-924284ce-kpcs <none>
web-deployment-5f4f68bf87-4ztjn 1/1 Running 0 5m39s 10.12.2.27 gke-my-worker-node-cluse-default-pool-924284ce-kpcs <none>
web-deployment-5f4f68bf87-m8wtz 1/1 Running 0 5m50s 10.12.2.26 gke-my-worker-node-cluse-default-pool-924284ce-kpcs <none>
web-deployment-5f4f68bf87-nfwbz 1/1 Running 0 6m4s 10.12.1.6 gke-my-worker-node-cluse-default-pool-924284ce-td1m <none>
Pod
の名前を確認するとすべてのPod
がまた差し替えられた事がわかります
□手順3‐10: kubectl rollout history
コマンドで3つ目のRevision
の情報を確認します
$ kubectl rollout history deployment web-deployment --revision 3
deployment.extensions/web-deployment with revision #3
Pod Template:
Labels: Environment=development
ServiceName=web-service
pod-template-hash=5f4f68bf87
Containers:
web-container:
Image: wordpress:5.2-apache
Port: 80/TCP
Host Port: 0/TCP
Limits:
memory: 256Mi
Requests:
cpu: 100m
memory: 256Mi
Liveness: http-get http://:80/readme.html delay=10s timeout=1s period=3s #success=1 #failure=3
Readiness: http-get http://:80/readme.html delay=10s timeout=1s period=3s #success=1 #failure=3
Environment:
WORDPRESS_DB_HOST: db-service:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress!
WORDPRESS_DB_NAME: wordpress
Mounts: <none>
Volumes: <none>
使用しているDockerイメージがwordpress:5.2-apache
に戻っていることを確認できます
Pod
の"Dockerイメージ"を簡単にアップデートしたりロールバックしたりできることを確認できました
4. Pod障害時の挙動確認
Pod
障害時の挙動について確認してみます。まずDeployment
によって作成された非永続的なPod
が障害になったときの挙動について確認します
□手順4‐1: kubectl get pods
コマンドで現在稼働しているPod
の情報を確認します
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE
db-statefulset-0 1/1 Running 0 3h44m 10.12.2.7 gke-my-worker-node-cluse-default-pool-924284ce-kpcs <none>
web-deployment-5f4f68bf87-4ztjn 1/1 Running 0 9m41s 10.12.2.27 gke-my-worker-node-cluse-default-pool-924284ce-kpcs <none>
web-deployment-5f4f68bf87-m8wtz 1/1 Running 0 9m52s 10.12.2.26 gke-my-worker-node-cluse-default-pool-924284ce-kpcs <none>
web-deployment-5f4f68bf87-nfwbz 1/1 Running 0 10m 10.12.1.6 gke-my-worker-node-cluse-default-pool-924284ce-td1m <none>
□手順4‐2: kubectl delete pod <Pod Name>
コマンドでリストの一番下のPod
を削除してみます
$ kubectl delete pod "web-deployment-5f4f68bf87-nfwbz"
pod "web-deployment-5f4f68bf87-nfwbz" deleted
□手順4‐3: kubectl get pods
コマンドで直後のPod
の状態を確認します
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE
db-statefulset-0 1/1 Running 0 3h47m 10.12.2.7 gke-my-worker-node-cluse-default-pool-924284ce-kpcs <none>
web-deployment-5f4f68bf87-4ztjn 1/1 Running 0 11m 10.12.2.27 gke-my-worker-node-cluse-default-pool-924284ce-kpcs <none>
web-deployment-5f4f68bf87-m8wtz 1/1 Running 0 12m 10.12.2.26 gke-my-worker-node-cluse-default-pool-924284ce-kpcs <none>
web-deployment-5f4f68bf87-sst4v 1/1 Running 0 41s 10.12.2.28 gke-my-worker-node-cluse-default-pool-924284ce-kpcs <none>
すぐに新しいPod
が別の名前で再作成されたことが確認できました。続いてStatefulSet
によって作成された永続的なPod
が障害になった場合の挙動について確認します
□手順4‐4: kubectl delete pod
コマンドでdb-statefulset-0
を削除してみます
$ kubectl delete pod "db-statefulset-0"
pod "db-statefulset-0" deleted
□手順4‐5: kubectl get pods
コマンドでPod
の状態を確認します
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE
db-statefulset-0 1/1 Running 0 59s 10.12.2.29 gke-my-worker-node-cluse-default-pool-924284ce-kpcs <none>
web-deployment-5f4f68bf87-4ztjn 1/1 Running 0 14m 10.12.2.27 gke-my-worker-node-cluse-default-pool-924284ce-kpcs <none>
web-deployment-5f4f68bf87-m8wtz 1/1 Running 0 15m 10.12.2.26 gke-my-worker-node-cluse-default-pool-924284ce-kpcs <none>
web-deployment-5f4f68bf87-sst4v 1/1 Running 0 3m41s 10.12.2.28 gke-my-worker-node-cluse-default-pool-924284ce-kpcs <none>
StatefulSet
によって作成されたPod
については、Deployment
の時とは異なり同じ名前のPod
が再作成されることが確認できました
5. ワーカーノード障害時の挙動確認
最後に、ワーカーノード
障害時の挙動について確認してみます
□手順5‐1: kubectl get pods
コマンドで現在稼働しているPod
の情報を確認します
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE
db-statefulset-0 1/1 Running 0 6m51s 10.12.2.29 gke-my-worker-node-cluse-default-pool-924284ce-kpcs <none>
web-deployment-5f4f68bf87-4ztjn 1/1 Running 0 20m 10.12.2.27 gke-my-worker-node-cluse-default-pool-924284ce-kpcs <none>
web-deployment-5f4f68bf87-cddpk 1/1 Running 0 2m 10.12.1.7 gke-my-worker-node-cluse-default-pool-924284ce-td1m <none>
web-deployment-5f4f68bf87-dvfns 1/1 Running 0 51s 10.12.2.31 gke-my-worker-node-cluse-default-pool-924284ce-kpcs <none>
□手順5‐2: StatefulSet
によって作成されたPod
が稼働しているワーカーノード
にログインします
$ gcloud compute ssh "gke-my-worker-node-cluse-default-pool-924284ce-kpcs"
WARNING: The public SSH key file for gcloud does not exist.
WARNING: The private SSH key file for gcloud does not exist.
WARNING: You do not have an SSH key for gcloud.
WARNING: SSH keygen will be executed to generate a key.
This tool needs to create the directory [/home/kukita_keisuke/.ssh]
before being able to generate SSH keys.
Do you want to continue (Y/n)? Y
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/kukita_keisuke/.ssh/google_compute_engine.
Your public key has been saved in /home/kukita_keisuke/.ssh/google_compute_engine.pub.
The key fingerprint is:
SHA256:FUxUU0YJTt5ObFMLIacFwiDU1kKz0ZAhqHeRiid6Eo8 kukita_keisuke@cs-6000-devshell-vm-e9163938-594a-4670-8c13-1d9ca474820d
The key's randomart image is:
+---[RSA 2048]----+
| o++BO=++*O=..|
| . oo=++o===o..|
| o . o.. ..o *. |
|.+ + . . + . |
|.++ . S . |
|E o |
| o |
| |
| |
+----[SHA256]-----+
Did you mean zone [asia-east1-b] for instance:
gke-my-worker-node-cluse-default-pool-924284ce-kpcs] (Y/n)? n
No zone specified. Using zone [asia-northeast1-a] for instance: [gke-my-worker-node-cluse-default-pool-924284ce-kpcs].
Updating project ssh metadata...⠶Updated [https://www.googleapis.com/compute/v1/projects/proud-command-246805].
Updating project ssh metadata...done.
Waiting for SSH key to propagate.
Warning: Permanently added 'compute.147868497783857976' (ED25519) to the list of known hosts.
Welcome to Kubernetes v1.12.8-gke.10!
You can find documentation for Kubernetes at:
http://docs.kubernetes.io/
The source for this release can be found at:
/home/kubernetes/kubernetes-src.tar.gz
Or you can download it at:
https://storage.googleapis.com/kubernetes-release-gke/release/v1.12.8-gke.10/kubernetes-src.tar.gz
It is based on the Kubernetes source at:
https://github.com/kubernetes/kubernetes/tree/v1.12.8-gke.10
For Kubernetes copyright and licensing information, see:
/home/kubernetes/LICENSES
□手順5‐3: ワーカーノード
を再起動します
$ sudo /sbin/shutdown -r now
Connection to 104.198.83.208 closed by remote host.
Connection to 104.198.83.208 closed.
ERROR: (gcloud.compute.ssh) [/usr/bin/ssh] exited with return code [255].
□手順5‐4: kubectl get pods
コマンドでPod
の状態を確認します
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE
db-statefulset-0 1/1 Running 1 18m 10.12.2.36 gke-my-worker-node-cluse-default-pool-924284ce-kpcs <none>
web-deployment-5f4f68bf87-4ztjn 1/1 Running 2 32m 10.12.2.35 gke-my-worker-node-cluse-default-pool-924284ce-kpcs <none>
web-deployment-5f4f68bf87-cddpk 1/1 Running 0 13m 10.12.1.7 gke-my-worker-node-cluse-default-pool-924284ce-td1m <none>
web-deployment-5f4f68bf87-dvfns 1/1 Running 2 12m 10.12.2.32 gke-my-worker-node-cluse-default-pool-924284ce-kpcs <none>
ワーカーノード
障害時にも各Pod
は自動的に復旧されることが確認できます
おまけ: "Google Kubernetes Engine(GKE)" では1つの "Ingress" で "namespace" が異なる "Service" を登録できない?
"1つのグローバルIPアドレス"(≒1つのIngress
)で複数のService
へのトラフィックを管理することが可能だというのがIngress
のメリットでもあります
この場合、namespace
は分けて管理したくなるのですが、"Google Kubernetes Engine(GKE)"側の制約として NG のようです(Kubernetes側の仕様としては問題ないです)
当初は以下のようなManifest
を作成し、Ingress
とService
とは異なるnamespace
を使って管理することを考えていました
$ vi $MANIFESTS_PATH/default/my-ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: my-ingress # このIngressの名前を定義します
namespace: default # Ingressのnamespaceはdefaultにします
annotations:
kubernetes.io/ingress.global-static-ip-name: my-ingress-address # 割り当てるスタティックIPアドレスを定義します
spec:
rules:
- http:
paths:
- path: /*
backend: # バックエンドのServiceとポート番号を定義します
serviceName: web-service
servicePort: 80
---
apiVersion: v1
kind: Service
metadata:
name: web-service
namespace: default # Ingressは同じ名前空間のServiceのみバックエンドとして登録可能です
labels: # このServiceに付与するラベルを定義します
ServiceName: web-service
Environment: development
spec:
type: ExternalName # ExternalName(外部名)は異なるnamespace上のServiceとリンクするために使用します
externalName: web-service.my-wordpress.svc.cluster.local # リンク先のServiceを指定します
ports:
- port: 80
targetPort: 80
protocol: TCP
ところがこの方法でIngress
を作成すると下記のようなエラーメッセージが出力されてしまいました
error while evaluating the ingress spec: service "default/web-service" is type "ExternalName", expected "NodePort" or "LoadBalancer"
どうやらこれは、現時点での"Google Kubernetes Engine(GKE)"の制約↓のようですので、改善を期待したいところです
Cross-namespace Ingress #17088
https://github.com/kubernetes/kubernetes/issues/17088
以上、Google Kubernetes Engine(GKE)"を使って"Kubernetes"について勉強した際の内容でした
今回は、Deployment
とStatefulSet
を中心に動きを確認してみましたが、Pod
を管理するためのオブジェクトとしては、他にも DaemonSet
、CronJob
といったものがあるため、別の記事としてまとめていきたいと思います