[k8s] Secrets について確認したときのメモ

以下あたりを見つつ確認したときのメモ

[Kubernetes完全ガイド](https://www.amazon.co.jp/Kubernetes%E5%AE%8C%E5%85%A8%E3%82%AC%E3%82%A4%E3%83%89-impress-top-gear-%E9%9D%92%E5%B1%B1/dp/4295004804)

[Secrets](https://kubernetes.io/docs/concepts/configuration/secret/)

[Secret](https://cloud.google.com/kubernetes-engine/docs/concepts/secret?hl=ja)

# Secrets って何

[Secret](https://cloud.google.com/kubernetes-engine/docs/concepts/secret?hl=ja)

>Secret は、パスワード、OAuth トークン、SSH 認証鍵などの機密データをクラスタに格納する安全なオブジェクトです。機密データを Secret に保存することは、平文の ConfigMap や Pod 仕様よりも安全です。Secret を使用すると、機密データの使用方法を制御できるようになり、権限のないユーザーにデータが公開されるリスクを軽減できます。

Pod に環境情報設定する場合、ConfigMap も利用できるがこちらの場合、平文なのでパスワードなどの場合には Secrets の方が安全となる。

# Secrets を作ってみる

`kubectl create secret type name data` という形式で Secrets が作成できる。
Type については以下の種類がある。

+ generic:ローカル ファイル、ディレクトリ、またはリテラル値から Secret を作成する
+ docker-registry:Docker レジストリで使う認証に利用
+ tls:指定された公開鍵/秘密鍵のペアから TLS Secret を作成
+ service account:Pod にサービスのトークンをマウントする際などに利用

多くの用途では `generic` を使う。

作成方法はいくつかある

+ kubectl でファイルから値を参照して作成(--from-file)
+ kubectl で envfile から値を参照して作成(--from-env-file)
+ kubectl で直接値を渡して作成(--from-literal)
+ マニュフェストファイルから作成

さくっと直接値を渡して作ってみる。

```bash
# Secrets を直接値を渡して作成
$kubectl create secret generic dev-db-secret --from-literal=username=devuser --from-literal=password='password'

# 取得。Type は Generic を指定したので Opaque となっている。データとして2つ設定しているのが分かる
$ k get secrets dev-db-secret
NAME            TYPE     DATA   AGE
dev-db-secret   Opaque   2      20s

# Base64 エンコードされているので値が直接は分からない
$k get secrets dev-db-secret -o yaml
apiVersion: v1
data:
  password: cGFzc3dvcmQ=
  username: ZGV2dXNlcg==
kind: Secret
metadata:
  creationTimestamp: "2020-06-06T21:46:25Z"
  name: dev-db-secret
  namespace: default
  resourceVersion: "2966637"
  selfLink: /api/v1/namespaces/default/secrets/dev-db-secret
  uid: 2b9b8a8e-a83f-11ea-80d8-0aafc37fdac4
type: Opaque

# Base64 デコードすることで値を確認できる
$k get secrets dev-db-secret -o json | jq -r .data.username | base64 --decode
devuser%

$k get secrets dev-db-secret -o json | jq -r .data.password | base64 --decode
password%
```

なお、マニュフェストファイルから Secrets を作る場合には予め Base64 エンコードした値を YAML に記述する必要あり

[Creating a Secret manually](https://kubernetes.io/docs/concepts/configuration/secret/#creating-a-secret-manually)

>The data field is used to store arbitrary data, encoded using base64

# Secrets の情報を Pod で取得する(環境変数)

[Use-Case: As container environment variables](https://kubernetes.io/docs/concepts/configuration/secret/#use-case-as-container-environment-variables)

先程作成した Secrets の情報を Pod の環境変数として取得してみる。
上記については Pod のマニュフェストファイルで `envFrom` `secretRef`　の `name`で s区政した Secrets 名を指定することで記載した全ての Key=Value のペアが環境変数として設定される。

```pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: secret-test-pod
spec:
  containers:
    - name: test-container
      image: k8s.gcr.io/busybox
      command: [ "/bin/sh", "-c", "env" ]
      envFrom:
      - secretRef:
          name: dev-db-secret
  restartPolicy: Never
```

```bash
# Pod 作成
$k apply -f pod.yaml

# 環境変数として設定されていることが分かる
$k logs secret-test-pod
KUBERNETES_PORT=tcp://10.100.0.1:443
KUBERNETES_SERVICE_PORT=443
HOSTNAME=secret-test-pod
SHLVL=1
HOME=/root
username=devuser
KUBERNETES_PORT_443_TCP_ADDR=10.100.0.1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_PROTO=tcp
password=password
KUBERNETES_PORT_443_TCP=tcp://10.100.0.1:443
KUBERNETES_SERVICE_PORT_HTTPS=443
PWD=/
KUBERNETES_SERVICE_HOST=10.100.0.1
```

なお、上記の通り、環境変数では Base64 デコードされた値として利用出来る。

Volume として Secrets をマウントする方法もあるようだが今回は割愛。