secretgen-controllerのSecretExport、SecretImportを使ってNamespace間でSecretを共有する

# secretgen-controllerとは
[secretgen-controller](https://github.com/vmware-tanzu/carvel-secretgen-controller)とはKubernetesの便利ツールを公開しまくっている[Carvel](https://carvel.dev/)が公開しているOSSで、SecretリソースをNamespaceを横断して参照できるようにするものだ。\
[ExternalSecret](https://external-secrets.io/)とも似ているところがあるが、こちらは完全にKubernetesに閉じたSecretマネージャーとなる。

# SecretExport、SecretImportとは
`SecretExport`、`SecretImport`はそれぞれsecretgen-controllerが提供するカスタムリソースで、このリソースを作成することでNamespace間のSecretの共有が可能となる。\
`SecretExport`で公開したいSecretと公開先を指定し、`SecretImport`で実際にNamespaceにSecretを取り込む。\
さっそく使ってみたいと思う。

## secretgen-controllerのインストール
最近のTanzu Kubernetes GridやTanzu Community Editionを使っている人は最初から入っているのでインストール不要。\
それ以外の人は[ここ](https://github.com/vmware-tanzu/carvel-secretgen-controller/blob/develop/docs/install.md)を参考にインストールする。\
Carvelのkappを使っている人は
```
kapp deploy -a sg -f https://github.com/vmware-tanzu/carvel-secretgen-controller/releases/latest/download/release.yml
```
それ以外の人は
```
kubectl apply -f https://github.com/vmware-tanzu/carvel-secretgen-controller/releases/latest/download/release.yml
```
でインストール出来ると思う。

## 検証

最初に検証用のSecretを適当に作成する。
```
kubectl create secret docker-registry my-synced-secret --docker-password "bar" --docker-username foo --docker-server myharbor.info --dry-run=client -o yaml > ./secret.yaml
kubectl apply -f ./secret.yaml
```

続いて、`SecretExport`を作成する。
```yaml
cat << EOF > ./secret-export.yaml
apiVersion: secretgen.carvel.dev/v1alpha1
kind: SecretExport
metadata:
  name: my-synced-secret
spec:
  toNamespace: "*"
EOF
kubectl apply -f ./secret-export.yaml
```
公開先Namespaceを`toNamespace`で指定する（複数指定する場合は`toNamespaces`を使う）。\
今回は全方向に公開するガバ設定で試す。

次に公開先のNamespaceを作成する。
```
kubectl create ns delme
```
この時点では共有されない。
```
$ kubectl get secret -n delme
NAME                  TYPE                                  DATA   AGE
default-token-b2jtd   kubernetes.io/service-account-token   3      2s
```
共有するためには、`SecretImport`を作成する必要があるため、作成する。
```yaml
cat << EOF > ./secret-import.yaml
apiVersion: secretgen.carvel.dev/v1alpha1
kind: SecretImport
metadata:
  name: my-synced-secret
spec:
  fromNamespace: default
EOF
kubectl apply -f ./secret-import.yaml -n delme
```
defaultのNamespaceに作った、`my-synced-secret`がdelmeのNamespaceにImportされた。
```
$ kubectl get secret -n delme
NAME                  TYPE                                  DATA   AGE
default-token-b2jtd   kubernetes.io/service-account-token   3      46s
my-synced-secret      kubernetes.io/dockerconfigjson        1      6s
$ kubectl view-secret my-synced-secret -n delme
Choosing key: .dockerconfigjson
{"auths":{"myharbor.info":{"username":"foo","password":"bar","auth":"Zm9vOmJhcmJvcg=="}}}
```
※確認にはkubectl pluginのview-secretを利用している\
ここで、Secretを書き換えて、passwordを`bar`から`barbor`に変更する。
```
kubectl create secret docker-registry my-synced-secret --docker-password "barbor" --docker-username foo --docker-server myharbor.info --dry-run=client -o yaml > ./secret-edit.yaml
kubectl replace -f ./secret.yaml
```
delmeの方にも反映されていることが分かる。
```
$ kubectl view-secret my-synced-secret -n delme
Choosing key: .dockerconfigjson
{"auths":{"myharbor.info":{"username":"foo","password":"barbor","auth":"Zm9vOmJhcmJvcg=="}}}
```
なお、このSecretはdelme側から書き換えることは出来ない。
先程保存していた最初のSecretをdelme側で当ててみた結果がこちら。
```
$ kubectl replace -f secret.yaml  -n delme
secret/my-synced-secret replaced
$ kubectl view-secret my-synced-secret -n delme
Choosing key: .dockerconfigjson
{"auths":{"myharbor.info":{"username":"foo","password":"barbor","auth":"Zm9vOmJhcmJvcg=="}}}
```
書き換わっていないことが分かる。\
このようにSecretを中央集権的にバラまきたい時には`SecretExport`、`SecretImport`はオススメである。