1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

EKSをカナリアリリースでupdateした話 (1.20 -> 1.23)

Last updated at Posted at 2022-11-29

はじめに

先日、プロダクション環境のEKSをupdateしました
その際に得られた知見を共有します

※ベストプラクティスである保証はできません

元々の環境

  • EKS v1.20
    • terraform管理
  • Flux2 v0.13.0
    • Github Enterpriseと同期

アップデート戦略

EKSのアップデート戦略については、以下の記事がとても参考になります
https://zenn.dev/nameless_gyoza/articles/how-to-update-eks-cluster-safely

ざっくり、以下の方法があります

  • in-place update
  • in-place update(control planeのみ) + node migration
  • ブルーグリーンデプロイメント
  • カナリアリリース

弊チームでは、以下の理由でカナリアリリースを採用しました

運用サービスのSLOが高い
→ 何かあった時、すぐ戻せる状態にしたい
→ 新規クラスターを作成し、切り替える方式が良さそう
→ ブルーグリーンはリスクが大きい (問題があるとサービスが止まる)
カナリアリリースだ!

しかし、in-place updateの方が圧倒的に楽です
具体的に、カナリア・ブルーグリーンは以下の手順が必要になります

  • 各種リソース複製(リソース名・バージョンが若干異なるので、レビュー必要)
    • terraformリソース
    • CI config
    • k8sマニフェスト
  • 動作確認
  • 切り替え
  • 後片付け(旧リソース削除)

また、カナリアリリースにおける重み付けは、ALBとRoute53のどちらかで実施することになります
https://dev.classmethod.jp/articles/alb-blue-green-deployment/

弊チームではALBを切り替えたくない事情があるため、ALBで行うことにしました

事前準備

EKS最新バージョン確認

EKSの最新バージョンがいくつか調べます
日本語だと情報が古いことがあるので、英語にして確認しましょう(1敗)
https://docs.aws.amazon.com/eks/latest/userguide/kubernetes-versions.html

作業時(2022年9月)、最新はv1.23.7らしいです

apirVersion確認

k8sリソースのapiVersionの差分を確認します

非推奨・削除を検出するツールであるPlutoを用います
https://kakakakakku.hatenablog.com/entry/2022/07/20/091424

Pluto インストール

$ brew install FairwindsOps/tap/pluto

$ pluto version
Version:5.10.6 Commit:0c3ca2eb1e34d03473948eb0dc82fc2cd6b8c9cf

Pluto 実行

$ pluto detect-files -d . -o wide --target-versions k8s=v1.23.7
NAME      NAMESPACE   KIND                  VERSION          REPLACEMENT   DEPRECATED   DEPRECATED IN   REMOVED   REMOVED IN  
xxx-pdb   xxx         PodDisruptionBudget   policy/v1beta1   policy/v1     true         v1.21.0         false     v1.25.0     
yyy       yyy         CronJob               batch/v1beta1    batch/v1      true         v1.21.0         false     v1.25.0     

PDBとCronJobが非推奨バージョンを用いてるみたいです

以下のようにk8sマニフェストを修正すると良さそうです

  • PodDisruptionBudget
    • policy/v1beta1 -> policy/v1
  • CronJob
    • batch/v1beta1 -> batch/v1

addon バージョン確認

addonのバージョンを、以下コマンドを用いて確認します

$ aws eks describe-addon-versions --kubernetes-version 1.23

上記結果をもとに、以下のように修正すると良さそうです

  • kube-proxy
    • v1.20.4-eksbuild.2 -> v1.23.7-eksbuild.1
  • coredns
    • v1.8.3-eksbuild.1 -> v1.8.7-eksbuild.2
  • vpc_cni
    • v1.7.10-eksbuild.1 -> v1.11.3-eksbuild.1

Flux2 バージョン確認

弊チームのk8s環境は、Flux2を用いて`GitHub Enterpriseと同期しています。

Flux2がずっとアップデートできていないので、これを機にアップデートしていきます

$ brew upgrade fluxcd/tap/flux

$ flux --version
flux version 0.33.0

ローカルで準備ができたら、あとは以下コマンドで生成したリソースをapplyするだけです
(新クラスター完成後に行います)

flux install \
  --version=v0.33.0 \
  --namespace=flux-system \
  --components=source-controller,kustomize-controller,helm-controller \
  --components-extra=image-reflector-controller,image-automation-controller \
  --log-level=error \
  --export > crd.yaml

また、GHE連携できないバグがあるみたいです
(v0.31.0の時に再現しました)
https://github.com/fluxcd/source-controller/issues/652

上記issueによると、source-controllev0.22.0から発生しているようです。
うまく連携できない方は、上記搭載前のv0.27.4にすると良いかもしれません

また、私の環境だとv0.33.0v0.27.4flux intallすることができなかったので、
v0.27.4をローカルインストールする方法を載せておきます

$ brew tap-new iwakirik/taps
$ brew extract fluxcd/tap/flux iwakirik/taps --version 0.27.4
$ brew install iwakirik/taps/flux@0.27.4

カナリア用リソース名の考察

カナリアリリースのために、切り替え先のリソースを作る必要があります
こちらの名前について、最初はprefixにcanaryを付けていました
(例: xxx_cluster -> xxx_cluster_canary)

しかし、これだと、*_canaryリソースが残ってしまう形になります

これを解消するには、リリースを終えた後に、以下のような作業が必要になります

方法1: カナリア用リソースを削除する方法

元クラスター→新クラスター→元クラスターで2回カナリアリリースを行うイメージです

  • 元リソースを更新する
    • EKS version
    • apiVersion
    • addon version
    • flux2 version
  • 元clusterの動作確認
  • ALBの向き先を戻す(カナリアで?)
  • 様子見
  • 問題無さそうなら、カナリア用リリースの削除

方法2: カナリア用リソースを使い続ける方法

  • 元リソースを削除する
  • カナリア用リソースの名前・パラメータ・ディレクトリ構造を、元リソースに合わせる(戻す)
    • terraform import等の不毛な作業が必要

はい、リリース後の作業が沢山になっちゃいます

リリース完了したら、旧リソースを削除するだけで終わりにしたいです。
つまり、カナリアリリース用のリソースだけが残っても自然な形にしたいです。

そのため、リソース名のprefixはversion名にすることにしました
(例: xxx_cluster -> xxx_cluster_v1_23)

これだと、今後のupdateも自然なリソース名にすることができます
xxx_20221001といった日付も良いと思います)

実作業

リソース複製

各種リソースを複製しつつ、準備編で挙げたルール・バージョンで変更します。

弊チームでは、ざっくり以下リソースを複製・追記しました

  • aws_eks_cluster
  • aws_eks_node_group
  • aws_iam_openid_connect_provider
  • aws_launch_template
  • aws_eks_addon
  • aws_lb_target_group
  • aws_autoscaling_attachment
  • 各種k8sマニフェスト(Flux2 crd, Datadog等のHelm Chart含む)
  • 各種CI設定

また、リソース複製から動作までの間に、いくつかトラブルに遭遇しました。
そちらの詳細と解決方法は後の章にまとめてあります。

動作確認

前手順で作成したクラスターで動作確認を行います。
ざっくり、主要な機能が動作するかといったことを検証しました。

また、以下のようなリスナールールを用意すると、
カナリアリリースの重み付けの中でもアクセスが任意で行えて便利でした。

resource "aws_lb_listener_rule" "<リソース名>" {
  listener_arn = aws_lb_listener.<リスナー名>.arn

  action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.<ターゲット名>.arn
  }

  condition {
    http_header {
      http_header_name = "canary"
      values           = ["true"]
    }
  }
}

カナリアリリース

動作確認も終えたので、実際にカナリアリリースを行います。
以下の重み付け推移で、1日毎にリリースを行いました。

0.1% -> 1% ->10% -> 50% ->100%

リソース削除

100%リリースから数日経過し、安定稼働を確認したら、旧リソースを削除します

遭遇したトラブル

ここからは、今回遭遇したトラブルと解決方法をまとめていきます。
たくさんリソースを生成するわけですから、どこかでミスは起こりそうですね。
初歩的なものも多いですが、自分への戒めとして残しておきます。

アプリケーションが動かない

新しく生成したクラスターのsecurity groupが不足していたようです。
追加して対応しました。

エラー:configmaps “aws-auth” already exists

k8s関連リソースの複製中に起こったエラーです。
どうやら、元々terraform管理していたaws-authと、クラスター生成時に生成されるaws-authが衝突しちゃったようです。

とりあえず、手動削除して再applyで解決しようとします

$ aws eks update-kubeconfig --region <リージョン名> --name <クラスター名> --profile <プロファイル名>
$ kubectl delete cm aws-auth -n kube-system
error: You must be logged in to the server (Unauthorized)

また怒られちゃいました。
どうやら、デフォルトのaws-authでは、EKSを作成したユーザーしか権限を持っていないようです。

弊チームでは、terraformをGitHub管理し、CircleCIでterraform applyしています。
そのため、CircleCI userでしかterraform applyできません。

CircleCIにsshして上記手順を行い、解消しました。

レスポンスタイム急上昇

アプリケーションの動作が取れた後、数分間レスポンスタイムが急上昇する問題が発生しました。
調査に時間をかけたり、サポートへ問い合わせたりしましたが、結局未解決でした…

原因が分からなかった大きな理由として、ログを有効化していなかった所にあります
(サポートから、「ログがないから調査できない」との返答がありました)

アプリレイヤーではログを取得してますが、ALBではログは有効にしていませんでした。
少なくとも安定稼働までは、各種リソースでログを有効にするのが良さそうですね。

まとめ

以下の反省点がありました

  • update戦略はちゃんと考える
    • リソース複製方式は想像よりずっと大変!
  • 安定稼働までの間、ログを取る
    • 原因を特定できないリスク

この辺りを反省して、次の業務に活かしていきたいところです。

(マサカリあったら遠慮なくお願いします!)

1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?