コンテンツにスキップ

プラクティス集@K8s Cluster

はじめに

本サイトにつきまして、以下をご認識のほど宜しくお願いいたします。


01. 運用

CDパイプライン

ArgoCD 自体は ArgoCD 以外でデプロイする必要がある。

GitOps を採用できないため、CIOps になる。

本番環境に対して、ローカルマシンまたは CI ツール (例:GitHub Actions、CircleCI、GitLab CI、Takton など) を使用して、ArgoCD をデプロイする。


02. アップグレード

アップグレードの設計規約

▼ マイナーバージョン単位でアップグレード

アップグレード時、新旧バージョンのコントロールプレーン Node が並行的に稼働する。

基本的にはいずれのコントロールプレーン Node も、並行的に稼働するコンポーネントのバージョンを前方/後方の 1 個のマイナーバージョン以内に収める必要がある。

そのため、Kubernetes のアップグレードもこれに合わせて、後方の 1 個のマイナーバージョンにアップグレードしていくことになる。

マイナーバージョンを 2 個以上跨いだアップグレードは非推奨である。

▼ コントロールプレーンNodeでダウンタイムを発生させない

コントロールプレーン Node でダウンタイムが発生すると、Node コンポーネントが正常に稼働しなくなる。

これにより、システム全体がダウンタイムになる可能性がある。

ただし、コントロールプレーン Node の、kube-controller-manager、kube-scheduler、ではダウンタイムが発生することは許容する。

▼ コントロールプレーンNodeのデータを損失させない

コントロールプレーン Node のデータを損失させないようにする。

ただし、コンテナ内のローカルストレージの損失は許容する。

▼ 廃止されるAPIグループのバージョンを確認する

アップグレードに伴い、kube-apiserver で API グループのバージョンが廃止されることもある。

これにより、マニフェストで API グループのバージョンを宣言できなくなってしまうため、確認が必要である。

静的解析ツール (例:pluto、kubepug) を使用すると検出しやすい。

▼ 監視ツールで廃止されるメトリクスやクエリロジックを確認する

アップグレードに伴い、監視系リソース (例:Prometheus、Grafana) でメトリクス名やクエリロジックが廃止されることもある。

これにより、メトリクスの元になるデータポイントを収集できなくなってしまうため、確認が必要である。

▼ アップグレード後は、PodだけでなくWorkloadのコンディションとステータスを確認する

動作確認として、Ready コンディションと Running ステータスを kubectl get pod で確認する。

また加えて、Pod の作成が始まらないと、kubectl get pod コマンドに Pod 自体が表示されない。

そのため、kubectl get deployment で、Pod の管理リソース (例:Deployment) のすべての Pod が Ready コンディションかどうかを確認しておく。

▼ 自動アップグレードを採用できるのであれば採用する

一連のコマンドを自動化できるツール (例:AWS Step Function、Fablic など) を使用して、アップグレードの実行から動作確認を自動化する。


コントロールプレーンNodeのアップグレード

▼ コントロールプレーンNodeのアップグレードとは

まず最初に、コントロールプレーン Node をアップグレードする。

必要であれば、コントロールプレーン Node のアドオン (例:AWS CoreDNS、AWS kube-proxy、Amazon VPC CNI) を別々にアップグレードする。

▼ インプレース方式

コントロールプレーン Node の kube-apiserver のアップグレード時間がダウンタイムに相当する。

ただし、コントロールプレーン Node がマネージドなクラウドプロバイダーのいくつか (例:AWS) では、kube-apiserver でダウンタイムの発生しないアップグレード手法を採用している。

このアップグレードでは、コントロールプレーン Node はインプレース方式でアップグレードしても、ダウンタイムは発生しないことが保証される。ワーカーNode はダウンタイムが発生する可能性もある。

▼ ローリング方式

記入中...


ワーカーNodeのアップグレード

▼ ワーカーNodeのアップグレードとは

コントロールプレーン Node のアップグレードが終了したら、ワーカーNode をアップグレードする。

クラウドプロバイダーのマネージド Node グループを採用している場合、ワーカーNode が新しいマシンイメージに基づいてオートスケーリングされるように設定しておく。

方法 作業時間 手順の煩雑さ ダウンタイム 補足
インプレース方式 より短い より簡単 より長い ダウンタイムが許されるなら、労力も時間もかからないのでオススメ。
ローリング方式 (サージ方式、ライブ方式) ^ ^ v
ブルー/グリーン方式 より長い より難しい なし Clusterの作成の労力が、もう 1 個実行環境を作成することに相当する。

▼ インプレース方式

既存の Node グループ内のワーカーNode をそのままアップグレードする。

ワーカーNode のアップグレード時間がそのままダウンタイムになるため、メンテナンス時間を設けられる場合にのみ使用できる。

(1)

ワーカーNode を削除する。

(2)

ワーカーNode を再作成する。

▼ セルフマネージドなローリング方式 (サージ方式、ライブ方式)

kubernetes_live-upgrade

『サージ方式』『ライブ方式』ともいう。

新 Node グループを作成し、旧 Node グループ内のワーカーNode を順にドレインしていくことにより、アップグレードする。

一度にアップグレードするワーカーNode 数 (Surge 数) を増やすことにより、アップグレードの速さを調整できる。

デメリットとして、新バージョンを 1 つずつしかアップグレードできない。

(1)

旧 Node グループ (Prod ブルー) を残したまま、新 Node グループ (Test グリーン) を作成する。

このとき、新 Node グループ内ワーカーNode 上には Pod が存在していないため、アクセスが新 Node グループにルーティングされることはない。

(2)

kubectl drain コマンドを実行することにより、旧 Node グループ内のワーカーNode でドレイン処理を開始させる。

この時、DaemonSetのPodを退避させられるように、--ignore-daemonsetsオプションを有効化する。

また、EmptyDir Volumeを持つPodを退避させられるように --delete-emptydir-dataオプションも有効化する。

ドレイン処理によって、旧Nodeグループ内のワーカーNodeがSchedulingDisabled状態になり、加えてこのワーカーNodeからPodが退避していく。

その後、新Nodeグループ内のSchedulingEnabled状態のワーカーNode上で、Podを再スケジューリングさせる。

この時、旧Nodeグループ内ワーカーNode上にはPodが存在していないため、アクセスが旧Nodeグループにルーティングされることはない。

$ kubectl drain <旧Nodeグループ内のワーカーNode名> \
    --ignore-daemonsets \
    --delete-emptydir-data

kubernetes_node_scheduling-pod-status

(3)

ドレイン処理が完了した後、新 Node グループ内ワーカーNode 上で Pod が正常に稼働していることを確認する。

(4)

動作が問題なければ、旧 Node グループを削除する。

▼ マネージドなローリング方式

クラウドプロバイダー (例:AWS、Google Cloud) ではローリング方式をサポートしている。

クラウドプロバイダーの Node グループ (例:Amazon EKS Node グループ) では、新旧 Node グループを作成することにより、Node を入れ替える。

例えば Amazon EC2 の Auto Scaling グループであれば、アップグレードを開始すると EC2AutoScaling に新旧の起動テンプレートが紐づく。

新旧の起動テンプレート配下の EC2 Node を段階的に入れ替えることにより、ローリングアップグレードを実現する。

$ kubectl get node

NAME                                       STATUS                        ROLES    AGE     VERSION
ip-*****.ap-northeast-1.compute.internal   Ready                         <none>   19m     v1.26.7-eks-*** # 作成した新しいK8sバージョンのNode
ip-*****.ap-northeast-1.compute.internal   Ready                         <none>   19s     v1.26.7-eks-***
ip-*****.ap-northeast-1.compute.internal   NotReady,SchedulingDisabled   <none>   66m     v1.25.7-eks-*** # 削除中の古いK8sバージョンのNode
ip-*****.ap-northeast-1.compute.internal   Ready                         <none>   21m     v1.26.7-eks-***
ip-*****.ap-northeast-1.compute.internal   NotReady,SchedulingDisabled   <none>   75m     v1.25.7-eks-***
ip-*****.ap-northeast-1.compute.internal   NotReady,SchedulingDisabled   <none>   73m     v1.25.7-eks-***

▼ ブルー/グリーン方式 (マイグレーション方式)

kubernetes_cluster-migration

『マイグレーション方式』ともいう。

新しい Cluster を作成することにより、ワーカーNode をアップグレードする。

いずれ (例:L7 ロードバランサー) を基点にしてルーティング先を切り替えるかによって、具体的な方法が大きく異なる。

メリットとして、バージョンを 1 つずつのみでなく飛び越えてアップグレードできる。

(1)

旧 Cluster (Prod ブルー) を残したまま、新 Cluster (Test グリーン) を作成する。新 Cluster には、すべての Kubernetes リソースが揃っている。

(2)

社内から、新 Cluster に特定のポート番号でアクセスし、動作を確認する。

(3)

動作が問題なければ、社外を含む全ユーザーのアクセスのルーティング先を新 Cluster に変更する。新 Cluster から旧 Cluster へロールバックする場合に備えて、旧 Cluster は削除せずに残しておく。


ツール別

▼ ArgoCD

ArgoCD の場合、チャート (ArgoCD のコンテナイメージ) と CRD の両方のアップグレードする。

ArgoCD を Namespaced スコープで分割している場合、カスタムリソースが Cluster 内に 1 つしかない CRD を共有しているため、CRD をアップグレードすると全サービスのカスタムリソースに影響が出る。

この場合、カスタムリソースへの影響を考えて、CRD の差分がないバージョンまでは ArgoCD をアップグレードできる。

kubectl diff コマンドで、現在と新 CRD の間に差分があるかどうかを確認できる。

$ kubectl diff -k "https://github.com/argoproj/argo-cd/manifests/crds?ref=<アップグレード先のArgoCDのバージョン>"

もし CRD に差分がある大きなアップグレードの場合、別の Cluster を新しく構築し、そのうえで新 ArgoCD も構築することとする。

▼ aws-loadbalancer-controller

aws-loadbalancer-controller の場合、チャートをアップグレードする。

各サービスの ALB への影響を考えて、CRD の差分がないバージョンまでは aws-loadbalancer-controller をアップグレードできる。

kubectl diff コマンドで、現在と新 CRD の間に差分があるかどうかを確認できる。

$ kubectl diff -k "https://github.com/kubernetes-sigs/aws-load-balancer-controller/helm/aws-load-balancer-controller/crds?ref=<アップグレード先のaws-loadbalancer-controllerのバージョン>"

▼ descheduler

descheduler の場合、チャートをアップグレードする。

ArgoCD のリソースに影響がないため、アップグレードは問題ない。

▼ external-dns

external-dns の場合、チャートをアップグレードする。

ArgoCD のリソースに影響がないため、アップグレードは問題ない。