最近インフラの勉強を始めた komatsu です。
今回はEKSクラスター作成から ArgoCD を使ったいこーよのデプロイまでの手順とそこから学んだことを書きたいと思います。
現在、いこーよ の Rails アップデートを行っています。 その検証としてカナリアリリースを実施予定ですが、 これは本番のEKSクラスターに ArgoCD でアプリケーションを追加する作業で、ローカル環境でしたかクラスターを作ったことがない不慣れな私にはハードルが高い作業でした。
そこで、テスト用アカウント(本番とはAWS アカウントが異なる)でEKSクラスター作成から ArgoCD を使ったデプロイまでをやってみて手順を確認することにしました。
これならコマンド実行時の AWS アカウントと Context をしっかり確認すれば最悪環境をぶっ壊しても安心です。壊してもいい環境があることに感謝です。
AWS アカウント ID が 111111111111
は本番アカウント、222222222222
はテスト用アカウントとします。
リポジトリ名は product
とします。
現在の AWS アカウント、Context の確認方法
APIを叩くコマンドの実行前にしっかりテスト用のAWS アカウントと Context になっているかを確認します。 アカウント確認はあらゆるインフラ作業に必須の習慣ですね。
現在の AWS アカウントを確認するコマンド
aws sts get-caller-identity
現在の Context を確認するコマンド
kubectl config current-context
手順
ブランチをビルドしてイメージを作成
まずは CodeBuild で Rails アップデート用ブランチの Docker イメージを作成します。 ビルドプロジェクトはカナリアリリース時のものを使います。 できたイメージは ECR に登録されるようになっています(Buildspec ファイルに処理を記述)
本番アカウントの ECR から ローカルに pull してテスト用アカウントの ECR に push する
https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/userguide/docker-pull-ecr-image.html に従って進めます。公式ドキュメントを確認するのがポイントです。
本番アカウントの ECR レジストリに対して Docker を認証
https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/userguide/registry_auth.html を基にECR プライベートレジストリに対して Docker を認証します。
ここで profile を指定する場合は aws --profile prd ecr ~
にします。
aws ecr get-login-password | docker login --username AWS --password-stdin https://111111111111.dkr.ecr.ap-northeast-1.amazonaws.com
product-nginx/production を pull
docker pull 111111111111.dkr.ecr.ap-northeast-1.amazonaws.com/product-nginx/production:canarybuild-XXXXXXX
product-rails/production を pull
docker pull 111111111111.dkr.ecr.ap-northeast-1.amazonaws.com/product-rails/production:canarybuild-XXXXXXX
イメージのリポジトリ名とタグ名を変更
product-nginx/production
docker tag 111111111111.dkr.ecr.ap-northeast-1.amazonaws.com/product-nginx/production:canarybuild-XXXXXXX 222222222222.dkr.ecr.ap-northeast-1.amazonaws.com/product-nginx/production:build-XXXXXXX
product-rails/production
docker tag 111111111111.dkr.ecr.ap-northeast-1.amazonaws.com/product-rails/production:canarybuild-XXXXXXX 222222222222.dkr.ecr.ap-northeast-1.amazonaws.com/product-rails/production:build-XXXXXXX
テスト用アカウントの ECR レジストリに対して Docker を認証
profile を指定する場合は aws --profile [] ecr ~
にします。
aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin 222222222222.dkr.ecr.ap-northeast-1.amazonaws.com
テスト用アカウントの ECR に push する
product-nginx/production
docker push 222222222222.dkr.ecr.ap-northeast-1.amazonaws.com/product-nginx/production:build-XXXXXXX
product-rails/production
docker push 222222222222.dkr.ecr.ap-northeast-1.amazonaws.com/product-rails/production:build-XXXXXXX
push されたのを ECR で確認します。
EKSクラスターの作成
AWS CDK (TypeScript) を使って Cloud Formation 経由でEKSクラスターを作成します。 このあたりは別途学習していかないといけないですね。
デプロイ先となる環境変数 NODE_CONFIG_ENV
に development
を設定します。
export NODE_CONFIG_ENV=development
確認する
echo $NODE_CONFIG_ENV
スタック一覧を表示してテスト用のスタックになっているか確認します。
yarn cdk list
すべてのスタックをデプロイします。yarn cdk list
で確認したスタックがEKSに作られます。
yarn cdk deploy '*-stack'
AWSコンソール上でEKSクラスターが作成されたか確認します。
kubeconfig の追加
Amazon EKS の kubeconfig を作成する - Amazon EKS
aws eks update-kubeconfig ~
コマンドで ~/.kube/config
にコンテキストを追加します。kubectl get nodes
でクラスターにアクセスできるかとノード数を確認します。
ArgoCDでアプリケーションをデプロイ
ローカルのマニュフェストがあるディレクトリに移動します。
作業ブランチを作成
Kubernetes の YAML管理ツールとして kustomize を使用しています。
argocd/development/kustomization.yaml の patchesStrategicMerge に patch-app-revision.yaml を追加して
targetRevision を HEAD(master) から今回用意するブランチ名に上書きします。
これで ArgoCD がこのブランチを監視して変更があれば自動で差分をデプロイしてくれます。
また、アプリケーションの Pod に使用するイメージのIDを書き換えます。
作業ブランチを作成してリモートリポジトリに push します。
kubectl apply を実行
いよいよデプロイですが、その前に Context を必ず確認します。
kubectl apply -k argocd/development
余談ですが、starship を導入して kubernetes の現在 Context をコマンドラインに表示すると常に確認できるのでおすすめです。
https://starship.rs/ja-jp/config/#kubernetes
ArgoCD 起動確認
apply から20分を過ぎても ArgoCD は立ち上がらない事象が発生しました。
自分では原因はわからず、有識者に調べてもらいましたが、稀に起こる事象で
たまたま ClusterAutoScaler の起動が遅くなると、ノードのリソース不足で他のもののが起動できない上に ClusterAutoScaler も起動できずにいつまでの立ち上がれないという状況になっていた。
とのことでAWSコンソールからノード数を 最小サイズ
と 希望のサイズ
を3 から 5 に変更したところ ArgoCD が立ち上がりました。
ブラウザ上から ArgoCD にログインして Healthy, Synced であることを確認します。
検証環境確認
ブラウザから検証環境にアクセスすると 503 エラーになりました。 こちらも自分では原因がわからず助けてもらいました。
下記の2つの原因を解消することでアクセスできるようになりました。手順は終了です。
原因1
EKSクラスターのノードグループ の Auto Scaling グループにロードバランサーのターゲットグループが登録されておらず通信できていませんでした。 ALBのターゲットグループがどの Node にリクエストを転送するかを設定している。 これだとまだノードのヘルスチェックがNGになりました (Health status: unhealthy)
原因2
EKSクラスターのセキュリティグループのインバウンドルールにロードバランサーのセキュリティグループが設定されていなかった。 AWSのリソース間通信は、何処とどこが通信するかを登録して、具体的なプロトコルやポート番号はセキュリティグループで設定することが多い。
料金
AWSリソースを作るため、当然料金が発生します。EKSクラスター及びインスタンス使用料金は1時間単位で請求されるので、 使わないリソースは削除するのもクラウド作業では必須の心得ですね。
感想
今の知識ではトラブルシューティングまでできないので学習と経験が必要です。 手順から作る場合は事前に手順書と解決できないエラーが発生した場合の切り戻し手順を作って有識者にレビューしてもらうのがベストですね。 インフラは奥が深いなと改めて感じた次第です。ひとまず習うより慣れろでした。
最後に
アクトインディではエンジニアを募集しています。