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

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

日本仮想化技術がお届けする「とことんDevOps」では、DevOpsに関する技術情報や、日々のDevOps業務の中での検証結果、TipsなどDevOpsのお役立ち情報をお届けします。
主なテーマ: DevOps、CI/CD、コンテナ開発、IaCなど
読者登録と各種SNSのフォローもよろしくお願いいたします。

vSphereプロバイダーのEKS AnywhereでKubernetes + GitOps環境を利用する

以前、「EKS AnywhereをvSphereプロバイダーで利用してみる」というブログ記事を以下に書いたことがあります。

tech.virtualtech.jp

EKS AnywhereにはオプションでGitOpsツールのFluxをセットアップするオプションが用意されていてそれを試してみましたので、 今回はその話題を取り上げたいと思います。

まず必要なものはこちらです。

  • GitHubアカウント
  • GitHubトークンキー(repoへのアクセス権限。詳細はManage cluster with GitOps)
  • 設定ファイルにGitopsオプション関連の設定の追記

一つ一つ設定してみます。

その前にGitOpsとFluxについておさらい

GitOpsはWeaveworksが提唱するCDの手法です。Gitのみを信頼できるソースとして利用して、アプリケーションをクラスターにデプロイするという開発の手法です。 GitOpsを実践するにはいくつかあるGitOpsツールを選んで動かしてみることです。

数あるGitOpsツールの中で今回取り上げるFluxはWeaveworksが開発をした、OSSのGitOpsツールの一つです。

大抵の場合はKubernetesにKubernetes Helmやマニフェストファイルを使ってGitOpsツールを追加する格好をとりますが、EKS Anywhereではセットアップ時にEKS Anywhereのデプロイマニフェストファイルに必要な設定を書いた上でデプロイを実行すると、Fluxも最初からインストールできます。

これのメリットとして、EKS AnywhereによってデプロイされたKubernetes環境のマニフェストもGitで管理され、設定変更やスケールアップ、スケールダウンなどが容易に行えます。

GitHubアカウントとGitHubトークンキーの用意

自分のGitHubアカウント使って、リポジトリーの操作を行うため、GitHubアクセストークンキーの用意が必要です、 Manage cluster with GitOpsに書かれているような設定のアクセストークンを設定します。

このような感じでSSHキーペアを作成して、GitHubにSSH公開鍵を登録しておきます。

% ssh-keygen -t ecdsa -C "my_email@example.com"

これをGitHubアカウントのSSH公開鍵として登録します。

以上です。

管理用のマシンにDockerをインストール

前回のブログではあまり詳しく説明していませんでしたが、EKS Anywhereの管理用クライアントではDockerのインストールとサービスの起動が必要です。 Docker自体はbootstrapの実行に一時的に必要であるようです。クラスターができたら一時的に作られたコンテナーは削除されるようです。

設定ファイルにGitopsオプション関連の設定の追記

デプロイ用のマニフェストファイルにGitOpsオプションが必要な点、環境変数EKSA_GITHUB_TOKENでトークンキーの設定が必要です。 デプロイの時と削除の時にこの環境変数が必要であるため、次のようにスクリプトファイルとして作成しておくほうが良いと思います。

% cat eksa-env.sh 
#!/bin/bash

export EKSA_VSPHERE_USERNAME='administrator@vsphere.local'
export EKSA_VSPHERE_PASSWORD='hogehuga5656'
export EKSA_GITHUB_TOKEN=ghp_hogehugg

次にマニフェストファイルを編集します。gitOpsRefをspec行に追加して、最後あたりにkind: GitOpsConfigの設定を追加します。 その他のオプションについては今回は省略します。

apiVersion: anywhere.eks.amazonaws.com/v1alpha1
kind: Cluster
metadata:
  name: prod
spec:
  clusterNetwork:
    cniConfig:
      cilium: {}
    pods:
      cidrBlocks:
      - 192.168.0.0/16
    services:
      cidrBlocks:
      - 10.96.0.0/12
...
  gitOpsRef:            #追加行
    kind: GitOpsConfig  #追加行
    name: eksacl        #追加行
---
apiVersion: anywhere.eks.amazonaws.com/v1alpha1
kind: GitOpsConfig
metadata:
  name: eksacl
spec:
  flux:
    github:
      branch: main
      clusterConfigPath: clusters/eksacl
      fluxSystemNamespace: flux-system
      owner: githubuser     #GitHubユーザー名
      personal: true
      repository: eksagitops

設定が終わったらスクリプトによって環境変数を読み込み、クラスターのデプロイを実行します。

% source eksa-env.sh && eksctl anywhere create cluster -f eksa-cluster.yaml

デプロイを実行すると、次のような出力があります。

Checking Github Access Token permissions
✅ Github personal access token has the required repo permissions
Performing setup and validations
Warning: VSphereDatacenterConfig configured in insecure mode
✅ Connected to server
✅ Authenticated to vSphere
✅ Datacenter validated
✅ Network validated
Creating template. This might take a while.
✅ Datastore validated
✅ Folder validated
✅ Resource pool validated
✅ Datastore validated
✅ Folder validated
✅ Resource pool validated
✅ Datastore validated
✅ Folder validated
✅ Resource pool validated
✅ Control plane and Workload templates validated
✅ Vsphere Provider setup is valid
✅ Flux path
✅ Validate certificate for registry mirror
✅ Create preflight validations pass
Creating new bootstrap cluster
Provider specific pre-capi-install-setup on bootstrap cluster
Installing cluster-api providers on bootstrap cluster
Provider specific post-setup
Creating new workload cluster
Installing networking on workload cluster
Installing storage class on cluster
Installing cluster-api providers on workload cluster
Installing EKS-A secrets on workload cluster
Moving cluster management from bootstrap to workload cluster
Installing EKS-A custom components (CRD and controller) on workload cluster
Installing EKS-D components on workload cluster
Creating EKS-A CRDs instances on workload cluster
Installing AddonManager and GitOps Toolkit on workload cluster
Finalized commit and committed to local repository  {"hash": "snip"}
Adding cluster configuration files to Git
Finalized commit and committed to local repository  {"hash": "snip"}
Writing cluster config file
Deleting bootstrap cluster
🎉 Cluster created!

GitHubにログインすると、eksagitopsのようなGitリポジトリーが自分のアカウントに追加されていると思います。 flux-systemとprod/eksa-systemというディレクトリーがリポジトリーに作られています。

このリポジトリーに登録されているファイルは、管理用のマシンのホームディレクトリーの中身と一緒です(流石にkubeconfigは含まれていません)。

これで、GitOpsツールであるFluxにより、このEKS AnywhereのKubernetesクラスターが管理されたことになります。

動作確認

念の為、動作確認をしましょう。 まず、kubeconfigを読み込みます。

% export KUBECONFIG=~/prod/prod-eks-a-cluster.kubeconfig

次にノードの確認。

% kubectl get no
NAME                                STATUS   ROLES                  AGE   VERSION
172-16-5-128.local.virtualtech.jp   Ready    <none>                 52m   v1.22.6-eks-b18cdc9
172-16-5-38.local.virtualtech.jp    Ready    control-plane,master   56m   v1.22.6-eks-b18cdc9
172-16-5-46.local.virtualtech.jp    Ready    <none>                 53m   v1.22.6-eks-b18cdc9
172-16-6-218.local.virtualtech.jp   Ready    control-plane,master   53m   v1.22.6-eks-b18cdc9

GitOpsツールが動いていることを確認します。

% kubectl get pod -n flux-system
NAME                                      READY   STATUS    RESTARTS   AGE
helm-controller-5f44848d46-qhzpw          1/1     Running   0          57m
kustomize-controller-67c64964fd-pbqxk     1/1     Running   0          57m
notification-controller-55d8568f4-7pblk   1/1     Running   0          57m
source-controller-d64cbf95c-fvdzj         1/1     Running   0          57m

「GitOps」を試してみる

とりあえずKubernetes環境とGitOpsツール Fluxの導入は完了していますので、簡単に「GitOps」を試してみましょう。

それにはまず、開発用のクライアントで、作成されたGitHubリポジトリーをクローンします。 当然ながら、クライアントにはgitコマンドがインストールされており、次のコマンドでsshでGitHubにアクセスできるような設定が必要です。

こちらが参考になります。

https://qiita.com/shizuma/items/2b2f873a0034839e47ce

% ssh -T git@github.com
Enter passphrase for key '/Users/ytooyama/.ssh/id_eksa_ecdsa': 
Hi ytooyama! You've successfully authenticated, but GitHub does not provide shell access.

あとはソースコード一式をクローンし、その中にディレクトリーを作成してコンテナアプリケーションのマニフェストファイルを作成します。

% cd ~/working/github/eksagitops
% tree
.
└── clusters
    └── eksacl
        ├── flux-system
        │   ├── gotk-components.yaml
        │   ├── gotk-patches.yaml
        │   ├── gotk-sync.yaml
        │   └── kustomization.yaml
        └── prod
            └── eksa-system
                ├── eksa-cluster.yaml
                └── kustomization.yaml
5 directories, 6 files

このディレクトリー配下にGitOpsで管理するアプリケーションのマニフェストファイルを格納するディレクトリーを作って、その中にマニフェストファイルを作成します。

clusters
    └── eksacl

nginx.yamlサンプル

apiVersion: v1
kind: Namespace
metadata:
  name: test
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx
  name: nginx
  namespace: test
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:alpine
        name: nginx
---
apiVersion: v1
kind: Service
metadata:
  name: nginx
  namespace: test
spec:
  selector:
    app: nginx
  type: NodePort
  ports:
    - port: 80
      targetPort: 80
      nodePort: 30080

追加後のディレクトリー構成

% tree
.
└── clusters
    └── eksacl
        ├── flux-system
        │   ├── gotk-components.yaml
        │   ├── gotk-patches.yaml
        │   ├── gotk-sync.yaml
        │   └── kustomization.yaml
        ├── prod
        │   └── eksa-system
        │       ├── eksa-cluster.yaml
        │       └── kustomization.yaml
        └── test
            └── nginx.yaml

6 directories, 7 files

この状態で、該当のGitリポジトリーにコードをPushします(以下実行例)。

% git add .
% git commit -m "Added demo code for gitops"
% git push -u origin main

Push後にしばらくすると、クラスター上でそのアプリケーションが実行されます。 設定を変更してさらにPushすると、Git上の変更を基として、Kubernetesクラスターに新しいバージョンのアプリケーションがデプロイされます。

% kubectl get ns test
NAME   STATUS   AGE
test   Active   111s

% kubectl get all -n test
NAME                         READY   STATUS    RESTARTS   AGE
pod/nginx-565785f75c-mczss   1/1     Running   0          2m14s
pod/nginx-565785f75c-z86ms   1/1     Running   0          2m14s
pod/nginx-565785f75c-zw6h2   1/1     Running   0          2m14s

NAME            TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
service/nginx   NodePort   10.99.133.220   <none>        80:30080/TCP   2m14s

NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx   3/3     3            3           2m14s

NAME                               DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-565785f75c   3         3         3       2m14s

ログを見ると、Deployment/test/nginxとService/test/nginxがFlux監視対象になっていることがわかります。

% kubectl logs kustomize-controller-67c64964fd-pbqxk  -n flux-system
...
{"level":"info","ts":"2022-05-16T09:56:32.506Z","logger":"controller.kustomization","msg":"server-side apply completed","reconciler group":"kustomize.toolkit.fluxcd.io","reconciler kind":"Kustomization","name":"flux-system","namespace":"flux-system","output":{"Cluster/default/prod":"unchanged","ClusterRole/crd-controller-flux-system":"unchanged","ClusterRoleBinding/cluster-reconciler-flux-system":"unchanged","ClusterRoleBinding/crd-controller-flux-system":"unchanged","Deployment/flux-system/helm-controller":"unchanged","Deployment/flux-system/kustomize-controller":"unchanged","Deployment/flux-system/notification-controller":"unchanged","Deployment/flux-system/source-controller":"unchanged","Deployment/test/nginx":"unchanged","GitOpsConfig/default/eksacl":"unchanged","GitRepository/flux-system/flux-system":"unchanged","Kustomization/flux-system/flux-system":"unchanged","NetworkPolicy/flux-system/allow-egress":"unchanged","NetworkPolicy/flux-system/allow-scraping":"unchanged","NetworkPolicy/flux-system/allow-webhooks":"unchanged","Service/flux-system/notification-controller":"unchanged","Service/flux-system/source-controller":"unchanged","Service/flux-system/webhook-receiver":"unchanged","Service/test/nginx":"unchanged","ServiceAccount/flux-system/helm-controller":"unchanged","ServiceAccount/flux-system/kustomize-controller":"unchanged","ServiceAccount/flux-system/notification-controller":"unchanged","ServiceAccount/flux-system/source-controller":"unchanged","VSphereDatacenterConfig/default/prod":"unchanged","VSphereMachineConfig/default/prod":"unchanged","VSphereMachineConfig/default/prod-cp":"unchanged","VSphereMachineConfig/default/prod-etcd":"unchanged"}}
{"level":"info","ts":"2022-05-16T09:56:32.527Z","logger":"controller.kustomization","msg":"Reconciliation finished in 2.466196559s, next run in 10m0s","reconciler group":"kustomize.toolkit.fluxcd.io","reconciler kind":"Kustomization","name":"flux-system","namespace":"flux-system","revision":"main/c7f0fecf009c2823d244b52c45eacd7af49695d3"}

kubectlコマンドを使って、Fluxの動作状況はある程度把握できますが、Flux CLIをインストールしていれば、Gitソース上でコマンドを実行すると、Gitと設定が同期されているかとどのバージョンと同期しているかがわかります。

% cd ~/working/github/eksagitops
% flux get kustomizations
NAME        REVISION        SUSPENDED   READY   MESSAGE                        
flux-system main/c7f0fec    False       True    Applied revision: main/c7f0fec

これで、vSphereプロバイダーのEKS AnywhereでKubernetes + GitOps環境を利用することができるようになりました。