LoginSignup
8
1

EKSクラスタのバージョンアップデートを自動化する

Posted at

この記事はZOZO Advent Calendar 2023 シリーズ9の12日目の記事です。

今年弊チームで運用しているEKSクラスタのバージョンアップデートを自動化する取り組みを行っていました。まだ運用に乗り切っていない部分はありますが、その取り組み内容と使用したツールやコマンドなどを紹介します。

K8sクラスタと一口に言ってもチームによって運用しているクラスタの規模、Fargateか否か、テナント数などなどによって、アップデートの大変さは異なると思うので、以下で補足します。

弊チームのK8sクラスタについて補足

特徴

  • EKS Fargateを使っている
  • マルチテナント
  • 日本とUSで2つクラスタを運用している
  • Cloudformationで管理
  • マニフェスト管理はArgoCD

バージョンアップデートの手順

弊チームでのクラスタバージョンアップデート手順は基本的に以下のようになります。Fargateを使っているおかげでかなり楽に済んでいると思われます。

  • アップデートを検知する
  • リリースノートを読んで、影響のある破壊的な変更があるか確認して対応する
  • deprecatedになるAPIがあればアップデートする
  • 開発環境で以下手順を実行する
    • クラスタのバージョンアップデートを実行
    • ワーカーノードの更新
    • それぞれのPodステータスに問題がなければOK
  • ステージング、本番環境の更新に移る(手順は開発環境同様)

自動化をやっていく

GitHub Actionsを使用して上の一連の作業を実行していきます。

アップデートの検知

EKSで新しいK8sバージョンがサポートされた際、基本的には公式のアナウンスによって知ることができます。

例えば、1.28であれば、この記事など。https://aws.amazon.com/jp/blogs/news/amazon-eks-now-supports-kubernetes-version-1-28/

ただ、自動化する際にはこれをコマンドで知りたいですよね。そこで、EKSのAddOnでサポートされているクラスタのバージョンが使えます。aws eks describe-addon-versionsで取得できますが、これを成形することでサポートされている最新のクラスタバージョンを取得することができたりします。

aws eks describe-addon-versions | jq -r ".addons[] | .addonVersions[] | .compatibilities[] | .clusterVersion" | sort -r | uniq | head -n 1

(もうちょっと綺麗なコマンドはあるとは思います。筆者はシェルが少々苦手です。)

また、現在使用してるクラスタのバージョンに関しては、以下のコマンドで取得できます。

aws eks describe-cluster --name <your cluster name> --query "cluster.version"

これを比較して、もし異なっていればクラスタのバージョンをアップデートするPRをGitHub Actionsから作成します。チームメンバーへのアサインまでするとなお良しです。

チームメンバーの取得はGitHub Teamsを使うと良いです。gh apiでGitHub Teamのメンバーリストが取得できるので、こんな感じでランダムなチームメンバーを取得できます。

organization=<your organization>
team=<your GitHub Team>
output=$(gh api -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" /orgs/$organization/teams/$team/members)
member_list_length=$(echo $output | jq 'length')
random_member_index=$((RANDOM % member_list_length))
jq_id_op=".[$random_member_index].login"
echo "ASSIGNEE=$(echo $output | jq $jq_id_op)" >> $GITHUB_ENV

リリースノートの確認

PRをアサインされたメンバーが確認します。

ここはさすがに自動化できていないですね...

deprecated APIのチェック

アップデートする際、APIのバージョンが非推奨になったり使えなくなったりすることがあります。そのため、アップデート前にリリースノートを見て使用しているAPIがその対象になっているか確認する必要がありますが、ここは機械に任せることができます。

確認方法は、カスタムリソースかそうでないかで異なります。

K8s API

plutoコマンド (https://github.com/FairwindsOps/pluto) が便利です。

> pluto detect-files -d <your k8s directory> --target-versions k8s=v1.28

There were no resources found with known deprecated apiVersions.

こんな感じで簡単にチェックしてくれます。

カスタムリソースのAPI

こちらは若干厄介ではありますが、ArgoCDを使用している場合Application Controllerのログを確認することで、deprecatedになっているAPIを拾うことができます。

kubectl logs argocd-application-controller-0 -n argocd | grep -q 'deprecated'

これらをGitHub Actionsに載せて、先ほどのPR作成時に走らせておくとリリースノート確認の負荷がだいぶ下がります。

クラスタのバージョンアップデートを実行

ここでは、アップデートの検知 で作成されたPRをマージして、それをトリガーにGitHub ActionsからCloudformationのスタック更新を行います。

弊チームでは、Cloudformationのスタックをsceptre (https://github.com/Sceptre/sceptre) を使って制御しています。

ワーカーノードの更新

クラスタのバージョンが更新されたら、次はPodが割り当てられているノードを更新する必要があります。弊チームの場合だとFargateを使用しているため、それぞれのPodを再起動することで新しいバージョンのノードに再配置することができます。

ここはK8sコマンドを実行するスクリプトを組んでいて、GitHub Actionsからスクリプトの実行を行っています。

スクリプトの内容としては、一つのnamespaceのDeploymentStatefulsetを全て取得して、kubectl rollout restartをかけます。Argo Rolloutsを使用している場合、Rolloutをここに含める必要があります。その後、それぞれのPodのステータスを確認して、正常に動作していることを確認します。

例えば Deployment の場合、以下のようになります。

Deploymentのリソース名の取得

deployments=`kubectl get deployment -n $ns -o=jsonpath="{range .items[*]}{.metadata.name}{'\n'}{end}"`

Podの再起動

parallel --no-run-if-empty "kubectl rollout restart deployment {} -n $ns" ::: $deployments

(並列実行すると楽)

Podのステータスチェック

for deployment in $deployments; do
  kubectl rollout status deployments/$deployment -n $ns
done

以上をスクリプトに入れて、並列でnamespaceごとに走らせることでワーカーノードの更新は完了です。

kubectl get namespaces -o=jsonpath="{range .items[*]}{.metadata.name}{'\n'}{end}" | parallel --no-run-if-empty "./rollout-pods.sh {}"

ここまでの作業を開発環境で実行して、動作環境をした上で問題なければステージング、本番環境に進みます。

最後に

ざっくりとしたまとめになりましたが、以上が弊チームでEKSクラスタのバージョンアップデートを自動化する上で行った内容となります。

幸いそこまで大きなK8sクラスタを運用しているわけではないので、これくらいの作業感で収まっているところはあると思います。

紹介したツールやコマンドなどの内容が少しでも役に立てば幸いです。

8
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
1