【Kubernetes】Secretとは(概要から生成・編集・利用方法まで) | 若手エンジニアのブログ

若手エンジニアのブログ

文系出身の若手女子エンジニアによる技術ブログ。
日々の経験や学びをアウトプットするためにブログを書いています。
バックエンド(Java+SpringFramework)を経てインフラエンジニアになりました。
今は育休中につき、本で勉強したことを中心にアウトプットしています。

今回はKubernetes(以下k8s)のSecretについてまとめていきます。

 

もくじ

1.Secretとは概要ConfigMapとの違い

2.Secret生成方法ファイル利用通常マニフェスト利用 / マニフェスト利用特殊版(stringData) / SecretGenerator利用 )

3.Secret編集方法

4.Secret利用方法環境変数として利用Volumeとしてマウント

参考文献

 

■Secretとは

◎概要

機密情報を保存・管理できるリソース。

k8sの初期化によって、k8s APIにアクセスするための認証情報を含むSecretが自動的に生成され、
作られたSecretをpodが参照するようになっている。

k8s利用のためのSecret以外にも、例えばDB接続のためのユーザIDとパスワードを登録しておくためなどに、Secretを自作・利用することができる。

 

Secretは、以下の4タイプが存在するが、今回の記事ではGenericタイプに焦点を当てる。

 ・Generic(type: Opaque)

   …最もよく使われる、一般的なSecret。

 ・TLS(type: kubernetes.io/tls)

   …証明書として利用されるSecret。Ingerssリソース等から利用されることが多い。

 ・Dockerレジストリ(type: kubernetes.io/dockerconfig.json)

   …プライベートリポジトリからのDockerイメージ取得で必要な、認証情報としてのSecret。

 ・Service Account(type: kubernetes.io/service-account-token)

   …Service Accountのトークンや証明書をpodにマウントするためのSecret。

 

◎ConfigMapとの違い

SecretとConfigMapは、ともにk8sのConfig & Storageリソースの1つであり、

設定した内容が、環境変数やk8sのVolumeプラグインとして利用されることも、共通している。

 

※ConfigMapの詳細記事はこちら。

https://ameblo.jp/bakery-diary/entry-12615300336.html

 

Secretは、機密情報を安全に保存しておくことができる点で、ConfigMapと異なる。

Secret内の情報は、ふだんMaster Node内のetcdに保管され、そのSecretを利用するpodがある場合のみ、 over SSL/TLS通信でコンテナへ転送される。転送後、Worker Node上にデータが残らないよう、値は一時記憶領域に保持されるようになっている。

 

保管する情報が、機密情報(パスワード等)かどうかで、SecretとConfigMapを使い分けるとよい。

 

■Secret生成方法

◎ファイル利用

値だけをあらかじめ記述しておいたファイルから、Secretを生成する。

キーは、デフォルトではファイル名になる。

 

<基本のコマンド>

kubectl create secret (Secret名) --from-file=(ファイルパス)

 

<コマンド例>

kubectl create secret generic db-auth-secret --from-file=./username.txt --from-file=./password.txt

→この場合、「username.txt」というキーに対して、username.txtのファイルの中身が値、

かつ、「password.txt」というキーに対して、password.txtのファイルの中身が値として、

「db-auth-secret」という名のSercretリソースに登録される。

 

<キー名の指定>

キーをファイル名にしたくない場合、任意のキー名を指定することも可能。

以下のように、ファイルパスの前に、「=」でつないでキーを指定する。

kubectl create secret generic db-auth-secret --from-file=username=./username.txt

 

この場合、キー名「username」に対して、username.txtの中身が値となる。

 

◎通常マニフェスト利用

マニフェストファイルを利用して、Secretを生成することも可能。

Genericタイプ(type: Opaque)にすることと、dataの値をBASE64でエンコードすべきことが注意点。

 

<例> ※内容は公式よりそのまま転記させて頂きました

apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:  #値をBASE64でエンコードする
  username: YWRtaW4=
  password: MWYyZDFlMmU2N2Rm

マニフェストファイル作成後は、通常のリソースと同様、kubectl apply -f ~で、デプロイすればOK。

 

<BASE64のエンコード・デコード>※通常のLinuxコマンド利用

値のBASE64でのエンコードは、以下のLinuxコマンドを使って先に行う。

エンコードされた出力結果を、マニフェストファイルにコピペするとよい。

 echo -n 'エンコードしたい値' | base64

 

例: echo -n 'P@ssw0rd' | base64

 

デコードしたい場合は以下コマンド。

echo 'デコードしたい値(base64でエンコードされた値)' | base64 --decode

 

 

◎マニフェスト利用特殊版(stringData)

Base64でエンコードされていない、平文の文字列を、マニフェストファイルに記述することもできる。
その場合は、通常のdataフィールドではなく、stringDataフィールドを用いる。

 

<例>

apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
stringData:
    username: testuser
    password: P@ssw0rd

もとの文字列は、Secretの生成・更新タイミングで、自動的にBase64にエンコードされることになる。

 

<その他注意点>

同じsecretに、dataとstringDataでそれぞれ同じキーでの定義をした場合、

stringDataのほうが優先される。

※以下の例は公式に記載された例より抜粋

data:
  username: YWRtaW4=
stringData:  #優先される
  username: administrator

 

◎SecretGenerator利用

ConfigMap同様、ジェネレーターを使ってSecretを生成することもできる。

 

まず、以下の例のようなyamlファイルを作成する。(例によって公式から転記しております)

このときyamlファイル名は、kustmization.yamlとしなければならない。

 

<例① リテラルから生成>

secretGenerator:
- name: db-user-pass
  literals:
  - username=testuser
  - password=P@ssw0rd

secretGenerator[].literals[]を用いる時は、直接、キーとバリュー(平文)を指定する。

 

<例② ファイルから生成>

secretGenerator:
- name: db-user-pass
  files:
  - username.txt
  - password.txt

secretGenerator[].files[]の際は、バリューをあらかじめファイルに記述したうえで、そのファイルを指定する。

 

<デプロイ方法>

例1、2ともに、kubectl apply時は、「-k」オプションを付ける必要がある。「-f」でないことに注意。

さらに、ファイル名は指定しなくて良い(Generatorとして勝手に認識してくれる)ことに気を付けたい。

 

上記を踏まえ、kustomization.yamlを配置したディレクトリ内で、以下のようにkubectl applyを実行すること。

kubectl apply -k .

 

 

■Secret編集方法

生成したSecretのデータ値は、あとから編集することが可能。

パスワードが変更になった等の時に便利。

 

<コマンド>

kubectl edit secrets mysecret

 →エディタ(vimなど。環境による)が開かれ、編集できるようになる。

 

■Secret参照方法

◎環境変数として利用

ConfigMap内の特定のキー&バリューを個別指定し、その値をpod内で使えるようにする方法。

pod内特有の定数名で、該当値を利用することができる。

<pod作成例① 個別キー指定>

apiVersion: v1
kind: Pod
metadata:
  name: test-pod
spec:
  containers:
    - name: sample
      env:
        - name: USERNAME
          valueFrom:
            secretKeyRef:
              name: test-secret
              key: username

環境変数の設定は、マニフェストファイル内の、spec.containers[].envで行う。

 

spec.containers[].env.name(例の「USERNAME」の部分)は、このpod内で使う環境変数の名称。

 

spec.containers[].env.valueFrom以下に、どのSecretの、どのキーの値を取ってくるか、を記述する。

今回は、「test-secret」という名前のSecret内に定義された、「username」というキー名の値を取得している。

 

<pod作成例② Secretまるごと取得>

作成例①は、キーを個別に指定していたが、Secretの内容をまるごととってくることも可能。

その際は以下のような記述になる。

apiVersion: v1
kind: Pod
metadata:
  name: test-pod
spec:
  containers:
    - name: sample
      envFrom:
      - secretRef:
          name: test-secret

個別キー指定時は、spec.containers[].env[]として設定していたところを、

spec.containers[].envFrom[]となっているところに注意。

 

◎Volumeとしてマウント

k8sのVolumeとして、Worker Node上にマウントし、Secretを参照することも可能。

以下のようにPodのマニフェストを作成する。

 

<pod作成例① 個別キー指定> ※公式より転記

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: mypod
    image: redis

    volumeMounts:
    - name: foo
      mountPath: "/etc/foo"

      readOnly: true

    secret:
      secretName: mysecret

      items:
      - key: username
        path: my-group/my-username

spec.volumes[].secretに、利用するSecretの情報を記述する。

 

例の場合は、「mysecret」という名のSecret内から、

キーを直接指定(items[].key)し、その値のマウント先を設定(items[].path)している。

マウント先は、volumeMounts.mountPathで指定したパスの配下となるため、

上記例ならば /etc/foo/my-group/my-username にマウントされることになる。

 

<pod作成例② Secretまるごと取得>

作成例①は、キーを個別に指定していたが、Secretの内容をまるごととってくることも可能。

その際は以下のような記述になる。

    volumeMounts:
    - name: foo
      mountPath: "/etc/foo"
      readOnly: true
  volumes:
  - name: foo

    secret:
      secretName: mysecret

 

<Volumeマウント時の注意点>

SecretをVolumeとしてマウントする際の注意点として、

必ず「.spec.containers[].volumeMounts[].readOnly = true」を設定するようにする。

 

readOnllyはvolumeMountsのオプションだが、trueにすることで、

コンテナからは設定値を読み込むだけ(書き込み等不可)の設定となる。

Secretは機密情報を含むため、セキュリティ上、読み込みだけの設定にすべきである。

 

■参考文献

・公式

https://kubernetes.io/docs/concepts/configuration/secret/

・青山真也著『Kubernetes完全ガイド