2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

kubernetesのSecretsを公式ドキュメントから学ぶ

Last updated at Posted at 2020-03-10

はじめに

この記事で取り上げること

  • k8sのSecrets機能について
  • 最低限の使い方

取り上げないこと

  • Kustomizeを使った生成
  • Secretsの値を取り扱う上でのベストプラクティス
  • Secretsを適切に扱うためのツール

2020/3/10時点の公式ドキュメントを参考にしてます。

概要

k8sにはSecretsというConfigMapに似た機能がある。
Podやコンテナに対して機密情報を比較的安全に渡すための機能である。ConfigMapは設定のための環境依存の変数を、SecretsはDBのパスワードやCredentialを取り扱うのが主な用途である。

先日、「kubernetesのConfigMapを理解する」という記事を書いたが、Secretsも生成方法と渡し方はConfigMapと大きく変わらない。

早速まとめていく。

Secretsを作成する方法

  • ファイルやディレクトリを指定して作成する方法
  • マニフェストファイルから作成する方法

Podやコンテナが読み取る方法

  • Secretsをボリュームマウントする方法
  • Secretsを環境変数として渡す方法

Secretsを作成する方法

ファイルやディレクトリを指定して作成する方法

まずはテストとしての機密ファイルを用意する。すでにある場合はスキップしてOK。


$ echo -n 'hoge' > ./mysql-username.txt
$ echo -n '1f2d1e2e67df' > ./mysql-password.txt

$ kubectl create secret generic mysql-user-pass --from-file=./mysql-username.txt --from-file=./mysql-password.txt
secret/mysql-user-pass created

作成したSecretsを確認する。


$ kubectl get secrets
Name:         mysql-user-pass
Namespace:    test
Labels:       <none>
Annotations:  
Type:         Opaque

Data
====
mysql-password:  12 bytes
mysql-username:  4 bytes

ちなみに$ \ * ! のような特殊文字が入っている場合、
--from-fileで作成するか、 --from-literalで作成するかで対応が異なる。


# --from-fileの場合は特に何もする必要はない(k8s側でよしなにやってくれる)
kubectl create secret generic secrets-2 --from-file=./mysql-password.txt

# --from-literalの場合はエスケープして渡す必要がある
kubectl create secret generic dev-db-secret --from-literal=mysql-username=hoge --from-literal=mysql-password='S!B\*d$zDsb'

公式によると

Note: The commands kubectl get and kubectl describe avoid showing the contents of a secret by default.
This is to protect the secret from being exposed accidentally to an onlooker, or from being stored in a terminal log.

とのことなのでたまたま画面を見てしまった人にSecretsを見られないように、getとdescribeでは機密情報がプリントされない。

ただし以下のコマンドを実行すると格納されているsecretが確認できる。


$ kubectl get secrets -o yaml
- apiVersion: v1
  data:
    mysql-password: MWYyZDFlMmU2N2Rm
    mysql-username: aG9nZQ==
  kind: Secret
  metadata:
    creationTimestamp: "2020-03-10T04:32:57Z"
    name: mysql-user-pass
    namespace: test
    resourceVersion: "8227949"
    selfLink: /api/v1/namespaces/test/secrets/mysql-user-pass
    uid: 375cbbb7-6288-11ea-84cf-062919a0e59e
  type: Opaque

平文で格納することも可能だが、base64を使って暗号化された文字列にして格納もできる。


# base64で暗号化し、それをそのままリダイレクトする
$ echo -n 'hoge' | base64 > ./mysql-username.txt
$ echo -n '1f2d1e2e67df' | base64 > ./mysql-password.txt

格納した暗号文も複号できる。


$ echo -n 'MWYyZDFlMmU2N2Rm' | base64

マニフェストファイルから作成する方法

マニフェストファイルを作成する。

secrets.yaml
apiVersion: v1
kind: Secret
metadata:
  name: mysql-user-pass
type: Opaque
data:
  mysql-username: aG9nZQ==
  mysql-password: MWYyZDFlMmU2N2Rm

$ kubectl get secrets
NAME                  TYPE                                  DATA   AGE
mysql-user-pass       Opaque                                2      3m51s

先程からOpaqueという単語が出てきているが、これはSecretsの種類。
普通に試す分ならOpaqueでOK。

種類 YAML内のtype表記 説明
Generic Opaque 一般的なフリースキーマのSecret
TLS kubernetes.io/tls 証明書として利用するSecret
Docker Registry kubernetes.io/dockerconfigjson 証明書として利用するSecret
Service Account kubernetes.io/service-account-token PodにService AccountのTokenをマウントするためのSecret

Podやコンテナが読み取る方法

Secretsをボリュームマウントする方法

このような感じでマニフェストファイルを作成。

test.yaml
apiVersion: v1
kind: Pod
metadata:
  name: test
spec:
  containers:
  - name: test-pod
    image: nginx:alpine
    volumeMounts:
    - name: secrets
      mountPath: /mount
      readOnly: true
  volumes:
  - name: secrets
    secret:
      secretName: mysql-user-pass

containers.volumeMounts.name と volumes.name は一致している必要がある。
またvolumes.secret.secretNameは先ほど作成した Secretsのnameと一致している必要もある。

Secretsを環境変数として渡す方法

以下のように記述する。

test.yaml
apiVersion: v1
kind: Pod
metadata:
  name: test
spec:
  containers:
  - name: test-pod
    image: nginx:alpine
    envFrom:
    - secretRef:
        name: mysql-user-pass

podの中に入って環境変数を確認する。


$ kubectl get pod
NAME                              READY   STATUS      RESTARTS   AGE
test                              1/1     Running     59s

$ kubectl exec -ti test /bin/sh
/# printenv
・
・
mysql-password=1f2d1e2e67df
mysql-username=hoge
・
・

podに渡される課程で複合された平文が読み取れればOK。

最後に

冒頭で取り上げないこととして以下を挙げた。

  • Kustomizeを使った生成
  • Secretsの値を取り扱う上でのベストプラクティス
  • Secretsを適切に扱うためのツール

特にSecretsを取り扱う上で、
セキュアさと現実の運用のつらさの間でどのようなバランスを取るかは難しい。そしてそれを楽にする手段は幾つかある。

ここらへんを書くと内容がてんこ盛りになってしまうので、それはまた別の機会に。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?