Terraformを使ってGKEでk8sクラスタとサービスアカウントを作り、サービスアカウントのクレデンシャルを Secrets として作成した。やったことはそれなんだけど、 Secrets の作成・参照と位置付けをメモしとく。
コンテナに秘密情報を与えるには2つの方法がある。
実行パラメタはマニフェストに平文で残すことになり使えない。
k8sにはSecretsというリソースがある。
環境変数にもファイルにも使うことができる。
Secretsの作り方は後に書くとして使い方を並べておく。
Secretsの使い方
ボリュームとしてマウントする
公式をそのままコピーしてきた。
mysecret という Secrets に foo という名前を与えて /etc/bar にマウントしてる。
秘密情報なのでコンテナに書き込まれないように readOnly が指定してる。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: mypod
image: redis
volumeMounts:
- name: foo
mountPath: "/etc/bar"
readOnly: true
volumes:
- name: foo
secret:
secretName: mysecret
|
環境変数として使う
公式をそのままコピーしてきた。
env で環境変数を渡している。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
apiVersion: v1
kind: Pod
metadata:
name: secret-env-pod
spec:
containers:
- name: mycontainer
image: redis
env:
- name: SECRET_USERNAME
valueFrom:
secretKeyRef:
name: mysecret
key: username
- name: SECRET_PASSWORD
valueFrom:
secretKeyRef:
name: mysecret
key: password
restartPolicy: Never
|
Secrets作り方
k8sは手続き的な方法と宣言的な方法を提供している。
今回は k8s 公式ツールでなく Terraform を使った。
これはGCP, AWSを Terraform で管理しているからで、その接続情報をPodsに渡すのは、
渡す情報・渡す先の両方を知っている Terraform が自然だと考えたからだ。
- コマンドラインで作る
- マニフェストで作る
- Terraformのマニフェストで作る
また後から思い出したので、最後に kustomize を使う方法も残しておく。
コマンドラインで作る
今回の目的に使える Secrets は generic 。
1
|
kubectl create secret generic NAME [--type=string] [--from-file=[key=]source] [--from-literal=key1=value1] [--dry-run] [options]
|
定義には3種類のデータソースが使える。ただし –from-env-file は他2つと併用できない。
1
2
3
4
5
6
7
8
|
cat <<EOF > ./creds.env
db_user=fuji
db_pass=orin
EOF
kubectl create secret generic orange-secrets /
--from-env-file=creds.env /
--dry-run
secret/orange-secrets created (dry run)
|
他の例はこんな感じ。
1
2
3
4
5
6
7
8
|
echo {"id": "hoge", "secret": "xxxx"} > ./credentials.json
cp ~/.ssh/id_rsa.github ./
kubectl create secret generic orange-secrets /
--from-file=credentials.json /
--from-file=id_rsa=id_rsa.github /
--from-literal=password=bad_password /
--dry-run
secret/orange-secrets created (dry run)
|
ref. https://kubernetes.io/docs/concepts/configuration/secret/#using-secrets
マニフェストで作る
data の項目はbase64エンコードして記述する。
1
2
3
4
5
6
7
8
9
|
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
username: YWRtaW4=
stringData:
username: administrator
|
ref. https://kubernetes.io/docs/concepts/configuration/secret/#using-secrets
Terraformで管理しているマネージドサービスに関連した情報を埋め込むのに使える。
公式でそのまま欲しかった例を見つけてしまった。 provider の設定だけ足しておく。
kubernetes プロバイダを GCP の情報からセットする。
この部分はterraform-google-gkeモジュールを参考にした。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
provider "kubernetes" {
version = "~> 1.7.0"
load_config_file = false
host = google_container_cluster.cluster.endpoint
token = data.google_client_config.client.access_token
cluster_ca_certificate = base64decode(google_container_cluster.cluster.master_auth[0].cluster_ca_certificate)
}
data "google_service_account" "cloud_proxy" {
account_id = "cloud-proxy"
}
resource "google_service_account_key" "cloud_proxy_key" {
service_account_id = data.google_service_account.cloud_proxy.name
}
resource "kubernetes_secret" "google-application-credentials" {
metadata {
name = "google-application-credentials"
}
data = {
credentials.json = base64decode(google_service_account_key.cloud_proxy_key.private_key)
}
}
|
ref.
Kustomize で作る
Kustomizeは今回の用途を目指していてかつ kubectl に統合されているため選択肢として自然。
CDで使うときは Terraform のoutputで必要な情報を取り出せるようにして Pipeline スクリプトでファイルを作成。
その後、それらのファイルから Kustomize で Secrets を生成って流れが良いと思う。
大掛かりになったので具体例のリポジトリを作った。
関連スクリプトが大きくなった。これが良いのかは怪しい。
ただCDとか自動化された作業自体は命令的だし、受け渡しがスクリプトになってても問題はないと思う。
Example
tfから中間生成物として取り出す部分と kustomize が利用する場所に書き込む部分に分けた。
書き込む部分は環境ごとに色々やりたいと思うのでヘルパースクリプトを作るにとどめた。
取り出す部分はここにコピーしておくとこんな感じ。
1
2
3
4
5
6
7
8
9
10
11
12
|
## for both manual and CD pipeline
set -eu
TOP_DIR=$(cd $(dirname $0); pwd)/..
TF_WORK_DIR=${TOP_DIR}/tf
cd $TF_WORK_DIR
terraform output -no-color \
| awk -f $TOP_DIR/scripts/save-output.awk \
-v target=$TOP_DIR/tmp
|
1
2
3
4
5
6
7
8
9
|
BEGIN{
env_file = sprintf("%s/_env.txt", target)
}
{
close(file)
file = sprintf("%s/%s", target, $1)
print $3 > file
print $1"="$3 >> env_file
}
|
kustomization.yaml は下。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
bases:
- ../base/
secretGenerator:
- name: app-tls
files:
- secrets/tls.cert
- secrets/tls.key
type: Opaque
- name: env-file-secret
env: env.txt
type: Opaque
|