ArgoCDをローカルPCでGitリポジトリにssh接続して使う

## はじめに

ArgoCDと連携するGitリポジトリは、GitLabやGitHubなどのWebサービスと連携して利用するのが一般的と思うが、「ちょっとお試しで使ってみたい」場合にWebのGitリモートリポジトリを用意するのが敷居が高かったりする。筆者のようにGitHubを普段利用していないと、自分でGitLabやGitBucketを作る必要が出てきて、PCのリソースもそれなりに使うのが難点だったりする。
そんな人のために本記事では、Webサービスと紐づけない「素のGitリモートリポジトリ」をローカルPC上に作り、sshで接続してArgoCDを使う手順について共有する。

## 前提条件

ローカルPC上で以下ができていること。

* Kubernetesクラスターの構築
* SSHサービス(sshd)が起動している

## 準備

※ArgoCDを使うための一般的手順も含まれており、必要部分だけ拾い読みしていただいても問題ないです。

### (1) ArgoCDのインストール

下記サイトの手順にしたがってインストールする。

https://argo-cd.readthedocs.io/en/stable/getting_started/

最後にArgoCDサーバのポートフォワード設定が必要だが、本記事では以下のコマンドでポート8080で受けつけていることを前提とする。

```
$ kubectl port-forward svc/argocd-server -n argocd 8080:443
```

### (2) ArgoCDサーバからローカルPCにSSH接続するための設定

ローカルPCに作るGitリポジトリに、ArgoCDサーバーからsshで接続するための秘密鍵／公開鍵のペアを作成する。以後の手順で、作成した公開鍵はローカルPCのauthorized_keysに追加し、秘密鍵はArgoCDサーバに登録する。

* ssh鍵の作成
  ```
  $ ssh-keygen -t rsa -f id_rsa_argocd
  ```

* 作成された鍵の確認
  ```
  $ ls | tr ' ' '\n' | grep id_rsa_argocd
  id_rsa_argocd     # 秘密鍵
  id_rsa_argocd.pub # 公開鍵
  ```

* 公開鍵をauthorized_keys に追加
  ```
  $ cat id_rsa_argocd.pub >> ~/.ssh/authorized_keys
  ```

### (3) Gitリポジトリの作成

* リモートリポジトリを適当な場所に作成
  * 一般的なArgoCDの使い方だと、GitLabなどのWebのGitリポジトリに相当する部分
  ```
  $ mkdir argocd-test.git
  $ cd argocd-test.git
  $ git init --bare
  ```

* ローカルリポジトリを適当な場所に作成
  * ここにArgoCDでCDするk8sマニフェストを作成して、後でリモートリポジトリにPushする

  ```
  $ mkdir argocd-test
  $ cd argocd-test
  $ git init
  ```

  * ローカルリポジトリとリモートリポジトリを次のコマンドで連携
    * ``[username]``、``[hostname]``はローカルPCのユーザ名とホスト名(IPアドレス等)を入れる

  ```
  $ git remote add origin [username]@[hostname]:/[path-to-repos]/argocd-test.git
  ```

### (4) 適当なマニフェストを準備してGitリモートにPush

下記は一例なので、ご自由に作っていただいて差し支えない。
```yaml:sample.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-dep
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.16
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
spec:
  selector:
    app: nginx
  ports:
    - name: http
      port: 8080
      targetPort: 80
```

* マニフェストをGitリモートにPush
  ```
  $ git add sample.yaml
  $ git commit -m "add"
  $ git push origin main(またはmaster)
  ```

## ArgoCDにGitリポジトリをssh接続で登録

ここからが本題の部分。
ArgoCDのApplicationリソース作成とは別で、Gitリポジトリにssh接続するための設定を行う必要がある。以下に手順を示す。

### (1) sshで接続するための情報をArgoCDサーバに追加

追加する方法として、以下のように「ArgoCDのCLIを使う方法」と「Secretリソースのマニフェストを登録する方法」の２通りがある。
いずれのケースでも、準備の手順(2)で作成したssh接続用の秘密鍵が必要なことにご注意を。

#### 方法1-1 : ArgoCDのCLIで設定する方法

* ログイン用のパスワード情報を取得

  ```
  $ kubectl -n argocd get secret \
  argocd-initial-admin-secret -o jsonpath="{.data.password}" \
  | base64 -d
  (ログイン用のパスワードが出力される)
  ```

* ログイン
  * WARNINGが表示されたら ``y`` と入力
  * ポート8080は準備の手順(1)のポートフォワードで設定した値にする

  ```
  $ argocd login localhost:8080
  Username: admin # ← 入力
  Password: (前コマンドで出力されたパスワードをここに入力)
  'admin:login' logged in successfully
  ```

* リポジトリ情報の追加
  * sshのパスは以下の形式で記入可能
    * ``ssh://[username]@[hostname]/[path-to-repos]/argocd-test.git``
    * ``[username]@[hostname]:/[path-to-repos]/argocd-test.git``
  * ``[hostname]``はローカルPCのIPアドレスなどでOK
  * ``--ssh-private-key-path``は準備の手順(2)で作成した秘密鍵ファイルを指定

  ```
  $ argocd repo add \
  ssh://[username]@[hostname]/[path-to-repos]/argocd-test.git \
  --ssh-private-key-path [path-to-key]/id_rsa_argocd \
  --insecure-ignore-host-key
  (以下出力)
  Repository 'ssh://[username]@[hostname]/[path-to-repos]/argocd-test.git' added
  ```

* 作成されたリポジトリの確認

  ```
  $ argocd repo list
  TYPE  NAME  REPO                                                         INSECURE  OCI    LFS    CREDS  STATUS      MESSAGE  PROJECT
  git         ssh://[username]@[hostname]/[path-to-repos]/argocd-test.git  true      false  false  false  Successful
  ```

#### 方法1-2 : マニフェストで設定する方法

* ``labels``に``argocd.argoproj.io/secret-type: repository``の設定が必要
* ``stringData``にリポジトリのURLやssh秘密鍵などを記載する

```yaml:secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: private-repo
  namespace: argocd
  labels:
    argocd.argoproj.io/secret-type: repository
stringData:
  type: git
  url: "ssh://[username]@[hostname]/[path-to-repos]/argocd-test.git"
  insecureIgnoreHostKey: "true"
  sshPrivateKey: |
    -----BEGIN OPENSSH PRIVATE KEY-----
    (秘密鍵id_rsa_argocdの中身をここにコピペする)
    -----END OPENSSH PRIVATE KEY-----
```

* Secretリソースをapply

  ```
  $ kubectl apply -f secret.yaml
  ```
:::note info
作成されたリポジトリは方法1-1と同様に、``argocd repo list``などで確認可能
:::

### (2) Applicationマニフェストの作成

* ArgoCDのアプリケーションをデプロイするためのマニフェストを作成する。
  * ``repoURL``がhttpsではなく、にssh接続するURLになっているところがポイント。

```yaml:application.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: argocd-test
  namespace: argocd
spec:
  project: default
  source:
    repoURL: "ssh://[username]@[hostname]/[path-to-repos]/argocd-test.git"
    path: "."
    targetRevision: HEAD
  destination:
    server: https://kubernetes.default.svc
    namespace: default
  syncPolicy:
    automated: {}
```

* Applicationリソース（ArgoCDのリソース）をapply

  ```
  $ kubectl apply -f application.yaml
  ```

* 動作確認

  ```
  $ argocd app list
  NAME                CLUSTER                         NAMESPACE  PROJECT  STATUS  HEALTH   SYNCPOLICY  CONDITIONS  REPO                                                         PATH  TARGET
  argocd/argocd-test  https://kubernetes.default.svc  default    default  Synced  Healthy  Auto        <none>      ssh://[username]@[hostname]/[path-to-repos]/argocd-test.git  .     HEAD
  ```

  ```
  $ kubectl get all -n default
  NAME                             READY   STATUS    RESTARTS   AGE
  pod/nginx-dep-5fbd7c9987-z6r42   1/1     Running   0          2m31s
  pod/nginx-dep-5fbd7c9987-tfz7s   1/1     Running   0          2m31s
  pod/nginx-dep-5fbd7c9987-zfvpw   1/1     Running   0          2m31s
  
  NAME                 TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)    AGE
  service/kubernetes   ClusterIP   10.43.0.1     <none>        443/TCP    15d
  service/nginx-svc    ClusterIP   10.43.3.179   <none>        8080/TCP   2m31s
  
  NAME                        READY   UP-TO-DATE   AVAILABLE   AGE
  deployment.apps/nginx-dep   3/3     3            3           2m31s
  
  NAME                                   DESIRED   CURRENT   READY   AGE
  replicaset.apps/nginx-dep-5fbd7c9987   3         3         3       2m31s
  ```

* 作成したアプリケーションの削除
  ```
  $ argocd app delete argocd/argocd-test
  Are you sure you want to delete 'argocd/argocd-test' and all its resources? [y/n] # 'y'と入力
  application 'argocd/argocd-test' deleted
  ```
:::note warn
``kubectl delete -f application.yaml``だとApplicationリソースのみが削除され、
PodやServiceなどの実体は消えずに残ってしまうようなので注意！
:::

## 参考にしたサイト

* ArgoCDのCLIでssh接続用のリポジトリを登録する方法

https://argo-cd.readthedocs.io/en/stable/user-guide/private-repositories/#ssh-private-key-credential

* マニフェストでssh接続用のリポジトリを登録する方法

https://argo-cd.readthedocs.io/en/stable/operator-manual/declarative-setup/#repositories