広告

kubernetes – Secret

infrastructure as code

今回から、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は基本使い方は同じなので、内容が薄くなってしまうかもしれません。

ここまで読んでいただいて、お疲れ様でした。

コメント

タイトルとURLをコピーしました