Amazon Web Services ブログ

Cluster API と Argo CD を用いた Kubernetes マルチクラスター管理

この記事は Multi-cluster management for Kubernetes with Cluster API and Argo CD (記事公開日: 2022 年 11 月 1 日) を翻訳したものです。

イントロダクション

お客様は、スケーラビリティと費用対効果を求めてクラウドに移行しています。また、中には Kubernetes を採用してワークロードをモダナイズすることで、よりアジャイルな方法で反復作業をおこない、市場投入までの時間が短いサービスや製品機能を顧客に提供しようとしている企業もあります。管理すべきクラスターの数が増えるにつれ、お客様は Kubernetes クラスターを管理するための様々なデプロイの仕組みや API (Application Programming Interface) と格闘しています。異なる形式で実行されているクラスターを作成し管理するために、別々のツールを使用するのではなく、より一元的なアプローチが求められています。この記事では、Cluster API と Argo CD を組み合わせて、複数の Kubernetes クラスターのデプロイと運用を効率化する方法を紹介します。

Cluster API とはなにか?

Cluster API は Kubernetes の宣言的な管理を実現するプロジェクトです。API を使用してクラスターの作成、設定、更新を簡単におこなうことができます。2021 年 10 月、Cloud Native Computing Foundation (CNCF) は、Cluster API v1.0 がプロダクションレディであること、その採用の拡大、機能の成熟、コミュニティと包括的なイノベーションへの強いコミットメントを発表しました。

オープンソースコミュニティによってメンテナンスされている Cluster API Provider for aws (CAPA) は、SIG Cluster Lifecycle のプロジェクトです。AWS でのインフラストラクチャのプロビジョニングをハンドリングすることで、Kubernetes クラスターのデプロイやアップグレードをおこなうことができます。CAPA を使用すると、Amazon EC2 ベース、および Amazon EKS ベースの Kubernetes クラスターをプロビジョニングできます。この記事では、Amazon EC2 上でセルフマネージドで動作する Kubernetes クラスターと Amazon EKS で動作するクラスターのどちらかを操作する必要があるという、マルチクラスターのシナリオをシミュレートするために、その両方をカバーしています。Amazon EKS Anywhere は、Kubernetes クラスターの作成、アップグレード、管理に vSphere またはベアメタルの Cluster API プロバイダーを使用します。

Amazon EKS の場合、CAPA には以下の機能があります。

  • Amazon EKS クラスターのプロビジョニングと管理
  • Amazon EKS クラスターの Kubernetes バージョンのアップグレード
  • Amazon EKS クラスターへのセルフマネージドのマシンを Node としてアタッチします
  • マシンプールを作成し、Amazon EKS クラスターにアタッチします。詳しくはマシンプールのドキュメントをご覧ください
  • マネージドのマシンプール (訳注:マネージド型ノードグループを使用するリソースです) を作成し、Amazon EKS クラスターにアタッチします。詳しくはマシンプールのドキュメントをご覧ください
  • EKS アドオンを管理します。詳しくは EKS アドオンのドキュメントをご覧ください
  • Amazon EKS AWS Fargate プロファイルを作成します
  • AWS Identity and Access management (AWS IAM) のaws-iam-authenticator の設定を管理します

Argo CD とはなにか?

Argo CD は、Kubernetes のための宣言的な GitOps 継続的デリバリーツールです。GitOps のパターンに従い、Git リポジトリを信頼できる唯一の情報源として望ましいアプリケーションの状態を定義します。Argo CD を使用すると、Git リポジトリで定義されたアプリケーションをターゲットのクラスター環境に自動でデプロイすることができます。

ソリューション概要

仕組み – ハイレベルなオーケストレーションフロー

このウォークスルーでは、Kind を使ってローカルの Docker マシンに 管理用クラスターを作成します。

注意:kind は本番環境での利用のために設計されていません。今回はデモンストレーションの目的で使用しています。本番環境では、適切なバックアップと DR ポリシーおよび手順が整備された、Amazon EKS のような専用の Kubernetes クラスターを使用することが推奨されます。Kubernetes クラスターは少なくとも v1.20.0 である必要があります。

Cluster API CLI で管理用クラスターを初期化します。クラスター全体とアプリケーションのデプロイプロセスは、Kind 管理用クラスターにインストールされた Argo CD によって管理されます。Argo CD はマルチクラスターに対応しており、Kind クラスターとこれから作成するワークロードクラスター (Amazon EC2 や Amazon EKS で動作) を、ワークロードの設定が保存された Git リポジトリと繋げるための Application を定義することができます。ワークロードクラスターを作成した後に、管理対象のクラスターとして Argo CD に登録し、さらにサンプルアプリケーションをデプロイしていきます。

セットアップの前提条件

  • Amazon EKS、Argo CD、Kubernetes を理解していること
  • kubectl、kind、clusterctl、clusterawsadm、argocd cli、aws cli、jq、docker がインストールしてあること
  • AWS アカウントと管理者権限のあるプロファイルが設定されていること

必要な CLI ツールのインストールについては、以下のリンクを参照してください。

ウォークスルー

Git リポジトリをフォークし、ローカルのワークステーションにクローンする

この記事では、環境を設定するためのサンプルマニフェストを提供しています。アクセスするには、以下の GitHub リポジトリをフォークし、クローンする必要があります。

git clone https://github.com/aws-samples/eks-ec2-clusterapi-gitops
Git

クローンしたディレクトリに移動します。

cd ./eks-ec2-clusterapi-gitops
Git

管理用クラスターの初期化

Kind はローカル環境に Kubernetes クラスターを作成するために使用されます。このクラスターは、Cluster API Provider AWS を用いてターゲットとなる管理用クラスターをプロビジョニングするために、一時的なブートストラップクラスターとして使用します。

では、Kind クラスターを作成し、成功することを確認します。

kind create cluster
kubectl cluster-info --context kind-kind
Git

Kind クラスターが正常に作成されると、以下のように表示されるはずです。

CoreDNS is running at https://127.0.0.1:60624/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
Kubernetes control plane is running at https://127.0.0.1:60624
Git

Kind Kubernetes クラスターは、Cluster API Provider コンポーネントをインストールすることで、管理用クラスターになります。Kind Kubernetes クラスターは、アプリケーションのワークロードから分離することが推奨されます。

Cluster API Provider AWS には、このプロジェクトの IAM オブジェクトを管理するためのユーテリティツールである clusterawsadm が同梱されています。clusterawsadm バイナリは、ワークロードクラスターを作成するために必要な権限を取得するために、環境変数を読み取り、Kind クラスターの Kubernetes Secret に格納する値としてその環境変数をエンコードします。

clusterawsadm bootstrap iam create-cloudformation-stack --region us-east-1
Git

では、必要なパラメータをあらかじめ定義しておきましょう。

export AWS_B64ENCODED_CREDENTIALS=$(clusterawsadm bootstrap credentials encode-as-profile)
export AWS_REGION=us-east-1
Git

EKS クラスターの起動に Cluster API を使用するため、以下のフィーチャーゲートを有効化する必要があります。

export EKS=true
export EXP_MACHINE_POOL=true (For using managed node group, this should be enabled)
export CAPA_EKS_IAM=true
HTML

AWS の Cluster API コンポーネントをインストールするために、kubeadm bootstrap provider とkubeadm control-plane provider を使用し、clusterctl init コマンドで Kind クラスターを管理クラスターにします。

clusterctl init --infrastructure aws
C++

以下の出力が表示されたら、Kind クラスターを管理用クラスターとして初期化することに成功したことを意味します。

Your management cluster has been initialized successfully!
Fetching providers
Installing cert-manager Version="v1.9.1"
Installing Provider="cluster-api" Version="v1.2.2" TargetNamespace="capi-system"
...
Installing Provider="infrastructure-aws" Version="v1.5.0" TargetNamespace="capa-system"
...
C-like

Amazon EKS と Amazon EC2 用の Kubernetes クラスターマニフェストを生成する

このステップでは、Amazon EC2 上の Kubernetes クラスターと Amazon EKS クラスターを、それぞれ us-east-1 リージョンと ap-southeast-2 リージョンに 1 つずつプロビジョニングします。Argo CD でワークロードクラスターをプロビジョニングする必要があり、そのための最初のステップは、各クラスター用のマニフェストファイルを準備することです。これをおこなう手っ取り早い方法は、clusterctl generate cluster とコマンドラインを使用して、定義した環境変数を読み取り、マニフェストを生成することです。

次に、定義しておくべき環境変数の一覧を示します。

export AWS_CONTROL_PLANE_MACHINE_TYPE=t3.large
export AWS_NODE_MACHINE_TYPE=t3.large
export AWS_SSH_KEY_NAME=capi-ec2 (Given we are deploying the EC2 cluster and EKS cluster in different regions, this should be adjusted accordingly )
export AWS_REGION=us-east-1 (This should be adjusted based on where you would like to create your clusters)
HTML

クラスターのワーカーノードにリモートアクセスするための SSH (secure shell) キーが作成されていないので、作成します。

aws ec2 create-key-pair --key-name capi-eks --region ap-southeast-2 --query 'KeyMaterial' --output text > capi-eks.pem
aws ec2 create-key-pair --key-name capi-ec2 --region us-east-1 --query 'KeyMaterial' --output text > capi-ec2.pem
C-like

以下のコマンドを実行することで、ワークロードクラスターのマニフェストを作成することができます。Git リポジトリをクローンした場合は、capi-cluster フォルダにマニフェストが存在するはずです。

Amazon EC2 上でセルフマネージドで動作する Kubernetes クラスターの場合、提供されているクラスターテンプレートを使用せずに新しくクラスターテンプレートを生成したい場合は、以下のコマンドを実行します。

clusterctl generate cluster capi-ec2 --kubernetes-version v1.24.0 --control-plane-machine-count=3 --worker-machine-count=3 > ./capi-cluster/aws-ec2/aws-ec2.yaml
CSS

Amazon EKS の場合、提供されているクラスターテンプレートを使用せずに新しいクラスターテンプレートを生成したい場合は、以下のコマンドを実行します。(eks-managedmachinepool は、Amazon EKS クラスターのワーカーノードを作成する時にマネージド型ノードグループを使用することを指定します。)

export AWS_SSH_KEY_NAME=capi-eks
export AWS_REGION=ap-southeast-2
clusterctl generate cluster capi-eks --flavor eks-managedmachinepool --kubernetes-version v1.22.6 --worker-machine-count=2 > ./capi-cluster/aws-eks/capi-eks.yaml
C-like

管理用 Kubernetes クラスターに Argo CD をインストールする

Cluster API のドキュメントによると、Amazon EKS / k8s クラスターを新しくデプロイする方法として、生成されたマニフェストを kubectl apply を実行して Kind 管理用クラスターに適用する方法があります。しかし、今回は Argo CD を使用して、Git リポジトリに格納された生成されたマニフェストを元に、ワークロードクラスターのデプロイを効率化します。

まず、Argo CD を Kind 管理用クラスターにインストールしましょう。

kubectl apply -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
C

では、ポートフォワーディングを利用して、Argo CD の Web ポータルにログインしてみましょう。

kubectl port-forward svc/argocd-server 8080:80
C

Argo CD にログインし、インストールが正しく行われたことを確認します。

Amazon EC2 上で動作する k8s クラスターと Amazon EKS クラスターをデプロイするために、Argo CD で Application を 作成する

Argo CD は、指定された Git リポジトリのコードを Kubernetes namespace にマッピングする、Application CRD を提供しています。Argo CD Application を管理用クラスターにデプロイする前に、Argo CD と Git の認証を確認する必要があります。これをおこなうには、Argo CD の Web UI にログインし、左側のメニューバーにある Setting ページに移動し、CONNECT REPO USING HTTPS をクリックします。Git リポジトリに接続するための適切な設定を入力します。

https://github.com/aws-samples/eks-ec2-clusterapi-gitops (fork した Git リポジトリの URL に置き換える必要があります)

Argo CD に Cluster API オブジェクトを管理する権限を与えるために、ClusterRoleBinding を作成して、Argo CD が引き受ける ServiceAccount に必要な権限を関連付けます。シンプルにするために、Argo CD が使用する argocd-application-controller ServiceAccount に、cluster-admin Roleを追加しましょう。

kubectl apply -f ./management/argo-cluster-role-binding.yaml
C-like
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: cluster-admin-argocd-contoller
subjects:
  - kind: ServiceAccount
    name: argocd-application-controller
    namespace: default
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
C-like

新しくAmazon EC2 上で動作する k8s クラスター またはAmazon EKS クラスターを作成するために、宣言的なアプローチで Application を定義します。これは、新しいクラスターをデプロイするための全ての部品を構成する Kubernetes マニフェストの集合を表します。このガイドでは、追加する Argo CD Application の設定は、クローンされたリポジトリの management フォルダに格納されています。例えば、以下は Amazon EC2 上で動作する k8s クラスターを作成するための Application マニフェストです。

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: ec2-cluster
spec:
  destination:
    name: ''
    namespace: 'default'
    server: 'https://kubernetes.default.svc'
  source:
    path: capi-cluster/aws-ec2
    repoURL: '[update the Git Repo accordingly]' #Indicate which source repo for fetching the cluster configuration
    targetRevision: HEAD
  project: default #You can give a project name here
  syncPolicy:
    automated:
      prune: true
      allowEmpty: true
C++

Argo CD Application の YAML ファイルを上記のように修正したあと、更新をコミットしてソースリポジトリにプッシュします。

git push .
git add .
git commit -m “updates Argo CD app manifest file” 
C-like

以下のコマンドを実行して、Amazon EC2 上で動作する k8s クラスターを作成するための新しい Application を作成します。

kubectl apply -f ./management/argocd-ec2-app.yaml
C

同様に、Argo CD Application を使用して、Amazon EKS クラスターの起動をサポートします。この例では Application を作成しました。repoURL が自身の Git リポジトリを指すように yaml ファイルを修正し、更新をコミットしてソースリポジトリにプッシュすることを忘れないでください。

Argo CD Application を適用して、Amazon EKS クラスターを起動します。

kubectl apply -f ./management/argocd-eks-app.yaml
C-like

Argo CD に 2 つの Application をデプロイすると、以下の図のように、Argo CD の Web UI で作成された Application を確認できるようになるはずです。

プロビジョニング中のすべてのクラスターをリストアップします。


$ kubectl get clusters
NAME         PHASE          AGE    VERSION
capi-ec2     Provisioning  70s 
capi-eks     Provisioning  39s 
C-like

クラスターの状態を確認します。

clusterctl describe cluster capi-eks
clusterctl describe cluster capi-ec2
C++
 └─3 Machines... True 6m14
NAME                                           READY  SEVERITY REASON  SINCE  
Cluster/capi-ec2                                True                   2m53s 
├─ClusterInfrastructure - AWSCluster/capi-ec2   True                   9m20s 
├─ControlPlane - KubeadmControlPlane/capi-ec2-control-plane True       2m53s 
│ └─3 Machines...                               True                   6m2s   
└─Workers  
 └─MachineDeployment/capi-ec2-md-0              False  Warning          12m  
HTML

Amazon EC2 上で動作しているクラスターで、ワーカーノードの READY ステータスが False のままであることに気づくはずです。クラスターに CNI が導入されていないため、ワーカーノードが正常にクラスターに参加できていません。Argo CD を使って CNI のデプロイを自動化することもできますが、ここではデモンストレーションを目的として、Calico CNI を Amazon EC2 クラスターにデプロイしてみましょう。

Amazon EC2 上に新しく構築したクラスターの kubeconfig ファイルを取得する

clusterctl get kubeconfig capi-ec2 > capikubeconfig-ec2
C-like

Calico CNI をデプロイする

kubectl --kubeconfig=./capikubeconfig-ec2 apply -f https://docs.projectcalico.org/v3.21/manifests/calico.yaml
Bash

Calico CNI が正常にデプロイされたので、再度クラスターの状態を確認します。

 └─3 Machines...                                True                   16m
NAME                                          READY SEVERITY REASON SINCE  
Cluster/capi-ec2                              True                   13m 
├─ClusterInfrastructure - AWSCluster/capi-ec2 True                   20m 
├─ControlPlane - KubeadmControlPlane/capi-ec2-control-plane True     13m 
│ └─3 Machines...                             True                   16m  
└─Workers 
 └─MachineDeployment/capi-ec2-md-0             True                   1s  
C++

AWS Management Console で Amazon EC2 サービスに移動し、us-east-1 リージョン を選択します。すべてのコントロールプレーンとワーカーノードが起動していることが確認できます。

Amazon EKS クラスターが正常にデプロイされたことを確認しましょう。

└─ControlPlane-AWSManagedControlPlane/capi-eks-control-plane True                  3m22s  
clusterctl describe cluster capi-eks
NAME                                                        READY SEVERITY REASON SINCE MESSAGE
Cluster/capi-eks                                             True                  3m22s 
C++

AWS Management Console で Amazon EKS サービスに移動し、ap-southeast-2 リージョン を選択すると、クラスターが作成されているのが確認できるはずです。

Amazon EKS クラスターを作成する際に、kubeconfigs が生成され、管理用クラスターの Secret として保存されることがあります。これは AWS Provider を使用して非管理用クラスターを作成する場合とは異なります。kubeconfig を含む Secret の名前は [cluster-name]-user-kubeconfig です。[cluster-name] は自身のクラスター名に置き換える必要があります。

capi-eks という名前のクラスターのユーザーのkubeconfig を取得するには、以下のようなコマンドを実行します。

kubectl --namespace=default get secret capi-eks-user-kubeconfig -o jsonpath={.data.value} | base64 --decode > capikubeconfig-eks
C-like

新しく作成された Amazon EKS クラスターのワーカーノードをすべてリストアップします。

ip-10-0-247-161.ap-southeast-2.compute.internal  Ready <none>  42m  v1.22.6-eks-7d68063
kubectl --kubeconfig=./capikubeconfig-eks get no
NAME                                            STATUS  ROLES AGE  VERSION
ip-10-0-191-240.ap-southeast-2.compute.internal  Ready <none>  42m  v1.22.6-eks-7d68063
C-like

新しく作成されたクラスターにサンプルアプリケーションをデプロイする

Argo CD を使ってサンプルアプリケーションをワークロードクラスターにデプロイするには、Amazon EC2 / Amazon EKS クラスターをマネージドクラスターとして Argo CD に追加する必要があります。ここではデモンストレーションののため、サンプル Nginx アプリケーションを Amazon EKS クラスターにデプロイする手順のみ紹介します。Amazon EC2 クラスターにデプロイする手順もほぼ同様です。まず、Amazon EKS クラスターをマネージドクラスターとして Argo CD に登録する必要があります。

ポートフォワーディングを有効にした状態で、Argo CD インスタンスにログインします。argocd CLI を使って、Argo CD サーバーに対して認証します。

argocd login localhost:8080 (安全でない接続を続けるかどうか尋ねられたら「はい」と答えてください。)

新しく作成された Amazon EKS クラスターのコンテキスト名を取得します。

kubectl config get-contexts --kubeconfig=./capikubeconfig-eks

CURRENT    NAME       CLUSTER        AUTHINFO 
*        default_capi-eks-control-plane-user@default_capi-eks-control-plane  default_capi-eks-control-plane  default_capi-eks-control-plane-user 
C++

以下のコマンドを実行し、新しく作成した Amazon EKS クラスターを、Argo CD のマネージドクラスターとして追加します。

argocd cluster add default_capi-eks-control-plane-user@default_capi-eks-control-plane --server localhost:8080 --insecure --kubeconfig capikubeconfig-eks
Bash

以下の WARNING を確認し yes と入力してください。

WARNING: This will create a service account `argocd-manager` on the cluster referenced by context `default_capi-eks-control-plane-user@default_capi-eks-control-plane` with full cluster level admin privileges. Do you want to continue [y/N]?
C-like
aws eks describe-cluster --name default_capi-eks-control-plane --region ap-southeast-2 | jq '.cluster.endpoint'
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: eks-nginx
spec:
  destination:
    name: ''
    namespace: ''
    server: '[Replace with your EKS API Endpoint URL]' #Replace the API endpint URL of your EKS cluster
  source:
    path: workload/aws-eks
    repoURL: '[Replace with your own Git Repo URL]' #Indicate which source repo for fetching the cluster configuration
    targetRevision: HEAD
  project: default #You can give a project name here
  syncPolicy:
    automated:
      prune: true
      allowEmpty: true
Bash

次に、Argo CD で新しい Application を作成し、Amazon EKS クラスターへのサンプルアプリケーションのデプロイを効率化できるようにします。以下のコマンドを実行する前に、repoURL が Git リポジトリを指すように上記のマニフェストファイルを修正し、更新をコミットしてプッシュしてください。

以下のコマンドを実行して、サンプル nginx アプリケーションをデプロイします。

kubectl apply -f ./app/eks-app/eks-nginx-deploy.yaml 
CSS

Argo CD の Web ポータルで、サンプル nginx アプリが Amazon EKS クラスターに正常にデプロイされたことが確認できます。

クリーンアップ

不要なクラウドのコストを発生させないためにも、環境をクリーンアップしてください。

Argo CD Application を削除する

kubectl delete -f ./management/argocd-ec2-app.yaml 
kubectl delete -f ./management/argocd-eks-app.yaml
kubectl delete -f ./app/eks-app/eks-nginx-deploy.yaml
C

作成したクラスターを削除する

kubectl delete cluster capi-eks
kubectl delete cluster capi-ec2
C++

各リージョンで作成した Amazon EC2 SSH キーを削除します。

aws ec2 delete-key-pair --key-name capi-eks --region ap-southeast-2
aws ec2 delete-key-pair --key-name capi-ec2 --region us-east-1
HTML

必要な IAM リソースを作成するために実行した clusterawsadm bootstrap コマンドによって作成された CloudFormation Stack を削除する

aws cloudformation delete-stack --stack-name cluster-api-provider-aws-sigs-k8s-io --region us-east-1
C++

管理用クラスターを削除する

kind delete cluster
C

結論

この記事では、Cluster API とは何かを紹介し、複数の Kubernetes クラスターを管理する際に異なる API やツールセットと格闘するのではなく、この便利なツールを使用できる理由を説明しました。Argo CD という GitOps ツールと組み合わせることで、信頼できる唯一の情報源として Git を利用し、クラスターとワークロードのマニフェストファイルを保存できます。それによって、新しいワークロードやワークロードの設定の更新を、ターゲットとなる環境に継続的にデリバリーさせることができます。

翻訳はソリューションアーキテクトの後藤が担当しました。原文はこちらです。