AWS EKSにArgo CDをインストールして、かんたんDevOps環境を作ってみます。
必要なもの
- AWSアカウント
- Route 53で管理されている実在するドメイン
- eksctl
- Helm
- kubectl
- argocd(CLI)
AWSアカウントは事前に用意しておいてください。
eksctl、Helm、kubectl、argocdは公式ドキュメントにインストール方法が記載されています。以下のドキュメントを参考にインストールをお願いします。 私は全てHomebrewからインストールしました。
EKS
以下のテキストをcluster.yamlというファイルに保存してください。これはEKSクラスターを作るためのコードで、testという名前のEKSクラスターが起動してきます。
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: test
region: ap-northeast-1
version: '1.22'
iam:
withOIDC: true
serviceAccounts:
- metadata:
name: aws-load-balancer-controller
namespace: kube-system
wellKnownPolicies:
awsLoadBalancerController: true
- metadata:
name: external-dns
namespace: kube-system
wellKnownPolicies:
externalDNS: true
vpc:
cidr: 10.21.0.0/16
nat:
gateway: Single
addons:
- name: vpc-cni
- name: coredns
- name: kube-proxy
managedNodeGroups:
- name: ng-1
instanceType: t3.medium
desiredCapacity: 1
minSize: 1
maxSize: 1
volumeSize: 20
privateNetworking: true
iam:
attachPolicyARNs:
- arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly
- arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy
- arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy
- arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
EKSを起動します。
eksctl create cluster -f cluster.yaml
以下のコマンドを実行し、Server Versionが取得できれば成功です。
kubectl version --short
Argo CD
Argo CDをHelmからインストールするので、HelmにArgo CDのリポジトリを追加します。
helm repo add argo https://argoproj.github.io/argo-helm
Argo CDをargocdというネームスペースにインストールします。
helm upgrade --install argocd argo/argo-cd --namespace argocd --create-namespace
ポートフォワードで接続できるようにします。後ほどALB経由で接続できるようにするので、これは一時的なものです。
kubectl port-forward service/argocd-server -n argocd 8080:443
Argo CDのadminパスワードを取得します。
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d
argocdコマンドでログインします。Usernameにはadmin、Passwordには先ほど取得したadminパスワードを入力してください。
argocd login localhost:8080 --insecure
http://localhost:8080 にアクセスするとWEB UIからログインすることもできます。
AWS Load Balancer Controller
AWS Load Balancer Controllerは、Kubernetesリソースを介して動的にALBをプロビジョニングします。
AWS Load Balancer Controllerを使用するにはTargetGroupBindingというカスタムリソースが必要になります。以下のコマンドで作成してください。
kubectl apply -k "github.com/aws/eks-charts/stable/aws-load-balancer-controller//crds?ref=master"
Argo CDにアプリケーションとして追加します。
argocd app create aws-load-balancer-controller \ --repo https://aws.github.io/eks-charts \ --helm-chart aws-load-balancer-controller \ --revision 1.4.5 \ --dest-namespace kube-system \ --dest-server https://kubernetes.default.svc \ --helm-set clusterName=test \ --helm-set serviceAccount.create=false \ --helm-set serviceAccount.name=aws-load-balancer-controller
このままではアプリケーションが追加されただけで、まだデプロイされていません。デプロイします。
argocd app sync aws-load-balancer-controller
ExternalDNS
ExternalDNSは、Kubernetesリソースを介して動的にRoute 53にDNSレコードを管理します。
Argo CDにアプリケーションとして追加します。
{{DOMAIN}}はRoute 53で管理している実在のドメインにしてください。
domain={{DOMAIN}}
txtownerid=test
argocd app create external-dns \
--repo https://kubernetes-sigs.github.io/external-dns/ \
--helm-chart external-dns \
--revision 1.11.0 \
--dest-namespace kube-system \
--dest-server https://kubernetes.default.svc \
--helm-set "domainFilters[0]=$domain" \
--helm-set "txtOwnerId=$txtownerid" \
--helm-set policy=sync \
--helm-set serviceAccount.create=false \
--helm-set serviceAccount.name=external-dns
デプロイします。
argocd app sync external-dns
Argo CDをALB経由でアクセスできるようにする
ALBでgRPCを使うにはHTTPS接続が必須になります。HTTPSを使えるようにACMでSSL証明書を発行します。
{{SUBDOMAIN}}はACMでSSL証明書を発行する対象のサブドメインにしてください。
domain={{SUBDOMAIN}}
arn=$(aws acm request-certificate --domain-name $domain --validation-method DNS --query CertificateArn --output text)
sleep 5
read name type value < <(aws acm describe-certificate --certificate-arn $arn --query 'Certificate.DomainValidationOptions[0].ResourceRecord.[Name,Type,Value]' --output text)
hosted_zone_id=$(aws route53 list-hosted-zones --query 'HostedZones[].Id' --output text | cut -d/ -f3)
cat <<EOF | aws route53 change-resource-record-sets --hosted-zone-id $hosted_zone_id --change-batch file:///dev/stdin
{
"Changes": [
{
"Action": "UPSERT",
"ResourceRecordSet": {
"Name": "$name",
"Type": "$type",
"TTL": 300,
"ResourceRecords": [
{
"Value": "$value"
}
]
}
}
]
}
EOF
Argo CDをデフォルトのままインストールするとIngressが無効の状態になっていますが、設定としては存在しています。以下のコマンドで有効化してください。
domain={{SUBDOMAIN}}
arn=$(aws acm list-certificates --query 'CertificateSummaryList[?DomainName==`'$domain'`].CertificateArn' --output text)
helm upgrade -i argocd argo/argo-cd \
-n argocd --create-namespace \
--set 'server.service.type=NodePort' \
--set 'server.ingress.enabled=true' \
--set 'server.ingressGrpc.enabled=true' \
--set 'server.ingressGrpc.isAWSALB=true' \
--set "server.ingress.hosts[0]=$domain" \
--set "server.ingress.annotations.external-dns\.alpha\.kubernetes\.io/hostname=$domain" \
--set 'server.ingress.ingressClassName=alb' \
--set 'server.ingress.annotations.alb\.ingress\.kubernetes\.io/scheme=internet-facing' \
--set "server.ingress.annotations.alb\.ingress\.kubernetes\.io/certificate-arn=$arn" \
--set 'server.extraArgs[0]=--insecure'
AWSコンソールからALBとRoute 53を確認してください。先ほどインストールしたAWS Load Balancer ControllerがALBを起動し、ExternalDNSがRoute 53にレコードを追加してくれていれば成功です。
続いて、argocdコマンドのログイン先を変更します。今はポートフォワードのlocalhost:8080を見ていると思いますが、ALBを追加したことにいより、LB経由でアクセスできるようになりました。
argocd login {{SUBDOMAIN}} --grpc-web
ブラウザでhttps://{{SUBDOMAIN}}/にアクセスするとWEB UIから操作することも可能です。
片付け
片付けをするには少し順序があります。これはArgo CDで管理しているAWS Load Balancer ControllerとExternalDNSがArgo CDのLBとドメインを管理しており、かつ、Argo CDのログイン先がALBの方に向いているからです。Argo CDを先にアンインストールするとAWS Load Balancer ControllerとExternalDNSが残ってしまいますし、アプリの方を先にアンインストールするとargocdコマンドが使えなくなってしまいます。
以下の手順に沿って、片付けを進めてください。
IngressをOFFにしてALBとサブドメインを解放します。
helm upgrade --install argocd argo/argo-cd --namespace argocd --create-namespace --set 'server.service.type=NodePort' --set 'server.ingress.enabled=false'
ALBとドメインが削除されたのを確認してください。どちらもなくなっていればargocdコマンドが使えなくなっているので、ポートフォワードに切り替えます。
kubectl port-forward service/argocd-server -n argocd 8080:443
argocdコマンドのログイン先も変更します。
argocd login --insecure localhost:8080
アプリを削除します。
argocd app delete aws-load-balancer-controller argocd app delete external-dns
Argo CDをアンインストールします。
helm uninstall --namespace argocd argocd
EKSを削除します。
eksctl delete cluster -f cluster.yaml
Route 53からACMのドメイン認証で追加したCNAMEを削除します。
arn=$(aws acm list-certificates --query 'CertificateSummaryList[?DomainName==`'argocd.ttanaka.virtualtech.jp'`].CertificateArn' --output text)
read name type value < <(aws acm describe-certificate --certificate-arn $arn --query 'Certificate.DomainValidationOptions[0].ResourceRecord.[Name,Type,Value]' --output text)
hosted_zone_id=$(aws route53 list-hosted-zones --query 'HostedZones[].Id' --output text | cut -d/ -f3)
cat <<EOF | aws route53 change-resource-record-sets --hosted-zone-id $hosted_zone_id --change-batch file:///dev/stdin
{
"Changes": [
{
"Action": "DELETE",
"ResourceRecordSet": {
"Name": "$name",
"Type": "$type",
"TTL": 300,
"ResourceRecords": [
{
"Value": "$value"
}
]
}
}
]
}
EOF
ACMからSSL証明書を削除します。
arn=$(aws acm list-certificates --query 'CertificateSummaryList[?DomainName==`'argocd.ttanaka.virtualtech.jp'`].CertificateArn' --output text) aws acm delete-certificate --certificate-arn $arn
以上で片付けは完了です。
