Kubernetes(AKS)をやさしく学ぶ旅 その8
アプリケーションのデプロイの観点から
Kubernetes には流行りの CI / CD を実現する上で重要なデプロイの機能を備えています。今までにキーワードとしては出ていないですがデプロイを管理する「Deployment」が便利です。
アプリケーションのバージョンアップの考え方として、「より安全(テスト済)に、より迅速に。」が重要です。そんな中でデプロイする手法として代表的なものは以下のようなものです。
ローリングアップデート
アプリケーションのバージョンアップの際にまとめて一気に変更せず、稼働状態を保ちながら少しずつ順繰り更新する方法です。ちなみに、更新中は新旧のアプリケーションが混在するため、ローリングアップデートに対応した仕組みになっている必要があります。
ブルー/グリーンデプロイメント
バージョンが異なる新旧2つのアプリケーションを同時に動作させておき、ネットワークの設定を変更して対応する方法です。ブルー(旧)とグリーン(新)を切り替えることからそう呼ばれます。
ブルーを本番としてグリーン側で機能追加したものでテストし確認できた上で切り替えます。万が一、アプリケーションに障害があってもブルーに切り戻せることがメリットです。
その他キーワードとして一部利用者のみに新機能を開放して問題ないことを確認した上で残りを大規模展開することを「カナリアリリース」といいます。
Deployment とは?
その5 でスケジューリングの話をチラッとしましたが、Pod をどの Node に配置するかはこのスケジューリングで実現します。クラスター上の Pod はラベルによって管理されており、バージョンアップの際にそのアクセスする Pod を変える、という制御を管理するのが Deployment になります。
ちなみに、Pod や ReplicaSet は履歴の概念がないのでリリース後に変更のないアプリケーションを管理するのに適しています。Deployment の場合は履歴の概念があります。すなわち、、
➡ Pod のロールアウトやロールバックができる
➡ ロールアウトの方式を指定したり条件や速度を決められる
アプリケーションの世界では一般的に「作成したらそれで終わり!」というものが基本は少ないため、Deployment の積極利用が勧められます。
ここからハンズオン
Deployment 用のマニフェストファイルを準備し進める形となります。
https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.15/#deployment-v1-apps
xxx > kubectl apply -f Deployment/nginx-deployment.yaml deployment.apps/nginx-deployment created xxx > kubectl get deploy NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 3/3 3 3 21s
Deployment の作成と共に自動的に ReplicaSet と Pod もできあがるようです。
xxx > kubectl get replicaset,pod NAME DESIRED CURRENT READY AGE replicaset.extensions/nginx-deployment-789d949f8b 3 3 3 3m21s NAME READY STATUS RESTARTS AGE pod/nginx-deployment-789d949f8b-cq9mv 1/1 Running 0 3m21s pod/nginx-deployment-789d949f8b-hq4pg 1/1 Running 0 3m21s pod/nginx-deployment-789d949f8b-xbpf7 1/1 Running 0 3m21s
Deployment 名を元に ReplicaSet と Pod の名称がつけられていることが分かります。
xxx > kubectl describe deploy nginx-deployment (略) OldReplicaSets:NewReplicaSet: nginx-deployment-789d949f8b (3/3 replicas created) (略)
この詳細を確認するコマンド実行結果を見ると上記2つで履歴をとっていることが分かります。次に一度 apply したファイルの中身 [spec] - [template] - [spec] - [containers] - [image] の行を変更します。
xxx > kubectl apply -f Deployment/nginx-deployment.yaml deployment.apps/nginx-deployment configured xxx > kubectl describe deploy nginx-deployment (略) OldReplicaSets: nginx-deployment-789d949f8b (1/1 replicas created) NewReplicaSet: nginx-deployment-69fdb6677 (3/3 replicas created) (略)
再度 apply した上で確認すると、変化の途中を捉えたものですが、「789~~」が「69f~~」になっています。
xxx > kubectl get replicaset --output=wide NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR nginx-deployment-69fdb6677 3 3 3 7m26s nginx nginx:1.15 app=nginx-pod,pod-template-hash=69fdb6677 nginx-deployment-789d949f8b 0 0 0 21m nginx nginx:1.14 app=nginx-pod,pod-template-hash=789d949f8b
Deployment の場合は内部で ReplicaSet の履歴を持っており、Label 確認コマンドを実行すると「pod-template-hash」というのを持っていることが分かります。ここでお馴染みの delete を発行します。
xxx > kubectl delete -f Deployment/nginx-deployment.yaml deployment.apps "nginx-deployment" deleted xxx > kubectl get pod,replicaset,deploy No resources found.
Deployment の削除と共に紐付いている ReplicaSet や Pod も削除されることが上記で分かります。
Deployment のしくみ
Kubernetes では大分類として2つのアップデート方式があります。
1つ目は「Recreate」方式で旧 Pod を全停止した上で新 Pod をその名の通り再作成する方法です。何となく勘の良い方はおわかりだと思うのですが、これではダウンタイムが発生します。すなわち、ダウンタイムが許される開発環境などで使用します。
2つ目は前述もしている「RollingUpdate」です。こちらは「Recreate」と違い順繰りに変更していくため、新旧が混在するもののダウンタイムはありません。当方法はマニフェストファイル上では [strategy] - [type] で設定できます。明示的に指定しない場合は「RollingUpdate」になるようです。
再度ハンズオンに入る前に「ロールアウト」という言葉を覚えておきます。この用語はアプリケーションをクラスター内にデプロイしサービスを動作させることを指します。
xxx > kubectl apply -f Deployment/rollout-depoyment.yaml deployment.apps/rollout-deployment created service/rollout created xxx > kubectl rollout status deploy rollout-deployment deployment "rollout-deployment" successfully rolled out xxx > kubectl get pod NAME READY STATUS RESTARTS AGE rollout-deployment-fc7c7cbdc-78d29 1/1 Running 0 66s rollout-deployment-fc7c7cbdc-7wwhj 1/1 Running 0 66s rollout-deployment-fc7c7cbdc-8k5sh 1/1 Running 0 66s rollout-deployment-fc7c7cbdc-cwzc9 1/1 Running 0 66s rollout-deployment-fc7c7cbdc-k8mkw 1/1 Running 0 66s rollout-deployment-fc7c7cbdc-knjdj 1/1 Running 0 66s rollout-deployment-fc7c7cbdc-v2hx4 1/1 Running 0 66s rollout-deployment-fc7c7cbdc-w5n4f 1/1 Running 0 66s rollout-deployment-fc7c7cbdc-xbdfn 1/1 Running 0 66s rollout-deployment-fc7c7cbdc-zjwd6 1/1 Running 0 66s xxx > kubectl get service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.0.0.1443/TCP 3d1h rollout LoadBalancer 10.0.160.142 40.115.182.229 80:32053/TCP 101s
Deployment だけでなく Service のリソースも作成されています。また、「kubectl rollout ~~」でDeployment の結果を確認できます。Pod は 10個 できており、外部からのアクセスIPは「40.115.182.229」といった状態です。アクセスしてみると?
アクセスできました。
xxx > kubectl describe deploy rollout-deployment Name: rollout-deployment (略) Annotations: deployment.kubernetes.io/revision=1 (略) Selector: app=photo-view Replicas: 10 desired | 10 updated | 10 total | 10 available | 0 unavailable StrategyType: RollingUpdate MinReadySeconds: 0 RollingUpdateStrategy: 25% max unavailable, 25% max surge ~~~~~ Pod Template: Labels: app=photo-view Containers: photoview-container: Image: sampleacrregistry999.azurecr.io/photo-view:v1.0 Port: 80/TCP (略) Conditions: Type Status Reason ---- ------ ------ Available True MinimumReplicasAvailable Progressing True NewReplicaSetAvailable OldReplicaSets:NewReplicaSet: rollout-deployment-fc7c7cbdc (10/10 replicas created) Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ScalingReplicaSet 11m deployment-controller Scaled up replica set rollout-deployment-fc7c7cbdc to 10
Deployment の概要が表示され「Annotations」行には「revision=1」があります。履歴管理のためのものでローリングアップに際して増分します。「Selector」行以降でローリングアップデート状況を確認できます。「Pod Template」行以降で Pod の仕様等を確認できます。
続いて その4 で ACR に登録した v2.0 を利用して挙動確認します。準備としてマニフェストファイルの一部を v1.0 から v2.0 に変更します。
xxx > kubectl apply -f Deployment/rollout-depoyment.yaml deployment.apps/rollout-deployment configured service/rollout unchanged xxx > kubectl get deploy NAME READY UP-TO-DATE AVAILABLE AGE rollout-deployment 10/10 10 10 28m xxx > kubectl describe deploy rollout-deployment Name: rollout-deployment (略) Annotations: deployment.kubernetes.io/revision=2 (略) Pod Template: Labels: app=photo-view Containers: photoview-container: Image: sampleacrregistry999.azurecr.io/photo-view:v2.0 (略) OldReplicaSets:NewReplicaSet: rollout-deployment-7bfc98cff8 (10/10 replicas created)
(略)
見比べてみると、「Annotations」行には「revision=2」となり「Image」行は「v2.0」となっております。また、Old と New の ReplicaSet も勿論変更されております。内部的な動作としては新しい ReplicaSet を作成してそちらの Pod を増やす、古い方の Pod を減らす、そして0になるまで続けるといった塩梅です。外見としては把握しにくいですが整合を取りつつ内部ではロールアウトしています。
では、次にロールバックを見てみます。マニフェストを当初の v1.0 に戻します。
xxx > kubectl apply -f Deployment/rollout-depoyment.yaml deployment.apps/rollout-deployment configured service/rollout unchanged xxx > kubectl describe deploy rollout-deployment Name: rollout-deployment (略) Annotations: deployment.kubernetes.io/revision=3 (略) Pod Template: Labels: app=photo-view Containers: photoview-container: Image: sampleacrregistry999.azurecr.io/photo-view:v1.0 (略) OldReplicaSets:NewReplicaSet: rollout-deployment-fc7c7cbdc (10/10 replicas created) (略)
「Annotations」行には「revision=3」となり「Image」行は「v1.0」となっております。その上で Old と New 行なのですが、「revision=1」の際の英数文字の羅列に戻っております。revision こそ進んでいるものの内部の履歴を参照しロールバックをしていることが分かります。
また、ロールアウトは条件として Pod のテンプレートを変更したときのみ行われます。一通りの動きが分かったので削除します。(コマンドは割愛します)
ローリングアップデートの制御に関して
describe のコマンド結果にも表示されていましたが、使用できない Pod の制御として「maxUnavailable」の指定、クラスターで Pod を作成できる最大数として「maxSurge」を指定できます。共にデフォルト値は 25% です。こちらのマニフェストファイルの変更のハンズオンは割愛します。
実際には前述している「ブルー/グリーンデプロイメント」もハンズオンしようと思ったのですがここまでにたっぷりと触れてしまったので その8 はここで打ち切り(笑)にします。
ざっくりとした内容としてはブルー用(旧)のマニフェストファイル v1.0 とグリーン用(新)のマニフェストファイル v2.0 を準備し共にクラスターへデプロイします。apply 方法はいつもと変わりありません。3つずつ Pod がある想定で計6つ Pod が共存する形になります。
これに加え外部からアクセスする際の Service マニフェストを作成する際に v1.0 へ向けるようにするとブルー用(旧)へ向く形となります。v2.0 での確認を一通り終えたところで Service マニフェストを v2.0 へ向けるようにすれば当デプロイメント完了です!
解散!