今回から、Config&Storageについて説明していきます。
Config&Storageリソースの概要
Config & Storageリソースは、設定や機密データをコンテナに埋め込んだり、永続ボリュームを提供するリソースです。
以下のものがあります。
- Secret:機密情報保存用
- ConfigMap:設定値や共通設定などの保存用
- PersistentVolumeClaim:Podが永続化ディスク(ディスク)を利用するためのリソース
Secret
データベースなどに接続するなどの際に、ユーザー名、パスワードが必要になります。
こういった内容は、もちろんコードの中に書いてはいけません。どこか他の場所から引っ張って来て使うのが一般的です。
ただ、機密情報なので、平分で保存してしまうと、危ないですよね。
そので、Secretの出番です。
Secretは簡単にいうと、データを暗号化して保存するファイルみたいなものです。保存するデータの部分だけ、base64の暗号化方式で暗号化されます。
ここで注意が必要です。base64は方法がわかれば、簡単に複合化できるので、暗号化されたといって、安全とは言えません。あくまで人が見てわからない程度です。
本当に安全な暗号化をしたい場合、kubesec(k8sのソフトウェア)を使って、さらにsecretを暗号化する方法があります。
※kubesecはGCPのKMS、AWSのKMSなどを利用することで、Secretのデータ部分を暗号化できます。
Secretでは、一つのSecretの中に複数のkey-valueのデータを保持できます。また、一つのSecretは最大データ量は1MBです。
Secretは4種類あります。
- Genericタイプ
- TLSタイプ
- Dockerレジストリ
- Service Account
Genericタイプ
manifestのリソース指定:
kind: Secret
type: Opaque
一般的な機密情報ファイルはGenericタイプで作成します。
作成方法は4つあります。
- ファイルから値を参照して作成する:
kubectl --from-file
- 1ファイルがkey-valueペア一個となる
- 一回で複数ファイル指定可能
- key:ファイル名
- ファイル名の拡張子を無視したい場合
--from-file=<key>=<filename>
で指定
- ファイル名の拡張子を無視したい場合
- value:ファイル内容
- 内容に改行を入れないこと
- envfileから値を参照して作成する:
kubectl --from-env-file
- 1ファイルで複数のkey-value導入可能
- ファイルの内容は行ごとに
<key>=<value>
で記述する
- 直接値を指定して、作成する:
kubectl --from-literal
--from-literal=<key>=<value>
で指定する- 一回で複数指定可能
- manifestから作成する:
kubectl apply -f
data.<key>: <base64暗号化後のvalue>
作成例:
# --from-file
kubectl create secret generic <secret名> --save-config --from-file=<file名> [--from-file=<file名>...]
# --from-env-file
kubectl create secret generic <secret名> --save-config --from-env-file=<file名>
# --from-literal
kubectl create secret generic <secret名> --save-config --from-literal=<key>=<value> [--from-literal=<key>=<value>...]
TLS(SSL)タイプ
manifestのリソース指定:
kind: Secret
type: kubernetes.io/tls
証明書として利用する場合、TLSタイプを利用する必要があります。多くの場合Ingressの証明書に使われます。
作成方法はシンプルでです。
まず、証明書の.keyファイルと.crtファイルを用意しておきます。
※.key、.crtファイルは証明書の公開キーと秘密キーファイルです。証明書の仕組みはここでは割愛します。
作成例:
kubectl create secret tls <secret名> --save-config --key <.keyファイル> --cert <.crtファイル>
Docker レジストリ
manifestのリソース指定:
kind: Secret
type: kubernetes.io/dockerconfigjson
コンテナのリポジトリ(イメージのダウンロード元)がプライベートリポジトリを使用する場合、イメージの取得は認識が必要です。
Docker registryはリポジトリの認証に使用されます。
作成例:
kubectl create secret docker-registry <secret名> \
--save-config \
--docker-server= <レジストリサーバ> \
--docker-username= <ユーザー名> \
--docker-password= <パスワード> \
--docker-email= <メールアドレス>
※これをmanifestで作るのは少々面倒です。こちらをご参照ください
Pod(Deployment)でプライベートレポジトリを使う場合、以下のようにSecretを使います。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template: # Podの設定
metadata:
labels:
app: nginx
spec:
containers: # コンテナの設定
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
imagePullSecrets: # ここでSecretを引用します。Podの設定に属します。
- name: <secret名> # Secretを指定します。複数指定可能
Secretの使用
Secretの使用は2パータンあります
- 環境変数として渡す
- Secretの特定のKeyのみ
- SecretのすべてのKey
- Volumeとしてマウントする
- Secretの特定のKeyのみ
- SecretのすべてのKey
※Dockerリポジトリタイプは上記紹介した方法で使いましょう
環境変数として渡す
Podの環境変数として渡す使用パータンです。
特徴:
- 一旦Podを作成したら、Secretが更新しても、Pod内の環境変数は動的更新しません。Podの再作成が必要です。
※環境変数に.
や-
を使わない用がいいです。
特定のKeyのみ.env[].valueFrom.secretKeyRef
Podのmanifestを例して説明します。
apiVersion: v1
kind: Pod
metadata:
name: secret-env-pod
spec:
containers:
- name: mycontainer
image: redis
env: # 環境変数定義
- name: SECRET_USERNAME # 環境変数名
valueFrom: # 環境変数引用
secretKeyRef: # SecretKeyを引用
name: mysecret # Secret名指定
key: username # SecretのKeyを指定
- name: SECRET_PASSWORD
valueFrom:
secretKeyRef:
name: mysecret
key: password
restartPolicy: Never
※公式ドキュメント例を使用
すべてののKey.env[].envFrom[].secretKeyRef
Podのmanifestを例して説明します。
apiVersion: v1
kind: Pod
metadata:
name: secret-env-pod
spec:
containers:
- name: mycontainer
image: redis
envFrom: # 環境変数取得先指定
- secretRef: # Secretを引用
name: mysecret1 # Secret名指定
- secretRef:
name: mysecret2
prefix: FOO_ # 環境変数の頭文字を付けることも可能、変数名の衝突を防ぐことが可能
restartPolicy: Never
※公式ドキュメント例を使用
Volumeとしてマウントする
Secretをボリュームとして、Podにマウントして使用するパータンです。
特徴:
- 一定頻度でSecretの更新を反映される(デフォルトは60秒一回)
- この時間を調整したい場合、リソース作成時
kubectl
コマンドに、--sync-frequency
オプションを使ってください。
- この時間を調整したい場合、リソース作成時
特定のKeyのみ.volumes[].secret.items[]
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: mypod
image: redis
volumeMounts: # コンテナにマウントする
- name: foo # コンテナにマウントするPodのVolume名
mountPath: "/etc/foo" # マウント先、コンテナから見るとファイルパスは/etc/foo/my-group/my-username
readOnly: true # 読み取り専用にする。デフォルトはfalse
# subPath: /data # マウントパスの配下にサブパスを作ってマウントすることも可能
volumes: # PodにVolumeをマウントする
- name: foo # PodのVolume名
secret: # Volume内にSecretをマウントする
secretName: mysecret # Secret名
items: # 複数のSecretをPodにマウントできます。
- key: username # SecretのKey
path: my-group/my-username # SecretがVolume内のファイルパス
※公式ドキュメント例を使用
すべてののKey.volumes[].secret.secretName
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: mypod
image: redis
volumeMounts: # コンテナにマウントする
- name: foo
mountPath: "/etc/foo"
readOnly: true
volumes:
- name: foo
secret: # Secretを指定
secretName: mysecret # Secret名
※公式ドキュメント例を使用
kubesec
kunesecはk8sのSecretを安全委管理するためのオープンソースソフトウェアです。
GunPG/Google Cloud KMS/AWS KMSを利用して、Secretを暗号化します。(data部分のみ暗号化)
筆者も使ったことないので、使用する場合になったら、調べながら使っていこうと思います。
今後機会があれば、内容を発信します。
最後に
今回で、Secretの作成方や使い方について、紹介しました。
次回で説明する予定のConfigMapは基本使い方は同じなので、内容が薄くなってしまうかもしれません。
ここまで読んでいただいて、お疲れ様でした。
コメント