ArgoCDで外部のクラスターにアプリケーションをデプロイ

2021.04.22

やりたいこと

前回はArgoCDをインストールしたEKSクラスター内にArgoCD経由でアプリケーションをデプロイしました。

今回は、ArgoCDをインストールするクラスターと、アプリケーションをデプロイするクラスターを別にした構成を作ってみたいと思います。かつ、この2クラスターは別々のAWSアカウント上に置きます。

deploy-app-in-external-cluster

ついでに、新たに学んだことを色々盛り込んでいきます。

前提条件

ArgoCDをインストールするEKSクラスターを作成

今回使用するAWSアカウントではAWS SSOでAdministratorAccess権限のロールが使えるので、aws configure ssoでそのロールのクレデンシャルでクラスターを作成します。 こんな感じのAWSプロファイルを作成します。

[profile argo-source-admin]
sso_region = us-east-1
sso_account_id = 111111111111
sso_role_name = AdministratorAccess
region = ap-northeast-1
output = json
sso_start_url = https://d-xxxxxxxxxx.awsapps.com/start

クラスターの作成は前回同様以下を使います。

Terraformのコードを修正したくなかったので、環境変数をセットすることでこのTerraformを実行する際のAWSプロファイルを指定します。

% export AWS_PROFILE="argo-source-admin"
% terraform init
% terraform apply

※ AWS SSOのユーザー(が引き受けるロール)の権限でTerraformを実行したい際のやり方色々は、以前以下エントリにまとめたのでご参照ください。

コンテキストの作成を行ないます。

% aws eks update-kubeconfig --name blue-with-module --alias argo-source

ちなみにですが、上記のようにAWS_PROFILE環境変数を定義した状態でaws eks update-kubeconfigを打つと、できあがるuserの設定は以下のような内容になります。

users:
- name: arn:aws:eks:ap-northeast-1:111111111111:cluster/blue-with-module
  user:
    exec:
      apiVersion: client.authentication.k8s.io/v1alpha1
      args:
      - --region
      - ap-northeast-1
      - eks
      - get-token
      - --cluster-name
      - blue-with-module
      command: aws
      env:
      - name: AWS_PROFILE
        value: argo-source-admin

最後の3行に注目です。ユーザー認証のためのコマンド実行時にAWS_PROFILE環境変数が設定されているので、kubectl使用前にAWSのクレデンシャルの切り替えを行なう必要がありません。ちょっと便利だなと感じました。 (該当プロファイルのsso loginができている必要はあります)

ArgoCDをインストール〜CLIでログイン

  • ArgoCDをインストール
  • ArgoCD API Serverにアクセス
  • CLIでログイン

これらのステップは前回と同じなので割愛します。前回の同項を参照ください。

アプリケーションデプロイ用のEKSクラスターを作成

次は別アカウントにアプリケーションデプロイ先となるクラスターを作成します。このアカウントでもAWS SSOでAdministratorAccess権限のロールが使えるので、aws configure ssoでAWSプロファイルを作成します。

[profile argo-dest-admin]
sso_region = us-east-1
sso_account_id = 222222222222
sso_role_name = AdministratorAccess
region = ap-northeast-1
output = json
sso_start_url = https://d-xxxxxxxxxx.awsapps.com/start

こちらでもクラスターの作成に前述のpublished moduleを使います。

環境変数をセットしてからTerraformを実行します。

% export AWS_PROFILE="argo-dest-admin"
% terraform init
% terraform apply

コンテキストの作成を行ないます。

% aws eks update-kubeconfig --name blue-with-module --alias argo-dest

外部クラスターを登録

ArgoCDをインストールした最初のクラスターが、アプリケーションデプロイ先のクラスターへアクセスできるように権限設定が必要です。 ArgoCD CLIのargocd cluster addコマンドを使います。

まずはコンテキストを確認します。

% kubectl config get-contexts
CURRENT   NAME                                                                 CLUSTER                                                              AUTHINFO                                                             NAMESPACE
*         argo-dest                                                            arn:aws:eks:ap-northeast-1:111111111111:cluster/blue-with-module     arn:aws:eks:ap-northeast-1:111111111111:cluster/blue-with-module
          argo-source                                                          arn:aws:eks:ap-northeast-1:222222222222:cluster/blue-with-module     arn:aws:eks:ap-northeast-1:222222222222:cluster/blue-with-module

argocd cluster addの次に、デプロイ先となるクラスターのコンテキスト名を入れます。

% argocd cluster add argo-dest

これを実行すると、デプロイ先クラスター内にService Account、ClusterRole(フルアクセス権限)、両者を紐付けるClusterRoleBindingが作成され、このService Accountを使って、argo-source内のArgoCDはデプロイなど各種処理を行えるようになります。

Service Account

% kubectl get sa argocd-manager -n kube-system -o yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  creationTimestamp: "2021-04-20T10:17:54Z"
  name: argocd-manager
  namespace: kube-system
  resourceVersion: "36137"
  selfLink: /api/v1/namespaces/kube-system/serviceaccounts/argocd-manager
  uid: 21014f5f-54e0-4ea9-bec1-2c587eed2199
secrets:
- name: argocd-manager-token-9bldg

ClusterRole

% kubectl get clusterrole argocd-manager-role -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  creationTimestamp: "2021-04-20T10:17:54Z"
  managedFields:
  - apiVersion: rbac.authorization.k8s.io/v1
    fieldsType: FieldsV1
    fieldsV1:
      f:rules: {}
    manager: argocd
    operation: Update
    time: "2021-04-20T10:17:54Z"
  name: argocd-manager-role
  resourceVersion: "36142"
  selfLink: /apis/rbac.authorization.k8s.io/v1/clusterroles/argocd-manager-role
  uid: 875a5c85-babd-408f-902e-ab2719cedf08
rules:
- apiGroups:
  - '*'
  resources:
  - '*'
  verbs:
  - '*'
- nonResourceURLs:
  - '*'
  verbs:
  - '*'

ClusterRoleBinding

% kubectl get clusterrolebindings argocd-manager-role-binding -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  creationTimestamp: "2021-04-20T10:17:54Z"
  managedFields:
  - apiVersion: rbac.authorization.k8s.io/v1
    fieldsType: FieldsV1
    fieldsV1:
      f:roleRef:
        f:apiGroup: {}
        f:kind: {}
        f:name: {}
      f:subjects: {}
    manager: argocd
    operation: Update
    time: "2021-04-20T10:17:54Z"
  name: argocd-manager-role-binding
  resourceVersion: "36143"
  selfLink: /apis/rbac.authorization.k8s.io/v1/clusterrolebindings/argocd-manager-role-binding
  uid: 81c358ee-77cb-43d4-bec9-8cb07bb0143c
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: argocd-manager-role
subjects:
- kind: ServiceAccount
  name: argocd-manager
  namespace: kube-system

アプリケーション作成(マニフェストファイルで)

前回はArgoCD CLIのargocd app createコマンドで作成しました。が、k8sマニフェストファイルでも作成可能なので、今回はそちらで行ないました。

% kubectl apply -f ../manifest/argocd-applications.yaml
application.argoproj.io/guestbook created

マニフェストファイルは以下です。

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: guestbook
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/kazuemasaki/argocd-example-apps.git
    targetRevision: HEAD
    path: guestbook
  destination:
    server: https://77D10421D4032045BE6D44E60B0453E2.gr7.ap-northeast-1.eks.amazonaws.com
    namespace: guestbook
  syncPolicy:
    automated: {}
    syncOptions:
    - CreateNamespace=true

前回はソースリポジトリにargocdから提供されているサンプルアプリのURLを指定していました。今回は変更をプッシュしての挙動も確認したいと思ったので、そのサンプルアプリを自分のアカウントにフォークしてきたものを指定しました。

また、前回と比べて2点の設定を加えています。

CreateNamespace=true

spec.destination.namespaceで指定した通り、今回はデプロイ先クラスターのguestbooknamespace上にアプリケーションをデプロイします。この設定は、もし該当のnamespaceがデプロイ先クラスターに存在しない場合は、併せて新規作成してくれるというものです。これがないと事前にデプロイ先クラスターで別途namespaceを作成しない限りはエラーになります。

automated

前回はアプリケーション作成後argocd app syncコマンドを打たないとデプロイが始まりませんでした。この設定を入れることで、アプリケーション作成後argocd app syncコマンドなしで自動的にデプロイが始まります。また以後もリポジトリに変更が発生するたびに自動でデプロイが走ります。

暫く待つとデプロイが完了しました。(STATUS=Synced)

% argocd app list
NAME       CLUSTER                                                                        NAMESPACE  PROJECT  STATUS  HEALTH   SYNCPOLICY  CONDITIONS  REPO                                                    PATH       TARGET
guestbook  https://77D10421D4032045BE6D44E60B0453E2.gr7.ap-northeast-1.eks.amazonaws.com  guestbook  default  Synced  Healthy  Auto        <none>      https://github.com/kazuemasaki/argocd-example-apps.git  guestbook  HEAD

変更をプッシュ

変更をリポジトリにプッシュすると自動で更新が行われることを確認しようと思います。Deploymentのreplicasの数を増やしてみました。

 metadata:
   name: guestbook-ui
 spec:
-  replicas: 1
+  replicas: 3
   revisionHistoryLimit: 3
   selector:
     matchLabels:

しばらくすると、ArgoCDのUIでPod数が増えたことが確認できました。

pod3

まとめ

ArgoCDをインストールしたクラスターとは別のクラスターにアプリケーションをデプロイしてみました。思ったより難しい設定無しで実現できました。AWSアカウントが異なるという点で苦労するかのと思っていたのですが、ArgoCDの設定はAWSの権限の世界ではなくk8sの権限の世界の話なので、あまりAWSアカウントが違うということを意識する必要はありませんでした。

併せて以下も試してみました。少しづつ理解が深まり楽しくなってきました。今後も色々試していきたいと思います。

  • マニフェストファイルでアプリケーションを定義
  • namespace自動作成
  • 自動デプロイ

参考リンク