2.6. Pod への機密性の高いデータの提供

アプリケーションによっては、パスワードやユーザー名など開発者に使用させない秘密情報が必要になります。

管理者として シークレット オブジェクトを使用すると、この情報を平文で公開することなく提供することが可能です。

2.6.1. シークレットについて

Secret オブジェクトタイプはパスワード、OpenShift Container Platform クライアント設定ファイル、プライベートソースリポジトリーの認証情報などの機密情報を保持するメカニズムを提供します。シークレットは機密内容を Pod から切り離します。シークレットはボリュームプラグインを使用してコンテナーにマウントすることも、システムが Pod の代わりにシークレットを使用して各種アクションを実行することもできます。

キーのプロパティーには以下が含まれます。

  • シークレットデータはその定義とは別に参照できます。
  • シークレットデータのボリュームは一時ファイルストレージ機能 (tmpfs) でサポートされ、ノードで保存されることはありません。
  • シークレットデータは namespace 内で共有できます。

YAML Secret オブジェクト定義

apiVersion: v1
kind: Secret
metadata:
  name: test-secret
  namespace: my-namespace
type: Opaque 1
data: 2
  username: dmFsdWUtMQ0K 3
  password: dmFsdWUtMg0KDQo=
stringData: 4
  hostname: myapp.mydomain.com 5

1
シークレットにキー名および値の構造を示しています。
2
data フィールドのキーに使用可能な形式については、Kubernetes identifiers glossaryDNS_SUBDOMAIN 値のガイドラインに従う必要があります。
3
data マップのキーに関連付けられる値は base64 でエンコーディングされている必要があります。
4
stringData マップのエントリーが base64 に変換され、このエントリーは自動的に data マップに移動します。このフィールドは書き込み専用です。この値は data フィールドでのみ返されます。
5
stringData マップのキーに関連付けられた値は単純なテキスト文字列で設定されます。

シークレットに依存する Pod を作成する前に、シークレットを作成する必要があります。

シークレットの作成時に以下を実行します。

  • シークレットデータでシークレットオブジェクトを作成します。
  • Pod のサービスアカウントをシークレットの参照を許可するように更新します。
  • シークレットを環境変数またはファイルとして使用する Pod を作成します (secret ボリュームを使用)。

2.6.1.1. シークレットの種類

type フィールドの値で、シークレットのキー名と値の構造を指定します。このタイプを使用して、シークレットオブジェクトにユーザー名とキーの配置を実行できます。検証の必要がない場合には、デフォルト設定の opaque タイプを使用してください。

以下のタイプから 1 つ指定して、サーバー側で最小限の検証をトリガーし、シークレットデータに固有のキー名が存在することを確認します。

  • kubernetes.io/service-account-token。サービスアカウントトークンを使用します。
  • kubernetes.io/basic-auth。Basic 認証で使用します。
  • kubernetes.io/ssh-auth.SSH キー認証で使用します。
  • kubernetes.io/tls。TLS 認証局で使用します。

検証が必要ない場合には type: Opaque と指定します。これは、シークレットがキー名または値の規則に準拠しないという意味です。opaque シークレットでは、任意の値を含む、体系化されていない key:value ペアも利用できます。

注記

example.com/my-secret-type などの他の任意のタイプを指定できます。これらのタイプはサーバー側では実行されませんが、シークレットの作成者がその種類のキー/値の要件に従う意図があることを示します。

シークレットのさまざまなタイプの例については、シークレットの使用 に関連するコードのサンプルを参照してください。

2.6.1.2. シークレットデータキー

シークレットキーは DNS サブドメインになければなりません。

2.6.2. シークレットの作成方法

管理者は、開発者がシークレットに依存する Pod を作成できるよう事前にシークレットを作成しておく必要があります。

シークレットの作成時に以下を実行します。

  1. 秘密にしておきたいデータを含む秘密オブジェクトを作成します。各シークレットタイプに必要な特定のデータは、以下のセクションで非表示になります。

    不透明なシークレットを作成する YAML オブジェクトの例

    apiVersion: v1
    kind: Secret
    metadata:
      name: test-secret
    type: Opaque 1
    data: 2
      username: dmFsdWUtMQ0K
      password: dmFsdWUtMQ0KDQo=
    stringData: 3
      hostname: myapp.mydomain.com
      secret.properties: |
        property1=valueA
        property2=valueB

    1
    シークレットのタイプを指定します。
    2
    エンコードされた文字列およびデータを指定します。
    3
    デコードされた文字列およびデータを指定します。

    data フィールドまたは stringdata フィールドの両方ではなく、いずれかを使用してください。

  2. Pod のサービスアカウントをシークレットを参照するように更新します。

    シークレットを使用するサービスアカウントの YAML

    apiVersion: v1
    kind: ServiceAccount
     ...
    secrets:
    - name: test-secret

  3. シークレットを環境変数またはファイルとして使用する Pod を作成します (secret ボリュームを使用)。

    シークレットデータと共にボリュームのファイルが設定された Pod の YAML

    apiVersion: v1
    kind: Pod
    metadata:
      name: secret-example-pod
    spec:
      containers:
        - name: secret-test-container
          image: busybox
          command: [ "/bin/sh", "-c", "cat /etc/secret-volume/*" ]
          volumeMounts: 1
              - name: secret-volume
                mountPath: /etc/secret-volume 2
                readOnly: true 3
      volumes:
        - name: secret-volume
          secret:
            secretName: test-secret 4
      restartPolicy: Never

    1
    シークレットが必要な各コンテナーに volumeMounts フィールドを追加します。
    2
    シークレットが表示される未使用のディレクトリー名を指定します。シークレットデータマップの各キーは mountPath の下にあるファイル名になります。
    3
    true に設定します。true の場合、ドライバーに読み取り専用ボリュームを提供するように指示します。
    4
    シークレットの名前を指定します。

    シークレットデータと共に環境変数が設定された Pod の YAML

    apiVersion: v1
    kind: Pod
    metadata:
      name: secret-example-pod
    spec:
      containers:
        - name: secret-test-container
          image: busybox
          command: [ "/bin/sh", "-c", "export" ]
          env:
            - name: TEST_SECRET_USERNAME_ENV_VAR
              valueFrom:
                secretKeyRef: 1
                  name: test-secret
                  key: username
      restartPolicy: Never

    1
    シークレットキーを使用する環境変数を指定します。

    シークレットデータと環境変数が設定されたビルド設定の YAML

    apiVersion: build.openshift.io/v1
    kind: BuildConfig
    metadata:
      name: secret-example-bc
    spec:
      strategy:
        sourceStrategy:
          env:
          - name: TEST_SECRET_USERNAME_ENV_VAR
            valueFrom:
              secretKeyRef: 1
                name: test-secret
                key: username

    1
    シークレットキーを使用する環境変数を指定します。

2.6.2.1. シークレットの作成に関する制限

シークレットを使用するには、Pod がシークレットを参照できる必要があります。シークレットは、以下の 3 つの方法で Pod で使用されます。

  • コンテナーの環境変数を事前に設定するために使用される。
  • 1 つ以上のコンテナーにマウントされるボリュームのファイルとして使用される。
  • Pod のイメージをプルする際に kubelet によって使用される。

ボリュームタイプのシークレットは、ボリュームメカニズムを使用してデータをファイルとしてコンテナーに書き込みます。イメージプルシークレットは、シークレットを namespace のすべての Pod に自動的に挿入するためにサービスアカウントを使用します。

テンプレートにシークレット定義が含まれる場合、テンプレートで指定のシークレットを使用できるようにするには、シークレットのボリュームソースを検証し、指定されるオブジェクト参照が Secret オブジェクトを実際に参照していることを確認できる必要があります。そのため、シークレットはこれに依存する Pod の作成前に作成されている必要があります。最も効果的な方法として、サービスアカウントを使用してシークレットを自動的に挿入することができます。

シークレット API オブジェクトは namespace にあります。それらは同じ namespace の Pod によってのみ参照されます。

個々のシークレットは 1MB のサイズに制限されます。これにより、apiserver および kubelet メモリーを使い切るような大規模なシークレットの作成を防ぐことができます。ただし、小規模なシークレットであってもそれらを数多く作成するとメモリーの消費につながります。

2.6.2.2. 不透明なシークレットの作成

管理者は、不透明なシークレットを作成できます。これにより、任意の値を含むことができる非構造化 key:value のペアを格納できます。

手順

  1. コントロールプレーンノードの YAML ファイルに Secret オブジェクトを作成します。

    以下に例を示します。

    apiVersion: v1
    kind: Secret
    metadata:
      name: mysecret
    type: Opaque 1
    data:
      username: dXNlci1uYW1l
      password: cGFzc3dvcmQ=
    1
    不透明なシークレットを指定します。
  2. 以下のコマンドを使用して Secret オブジェクトを作成します。

    $ oc create -f <filename>.yaml
  3. Pod でシークレットを使用するには、以下を実行します。

    1. シークレットの作成方法についてセクションに示すように、Pod のサービスアカウントを更新してシークレットを参照します。
    2. シークレットの作成方法についてに示すように、シークレットを環境変数またはファイル (secret ボリュームを使用) として使用する Pod を作成します。

関連情報

2.6.2.3. サービスアカウントトークンシークレットの作成

管理者は、サービスアカウントトークンシークレットを作成できます。これにより、API に対して認証する必要のあるアプリケーションにサービスアカウントトークンを配布できます。

注記

サービスアカウントトークンシークレットを使用する代わりに、TokenRequest API を使用してバインドされたサービスアカウントトークンを取得することをお勧めします。TokenRequest API から取得したトークンは、有効期間が制限されており、他の API クライアントが読み取れないため、シークレットに保存されているトークンよりも安全です。

TokenRequest API を使用できず、読み取り可能な API オブジェクトで有効期限が切れていないトークンのセキュリティーエクスポージャーが許容できる場合にのみ、サービスアカウントトークンシークレットを作成する必要があります。

バインドされたサービスアカウントトークンの作成に関する詳細は、以下の追加リソースセクションを参照してください。

手順

  1. コントロールプレーンノードの YAML ファイルに Secret オブジェクトを作成します。

    secret オブジェクトの例:

    apiVersion: v1
    kind: Secret
    metadata:
      name: secret-sa-sample
      annotations:
        kubernetes.io/service-account.name: "sa-name" 1
    type: kubernetes.io/service-account-token 2

    1
    既存のサービスアカウント名を指定します。ServiceAccountSecret オブジェクトの両方を作成する場合は、ServiceAccount オブジェクトを最初に作成します。
    2
    サービスアカウントトークンシークレットを指定します。
  2. 以下のコマンドを使用して Secret オブジェクトを作成します。

    $ oc create -f <filename>.yaml
  3. Pod でシークレットを使用するには、以下を実行します。

    1. シークレットの作成方法についてセクションに示すように、Pod のサービスアカウントを更新してシークレットを参照します。
    2. シークレットの作成方法についてに示すように、シークレットを環境変数またはファイル (secret ボリュームを使用) として使用する Pod を作成します。

関連情報

2.6.2.4. Basic 認証シークレットの作成

管理者は Basic 認証シークレットを作成できます。これにより、Basic 認証に必要な認証情報を保存できます。このシークレットタイプを使用する場合は、Secret オブジェクトの data パラメーターには、base64 形式でエンコードされた以下のキーが含まれている必要があります。

  • username: 認証用のユーザー名
  • password: 認証のパスワードまたはトークン
注記

stringData パラメーターを使用して、クリアテキストコンテンツを使用できます。

手順

  1. コントロールプレーンノードの YAML ファイルに Secret オブジェクトを作成します。

    secret オブジェクトの例

    apiVersion: v1
    kind: Secret
    metadata:
      name: secret-basic-auth
    type: kubernetes.io/basic-auth 1
    data:
    stringData: 2
      username: admin
      password: t0p-Secret

    1
    Basic 認証のシークレットを指定します。
    2
    使用する Basic 認証値を指定します。
  2. 以下のコマンドを使用して Secret オブジェクトを作成します。

    $ oc create -f <filename>.yaml
  3. Pod でシークレットを使用するには、以下を実行します。

    1. シークレットの作成方法についてセクションに示すように、Pod のサービスアカウントを更新してシークレットを参照します。
    2. シークレットの作成方法についてに示すように、シークレットを環境変数またはファイル (secret ボリュームを使用) として使用する Pod を作成します。

関連情報

2.6.2.5. SSH 認証シークレットの作成

管理者は、SSH 認証シークレットを作成できます。これにより、SSH 認証に使用されるデータを保存できます。このシークレットタイプを使用する場合、Secret オブジェクトの data パラメーターには、使用する SSH 認証情報が含まれている必要があります。

手順

  1. コントロールプレーンノードの YAML ファイルに Secret オブジェクトを作成します。

    secret オブジェクトの例:

    apiVersion: v1
    kind: Secret
    metadata:
      name: secret-ssh-auth
    type: kubernetes.io/ssh-auth 1
    data:
      ssh-privatekey: | 2
              MIIEpQIBAAKCAQEAulqb/Y ...

    1
    SSH 認証シークレットを指定します。
    2
    SSH のキー/値のペアを、使用する SSH 認証情報として指定します。
  2. 以下のコマンドを使用して Secret オブジェクトを作成します。

    $ oc create -f <filename>.yaml
  3. Pod でシークレットを使用するには、以下を実行します。

    1. シークレットの作成方法についてセクションに示すように、Pod のサービスアカウントを更新してシークレットを参照します。
    2. シークレットの作成方法についてに示すように、シークレットを環境変数またはファイル (secret ボリュームを使用) として使用する Pod を作成します。

2.6.2.6. Docker 設定シークレットの作成

管理者は Docker 設定シークレットを作成できます。これにより、コンテナーイメージレジストリーにアクセスするための認証情報を保存できます。

  • kubernetes.io/dockercfg.このシークレットタイプを使用してローカルの Docker 設定ファイルを保存します。secret オブジェクトの data パラメーターには、base64 形式でエンコードされた .dockercfg ファイルの内容が含まれている必要があります。
  • kubernetes.io/dockerconfigjson.このシークレットタイプを使用して、ローカルの Docker 設定 JSON ファイルを保存します。secret オブジェクトの data パラメーターには、base64 形式でエンコードされた .docker/config.json ファイルの内容が含まれている必要があります。

手順

  1. コントロールプレーンノードの YAML ファイルに Secret オブジェクトを作成します。

    Docker 設定の secret オブジェクトの例

    apiVersion: v1
    kind: Secret
    metadata:
      name: secret-docker-cfg
      namespace: my-project
    type: kubernetes.io/dockerconfig 1
    data:
      .dockerconfig:bm5ubm5ubm5ubm5ubm5ubm5ubm5ubmdnZ2dnZ2dnZ2dnZ2dnZ2dnZ2cgYXV0aCBrZXlzCg== 2

    1
    シークレットが Docker 設定ファイルを使用することを指定します。
    2
    base64 でエンコードされた Docker 設定ファイルの出力

    Docker 設定の JSON secret オブジェクトの例

    apiVersion: v1
    kind: Secret
    metadata:
      name: secret-docker-json
      namespace: my-project
    type: kubernetes.io/dockerconfig 1
    data:
      .dockerconfigjson:bm5ubm5ubm5ubm5ubm5ubm5ubm5ubmdnZ2dnZ2dnZ2dnZ2dnZ2dnZ2cgYXV0aCBrZXlzCg== 2

    1
    シークレットが Docker 設定の JSON ファイルを使用することを指定します。
    2
    base64 でエンコードされた Docker 設定 JSON ファイルの出力
  2. 以下のコマンドを使用して Secret オブジェクトを作成します。

    $ oc create -f <filename>.yaml
  3. Pod でシークレットを使用するには、以下を実行します。

    1. シークレットの作成方法についてセクションに示すように、Pod のサービスアカウントを更新してシークレットを参照します。
    2. シークレットの作成方法についてに示すように、シークレットを環境変数またはファイル (secret ボリュームを使用) として使用する Pod を作成します。

関連情報

2.6.3. シークレットの更新方法

シークレットの値を変更する場合、値 (すでに実行されている Pod で使用される値) は動的に変更されません。シークレットを変更するには、元の Pod を削除してから新規の Pod を作成する必要があります (同じ PodSpec を使用する場合があります)。

シークレットの更新は、新規コンテナーイメージのデプロイメントと同じワークフローで実行されます。kubectl rolling-update コマンドを使用できます。

シークレットの resourceVersion 値は参照時に指定されません。したがって、シークレットが Pod の起動と同じタイミングで更新される場合、Pod に使用されるシークレットのバージョンは定義されません。

注記

現時点で、Pod の作成時に使用されるシークレットオブジェクトのリソースバージョンを確認することはできません。コントローラーが古い resourceVersion を使用して Pod を再起動できるように、Pod がこの情報を報告できるようにすることが予定されています。それまでは既存シークレットのデータを更新せずに別の名前で新規のシークレットを作成します。

2.6.4. シークレットで署名証明書を使用する方法

サービスの通信を保護するため、プロジェクト内のシークレットに追加可能な、署名されたサービス証明書/キーペアを生成するように OpenShift Container Platform を設定することができます。

サービス提供証明書のシークレット は、追加設定なしの証明書を必要とする複雑なミドルウェアアプリケーションをサポートするように設計されています。これにはノードおよびマスターの管理者ツールで生成されるサーバー証明書と同じ設定が含まれます。

サービス提供証明書のシークレット用に設定されるサービス Pod 仕様

apiVersion: v1
kind: Service
metadata:
  name: registry
  annotations:
    service.beta.openshift.io/serving-cert-secret-name: registry-cert1
# ...

1
証明書の名前を指定します。

他の Pod は Pod に自動的にマウントされる /var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt ファイルの CA バンドルを使用して、クラスターで作成される証明書 (内部 DNS 名の場合にのみ署名される) を信頼できます。

この機能の署名アルゴリズムは x509.SHA256WithRSA です。ローテーションを手動で実行するには、生成されたシークレットを削除します。新規の証明書が作成されます。

2.6.4.1. シークレットで使用する署名証明書の生成

署名されたサービス証明書/キーペアを Pod で使用するには、サービスを作成または編集して service.beta.openshift.io/serving-cert-secret-name アノテーションを追加した後に、シークレットを Pod に追加します。

手順

サービス提供証明書のシークレット を作成するには、以下を実行します。

  1. サービスの Pod 仕様を編集します。
  2. シークレットに使用する名前に service.beta.openshift.io/serving-cert-secret-name アノテーションを追加します。

    kind: Service
    apiVersion: v1
    metadata:
      name: my-service
      annotations:
          service.beta.openshift.io/serving-cert-secret-name: my-cert 1
    spec:
      selector:
        app: MyApp
      ports:
      - protocol: TCP
        port: 80
        targetPort: 9376

    証明書およびキーは PEM 形式であり、それぞれ tls.crt および tls.key に保存されます。

  3. サービスを作成します。

    $ oc create -f <file-name>.yaml
  4. シークレットを表示して、作成されていることを確認します。

    1. すべてのシークレットの一覧を表示します。

      $ oc get secrets

      出力例

      NAME                     TYPE                                  DATA      AGE
      my-cert                  kubernetes.io/tls                     2         9m

    2. シークレットの詳細を表示します。

      $ oc describe secret my-cert

      出力例

      Name:         my-cert
      Namespace:    openshift-console
      Labels:       <none>
      Annotations:  service.beta.openshift.io/expiry: 2023-03-08T23:22:40Z
                    service.beta.openshift.io/originating-service-name: my-service
                    service.beta.openshift.io/originating-service-uid: 640f0ec3-afc2-4380-bf31-a8c784846a11
                    service.beta.openshift.io/expiry: 2023-03-08T23:22:40Z
      
      Type:  kubernetes.io/tls
      
      Data
      ====
      tls.key:  1679 bytes
      tls.crt:  2595 bytes

  5. このシークレットを使って Pod 仕様を編集します。

    apiVersion: v1
    kind: Pod
    metadata:
      name: my-service-pod
    spec:
      containers:
      - name: mypod
        image: redis
        volumeMounts:
        - name: foo
          mountPath: "/etc/foo"
      volumes:
      - name: foo
        secret:
          secretName: my-cert
          items:
          - key: username
            path: my-group/my-username
            mode: 511

    これが利用可能な場合、Pod が実行されます。この証明書は内部サービス DNS 名、 <service.name>.<service.namespace>.svc に適しています。

    証明書/キーのペアは有効期限に近づくと自動的に置換されます。シークレットの service.beta.openshift.io/expiry アノテーションで RFC3339 形式の有効期限の日付を確認します。

    注記

    ほとんどの場合、サービス DNS 名 <service.name>.<service.namespace>.svc は外部にルーティング可能ではありません。<service.name>.<service.namespace>.svc の主な使用方法として、クラスターまたはサービス間の通信用として、 re-encrypt ルートで使用されます。

2.6.5. シークレットのトラブルシューティング

サービス証明書の生成は以下を出して失敗します (サービスの service.beta.openshift.io/serving-cert-generation-error アノテーションには以下が含まれます)。

secret/ssl-key references serviceUID 62ad25ca-d703-11e6-9d6f-0e9c0057b608, which does not match 77b6dd80-d716-11e6-9d6f-0e9c0057b60

証明書を生成したサービスがすでに存在しないか、またはサービスに異なる serviceUID があります。古いシークレットを削除し、サービスのアノテーション (service.beta.openshift.io/serving-cert-generation-errorservice.beta.openshift.io/serving-cert-generation-error-num) をクリアして証明書の再生成を強制的に実行する必要があります。

  1. シークレットを削除します。

    $ oc delete secret <secret_name>
  2. アノテーションをクリアします。

    $ oc annotate service <service_name> service.beta.openshift.io/serving-cert-generation-error-
    $ oc annotate service <service_name> service.beta.openshift.io/serving-cert-generation-error-num-
注記

アノテーションを削除するコマンドでは、削除するアノテーション名の後に - を付けます。