TECHSTEP

ITインフラ関連の記事を公開してます。

Flux+ArgoCD? Flamingoを試す

今回は、ArgoCD GUIからFluxのリソースの可視化を実現する、Flamingoというプロダクトを動かしてみます。

Flamingoとは

Flamingoは、Flux subsystem for Argo (FSA) という名称を持っており、その名前の通りFluxとArgoCDを組み合わせて利用することを可能にします。Flamingoのコンテナイメージは既存のArgoCDと置き換え可能で、FluxのワークロードをArgoCD UIから可視化することを可能にします。

以前Weave GitOpsを試したとき、GUIからリソースの操作やログの確認ができないことを記載しましたが、Flamingoを導入することで、Fluxの管理するリソースをArgoCD UIで操作し、これらの課題を解消することが期待できます。

また、Flux OCI Repositoryや、以前扱ったTerraform Controllerなど、Fluxの利用を前提としたリソースをArgoCD UIから操作したり、逆にFluxの管理するリソースのためにApplicationsetを使ったりと、ArgoCDとFluxの機能を組み合わせることも期待できます。

FlamingoはもともとArgoCDベースなので、通常のArgoCDと同じく Application リソースを管理することができます。FSAはそれに加えてArgoCD ApplicationをFlux Objectに変換する機能が追加されており、これによってFluxのリソースをArgoCD UIから管理することを実現します。

図: Flamingo Doc

なお、リリースページを見る限りかなり新しいプロジェクトのようなので、今後仕様変更などが発生する可能性もありそうです。

Flamingoを動かす

ここからFlamingoを実際に動かします。Flamingoを使うため、あらかじめFluxをインストールしたKubernetesクラスターを用意します。

$ kubectl version
Client Version: version.Info{Major:"1", Minor:"22", GitVersion:"v1.22.0", GitCommit:"c2b5237ccd9c0f1d600d3072634ca66cefdf272f", GitTreeState:"clean", BuildDate:"2021-08-04T18:03:20Z", GoVersion:"go1.16.6", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"22+", GitVersion:"v1.22.16-eks-ffeb93d", GitCommit:"52e500d139bdef42fbc4540c357f0565c7867a81", GitTreeState:"clean", BuildDate:"2022-11-29T18:41:42Z", GoVersion:"go1.16.15", Compiler:"gc", Platform:"linux/amd64"}

 flux install
✚ generating manifests
✔ manifests build completed
► installing components in flux-system namespace

(省略)

◎ verifying installation
✔ helm-controller: deployment ready
✔ kustomize-controller: deployment ready
✔ notification-controller: deployment ready
✔ source-controller: deployment ready
✔ install finished

Demoの実施

まずはDemo用の操作をなぞってみます。このDemoでは、Flamingoのイメージをインストールし、GUIからリソースが確認できるところまで実施します。

※参考: GitHub - Flamingo: Getting Started with a fresh KIND cluster

ここでは以下のマニフェストファイルを使用します。ここでは、Flamingoのインストールに加え、デモ用のアプリケーションも合わせて定義されています。

---
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: OCIRepository
metadata:
  name: fsa-demo
  namespace: flux-system
spec:
  interval: 30s
  url: oci://ghcr.io/flux-subsystem-argo/flamingo/manifests
  ref:
    tag: v2.5
---
apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
kind: Kustomization
metadata:
  name: fsa-demo
  namespace: flux-system
spec:
  prune: true
  interval: 2m
  path: "./demo"
  sourceRef:
    kind: OCIRepository
    name: fsa-demo
  timeout: 3m

上記ファイルをデプロイします。

$ kubectl apply -f fsa-demo.yaml
ocirepository.source.toolkit.fluxcd.io/fsa-demo created
kustomization.kustomize.toolkit.fluxcd.io/fsa-demo created

$ kubectl get ocirepository -n flux-system
NAME       URL                                                    READY   STATUS                                                                                               AGE
fsa-demo   oci://ghcr.io/flux-subsystem-argo/flamingo/manifests   True    stored artifact for digest 'v2.5/b6a0b0e388b930d2f2b0c24e6f794e438e06e3da2142d25baf537655d38c95f4'   12s

$ kubectl get kustomization -n flux-system
NAME       AGE   READY   STATUS
fsa-demo   28s   True    Applied revision: v2.5/b6a0b0e388b930d2f2b0c24e6f794e438e06e3da2142d25baf537655d38c95f4

デプロイ後、ArgoCDが起動していることも確認できます。

$ kubectl get ns
NAME              STATUS   AGE
argocd            Active   34s
default           Active   19m
flux-system       Active   5m50s
kube-node-lease   Active   19m
kube-public       Active   19m
kube-system       Active   19m

$ kubectl get pods -n argocd
NAME                                               READY   STATUS    RESTARTS   AGE
argocd-application-controller-0                    1/1     Running   0          33s
argocd-applicationset-controller-7888c4567-c5p8l   1/1     Running   0          33s
argocd-dex-server-8446698bbb-fpz5g                 1/1     Running   0          33s
argocd-notifications-controller-698d9ff4f5-zp57w   1/1     Running   0          33s
argocd-redis-6d67ff987b-g4pzd                      1/1     Running   0          33s
argocd-repo-server-7f5488d584-2dxl9                1/1     Running   0          33s
argocd-server-86764d6945-ls6m2                     1/1     Running   0          33s

$ kubectl get application -n argocd
NAME               SYNC STATUS   HEALTH STATUS
default-app        Synced        Healthy
fsa-installation   Synced        Healthy

デプロイが完了したので、Flamingo GUIにアクセスします。ここではport-forwardを使いました。

Flamingo GUIにアクセスすると、以下のようにArgoCDのようなGUIを確認できます (このDemoではログイン操作は不要です)。

$ kubectl -n argocd port-forward svc/argocd-server 8080:443
Forwarding from 127.0.0.1:8080 -> 8080
Forwarding from [::1]:8080 -> 8080
Handling connection for 8080
Handling connection for 8080

Terraform Controllerの利用

次に、Terraform Controller (以降 tf-controller) を使用し、Terraformリソースを操作してみます。先ほど使ったDemo用のリソースを先に削除しておきます。tf-controllerは先日投稿したこちらの記事を参考にしてください。

※参考: Flamingo Doc - GitOps Terraform Resources with Argo CD and Flux Subsystem for Argo

$ kubectl delete -f fsa-demo.yaml
ocirepository.source.toolkit.fluxcd.io "fsa-demo" deleted
kustomization.kustomize.toolkit.fluxcd.io "fsa-demo" deleted

次にFlamingoをデプロイします。まずは argocd Namespaceを作成し、その後GitHubに記載されたインストールコマンドを実行します。

$ kubectl create ns argocd
namespace/argocd created

$ kubectl -n argocd apply -k https://github.com/flux-subsystem-argo/flamingo//release?ref=v2.2.8-fl.1-main-305be5e6
customresourcedefinition.apiextensions.k8s.io/applications.argoproj.io created
customresourcedefinition.apiextensions.k8s.io/appprojects.argoproj.io created
serviceaccount/argocd-application-controller created
serviceaccount/argocd-dex-server created
serviceaccount/argocd-redis created
serviceaccount/argocd-server created
role.rbac.authorization.k8s.io/argocd-application-controller created
role.rbac.authorization.k8s.io/argocd-dex-server created
role.rbac.authorization.k8s.io/argocd-server created
clusterrole.rbac.authorization.k8s.io/argocd-application-controller created
clusterrole.rbac.authorization.k8s.io/argocd-server created
rolebinding.rbac.authorization.k8s.io/argocd-application-controller created
rolebinding.rbac.authorization.k8s.io/argocd-dex-server created
rolebinding.rbac.authorization.k8s.io/argocd-redis created
rolebinding.rbac.authorization.k8s.io/argocd-server created
clusterrolebinding.rbac.authorization.k8s.io/argocd-application-controller created
clusterrolebinding.rbac.authorization.k8s.io/argocd-server created
configmap/argocd-cm created
configmap/argocd-cmd-params-cm created
configmap/argocd-gpg-keys-cm created
configmap/argocd-rbac-cm created
configmap/argocd-ssh-known-hosts-cm created
configmap/argocd-tls-certs-cm created
secret/argocd-secret created
service/argocd-dex-server created
service/argocd-metrics created
service/argocd-redis created
service/argocd-repo-server created
service/argocd-server created
service/argocd-server-metrics created
deployment.apps/argocd-dex-server created
deployment.apps/argocd-redis created
deployment.apps/argocd-repo-server created
deployment.apps/argocd-server created
statefulset.apps/argocd-application-controller created
networkpolicy.networking.k8s.io/argocd-application-controller-network-policy created
networkpolicy.networking.k8s.io/argocd-dex-server-network-policy created
networkpolicy.networking.k8s.io/argocd-redis-network-policy created
networkpolicy.networking.k8s.io/argocd-repo-server-network-policy created
networkpolicy.networking.k8s.io/argocd-server-network-policy created

インストール後のリソースを確認します。

$ kubectl get ns
NAME              STATUS   AGE
argocd            Active   5m15s
default           Active   44m
flux-system       Active   30m
kube-node-lease   Active   44m
kube-public       Active   44m
kube-system       Active   44m

$ kubectl get pods -n argocd
NAME                                 READY   STATUS    RESTARTS   AGE
argocd-application-controller-0      1/1     Running   0          3m28s
argocd-dex-server-5489d874b-2fn5j    1/1     Running   0          3m28s
argocd-redis-d486999b7-2h8hr         1/1     Running   0          3m28s
argocd-repo-server-9f4d7498f-sl7ks   1/1     Running   0          3m28s
argocd-server-d58f5c6b6-4rflx        1/1     Running   0          3m28s

# ログインパスワードの確認
$ kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d; echo
MxzAJVkfj5qdcmCn

続いてtf-controllerをインストールします。ここでは以下の Application 定義ファイルを利用し、用意されたtf-controllerマニフェストファイルを使用してインストールします。

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: tf-controller
spec:
  destination:
    namespace: flux-system
    server: 'https://kubernetes.default.svc'
  source:
    repoURL: 'https://weaveworks.github.io/tf-controller'
    targetRevision: 0.9.6
    chart: tf-controller
  project: default
  syncPolicy:
    syncOptions:
      - ApplyOutOfSyncOnly=true
      - FluxSubsystem=true
      - AutoCreateFluxResources=true

上記ファイルをデプロイし、argocd CLIGUIからSyncをかけ、tf-controllerがインストールされたことを確認します。

$ kubectl apply -n argocd -f fsa-tf-controller.yaml
application.argoproj.io/tf-controller created

# Sync後
$ kubectl get application -n argocd
NAME            SYNC STATUS   HEALTH STATUS
tf-controller   Synced        Healthy

# リソースの確認
$ kubectl get helmrelease -n flux-system
NAME            AGE     READY   STATUS
tf-controller   3m40s   True    Release reconciliation succeeded

$ kubectl get helmrepository -n flux-system
NAME            URL                                          AGE   READY   STATUS
tf-controller   https://weaveworks.github.io/tf-controller   4m    True    stored artifact for revision '483cdb04ff510d91707adfeca19a91a4bdf3a19506074195d300ff6866a6fc5b'

$ kubectl get pods -n flux-system
NAME                                       READY   STATUS    RESTARTS   AGE
helm-controller-85b89f8958-7jszl           1/1     Running   0          77m
kustomize-controller-59d6498d5-5tw8h       1/1     Running   0          77m
notification-controller-7cf6f94f46-z9llj   1/1     Running   0          77m
source-controller-b8bf68987-r2bvd          1/1     Running   0          77m
tf-controller-795f76f645-8rk4j             1/1     Running   0          26m

tf-controllerがインストールできたので、tf-controllerの扱う Terraform リソースとGitHubリポジトリを用意します。ここでは あらかじめ用意されているこちらのリポジトリをForkし、必要な箇所を書き換えておきます。書き換えるのはリポジトリ中にある ./infra/setup.yaml ファイル中の以下の箇所です。

---
apiVersion: source.toolkit.fluxcd.io/v1beta1
kind: GitRepository
metadata:
  name: helloworld-tf
spec:
  interval: 1m
  url: https://github.com/flux-subsystem-argo/tf-controller-helloworld  # このURLをFork後のURLに書き換える
  ref:
    branch: main
---
apiVersion: infra.contrib.fluxcd.io/v1alpha1
kind: Terraform

(以降割愛)

次に、上記リポジトリを指定した Application ファイルを用意し、デプロイします。マニフェストファイルは以下の通りです。

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: helloworld
spec:
  destination:
    namespace: dev
    server: 'https://kubernetes.default.svc'
  source:
    path: ./infra
    repoURL: 'https://github.com/<repository name>/tf-controller-helloworld'
    targetRevision: main
  project: default
  syncPolicy:
    syncOptions:
      - CreateNamespace=true
      - ApplyOutOfSyncOnly=true
      - FluxSubsystem=true
      - AutoCreateFluxResources=true
$ kubectl apply -n argocd -f fsa-tf-helloworld.yaml
application.argoproj.io/helloworld created

$ kubectl get app -n argocd
NAME            SYNC STATUS   HEALTH STATUS
helloworld      Synced        Healthy
tf-controller   Synced        Healthy

しばらくすると dev Namespaceが作成され、tf-controllerの管理するtfstate/tfplanなどが確認できます。

$ kubectl get secret -n dev
NAME                              TYPE                                  DATA   AGE
default-token-xvtlk               kubernetes.io/service-account-token   3      51m
helloworld-outputs                Opaque                                1      89s
terraform-runner.tls-1672559922   kubernetes.io/tls                     4      45m
tf-runner-token-zlkwq             kubernetes.io/service-account-token   3      11m
tfplan-default-helloworld-tf      Opaque                                1      89s
tfstate-default-helloworld-tf     Opaque                                1      45m

tfstateファイルや helloworld-outputs から、実行結果を確認することができます。

$ kubectl get secret -n dev tfstate-default-helloworld-tf -ojsonpath='{.data.tfstate}' | base64 -d | gzip -d

{
  "version": 4,
  "terraform_version": "1.3.1",
  "serial": 1,
  "lineage": "133da118-1101-8ef4-00e2-31b527b932f5",
  "outputs": {
    "hello_world": {
      "value": "hey hey ya, tfctl-rc!",
      "type": "string"
    }
  },
  "resources": [],
  "check_results": []
}

$ kubectl -n dev get secret helloworld-outputs -o jsonpath="{.data.hello_world}" | base64 -d; echo
hey hey ya, tfctl-rc!

GUIから見た結果は以下の通りです。