---
title: Bitnami Helm ChartでArgo CDをインストール及びArgo CDでyttを使用するメモ
tags: ["Kubernetes", "Argo CD", "Bitnami", "ytt", "Helm", "GitOps", "Carvle"]
categories: ["Dev", "CaaS", "Kubernetes", "ArgoCD"]
date: 2021-08-10T08:33:42Z
updated: 2021-08-18T16:39:46Z
---

[BitnamiのHelm Chart](https://github.com/bitnami/charts) の [Argo CD](https://argoproj.github.io/argo-cd/) をインストールするメモ。併せてArgo CDで [ytt](https://carvel.dev/ytt/) を使う設定も行います。


**目次**
<!-- toc -->

### Kindクラスタの作成

Kindでk8sクラスタを作成します。Ingress用に80, 443ポートをexposeする設定を行います。

```
curl -sL https://github.com/projectcontour/contour/raw/main/examples/kind/kind-expose-port.yaml > kind-expose-port.yaml
kind create cluster --config kind-expose-port.yaml 
```

### Contourのインストール

Ingressとして [Contour](https://projectcontour.io) を使用します。

```
kubectl apply -f https://projectcontour.io/quickstart/contour.yaml
```


### Argo CDのインストール

使用するHelmのバージョンは次の通りです。

```
$ helm version                                                         
version.BuildInfo{Version:"v3.6.3", GitCommit:"d506314abfb5d21419df8c7e7e68012379db2354", GitTreeState:"dirty", GoVersion:"go1.16.5"}
```

`helm install`でインストールする方法と`helm template` + `kapp`でインストールする方法を説明します。

BitnamiのChartレポジトリを追加します。

```
helm repo add bitnami https://charts.bitnami.com/bitnami
```

次のバージョンのChartをインストールします。

```
$ helm search repo argo-cd
NAME            CHART VERSION   APP VERSION     DESCRIPTION                                       
bitnami/argo-cd 1.0.1           2.0.5           Declarative, GitOps continuous delivery tool fo...
```


#### helm installでインストール

Argo CDで使用するホスト名を設定します。`ARGO_CD_HOSTNAME`はWebブラウザ用、`ARGO_CD_GRPC_HOSTNAME`は`argocd` CLI用です。

```bash
export ARGO_CD_HOSTNAME=argo-cd.localhost.ik.am
export ARGO_CD_GRPC_HOSTNAME=grpc.argo-cd.localhost.ik.am
```

> `*.localhost.ik.am`は`127.0.0.1`に解決されます。KindにArgo CDをインストールする場合は、このドメインを使用できます。

次のコマンドで`helm install`に渡す設定値を生成します。

```yaml
cat <<EOF > values.yaml
server:
  service:
    annotations:
      projectcontour.io/upstream-protocol.h2c: https,443 
  ingress:
    enabled: true
    hostname: ${ARGO_CD_HOSTNAME}
    tls: false
    selfSigned: true
    extraTls:
    - hosts:
      - ${ARGO_CD_HOSTNAME}
      secretName: ${ARGO_CD_HOSTNAME}-tls
  ingressGrpc:
    enabled: true
    hostname: ${ARGO_CD_GRPC_HOSTNAME}
    tls: true
    selfSigned: true    
  insecure: true
  config: |
    configManagementPlugins: |-
      - name: bash
        generate:
          command:
          - /bin/bash
          args:
          - -ce    
          - ./generate
redis:
  replica:
    replicaCount: 1
EOF
```

> `configManagementPlugins`に、Argo CDがKubernetesにデプロイするマニフェストを`generate`というファイル名の任意のBASHスクリプトで生成できるbashプラグインを設定しています。汎用的に使えて便利です。<br>

次のコマンドでArgo CDをインストールします。

```
export TZ=UTC
helm install argo-cd --create-namespace -n argo-cd bitnami/argo-cd --values values.yaml --wait
```

> ⚠️ `helm install`実行時のタイムゾーンをUTCにしないと、正しい認証情報でログインしようとしても生成される`admin.passwordMtime`のタイムゾーンがずれ、 `invalid session: Account password has changed since token issued` というエラーメッセージが出力されました。 <br>
> https://github.com/argoproj/argo-cd/issues/4177 と同じ現象です。

インストールが完了後、作成されたリソースを次のコマンドで確認できます。

```
$ kubectl get all,secret,cm,ingress -n argo-cd
NAME                                          READY   STATUS    RESTARTS   AGE
pod/argo-cd-app-controller-6b58c49d7f-nqstq   1/1     Running   0          78s
pod/argo-cd-redis-master-0                    1/1     Running   0          78s
pod/argo-cd-redis-replicas-0                  1/1     Running   0          78s
pod/argo-cd-repo-server-687c9d5446-p7jpm      1/1     Running   0          78s
pod/argo-cd-server-84d568b4c7-9v5tr           1/1     Running   0          78s

NAME                             TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
service/argo-cd-app-controller   ClusterIP   10.96.166.20    <none>        8082/TCP         78s
service/argo-cd-redis-headless   ClusterIP   None            <none>        6379/TCP         78s
service/argo-cd-redis-master     ClusterIP   10.96.186.201   <none>        6379/TCP         78s
service/argo-cd-redis-replicas   ClusterIP   10.96.25.86     <none>        6379/TCP         78s
service/argo-cd-repo-server      ClusterIP   10.96.188.128   <none>        8081/TCP         78s
service/argo-cd-server           ClusterIP   10.96.205.121   <none>        80/TCP,443/TCP   78s

NAME                                     READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/argo-cd-app-controller   1/1     1            1           78s
deployment.apps/argo-cd-repo-server      1/1     1            1           78s
deployment.apps/argo-cd-server           1/1     1            1           78s

NAME                                                DESIRED   CURRENT   READY   AGE
replicaset.apps/argo-cd-app-controller-6b58c49d7f   1         1         1       78s
replicaset.apps/argo-cd-repo-server-687c9d5446      1         1         1       78s
replicaset.apps/argo-cd-server-84d568b4c7           1         1         1       78s

NAME                                      READY   AGE
statefulset.apps/argo-cd-redis-master     1/1     78s
statefulset.apps/argo-cd-redis-replicas   1/1     78s

NAME                                               TYPE                                  DATA   AGE
secret/argo-cd-argocd-app-controller-token-7xtcd   kubernetes.io/service-account-token   3      78s
secret/argo-cd-argocd-repo-server-token-4v6kn      kubernetes.io/service-account-token   3      78s
secret/argo-cd-argocd-server-token-vtp4q           kubernetes.io/service-account-token   3      78s
secret/argo-cd-redis                               Opaque                                1      78s
secret/argo-cd-redis-token-tlnlt                   kubernetes.io/service-account-token   3      78s
secret/argo-cd.localhost.ik.am-tls                 kubernetes.io/tls                     3      78s
secret/argocd-secret                               Opaque                                4      78s
secret/default-token-zptxj                         kubernetes.io/service-account-token   3      78s
secret/grpc.argo-cd.localhost.ik.am-tls            kubernetes.io/tls                     3      78s
secret/sh.helm.release.v1.argo-cd.v1               helm.sh/release.v1                    1      78s

NAME                                    DATA   AGE
configmap/argo-cd-redis-configuration   3      78s
configmap/argo-cd-redis-health          6      78s
configmap/argo-cd-redis-scripts         2      78s
configmap/argocd-cm                     1      78s
configmap/argocd-ssh-known-hosts-cm     1      78s
configmap/kube-root-ca.crt              1      78s

NAME                                            CLASS    HOSTS                          ADDRESS   PORTS     AGE
ingress.networking.k8s.io/argo-cd-server        <none>   argo-cd.localhost.ik.am                  80, 443   78s
ingress.networking.k8s.io/argo-cd-server-grpc   <none>   grpc.argo-cd.localhost.ik.am             80, 443   78s
```


`https://${ARGO_CD_HOSTNAME}`にアクセスします。自己署名証明書を使用しているので、Chromeの場合はブラウザに"thisisunsafe"を入力して進んでください。

![image](https://user-images.githubusercontent.com/106908/128816659-0775e1d4-705c-4e0c-93f6-a9c5b93782db.png)

ユーザー名はadmin、パスワードは次のコマンドで取得できます。

```
kubectl -n argo-cd get secret argocd-secret -o template="{{.data.clearPassword | base64decode}}"
```

![image](https://user-images.githubusercontent.com/106908/128816707-d8f53672-fc29-4306-b546-93ca3108121a.png)

`helm install`コマンドでパスワードやTLS証明書が自動生成されています。この状態で`helm upgrade`を実行すると、再生成が行われ、アプリケーションが壊れる可能性があるので、
次のコマンドで生成された値を`values.yaml`に反映し、`helm upgrade`で再生性が行われないようにします。

```yaml
cat <<EOF > values.yaml
server:
  service:
    annotations:
      projectcontour.io/upstream-protocol.h2c: https,443
  ingress:
    enabled: true
    hostname: ${ARGO_CD_HOSTNAME}
    tls: false
    selfSigned: false
    extraTls:
    - hosts:
      - ${ARGO_CD_HOSTNAME}
      secretName: ${ARGO_CD_HOSTNAME}-tls    
    secrets:
    - name: $(kubectl get secret -n argo-cd --field-selector type=kubernetes.io/tls -o template='{{(index (index (index .items 0) "metadata") "name")}}')
      certificate: |
$(kubectl get secret -n argo-cd --field-selector type=kubernetes.io/tls -o template='{{index (index (index .items 0) "data") "tls.crt" | base64decode}}' | sed 's/^/        /g')      
      key: |
$(kubectl get secret -n argo-cd --field-selector type=kubernetes.io/tls -o template='{{index (index (index .items 0) "data") "tls.key" | base64decode}}' | sed 's/^/        /g')
  ingressGrpc:
    enabled: true
    hostname: ${ARGO_CD_GRPC_HOSTNAME}
    tls: true
    selfSigned: false
    secrets:
    - name: $(kubectl get secret -n argo-cd --field-selector type=kubernetes.io/tls -o template='{{(index (index (index .items 1) "metadata") "name")}}')
      certificate: |
$(kubectl get secret -n argo-cd --field-selector type=kubernetes.io/tls -o template='{{index (index (index .items 1) "data") "tls.crt" | base64decode}}' | sed 's/^/        /g')      
      key: |
$(kubectl get secret -n argo-cd --field-selector type=kubernetes.io/tls -o template='{{index (index (index .items 1) "data") "tls.key" | base64decode}}' | sed 's/^/        /g')
  insecure: true
  config: |
    configManagementPlugins: |-
      - name: bash
        generate:
          command:
          - /bin/bash
          args:
          - -ce    
          - ./generate
redis:
  replica:
    replicaCount: 1
  auth:
    password: $(kubectl get secret -n argo-cd argo-cd-redis -otemplate='{{index .data "redis-password" | base64decode}}')
config:
  secret:
    argocdServerAdminPassword: $(kubectl get secret -n argo-cd argocd-secret -otemplate='{{index .data "clearPassword" | base64decode}}')
    argocdServerAdminPasswordMtime: $(kubectl get secret -n argo-cd argocd-secret -otemplate='{{index .data "admin.passwordMtime" | base64decode}}')
    extra:
      server.secretkey: $(kubectl get secret -n argo-cd argocd-secret -otemplate='{{index .data "server.secretkey" | base64decode}}')
EOF
```

次のコマンドで`helm upgrade`を実行します。

```
helm upgrade argo-cd -n argo-cd bitnami/argo-cd --values values.yaml --wait
```

> パスワード自体は変わっていませんが、Redisクラスタの再作成が行われます。

ブラウザをReloadしても同じ画面が表示されることを確認してください。


Argo CDをアンインストールしたい場合は次のコマンドを実行してください。
```
helm uninstall -n argo-cd argo-cd
```

#### helm template + kappでインストール

`helm install`でインストールするよりも`helm template`で生成したマニフェストを`kapp`でインストールした方が
作成されるリソースが分かりやすいのとアップデート時に変更の差分を確認できてメンテナンスしやすいです。

`helm install`の代わりに`helm template`でマニフェストを生成する場合は次のコマンドを実行します。`values.yaml`と`./post-render.sh`の生成方法は上記の通りです。

```
export TZ=UTC
helm template argo-cd --create-namespace --include-crds -n argo-cd bitnami/argo-cd --values values.yaml > argo-cd.yaml
```

このマニフェストを`kapp`でデプロイする場合は次のコマンドを実行してください。

```
kubectl create ns argo-cd
kapp deploy -a argo-cd -f argo-cd.yaml -c --diff-mask=false
```

Argo CDをアンインストールしたい場合は次のコマンドを実行してください。

```
kapp delete -a argo-cd --apply-ignored=true
```

### Argo CDでCarvel(ytt)を使用できるようにする

Argo CDはKusomize、Helm、Jsonnetを直接サポートしていますが、yttはサポートされていません。
上記のインストールでbashプラグインを設定したので、`generate`スクリプト内でyttを使ってmanifestを作成すれば良いです。

そのために、`generate`スクリプトを実行するrepo-serverにyttをインストールする必要があります。
ドキュメントは [こちら](https://argoproj.github.io/argo-cd/operator-manual/custom_tools/)。

`values.yaml`に次の設定を追記して、repo-serverにCarvelをインストールします。

```yaml
cat <<'EOF' >> values.yaml
repoServer:
  extraVolumes:
  - name: carvel
    emptyDir: {}
  initContainers:
  - name: install-carvel
    image: docker.io/k14s/image
    command:
    - bash
    - -ce
    args:
    - |
      mv `which ytt` ${K14SIO_INSTALL_BIN_DIR}
      mv `which kapp` ${K14SIO_INSTALL_BIN_DIR}
      mv `which kbld` ${K14SIO_INSTALL_BIN_DIR}
      mv `which kwt` ${K14SIO_INSTALL_BIN_DIR}
      mv `which imgpkg` ${K14SIO_INSTALL_BIN_DIR}
      mv `which vendir` ${K14SIO_INSTALL_BIN_DIR}
      # or if you want to install the latest carvel tools
      # wget -O- https://carvel.dev/install.sh | bash
    env:
    - name: K14SIO_INSTALL_BIN_DIR
      value: /carvel
    volumeMounts:
    - mountPath: /carvel
      name: carvel
  extraVolumeMounts:
  - mountPath: /usr/local/bin/ytt
    name: carvel
    subPath: ytt
  - mountPath: /usr/local/bin/kapp
    name: carvel
    subPath: kapp
  - mountPath: /usr/local/bin/kbld
    name: carvel
    subPath: kbld
  - mountPath: /usr/local/bin/kwt
    name: carvel
    subPath: kwt
  - mountPath: /usr/local/bin/imgpkg
    name: carvel
    subPath: imgpkg
  - mountPath: /usr/local/bin/vendir
    name: carvel
    subPath: vendir  
EOF
```

`helm install`でArgo CDをインストールした場合は次のコマンドでアップデートしてください。

```
helm upgrade argo-cd -n argo-cd bitnami/argo-cd --values values.yaml --wait
```

`helm template` + `kapp`でArgo CDをインストールした場合は次のコマンドでアップデートしてください。

```
kapp deploy -a argo-cd -f argo-cd.yaml -c --diff-mask=false
```

アップデートが完了したら次のコマンドを実行してrepo-serverにCarvelがインストールされていることを確認してください。

```
$ kubectl exec -ti -n argo-cd $(kubectl get pod -n argo-cd -l app.kubernetes.io/component=repo-server -o jsonpath='{.items[0].metadata.name}') -- bash -c "find /usr/local/bin -type f -exec {} version \;"

imgpkg version 0.11.0

Succeeded
kbld version 0.30.0

Succeeded
ytt version 0.34.0
vendir version 0.16.0

Succeeded
Client Version: 0.0.6

Succeeded
kapp version 0.37.0

Succeeded
```

### Applicationの作成

インストールしたArgo CDを使ってApplicationを作成します。ここからはCLIを使います。
CLIは次のコマンドでインストールできます。

```
brew install argocd
```

次のバージョンを使用しました。

```
$ argocd version --client
argocd: v2.0.5+4c94d88.dirty
  BuildDate: 2021-07-23T05:09:14Z
  GitCommit: 4c94d886f56bcb2f9d5b3251fdc049c2d1354b88
  GitTreeState: dirty
  GoVersion: go1.16.6
  Compiler: gc
  Platform: darwin/amd64
```

次のコマンドでArgo CDへログインします。gRPCのIngressを経由します。


```
argocd login ${ARGO_CD_GRPC_HOSTNAME} --insecure --username admin --password $(kubectl get secret -n argo-cd argocd-secret -otemplate='{{index .data "clearPassword" | base64decode}}') 
```

Dev用のApplicationを作成します

```
# Dev
argocd app create hello-tanzu-dev \
--repo https://github.com/making/argo-cd-gitops-demo.git \
--path dev \
--config-management-plugin bash \
--dest-server https://kubernetes.default.svc \
--sync-policy automated \
--auto-prune
```

Prod用のApplicationも作成します。

```
# Prod
argocd app create hello-tanzu-prod \
--repo https://github.com/making/argo-cd-gitops-demo.git \
--path prod \
--config-management-plugin bash \
--dest-server https://kubernetes.default.svc \
--sync-policy automated \
--auto-prune
```

Dashboardには次のように表示されます。

> APP HEALTHが"Progressing"になっているのはArgo CDが中からIngress(`*.localhost.ik.am` = `127.0.0.1`)にアクセスできないからだと思います。Kind以外では問題ないはずです。

![image](https://user-images.githubusercontent.com/106908/128818086-171b4f36-aac6-4fe2-8b62-74f8be2cacf2.png)

![image](https://user-images.githubusercontent.com/106908/128818099-7fe2fc1d-d734-4521-b75c-8f115b9ccd76.png)

![image](https://user-images.githubusercontent.com/106908/128818113-71f23b83-f984-4da4-b37d-ae0471ee9ff3.png)

実際にアプリケーションにアクセスします。

* Dev: http://argo-cd.localhost.ik.am
* Prod: http://argo-cd.dev.localhost.ik.am

![image](https://user-images.githubusercontent.com/106908/128818128-3bb0d64c-d536-472a-9fa7-8167ee1c00d4.png)

yttを使用しているのでDev/Prodそれぞれに対してoverlayを用意することが可能です。
