とことんDevOps | 日本仮想化技術のDevOps技術情報メディア

DevOpsに関連する技術情報を幅広く提供していきます。

日本仮想化技術がお届けする「とことんDevOps」では、DevOpsに関する技術情報や、日々のDevOps業務の中での検証結果、TipsなどDevOpsのお役立ち情報をお届けします。
主なテーマ: DevOps、CI/CD、コンテナ開発、IaCなど

開催予定の勉強会

読者登録と各種SNSのフォローもよろしくお願いいたします。

AWSとArgo CDでかんたんDevOps

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にはadminPasswordには先ほど取得した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

以上で片付けは完了です。