はじめに
お疲れ様です。矢儀 @yuki_ink です。
EKS CapabilitiesのマネージドArgo CD × EKS Auto Mode × GitHub でGitOpsを体感したかったのですが、いい感じにまとまったハンズオンが見当たらなかったので、自力でやりました。
GitHubのアカウント作成からやりました!!😂
AWSアカウント以外に何もない状態からのスタートだったので、なかなか大変でした!!
私の体験が、私と同じ状況の方のお役に立てば幸いです。
この記事により、以下の体験ができます。
- インターネットに公開されたApplication Load Balancer(ALB)を、EKS Auto ModeのIngressから自動で立ち上げ、Argo CDがデプロイしたアプリに手元のブラウザからアクセスする
- アプリのHTMLを書き換えてPushすると、Argo CDにより自動で環境に適用されて(
kubectl applyなしで)ブラウザの画面が変わることを確認する - 稼働中のリソースをわざと手で壊し、Argo CDが自動であるべき状態に戻す「セルフヒール」の動きを確認する
EKS CapabilitiesのマネージドArgo CD × EKS Auto Mode × GitHub の構成を目指す理由
EKS CapabilitiesのArgo CD について
そもそもGitOpsとは、Gitリポジトリを唯一の信頼できる情報源(Single Source of Truth)としてインフラやアプリの状態を管理する運用手法です。
Argo CDはGitOpsを実現するための代表的なツールであり、Kubernetes環境とGit上の定義を常に同期させます。
Amazon EKSでArgo CDを利用したいと考えたとき、現時点では、まずEKS Capabilitiesで提供されるマネージドなArgo CDの利用を考えます。
Argo CDがAWS管理領域で動くフルマネージド機能として提供され、コントローラのインストールもメンテナンスもスケーリングも、AWS側がよしなにやってくれます。
EKS Capabilitiesと後述のEKS Auto Modeを組み合わせて使ったときのイメージがこちら。
マネージドArgo CDの本体は、EKSクラスタのワーカーノード上では動かず、AWSが所有する管理領域(コントロールプレーン側)で動作することが分かります。

(出典)Deep dive: Simplifying resource orchestration with Amazon EKS Capabilities
マネージドArgo CD特有の制約には留意する必要がありますが、これからEKSにArgo CDを導入する場合はEKS Capabilitiesの利用が本命となるでしょう。
制約については、こちらのブログが分かりやすかったです。
EKS Auto Mode について
EKS Auto Modeを利用することで、ノードやアドオンなどのデータプレーン運用をAWSが自動管理し、ノード管理の手間削減、セキュリティ運用の自動化、初期設定の簡素化を実現できます。
EKS Auto Modeでの責任共有モデルはこのようになっており、開発者はアプリの開発に集中できることが分かります。

(出典)詳解: Amazon EKS Auto Mode
Auto Modeを利用することによる制約や留意点ももちろんありますが、実現したい要件に照らし合わせてクリティカルなものがない場合はAuto Modeの利用が推奨されます。
- Amazon EKS Auto Mode を利用する際に気をつけるべきこと
- Amazon EKS Auto Mode のノード自動更新を Deep Dive する ~ 長期実行ワークロードを正しく取り扱う
この記事でも、構築手順の簡素化のためにEKS Auto Modeを活用しました。
なお、EKS CapabilitiesのマネージドArgo CDは、EKS Auto Modeだけでなく、標準のEKSクラスタでもサポートされています。
「マネージドArgo CDを使うからEKS Auto Modeを使う」という話ではないことを明記しておきます。
GitHub について
GitOpsを実現するためのGitサービスは、GitHubである必要はありません。
ネット上にはCodeCommitを使った事例がいくつか公開されていました。
- Amazon EKS で実現するプラットフォームエンジニアリング - GitOps によるセルフサービス型開発プラットフォーム
- EKS CapabilityとCodeCommitで、簡単にGitOpsを始めよう!
ただ、GitHubは世界最大手のプラットフォームであり、事実上のデファクトスタンダードです。
2025年12月にはGitHub Enterprise Cloudによる日本国内でのデータレジデンシーの提供も開始され、エンタープライズ領域での利用も益々進んでいくと考えられます。
なので、この記事ではGitHubを使うことにこだわりました。
この記事で目指すアーキテクチャ
この記事で作るものの全体像を示します。
登場人物は大きく5人(?)です。
- マニフェストを保管する プライベートなGitHubリポジトリ
- AWSとGitHubの間を接続する AWS CodeConnections
- 実際にコンテナが動く EKS Auto Modeクラスタ
- GitHubとEKSクラスタを監視して同期する EKS CapabilitiesのマネージドArgo CD
- アプリを公開する EKSにより生成されるALB
この記事では作業環境として AWS CloudShellを使います。
ブラウザだけでAWS CLIが使え、認証情報の設定も不要なので、ローカル環境を汚さずに始められるのが利点です。
本記事の執筆にあたっては東京リージョンを利用していますが、他リージョンでも再現可能だと思います。
なお、CloudShellからGitHubへPushする場合と、Argo CDからGitHubへPullする場合では、それぞれ異なる認証方式を使用します。
CloudShellからGitHubへPushする際は、単一リポジトリに権限を絞ったfine-grained PAT(Personal Access Token)を使用します。
一方、Argo CDからGitHubへPullする際は、AWS CodeConnectionsを使用します。
CodeConnectionsを使えば、Argo CDにGitHubのPATなどの長期資格情報を持たせる必要がなく、IAMによる認可でプライベートリポジトリへアクセスできます。
本記事では、プライベートリポジトリを利用しつつ、長期資格情報の管理を避けられることから、Argo CDのPullにはCodeConnectionsを採用します。
ちなみに、CodeConnectionsでGitHubと接続するために、GitHub側では「AWS Connector for GitHub」の設定が必要です。
Argo CDから参照するリポジトリは、このGitHub Appのアクセス対象に含めておく必要があります(Step 6の操作を参照)
◆ 参考情報 ◆
- Configure repository access - Amazon EKS
- Accessing private Git repositories from Amazon EKS capability for Argo CD
やってみる
ここからハンズオンです!
是非手を動かしてください!
Step 0. GitHubアカウントとプライベートリポジトリを作る
まずはGitHubアカウントの作成からです。
2FA(2要素認証)も有効化しておきましょう!!
次に、マニフェストを置くリポジトリを作ります。
画面右上の「+」から「New repository」を選び、リポジトリ名をgitops-handsonとします。
公開設定はPrivate を選んで、「Add README」にも一応チェックを入れて「Create repository」を押します。

https://github.com/<ユーザー名>/gitops-handson が非公開で作成されます。
リポジトリの公開設定は、あとから対象リポジトリ →「Settings」→「General」最下部の「Change repository visibility」でも変更できます。
Step 1. Push用のPersonal Access Token(PAT)を発行する
CloudShellからgit pushするためにPATを発行します。
最小権限の原則に従い、対象リポジトリ1つに絞ったfine-grained PATを発行します。
GitHubにログインした状態で、https://github.com/settings/personal-access-tokens/new を開きます(メニューからたどる場合は Settings → Developer settings → Personal access tokens → Fine-grained tokens → Generate new token)。
設定内容は次のようにします。
設定できたら「Generate token」を押してください。github_pat_...で始まる文字列が一度だけ表示されます。
生成されたPATは、この画面を離れると二度と表示されません!!
必ずその場でコピーして、一時的に安全な場所へ控えておいてください。
以降、CloudShellからのPush時にパスワードの代わりにこの値を使います。
◆ 参考情報 ◆
Step 2. 作業環境(CloudShell)を整える
東京リージョンのCloudShellを開きます。
以降のコマンドはすべてこのCloudShellで実行します。
CloudShellにはAWS CLIとgitが最初から入っているので、追加で導入するのはkubectl・eksctl・argocd CLIの3つです。
# 作業リージョンを東京に固定(おまじない)
export AWS_REGION=ap-northeast-1
export AWS_DEFAULT_REGION=ap-northeast-1
# アカウントIDを控えておく(後続で多用する)
export ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
echo "ACCOUNT_ID=${ACCOUNT_ID}"
# kubectl の導入
curl -sSLO "https://dl.k8s.io/release/$(curl -sSL https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x kubectl && mkdir -p ~/bin && mv kubectl ~/bin/
export PATH=$HOME/bin:$PATH
# eksctl の導入
curl -sSL "https://github.com/eksctl-io/eksctl/releases/latest/download/eksctl_Linux_amd64.tar.gz" | tar xz -C /tmp
mv /tmp/eksctl ~/bin/
# argocd CLI の導入
curl -sSL -o ~/bin/argocd https://github.com/argoproj/argo-cd/releases/latest/download/argocd-linux-amd64
chmod +x ~/bin/argocd
# バージョン確認(eksctl が 0.195.0 以上であることを確認)
kubectl version --client && eksctl version && argocd version --client
続いて、GitHubの認証情報を毎回入力しなくて済むよう、gitの資格情報ヘルパーを設定します。
# GitHubユーザー名を設定
export GITHUB_USER=<あなたのGitHubユーザー名>
# PATを画面に出さずに入力(Step 1でコピーした値を貼り付け)
read -s -p "Paste your GitHub PAT: " GITHUB_PAT; echo
# CloudShellセッション内でのみ資格情報をキャッシュ
git config --global credential.helper 'cache --timeout=3600'
git config --global user.name "${GITHUB_USER}"
git config --global user.email "${GITHUB_USER}@users.noreply.github.com"
CloudShellのホームディレクトリは永続化されますが、環境変数はセッションごとにリセットされます。
時間を置いて作業を再開したときは、AWS_REGIONやACCOUNT_ID、GITHUB_USERなどを再設定してください。
◆ 参考情報 ◆
- AWS CloudShell とは - AWS CloudShell ユーザーガイド
- Create an EKS Auto Mode Cluster with the eksctl CLI - Amazon EKS
Step 3. EKS Auto Modeクラスタを作成する
eksctl create cluster コマンドでEKSクラスタを作成します。
autoModeConfig.enabled: true の記述だけで、Auto Modeが既定のノードプール(general-purpose と system)を自動的に用意します。
ノードプールを明示しないのがAWSの推奨で、必要になったときにKubernetes APIで追加できます。
また、今回利用しようとしているマネージドArgo CDは、指定したIAM Capability Roleを使ってEKSクラスタにアクセスし、その認証にEKS Access Entryを利用します。
そのため、EKSクラスタでは認証モード(authenticationMode)としてAPI または API_AND_CONFIG_MAP を有効にしておく必要があります。
cat <<'EOF' > cluster.yaml
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: gitops-handson
region: ap-northeast-1
version: "1.36"
accessConfig:
authenticationMode: API_AND_CONFIG_MAP
autoModeConfig:
enabled: true
EOF
eksctl create cluster -f cluster.yaml
eksctlは、EKSクラスタとあわせて、VPCと公開・非公開サブネットを作り、ELBが使うためのサブネットタグまで付けてくれます。
このおかげで、後のStepでALBをすんなり作れるようになります。
createが完了したら、kubectlの疎通を確認し、あわせてクラスタのARNを控えておきます。
このARNは後のクラスタ登録で使います。
aws eks update-kubeconfig --name gitops-handson --region ap-northeast-1
export CLUSTER_ARN=$(aws eks describe-cluster --name gitops-handson \
--query 'cluster.arn' --output text)
echo "CLUSTER_ARN=${CLUSTER_ARN}"
◆ 参考情報 ◆
- Automate cluster infrastructure with EKS Auto Mode - Amazon EKS
- Create an EKS Auto Mode Cluster with the eksctl CLI - Amazon EKS
- Argo CD considerations - Amazon EKS
- Change authentication mode to use access entries - Amazon EKS
Step 4. マニフェストをプライベートリポジトリにPushする
GitOpsの「唯一の信頼できる情報源(Single Source of Truth)」となるリポジトリに、デプロイ対象のマニフェストを配置します。
今回は4つのファイルを用意します。
- 表示するHTMLを持つ ConfigMap
- それをマウントして配信する nginxのDeployment
- Podを束ねる Service
- 外部公開のための Ingress一式(IngressClassParams / IngressClass / Ingress)
Argo CDのApplicationが参照するappディレクトリにまとめます。
# Step 0で作った空リポジトリ(この時点ではREADMEのみ)をクローン
git clone https://github.com/${GITHUB_USER}/gitops-handson.git
cd gitops-handson
mkdir -p app
今回はGitOpsによる変更の反映をブラウザ上で分かりやすく体験するため、HTMLをConfigMapとして作成します。
バージョンがひと目でわかるよう、見出しに v1 と入れておきます。
cat <<'EOF' > app/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: web-content
data:
index.html: |
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8" />
<title>GitOps Handson</title>
<style>
body { font-family: sans-serif; background: #0f2027; color: #fff;
display: flex; height: 100vh; align-items: center;
justify-content: center; margin: 0; }
.card { text-align: center; }
h1 { font-size: 3rem; margin: 0.2em; }
.tag { display: inline-block; padding: 0.3em 1em; border-radius: 999px;
background: #16c79a; font-weight: bold; }
</style>
</head>
<body>
<div class="card">
<h1>🚀 GitOps is working!</h1>
<p>このページは Argo CD がGitから同期しました。</p>
<p class="tag">version: v1</p>
</div>
</body>
</html>
EOF
次に、そのHTMLをドキュメントルートにマウントするDeploymentです。
Auto Modeが適切にノードを選び、効率よく詰め込めるよう、Podにはリソース要求(requests)を明示します。
cat <<'EOF' > app/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
labels:
app: web
spec:
replicas: 2
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: nginx
image: public.ecr.aws/nginx/nginx:1.27
ports:
- containerPort: 80
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "250m"
memory: "256Mi"
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 10
volumeMounts:
- name: web-content
mountPath: /usr/share/nginx/html
volumes:
- name: web-content
configMap:
name: web-content
EOF
Serviceは、Ingress(ALB)がPodへトラフィックを流すための入り口です。
ALBのターゲットタイプにPod IPを使うので、Podを束ねるClusterIPのままで問題ありません。
cat <<'EOF' > app/service.yaml
apiVersion: v1
kind: Service
metadata:
name: web
spec:
selector:
app: web
ports:
- port: 80
targetPort: 80
EOF
最後に、外部公開のためのIngress一式です。
EKS Auto ModeでALBを使うには、AWS固有の設定を持つIngressClassParams、それを参照してAuto Modeをコントローラーに指名するIngressClass、そして実際の経路を定義するIngressの3点セットを作ります。
コントローラーにはeks.amazonaws.com/albを指定するのがポイントで、これがAuto Mode内蔵のALB機能を指します。
scheme: internet-facingで、インターネットから到達できる公開ALBになります。
cat <<'EOF' > app/ingress.yaml
apiVersion: eks.amazonaws.com/v1
kind: IngressClassParams
metadata:
name: alb
spec:
scheme: internet-facing
---
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: alb
annotations:
ingressclass.kubernetes.io/is-default-class: "true"
spec:
controller: eks.amazonaws.com/alb
parameters:
apiGroup: eks.amazonaws.com
kind: IngressClassParams
name: alb
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web
annotations:
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
spec:
ingressClassName: alb
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web
port:
number: 80
EOF
ここまで準備できたら、まとめてPushします。
git add .
git commit -m "Add nginx deployment, service, configmap(html) and public ALB ingress"
git push origin main
Push時にユーザー名とパスワードを求められたら、ユーザー名にはGitHubのユーザー名を、パスワードにはStep 1で発行したPATを貼り付けます。
これでmainブランチのapp/配下に、アプリ本体とALB定義が載りました。
このリポジトリは非公開なので、次のStepでArgo CDがここを読めるよう、CodeConnectionsの認証経路を用意していきます。
◆ 参考情報 ◆
- Caching your GitHub credentials in Git - GitHub Docs
- Create an IngressClass to configure an Application Load Balancer - Amazon EKS
Step 5. Argo CD Capability用のIAMロールを作る
EKS Capabilitiesは、AWS管理領域で動くコントローラーが利用者に代わって動作するための、専用のIAMロール(Capabilityロール)を必要とします。
というわけで、作っていきます。
通常、EKS向けのロールが信頼するサービスプリンシパルはeks.amazonaws.comですが、EKS Capabilitiesではcapabilities.eks.amazonaws.comという別のプリンシパルを信頼させる必要がある点だけ、注意が必要です。
cat <<'EOF' > argocd-trust-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": { "Service": "capabilities.eks.amazonaws.com" },
"Action": ["sts:AssumeRole", "sts:TagSession"]
}
]
}
EOF
aws iam create-role \
--role-name ArgoCDCapabilityRole \
--assume-role-policy-document file://argocd-trust-policy.json
このロールには、あとからCodeConnectionsを利用するための最小権限を足していきます(Step 6で作成)。
◆ 参考情報 ◆
Step 6. CodeConnectionsでGitHubと接続する
GitHubとの接続を作り、GitHub App側で対象リポジトリへのアクセスを許可し、最後にCapabilityロールへ接続の利用権限を与えます。
6-1. 接続を作成する
まず接続を作成します。
aws codeconnections create-connection \
--provider-type GitHub \
--connection-name argocd-github \
--region ap-northeast-1
作成直後の接続はPENDING状態です。
この時点ではまだGitHubと接続できていません。
CodeConnectionsの接続は、EKSクラスタと同じリージョン(今回は東京)に作る必要があります。
6-2. OAuth認可とGitHub Appのインストールを完了する
マネジメントコンソールの「接続」画面でargocd-githubが表示されることを確認します。

argocd-githubの詳細画面に遷移し、「保留中の接続を更新」を押します。

GitHubのOAuth認可画面が開くので、指示に従って AWS Connector for GitHub というGitHub Appをインストールします。
詳細な手順はこちらを参照させていただきました。
AWS Connector for GitHubアプリは、インストール時に「どのリポジトリにアクセスしてよいか」を選びます。
ここで「Only select repositories」を選んでgitops-handsonを含めるようにしてください。
、
承認が終わると、接続の状態が利用可能に変わります。

このリポジトリ許可を飛ばすと、後のStep 10でApplicationを作った際に次のエラーになります(実際に遭遇しました😅)
Failed to load target state: failed to generate manifest for source 1 of 1:
rpc error: code = Unknown desc = failed to list refs:
authorization failed: Write access to repository not granted.
メッセージは「Write access(書き込み権限)」と言っていますが、実際に足りないのはそのプライベートリポジトリへの読み取りアクセスの認可です。
GitHubで自分のプロフィール →「Settings」→ 左メニュー「Applications」→「Installed GitHub Apps」タブと進み、AWS Connector for GitHub の「Configure」を開きます。
「Repository access」の項目で、Only select repositoriesを選び、リストに gitops-handson が明示されているか確認してください。
もし含まれてなかったら、gitops-handsonを選択して設定を保存します。
6-3. Capabilityロールへ接続の利用権限を付与する
接続が使える状態になったら、Capabilityロールへ接続の利用権限を付与します。
プライベートリポジトリを参照するだけなので、付与するのは当該の接続に対するcodeconnections:UseConnectionとcodeconnections:GetConnectionだけで十分です。
export CONNECTION_ARN=$(aws codeconnections list-connections \
--query "Connections[?ConnectionName=='argocd-github'].ConnectionArn" \
--output text --region ap-northeast-1)
echo "CONNECTION_ARN=${CONNECTION_ARN}"
cat <<EOF > argocd-codeconnections-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["codeconnections:UseConnection", "codeconnections:GetConnection"],
"Resource": "${CONNECTION_ARN}"
}
]
}
EOF
aws iam put-role-policy \
--role-name ArgoCDCapabilityRole \
--policy-name ArgoCDCodeConnections \
--policy-document file://argocd-codeconnections-policy.json
◆ 参考情報 ◆
- Connect to Git repositories with AWS CodeConnections - Amazon EKS
- Configure repository access - Amazon EKS
Step 7. IAM Identity Centerを準備する
マネージドArgo CDのUIログイン時の認証はIAM Identity Centerが担うため、IAM Identity Centerの有効化とユーザの作成を行います。
手順はこちらのブログを参照させていただきました。
IAM Identity Centerの組織インスタンスが使えないときはアカウントインスタンスでOKです。
EKS Capabilities(Argo CD)は、単一アカウントで完結するアカウントインスタンスにも対応しています。

(出典)AWS managed applications that you can use with IAM Identity Center
Step 8. Argo CD Capabilityを作成する
EKSコンソールで対象クラスタgitops-handsonを開き、「機能(Capabilities)」タブへ移動します。
「機能を作成」から入り、Argo CDにチェックを入れて次へ進むと設定画面になります。

設定画面では、「機能ロール」にStep 5で作成したArgoCDCapabilityRoleを選択します(ウィザードで新規作成も選べますが、CodeConnections権限を自分で管理したいので既存ロールを指定します)。
「認証」にはStep 7で確認したIdentity Centerインスタンスを選び、RBACロールの割り当てで、自分のIdentity Centerユーザに**管理者(Admin)**を付与します。
内容を確認して作成すると、ステータスがCREATINGからACTIVEへ変わります。

Argo CDの詳細画面を見ると、UI用URL(Argo API エンドポイント)が払い出されます。
Capabilityが作成されると、裏側では次のことが起きています。
- AWS管理領域にArgo CD本体がデプロイされる
-
gitops-handsonクラスタにはApplication・ApplicationSet・AppProjectのCRDだけが導入される - Capabilityロールに対するEKSアクセスエントリーが自動作成される
※ただしこのアクセスエントリーは、Capabilityが動くための基本的なKubernetes権限を与えるだけで、アプリを実際にデプロイするRBAC権限までは含みません。デプロイ先クラスタとその権限は、次のStepで明示的に設定します。
CRDが入ったことは、kubectlからも確認できます。
kubectl get crd | grep argoproj.io
# applications.argoproj.io / applicationsets.argoproj.io / appprojects.argoproj.io が見える
◆ 参考情報 ◆
Step 9. デプロイ先クラスタを登録し、デプロイ権限を与える
マネージドArgo CDは、そのままでは「自分自身のクラスタ」を自動でデプロイ先にはしません(してくれればいいのに)
EKSのARNを使って明示的に登録したうえで、そのクラスタにアプリを展開するためのKubernetes RBAC権限を与える必要があります。
そのためにまず、argocd CLIをマネージドArgo CDに対して認証させます。
9-1. Argo CD UIでアカウントトークンを発行する
EKSコンソールの「機能」タブに表示されているArgo CDのUI URLをブラウザで開きます。

Argo UIのログイン画面で、Identity Centerのユーザーでログインします。
ログイン完了後、このような画面に遷移します。

左ペインの歯車から Settings → Accounts と進み、自分のアカウント(アカウントID)を開いて、Tokens セクションで Generate New(トークンの生成)を実行します。表示されたトークン文字列を控えておきます(この値は生成時にしか表示されないことがあるので、必ずコピーしてください)。
9-2. トークンとサーバURLを環境変数に設定する
発行したトークンと、Argo CDのAPIエンドポイントを環境変数に設定します。ここで一つ、間違えやすい注意点があります。ARGOCD_SERVERに指定するのはホスト名部分だけで、先頭のhttps://は付けません。スキームまで含めると、CLIがエンドポイントを解釈できずに接続へ失敗します。
# 9-1でArgo CD UIから発行したアカウントトークン
export ARGOCD_AUTH_TOKEN="<TOKEN>"
# gRPC-Webプロトコルを使うためのオプション
export ARGOCD_OPTS="--grpc-web"
# Argo CDのAPIエンドポイント(EKSコンソールのArgo CD UI URL、またはAWS CLIで取得)
# ★先頭の "https://" は含めない! ホスト名だけを設定する
export ARGOCD_SERVER="<Argo CD APIエンドポイント>"
argocd loginを明示的に実行しなくても、ARGOCD_AUTH_TOKENとARGOCD_SERVERが揃っていれば、CLIはこのトークンを使って各コマンドを認証付きで実行します。
ARGOCD_SERVERにhttps://を付けたまま実行すると、接続に失敗します。
UIのURLからスキームを除いたホスト名部分だけをコピーしてください。
9-3. デプロイ先のEKSクラスタを登録する
argocd cluster add コマンドでデプロイ先のEKSクラスタを登録します。
--aws-cluster-nameには、Step 3で控えたEKSクラスタのARNを渡します。
ここでは、名前はin-clusterにしておきます。
# 現在のkubectlコンテキスト名を取得
export KUBE_CONTEXT=$(kubectl config current-context)
argocd cluster add ${KUBE_CONTEXT} \
--aws-cluster-name ${CLUSTER_ARN} \
--name in-cluster
# 以下のように表示されればOK
# Cluster 'https://EF3C2614CA47D3002B127805D5868DB3.gr7.ap-northeast-1.eks.amazonaws.com' added
9-4. デプロイ用のKubernetes RBAC権限を付与する
登録しただけでは、まだデプロイ権限がありません。
Capabilityロールに対して、このクラスタへアプリを展開するためのアクセスポリシーを関連付けます。
export CAP_ROLE_ARN=$(aws iam get-role --role-name ArgoCDCapabilityRole \
--query 'Role.Arn' --output text)
aws eks associate-access-policy \
--region ap-northeast-1 \
--cluster-name gitops-handson \
--principal-arn ${CAP_ROLE_ARN} \
--policy-arn arn:aws:eks::aws:cluster-access-policy/AmazonEKSClusterAdminPolicy \
--access-scope type=cluster
AmazonEKSClusterAdminPolicyはクラスタ全体への強い権限です。
実業務では対象名前空間に絞った権限へ落とすのがベストプラクティスです。
名前空間スコープにする場合は、--access-scope type=namespace,namespaces=webのように限定し、あわせて名前空間を事前作成する必要があります。
◆ 参考情報 ◆
Step 10. Applicationを作り、初回同期とブラウザ表示を見届ける
Step 6で作ったCodeConnections接続を通して、プライベートリポジトリを参照する設定を入れます。
ポイントはrepoURLで、通常のhttps://github.com/...ではなく、https://codeconnections.<region>.amazonaws.com/git-http/<account-id>/<region>/<connection-id>/<owner>/repository.gitのような形で指定します。
# 接続ID(UUID部分)を取得
export CONNECTION_ID=$(echo "${CONNECTION_ARN}" | awk -F'/' '{print $2}')
# GitHubリポジトリ情報
export REPO_OWNER="${GITHUB_USER}"
export REPO_NAME="gitops-handson"
# Argo CD用のCodeConnections URLを生成
export REPO_URL="https://codeconnections.${AWS_REGION}.amazonaws.com/git-http/${ACCOUNT_ID}/${AWS_REGION}/${CONNECTION_ID}/${REPO_OWNER}/${REPO_NAME}.git"
echo "${REPO_URL}"
# Applicationマニフェストを作成
cat <<EOF > application.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: web
namespace: argocd
spec:
project: default
source:
repoURL: ${REPO_URL}
targetRevision: main
path: app
destination:
name: in-cluster
namespace: web
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
EOF
kubectl apply -f application.yaml
Applicationを作ると、Argo CDがCodeConnections経由でGitHubからマニフェストを読み取り、web名前空間を作成したうえで、ConfigMap・Deployment・Service・Ingress一式を同期します。
この同期をトリガーに、Auto Modeが必要なノードを立ち上げ、Ingressに応じて公開ALBのプロビジョニングを始めます。
以下のコマンドを使って、状態を追いかけてみましょう。
# Argo CDから見た同期状態
kubectl get application web -n argocd
## デプロイ完了時はこんな出力になるはず
## NAME SYNC STATUS HEALTH STATUS
## web Synced Healthy
# 実際に立ち上がったPod
kubectl get pods -n web
## デプロイ完了時はこんな出力になるはず
## NAME READY STATUS RESTARTS AGE
## web-d48d9f5b6-776kz 1/1 Running 0 29m
## web-d48d9f5b6-qpkgz 1/1 Running 0 29m
# Ingressと、割り当てられたALBのDNS名(ADDRESS列)
kubectl get ingress -n web
## デプロイ完了時はこんな出力になるはず
## NAME CLASS HOSTS ADDRESS PORTS AGE
## web alb * k8s-web-web-0df433fb08-810476479.ap-northeast-1.elb.amazonaws.com 80 37m
webのApplicationがSyncedかつHealthyになり、web名前空間にnginxのPodが2つ立ち上がれば、初回デプロイは成功です。

Argo UI画面からは、アプリケーションのトポロジー図や同期履歴を視覚的に確認できます。

10-2. 公開ALBのURLをブラウザで開く
Ingressに割り当てられたALBのDNS名を取り出し、ブラウザで開きます。
# IngressのALB DNS名を取得
export ALB_DNS=$(kubectl get ingress web -n web \
-o jsonpath='{.status.loadBalancer.ingress[0].hostname}')
echo "http://${ALB_DNS}"
出力された http://k8s-web-...elb.amazonaws.com のURLを、そのままブラウザのアドレスバーに貼り付けます。
ConfigMapに書いた「🚀 GitOps is working!」と「version: v1」のページが表示されるはずです!!

ここまでで、「Gitに置いた宣言が、そのままクラスタの実体になり、ALB経由でブラウザに映る」という一連の流れを、プライベートリポジトリとフルマネージド基盤の上で確認できました。
◆ 参考情報 ◆
- Configure repository access - Amazon EKS
- Create an IngressClass to configure an Application Load Balancer - Amazon EKS
Step 11. GitOpsを体感する
ようやくここまで来ました。
GitOpsを味わおうじゃないか。
今回の構成ではGitHub Webhookの設定をしておらず、変更の反映はArgo CDの自動ポーリングのタイミングに依存します。
なので、変更の反映までには6分ほどかかります(地味にストレスですね)
デフォルトでは、Argo CD は 6 分ごとに Git リポジトリをポーリングして変更がないか検出します。デプロイの応答性を高めるには、変更がプッシュされたらすぐに同期をトリガーするように Git ウェブフックを設定します。
ウェブフックには、次のような利点があります。
- コードがプッシュされたらすぐに同期応答が返されます (秒か分かの違い)
- ポーリングのオーバーヘッドが軽減され、システムのパフォーマンスが向上します。
- API レートリミットをより効率的に使用できます。
- フィードバックがすぐに返されるので、ユーザーエクスペリエンスが向上します。
実験1:Gitを書き換えると、ブラウザの画面が変わる
GitのConfigMapに書いたHTMLをv1からv2へ変え、見出しの絵文字も差し替えて、Pushするだけです。
kubectlは一切触りません。
cd ~/gitops-handson
# 表示テキストを書き換える(v1 → v2、絵文字も変更)
sed -i 's/version: v1/version: v2/' app/configmap.yaml
sed -i 's/🚀 GitOps is working!/🎉 Updated by GitOps! (v2)/' app/configmap.yaml
git commit -am "Update web page content to v2"
git push origin main
Pushして少し待つと、Argo CDがGitHubの変更を検知してConfigMapを同期します。
今回はConfigMapのボリュームマウント更新を使って、Podを作り直さずに表示を変えています。
マウントされたHTMLファイルはkubeletの同期周期に合わせて更新されるため、変更の反映までに数分かかります。
先ほどのALBのURLをブラウザでリロードしてみます。
「🎉 Updated by GitOps! (v2)」に変わっていれば成功です。

実験2:Gitを書き換えるだけでスケールする
次はレプリカ数です。
kubectl scaleは使わず、Gitのマニフェストでreplicasを2から4に変えてPushします。
sed -i 's/replicas: 2/replicas: 4/' app/deployment.yaml
git commit -am "Scale web to 4 replicas"
git push origin main
数分待つと、Podが4つへ増えます。
kubectl get pods -n web -w
## デプロイ完了時はこんな出力になるはず
## NAME READY STATUS RESTARTS AGE
## web-d48d9f5b6-776kz 1/1 Running 0 55m
## web-d48d9f5b6-qpkgz 1/1 Running 0 55m
## web-d48d9f5b6-r9g4h 1/1 Running 0 9m57s
## web-d48d9f5b6-4tbpr 1/1 Running 0 9m57s
実験3:手で壊しても、自動で戻る(セルフヒール)
最後に、あえてクラスタを手で壊してみます。Deploymentを直接3 replicasに縮めてみましょう。
kubectl scale deployment web -n web --replicas=3
kubectl get pods -n web
一瞬だけ3つになりますが(本当に一瞬です)、selfHeal: trueが効いているため、Argo CDは「Gitでは4、実体は3」というドリフト(乖離)を検知し、自動的に4へ戻します。
本当に一瞬で戻るので kubectl get pods -n web で確認するのはむしろ分かりづらいのですが、、笑
ALBのターゲットが、1つDrainingされているので、一瞬3つになって、すぐ4つに戻ったんだなあと感じることができます😅

◆ 参考情報 ◆
- Argo CD concepts(Sync policies / Self-heal)- Amazon EKS
- Automated Sync Policy - Argo CD Documentation
Step 12. 後片付け
以下のコマンドで、今回作成したAWSリソースを削除します。
# 1) Applicationを削除(クラスタ上のアプリもpruneされる)
kubectl delete -f ~/gitops-handson/application.yaml
# 2) Argo CD Capabilityを削除
# → EKSコンソールの「機能」タブからArgo CDを選択して削除するのが確実
# 3) EKS Auto Modeクラスタを削除(Auto Modeが起動したノードごと消える)
eksctl delete cluster --name gitops-handson --region ap-northeast-1
# 4) CodeConnectionsの接続を削除
aws codeconnections delete-connection \
--connection-arn "${CONNECTION_ARN}" --region ap-northeast-1
# 5) IAMロール(付与したインラインポリシーを外してから削除)
aws iam delete-role-policy --role-name ArgoCDCapabilityRole --policy-name ArgoCDCodeConnections 2>/dev/null
aws iam delete-role --role-name ArgoCDCapabilityRole
GitHub側では、学習で使ったPATを https://github.com/settings/personal-access-tokens から失効(Delete)させ、CodeConnectionsのために入れた AWS Connector for GitHub アプリも不要であればアンインストールしておくと安全です(Settings → Applications → Installed GitHub Apps → AWS Connector for GitHub → Uninstall)。
今回のためにIdentity Centerを新規有効化した場合は、不要であれば無効化を検討してください。
◆ 参考情報 ◆
おわりに
GitOps、体感できましたでしょうか?
今後、以下の点についても実際に手を動かして体感してみたいと思っています。
-
devとstgのようにディレクトリを分けてApplicationSetで束ねる - AppProjectで参照可能なリポジトリやデプロイ先を制限してさらに権限を絞る
- ACK Capabilityを併用してGitHubのマニフェストからS3やRDSといったAWSリソースまでGitOpsで管理する
最後までお目通しいただきありがとうございました。


