KICを使ってArgoCDを立てる

ArgoCDは[Ingressの説明が充実している](https://argo-cd.readthedocs.io/en/stable/operator-manual/ingress/)が、[Kong Ingress Controller(KIC)](https://docs.konghq.com/kubernetes-ingress-controller/latest/)の説明はなかったので実際に試してみた時のメモ。

## 検証の前提
以下が用意・導入されているものとする。
- helmコマンド
- Kubernetesクラスタ
- KIC
- [cert-manager](https://cert-manager.io/docs/installation/helm/)
- GitHub CLI(`gh`コマンド)

また、証明書については自己署名証明書を使う。
`gh`コマンド部分はコマンドを使わずWebUI等で作業しても問題ない。

## ArgoCDの導入
ArgoCDでTLSを利用する場合、本体自身をTLS化して`Ingress`をTLS Passthroughさせる方法と、`Ingress`をTLSの終端とする方法の2種類がある。
ただし、TLS Passthroughに関してはIngress側が対応している必要がある。
KICの場合、`kind: Gateway`であればTLS Passthroughに対応するが、`Ingress`では[対応していない](https://docs.konghq.com/kubernetes-ingress-controller/latest/guides/services/tls/)。
ArgoCDをHelmで構築する場合は`Ingress`のみ指定可能なので、ここではTLSはIngress終端で進める。

自己署名証明書を発行するためのIssuerを作成する。
```yaml
cat <<EOF | kubectl apply -f -
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: selfsigned-issuer
spec:
  selfSigned: {}
EOF
```
ArgoCDのhelm用values.yamlを作成する。
```yaml
ARGOCD_HOST=argocd.mydomain.com
GRPC_HOST=grpc.$ARGOCD_HOST
cat <<EOF > ./argocd-values.yaml
global:
  domain: $ARGOCD_HOST

configs:
  params:
    server.insecure: true

server:
  ingress:
    enabled: true
    ingressClassName: kong
    hostname: $ARGOCD_HOST
    annotations:
      cert-manager.io/cluster-issuer: selfsigned-issuer
    extraTls:
      - hosts:
        - $ARGOCD_HOST
        secretName: argocd-server-tls
  ingressGrpc:
    enabled: true
    ingressClassName: kong
    hostname: $GRPC_HOST
    annotations:
      cert-manager.io/cluster-issuer: selfsigned-issuer
    extraTls:
      - hosts:
        - $GRPC_HOST
        secretName: grpc-argocd-server-tls
EOF
```
ポイントとしては以下となる。
- IngressでTLSを終端させるため、本体をTLS化させないために`server.insecure: true`を指定
- Ingressは単一のプロトコルしかサポート出来ないため、gRPCとArgoCD本体でIngressを別々に作成する

作り終わったらデプロイする。
```sh
helm upgrade -i argocd argo/argo-cd -n argocd --create-namespace -f ./argocd-values.yaml
```
デプロイが終わると初期パスワードがSecretで作成されているので取得する。
```sh
kubectl get secret -n argocd argocd-initial-admin-secret -o jsonpath={.data.password} | base64 -d
 ```
 ArgoCDのURLの方にアクセスし、Username:`admin`、Password:`取得したパスワード`でアクセスする。
 問題なければ以下のような画面が取得できる。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/3230593c-6a3f-4854-c18a-35092dfabf20.png)

次にgRPC側の確認も行う。
CLIは[ここ](https://argo-cd.readthedocs.io/en/stable/cli_installation/)にインストール方法がある。
ここではMacで進める。
```sh
brew install argocd
```
この後、CLIでArgoCDにアクセスすると以下のような警告が出る。
```sh
$ argocd login $GRPC_HOST --insecure
WARN[0002] Failed to invoke grpc call. Use flag --grpc-web in grpc calls. To avoid this warning message, use flag --grpc-web.
Username:
```
KICでgRPCを使う場合、[ここ](https://docs.konghq.com/kubernetes-ingress-controller/latest/guides/services/grpc/#grpc-over-https)にあるようにServiceのAnnotationでプロトコルの指定が必要なのだが、ArgoCDの`Service`で`konghq.com/protocol: grpc`を指定すると今度はWebUIのアクセスが出来なくなってしまう。
`konghq.com/protocol: grpc,http`と複数指定してもどうもhttpが優先されてしまうようなので、ここではgRPC用に別のServiceを手動で作成する。
```yaml
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
  annotations:
    konghq.com/protocol: grpc
  name: argocd-server-grpc
  namespace: argocd
spec:
  ports:
  - name: https
    port: 443
    targetPort: 8080
  selector:
    app.kubernetes.io/instance: argocd
    app.kubernetes.io/name: argocd-server
EOF
```
なお、TLSはIngressで終端しているので、`grpcs`ではなく`grpc`となる。
作った`Service`に飛ぶよう`Ingress`側も更新する。
```sh
kubectl patch ingress -n argocd argocd-server-grpc --type='json' -p='[{"op": "replace", "path": "/spec/rules/0/http/paths/0/backend/service/name", "value":"argocd-server-grpc"}]'
```
これでアクセスすると警告表示が出なくなる。
```sh
$ argocd login $GRPC_HOST --insecure
Username:
```
問題なければ以下のようにログイン出来る。
```
Username: admin
Password:
'admin:login' logged in successfully
Context 'grpc.argocd.mydomain.com' updated
```

## GitOpsの疎通確認
ここではArgoCDとGitHubを繋いでnginxをクラスタ上にデプロイしてみる。
まずGitHub上に適当なリポジトリを作成してcloneする。
```sh
gh repo create argocd-simple-test --public
gh repo clone argocd-simple-test
```
nginx用のDeploymentのManifestをリポジトリに登録する。
```sh
cd argocd-simple-test
mkdir dev
kubectl create deploy nginx-argocd -r 1 -n default --image nginx --dry-run=client -o yaml > ./dev/nginx-deploy.yaml
git add .
git commit -m "initial commit"
git push origin main
```

次にArgoCDとGitHubを接続する。
ArgoCDのUIで`Settings`->`Repositories`->`CONNECT REPO`から以下のように入力して接続する。
- connection method: `VIA HTTPS`
- Type: `git`
- Project: `default`
- Repository URL: `作成したリポジトリのURL`
問題なければ以下のように`CONNECTION STATUS`が`Successful`となる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/8b993b76-b969-d3c7-5c4f-4370e8340504.png)

次に`Applications`->`NEW APP`からApplication（ArgoCDのプロジェクト管理単位）を作成する。
設定項目は以下の通り。
- Application Name: `nginx`
- Project Name: `default`
- SYNC POLICY: `Manual`
- Repository URL: `登録したリポジトリ`
- Path: `dev`
- Cluster URL: `https://kubernetes.default.svc`

以下を入力し終えたら上の`CREATE`をクリックすると以下のようにApplicationが作成される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/15770396-8c5b-e964-35ee-5b6c0c67dd04.png)

せっかくなのでコマンドでsyncさせてデプロイさせる。
ログインした状態で`argocd app sync <Application名>`でsyncできるのでコマンドを実行する。
```
argocd app sync nginx
```
コマンドを実行するとWebUIの方が`Synced`に変わる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/9e2a3b44-8fd9-0714-d8c5-3308988a010d.png)

デプロイの方も正常に行われている。
```
$ kubectl get pod -n default
NAME                            READY   STATUS    RESTARTS   AGE
nginx-argocd-5797cc5546-cpbk9   1/1     Running   0          84s
```
以上で、KICでもArgoCDが正常に使えることが確認できた。