AlgoCDとsealed-secretsを使ってk8sのシークレット管理をしてみるハンズオン

通常、k8sでsecrets.yamlファイルを定義した場合、Secretのvalueはbase64で、エンコードされるだけで、エンコードされた文字列を知れば、簡単にデコードできてしまう問題がある。エンコード前のvalueを知られない様にするにはどうすればよいか？という問題にぶち当たる。

kubernetes Secrets管理で`sealed-secrets`を利用したシークレット管理についてキャッチアップした内容と手順をまとめておこうと思います。

https://qiita.com/magisystem0408/items/7cf67728756f0f87d1d7

### sealed-secrets

Sealed Secretsでは一言で言うと、SealedSecrets自体をDeployした時に、得られる秘密鍵(と公開鍵)のペアを使用して、シークレット情報を暗号化します。

https://github.com/bitnami-labs/sealed-secrets

より具体的な説明。

![スクリーンショット 2023-05-17 0.58.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466470/dcfc9c6e-930a-d7e9-3f82-776024d74e3f.png)


また、Secret関連だと、AWEのパラメータストアに格納した、Secretを使用したいといった場合ですとExternal-Secret-Operatorなどを使ったりもします。

https://external-secrets.io/v0.8.1/


今回は、AlgoCDとsealed-secretを組み合わせたシークレット管理ハンズオンをしてみたいと思います。


### 下記で使用したハンズオンのリポジトリ

https://github.com/magisystem0408/algocd-sealed-secrets-template


### 今回構築する構成

ArgoCDでGithub-repositoryとgit-syncさせて、argoCD管理下でkubernetesリソースを管理するものとする

![arch.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466470/95a2c30c-d422-e828-84b2-32b92ac6de46.png)


secretの暗号化は、sealed-secretsをdeployした時に作成される、秘密鍵からローカルに公開鍵を落として行うやり方がありますが、key管理嫌なので、keyを作成せずにそのまま`kubeseal`コマンドで、.envファイルをEncriptionします。

![arch_encryption_process.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466470/045d8ce5-fae3-b645-6c10-f4d81c434991.png)


### 実行手順 

#### minikube start

```shell
minikube start
```


#### ArgoCDをDeploy

##### get-startedでDeploy

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


```shell
kubectl create namespace argocd
```

```shell
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
```


##### ArgoCDとGithubをsync

Argocdのdashboardに入るためにシークレットを取得

```shell
kubectl get secret argocd-initial-admin-secret -n argocd -o jsonpath={'.data.password'} | base64 -d
```

ArgocdのDashBoardにアクセスするために、port-forwardで`localhost:8080`にアクセス可能へ
```shell
kubectl port-forward svc/argocd-server -n argocd 8080:443
```

DashBoardへログイン(IDはadmin)してリポジトリをgit-Syncさせる
![スクリーンショット 2023-05-16 23.01.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466470/93f4738f-fcae-cd0b-d45d-0f392058b110.png)

Sync-Done
![スクリーンショット 2023-05-16 23.02.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466470/e97770c1-3a55-71a0-7f30-7dff662204bc.png)

ArgoCD準備完了


#### helmからsealed-secretsのChartをローカルに落とす
##### helmのrepoにAddする

使用するhelmのChart

https://artifacthub.io/packages/helm/bitnami-labs/sealed-secrets


```shell
helm repo add sealed-secrets https://bitnami-labs.github.io/sealed-secrets
```
#### helmのsealed-secretsコードをローカルにpull

格納したのは、`algocd-sealed-secrets-template/services/sealed-secrets`に配置する。

pullしてきたときに、圧縮されてるので、解凍をして上げる。

```shell:services/sealed-secrets/
helm pull sealed-secrets/sealed-secrets
```

ちなみにhelmをローカルに落とすのが手こずったので記事化しました。

https://qiita.com/magisystem0408/items/de884d9aaa286c50c835

pullできたらgithubにpushする。


### Argocd application定義してArgoCDにApply


```yaml:services/argocd/application/sealed-secrets/sealed-secrets.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: sealed-secrets
  namespace: argocd
spec:
  project: default

  source:
    repoURL: git@github.com:magisystem0408/algocd-sealed-secrets-template.git #repositoryのUR
    targetRevision: main #syncさせるbranch指定
    path: services/sealed-secrets/sealed-secrets/ #syncさせるディレクトリ指定

    helm: #helmモードで読み込む合図
      valueFiles:
      - values.yaml
  destination:
    server: https://kubernetes.default.svc
    namespace: sealed-secrets #どこのNamespaceにDeployするかを指定

  # Sync policy
  syncPolicy:
    automated: # automated sync by default retries failed attempts 5 times with following delays between attempts ( 5s, 10s, 20s, 40s, 80s ); retry controlled using `retry` field.
      prune: true # Specifies if resources should be pruned during auto-syncing ( false by default ).
      selfHeal: true # Specifies if partial app sync should be executed when resources are changed only in target Kubernetes cluster and no git change detected ( false by default ).
    syncOptions:     # Sync options which modifies sync behavior
    - Validate=true # disables resource validation (equivalent to 'kubectl apply --validate=true')
    - CreateNamespace=true # Namespace Auto-Creation ensures that namespace specified as the application destination exists in the destination cluster.
    retry:
      limit: 5 less than 0
      backoff:
        duration: 5s # the amount to back off. Default unit is seconds, but could also be a duration (e.g. "2m", "1h")
        factor: 2 # a factor to multiply the base duration after each failed retry
        maxDuration: 3m # the maximum amount of time allowed for the backoff strategy
```

Argocdにapplyする。

```shell:services/argocd/application/sealed-secrets/
kubectl apply -f sealed-secrets.yaml -n argocd
```


展開完了。

![スクリーンショット 2023-05-16 23.40.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466470/53d3f18d-16d0-524a-59c6-2bbe757858f9.png)

![スクリーンショット 2023-05-16 23.42.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466470/72967673-c0af-3528-8cdd-a9ad92da7253.png)



### sealed-secretsでsecretをEncreptionする。

#### kubesealをinstall

```shell
brew install kubeseal
```


#### secretを生成
今回は`.env`に以下の変数を格納する。
```text:/services/sample-app/.env
NEKO=mamushi
```

pemファイルをローカルに落として、そのpemファイルを元にEncryptionすることも可能だが、以下コマンドで、
ローカルに落とさないでEncryptionできる。`/services/sample-app`配下でencryptionして、secret.yamlにする。**注意として、-n sample-appで使用する、namespaceを指定してないと正しく、kubernetesに載せたときにエンコードができないので注意**


```shell:/services/sample-app/
kubeclt create secret generic secret --dry-run=client -n sample-app --from-env-file=.env -o json | kubeseal --controller-name=sealed-secrets --controller-namespace=sealed-secrets --format yaml > secret.yaml
```

.envからsecret.yamlを生成する。
![スクリーンショット 2023-05-17 0.19.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466470/efe02a4d-2d40-e0af-cdfe-c3d6f51decd5.png)



実際に生成されたファイル
```yaml:/services/sample-app/secret.yaml
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
  creationTimestamp: null
  name: secret
  namespace: sample-app
spec:
  encryptedData: #encriptionされたデータ
    NEKO: AgCrMWeBt3z2341++ylBJ2NnRx9PqbIolhLlhSKw/0d6qzgC5RlGiTm43cMbeBo/xyXAIy+ytK8h5lTdFKhuUczNrxEpiX6f+Sy01dDUuL9k2nco5WIcX3ynIZR8bgwFboh+PQMOB5Rlg4sxyngDYkqcjSkGQnjRgjjFdeQuKyY96I0QEM6g373RI3TvFRGoX6hMiXobp3GnDgGKc9ww8adjuYNQ3dhQaIx8skeF67k2/Bx/Olf+3diUU3mldr7vcskWBcygppOUAz+cb7uNvjznY+ePKNZ1ThKkxGFo16l7CpKfN4Ob89N5CtE1FkBTpNtWEV0v1wh+KBCKuZ1+UTWnmddXOaZE3icF7pLVyKGCB7NgKaI5NSHr3Pl5ZFpBBOtiUb4Eteeu57mAHfDkM2DMjrZQoBsSHpehBbaR+6C17/pGpavSNPDELbH12juzeVoUkYD8Zx6luJZIEBHcrNU/4+LXr/5BHQGayu6kKtWkUvkmoOdtiYpuPKIg0mZ+aTFzjkqoRAUjXXIzipU0yhkwjlGj4Z5vfvxyjyIMUFnvUQ5WD+yQg6V10/aBNyCXvunoP9pgGSuQfZwhTt7KNfVhCjnAx+gNY8De9+i7fK7wlYg7TPkmq2DwNuyuwINEQ+N9A9Emd8fvzHEGB4tpOVF8c1SoWKvTLvv3qqI5m+RZ2YYrGplGVOj0bf+ITxZcjqjfaJBp3n5I
  template:
    metadata:
      creationTimestamp: null
      name: secret
      namespace: sample-app
```

実際にencordしても見ることはできない。

![スクリーンショット 2023-05-17 0.21.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466470/42703e37-7100-074c-dd89-78fc59521ede.png)

### deploymentにsecretを生成したものを指定してgithubに上げてArgoCDにapply

#### secretをDeploymentにInjectしてあげる。
```yaml:/services/sample-app/Deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: nginx
  name: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  strategy: {}
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx
        name: nginx
        envFrom:
          - secretRef: #ここでいつものように指定してあげる。
              name: secret
              optional: true
```



#### ArgoCDに読み込ませる様のmanifestsを定義

```yaml:/services/argocd/application/sample-app/sample-app.yaml

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: sample-app
  namespace: argocd
spec:
  project: default

  source:
    repoURL: git@github.com:magisystem0408/algocd-sealed-secrets-template.git
    targetRevision: main
    path: services/sample-app/

  destination:
    server: https://kubernetes.default.svc
    namespace: sample-app

  # Sync policy
  syncPolicy:
    automated: # automated sync by default retries failed attempts 5 times with following delays between attempts ( 5s, 10s, 20s, 40s, 80s ); retry controlled using `retry` field.
      prune: true # Specifies if resources should be pruned during auto-syncing ( false by default ).
      selfHeal: true # Specifies if partial app sync should be executed when resources are changed only in target Kubernetes cluster and no git change detected ( false by default ).
    syncOptions:     # Sync options which modifies sync behavior
      - Validate=true # disables resource validation (equivalent to 'kubectl apply --validate=true')
      - CreateNamespace=true # Namespace Auto-Creation ensures that namespace specified as the application destination exists in the destination cluster.
    # The retry feature is available since v1.7
    retry:
      limit: 5 # number of failed sync attempt retries; unlimited number of attempts if less than 0
      backoff:
        duration: 5s # the amount to back off. Default unit is seconds, but could also be a duration (e.g. "2m", "1h")
        factor: 2 # a factor to multiply the base duration after each failed retry
        maxDuration: 3m # the maximum amount of time allowed for the backoff strategy

```


```shell:services/argocd/application/sample-app/
kubectl apply -f sample-app.yaml
```

ArgoCDのダッシュボードでsecretとdeploymentがapplyされているかを確認

![スクリーンショット 2023-05-17 0.32.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466470/0c12b634-6d55-2f93-bc55-24a9d844da07.png)


![スクリーンショット 2023-05-17 0.33.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466470/2ca7fd1c-e1f0-172c-d1c6-e9cbfa1aeb66.png)


### 試しにDeploymentが生成したpodの中に入って、secretがエンクリプトされているかをチェックする

podを取得

```shell
kubectl get pod -n sample-app
```

環境変数一覧出力

```shell
kubectl exec -it <pod名> -n sample-app -- env
```

![スクリーンショット 2023-05-17 0.37.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466470/ac348170-5ac8-54a1-99ef-7f20a8ab70b8.png)

DONE！

実際には、.envファイルなどはgithubに上げずに、kubesealでencryptionしたもののみをgithubに上げれば、良いです。


### 参考文献

https://www.udemy.com/course/mastering-gitops-with-argo-cd/