# Kubernetes

<figure><img src="https://859776093-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FPL6k1aGsLiFiiJ3Y7zCl%2Fuploads%2FKG8reatDSzZZ0EBpKk5R%2Fimage.png?alt=media&#x26;token=8027f7d5-a804-4cc6-9cd9-0dc730c55043" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
ほとんどの事例で、Kubernetes External Secrets Operator連携を推奨します。本ページでは、外部シークレットオペレーターを使用しない連携方法について解説します。
{% endhint %}

## 機能

* Kubernetes内にKeeperボルトからシークレットを取り込みます
* すべてのポッドでKeeperボルトのシークレットにリアルタイムにアクセスできます
* Keeperボルトからローカルファイルシステムにファイル添付を安全にコピーします

{% hint style="info" %}
Keeper Secrets Manager機能の完全なリストについては、[概要](/keeperpam/jp/secrets-manager/overview.md)をご参照ください。
{% endhint %}

## 前提条件

このページでは、Secrets ManagerとKubernetesとの連携について説明します。 この連携を利用するための必要条件は以下のとおりです。

* Keeper Secrets Managerへのアクセス（詳細は、[クイックスタートガイド](/keeperpam/jp/secrets-manager/quick-start-guide.md)をご参照ください）
  * KeeperアカウントのSecrets Managerアドオンの有効化
  * Secrets Manager強制ポリシーが有効化されたロールを割り当てられたメンバーシップ
* シークレットを共有するKeeper [Secrets Managerアプリケーション](/keeperpam/jp/secrets-manager/about/terminology.md)
  * アプリケーションの作成手順については、[クイックスタートガイド](/keeperpam/jp/secrets-manager/quick-start-guide.md)をご参照ください

## 概説

Keeper Secrets ManagerをK8sクラスタに統合して、すべてのポッドでKeeperシークレットにリアルタイムにアクセスできます。

## 設定

### Secrets Managerの設定を作成

Commanderを使用して、Kubernetes用のSecrets Managerデバイスの設定を作成します。この設定はIPが固定されておらず、事前に初期化されていることにご注意ください。

次のコマンドを使用して、Commanderで設定を作成します。

`secrets-manager client add --app <APP NAME> --unlock-ip --config-init k8s`

**例:**

```
My Vault> sm client add --app MyAdd --unlock-ip --config-init k8s

Successfully generated Client Device
====================================

Initialized Config:

apiVersion: v1
data:
  config: ewog2N...ICIxMCIKfQ==
metadata:
  name: ksm-config
  namespace: default
type:Opaque

IP Lock:Disabled
Token Expires On:2021-10-13 12:45:45
App Access Expires on:Never
```

上記の例では、8行目から14行目までをコピーし、secret.yamlという名前のファイルに挿入します。 次に、**Kubectl**がインストールされたマシンを使用していて、クラスタにアクセスできる場合は、KSM SDKの設定をKubernetesシークレットに追加します。

```
$ kubectl apply -f secret.yaml
```

{% hint style="info" %}
Secrets Mangerの設定の作成について詳しくは、[設定のドキュメント](/keeperpam/jp/secrets-manager/about/secrets-manager-configuration.md)をご参照ください。
{% endhint %}

### 代替方法:ワンタイムアクセストークンとKSM CLI

または、Commander（もしくはVault UI）でワンタイムアクセストークンを生成し、[Keeper Secrets Manager CLI](/keeperpam/jp/secrets-manager/secrets-manager-command-line-interface.md)でワンタイムアクセストークンを使用した、以下に示すような設定（XX:XXXは置き換えます）を作成することもできます。

```yaml
$ ksm init k8s XX:XXX

apiVersion: v1
data:
  config: ewog2N[...]ICIxMCIKfQ==
kind:Secret
metadata:
  name: ksm-config
  namespace: default
type:Opaque
```

**Kubectl**がインストールされたマシンを使用していて、クラスタにアクセスできる場合は、`--apply`パラメータを設定して、KSM SDKの設定をKubernetesシークレットに自動的に追加できます。

トークンの引き換えの出力をファイルにパイプし、**Kubectl**で適用できます。 以下に例を示します。

```bash
$ ksm init k8s XX:XXX > secret.yaml
$ kubectl apply -f secret.yaml
secret/ksm-config created
```

## KSM設定の使用

KSM設定は、[シークレット](https://kubernetes.io/docs/concepts/configuration/secret/#using-secrets-as-environment-variables)を使用してK8sコンテナにプルできます。

```
apiVersion: v1
kind:Pod
metadata:
  name: secret-env-pod
spec:
  containers:
  - name: mycontainer
    image: my_container:XXXXX
    env:
      - name:KSM_CONFIG
        valueFrom:
          secretKeyRef:
            name: ksm-config
            key: config
  restartPolicy:Never
```

K8sクラスタで実行されているKeeper Developer SDKは、実行時に環境変数**KSM\_CONFIG**を使用してデバイス設定を取得し、Keeperボルトと通信します。

## 例

### 例1 - SDKを使用したカスタムアプリ

ウェブアプリケーションを使用してデータベースシークレットを表示するデプロイメントとサービスを生成する簡単な例を以下に示します。この例では、ウェブアプリケーション用のKeeper Python Developer SDKを使用します。このSDKでKubernetesシークレットから設定を取得し、KeeperボルトからPostgreSQLデータベース記録の情報を取得します。

Keeperボルトから、以下の情報を使用して「データベース」記録タイプが作成されます。

<figure><img src="https://859776093-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FPL6k1aGsLiFiiJ3Y7zCl%2Fuploads%2F7bxum7t0zP4vom8zWdSU%2Fimage.png?alt=media&#x26;token=f7d3b699-0991-4e4b-b3fb-9158c484e9fe" alt=""><figcaption></figcaption></figure>

では、ウェブアプリケーションを作成しましょう。ウェブページは、任意の開発者用SDKを使用して作成できます。この例では、Python SDKを使用します。単一のエンドポイントを指定する単純なFlaskアプリケーションは、ボルトの記録シークレットを含むHTMLを表示します。シークレットは、[Keeper表記法](/keeperpam/jp/secrets-manager/about/keeper-notation.md)構文を使用して取得されます。

```
from flask import Flask
from keeper_secrets_manager_core import SecretsManager
import os

app = Flask(__name__)

@app.route("/")
def hello_world():
    sm = SecretsManager()
    return """
<h1>Database</h1>
<ul>
    <li>Type: {}</li>
    <li>Host: {}</li>
    <li>Port: {}</li>
    <li>Login: {}</li>
    <li>Password: {}</li>
</ul>
""".format(
       sm.get_notation(os.environ.get("DB_TYPE")),
       sm.get_notation(os.environ.get("DB_HOST")),
       sm.get_notation(os.environ.get("DB_PORT")),
       sm.get_notation(os.environ.get("DB_LOGIN")),
       sm.get_notation(os.environ.get("DB_PASS")))
```

次のパートでは、**Dockerfile**を作成します。以下のDockerfileのベースは、Docker HubのPython Debianイメージです。

{% hint style="info" %}
Python SDKは、暗号化モジュールを使用します。このモジュールはRust言語をインストールする必要があります。RustがプレインストールされているDocker Hubイメージもあります。
{% endhint %}

```
FROM python:3.10.0-slim-bullseye
RUN apt-get update \
    && apt-get install -y gcc make libffi-dev curl libssl-dev \
    && apt-get clean
RUN pip3 install --upgrade pip wheel

# 暗号化のビルドにRustが必要
RUN curl https://sh.rustup.rs -sSf > /tmp/rust.sh \
    && chmod a+x /tmp/rust.sh \
    && /tmp/rust.sh -y
ENV PATH $PATH:/root/.cargo/bin

RUN pip3 install \
    flask \
    keeper-secrets-manager-core

RUN groupadd -g 5000 demo
RUN useradd -g demo demo

# アプリケーションをイメージにコピー
COPY demo.py /demo.py

USER demo

ENV FLASK_APP demo

EXPOSE 5000
CMD ["flask", "run"]
```

次に、ksm\_demoという名前のDockerイメージをビルドします。

```
$ docker build -t ksm_demo .
```

Kubernetesクラスタにアクセスできると仮定すると、設定はワンタイムアクセストークンから生成されて、自動的に適用されます。

```
$ ksm init k8s --apply XX:XXXXXXXXXXX
secret/ksm-config created
Created secret for KSM config.
```

`kubectl get secret`と入力すると、シークレットのエントリが表示されます。

```
$ kubectl get secret ksm-config
NAME         TYPE     DATA   AGE
ksm-config   Opaque   1      55s
```

これで、**ksm\_demo** Dockerイメージのデプロイメントとサービスを作成できます。この例では、ファイルに**ksm\_demo.yaml**という名前を付けます。

必要なシークレットとSDKの設定は、**コンテナ**の一覧の**env**セクションで定義します。このセクションでは、**KSM\_CONFIG**環境変数を定義して、**ksm-config** Kubernetesシークレット、特にシークレットの**config**キーの値を取得します。

他の環境変数は単なる名前/値のリストです。この値はKeeper表記法で、ウェブアプリケーションによってSDKの表記法取得メソッドに送信されます。

**ksm\_demo.yaml**ファイルの2番目の記録は、**サービス**の定義です。これは、Kubernetesクラスタで動作するサービスであれば何にでも変更できます。この例では、外部IPアドレスを使用します。この例では、KubernetesノードのIPアドレスのいずれかを使用するのが安全です。たとえば、10.0.1.18を使用します。

```
---
apiVersion: apps/v1
kind:Deployment
metadata:
  name: ksm-demo-deployment
  labels:
    app: ksm-demo
spec:
  replicas:1
  selector:
    matchLabels:
      app: ksm-demo
  template:
    metadata:
      labels:
        app: ksm-demo
    spec:
      nodeSelector:
        kubernetes.io/hostname: work
      dnsPolicy:"None"
      dnsConfig:
        nameservers:
          - 10.0.1.207
          - 1.1.1.1
      containers:
        - name: ksm-demo
          image: ksm_demo:latest
          imagePullPolicy:IfNotPresent
          ports:
            - containerPort:5000
              protocol:TCP
          env:
            - name:KSM_CONFIG
              valueFrom:
                secretKeyRef:
                  name: ksm-config
                  key: config
            - name:DB_TYPE
              value: "keeper://IUCvqyWcx7sG-BGIK1R9-g/field/Type"
            - name:DB_HOST
              value: "keeper://IUCvqyWcx7sG-BGIK1R9-g/field/host[hostName]"
            - name:DB_PORT
              value: "keeper://IUCvqyWcx7sG-BGIK1R9-g/field/host[port]"
            - name:DB_LOGIN
              value: "keeper://IUCvqyWcx7sG-BGIK1R9-g/field/login"
            - name:DB_PASS
              value: "keeper://IUCvqyWcx7sG-BGIK1R9-g/field/password"
---   
apiVersion: v1
kind:Service
metadata:
  name: ksm-demo-service
spec:
  ports:
    - name: http
      port:5000
      targetPort:5000
      protocol:TCP
  selector:
    app: ksm-demo
  externalIPs:
    - 10.0.1.18
```

これで、デプロイメントとサービスを適用する準備ができました。

```
$ kubectl apply -f ksm_demo.yaml
deployment/ksm-demo-deployment created
service/ksm-demo-service created
```

デプロイメントの準備ができるまで待ちます。コマンドラインまたはKubernetesダッシュボードを使用して監視します。

```
$ kubectl get deployment ksm-demo-deployment
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
ksm-demo-deployment   1/1     1            1           46m

$ kubectl get svc ksm-demo-service
NAME               TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
ksm-demo-service   ClusterIP   10.107.91.89   10.0.1.18     5000/TCP   56m
```

最後に、ウェブブラウザを使用して外部IPアドレスのポート5000にアクセスすると、Keeperボルトのデータベース記録のシークレットが表示されます。

<figure><img src="https://859776093-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FPL6k1aGsLiFiiJ3Y7zCl%2Fuploads%2Fp6x0OINeGFu9qfwvtdRr%2Fimage.png?alt=media&#x26;token=e81b880a-473a-4743-86b8-84bd411603cc" alt=""><figcaption><p>Keeperシークレットを表示するウェブアプリケーションの例</p></figcaption></figure>

### 例2 - NGINX SSL証明書

この例では、Keeperボルトから取得したデフォルトのNGINX DockerイメージとSSL証明書を含むポッドが作成されます。

SSL証明書、秘密鍵、証明書のパスワードを格納するログイン記録がボルトに作成されます。

<figure><img src="https://859776093-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FPL6k1aGsLiFiiJ3Y7zCl%2Fuploads%2FkxHJEWDI0BCEIuVp97ew%2Fimage.png?alt=media&#x26;token=16779bdc-683b-4259-8e50-7ae1af836af6" alt=""><figcaption></figcaption></figure>

ワンタイムトークンが生成され、KubernetesのConfigMapに追加されます。

```bash
$ ksm init k8s XX:XXX > secret.yaml
$ kubectl apply -f secret.yaml
secret/ksm-config created
```

例のウェブサイトは、単なるインデックスHTMLページです。このHTMLをConfigMapに保存して、ドキュメントのルートディレクトリにマウントできます。

```yaml
---
apiVersion: v1
kind:ConfigMap
metadata:
  name: nginx-html-config
  namespace: default
  labels:
    app: nginx
data:
  index.html: |
    <html>
      <head>
         <title>Nginx Test Page</title>
      </head>
      <body>
        <h1>Hello From Keeper Secrets Manager!</h1>
      </body>
    </html>
```

`default.conf`は、この例によって上書きされます。証明書、鍵、パスワードは、`/etc/keys`ディレクトリに格納されます。非対話型起動の場合、NGINXは証明書のパスワードをファイルに格納し、サーバー設定で`ssl_password_file`を指定する必要があります。

```yaml
---
apiVersion: v1
kind:ConfigMap
metadata:
  name: nginx-config
  namespace: default
  labels:
    app: nginx
data:
  default.conf: |
    server {
      listen 80 default;
      server_name localhost;
      location / {
        root /var/www/nginx-default;
        index index.html index.htm;
      }
    }
    server {
      listen 443 ssl;
      server_name localhost;
      ssl_certificate /etc/keys/example.com.crt;
      ssl_certificate_key /etc/keys/example.com.key;
      ssl_password_file /etc/keys/global.pass;
      ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
      ssl_ciphers HIGH:!aNULL:!MD5;
      location / {
        root /var/www/nginx-default;
        index index.html index.htm;
      }
    }
```

この例のデプロイメントは以下のようになります。

```yaml
---
apiVersion: apps/v1
kind:Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas:1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      initContainers:
        - name: ksm
          image: keeper/keeper-secrets-manager-writer:latest
          env:
            - name:KSM_CONFIG
              valueFrom:
                secretKeyRef:
                  name: ksm-config
                  key: config
            - name:SECRETS
              value: |
                5x0v0VFwYj2VvuhamrJhzQ/field/password > file:/etc/keys/global.pass
                5x0v0VFwYj2VvuhamrJhzQ/file/example.com.crt > file:/etc/keys/example.com.crt
                5x0v0VFwYj2VvuhamrJhzQ/file/example.com.key > file:/etc/keys/example.com.key
          volumeMounts:
            - mountPath: "/etc/keys"
              name: keys-volume
      containers:
        - name: nginx
          image: nginx:1.21.4-alpine
          imagePullPolicy:IfNotPresent
          ports:
            - containerPort:80
              protocol:TCP
            - containerPort:443
              protocol:TCP
          volumeMounts:
            - mountPath: "/etc/keys"
              name: keys-volume
            - mountPath: "/etc/nginx/conf.d/default.conf"
              name: nginx-config-file
              subPath: default.conf
            - mountPath: "/var/www/nginx-default/index.html"
              name: nginx-html-file
              subPath: index.html
      volumes:
        - name: keys-volume
          emptyDir: {}
        - name: nginx-config-file
          configMap:
            name: nginx-config
        - name: nginx-html-file
          configMap:
            name: nginx-html-config
      imagePullSecrets:
        - name: my-docker-hub-secrets
```

初期化コンテナには、dockerイメージ`keeper/keeper-secrets-manager-writer`が使用されます。コンテナはシークレットを取得し、NGINXで使用できるようにディスクに書き込みます。シークレットはポッドのemptyDirボリュームに書き込まれ、/etc/keysにマウントされます。このディレクトリは、ポッドが削除されると削除されます。

{% hint style="info" %}
Keeper Secrets Manager Writerのドキュメントは[こちら](/keeperpam/jp/secrets-manager/integrations/docker-writer-image.md)で入手できます。
{% endhint %}

また、メインコンテナは、ポッドのemptyDirボリュームを/etc/keysにマウントします。さらに、`default.conf`を/etc/nginx/conf.dにマウントし、`index.html`ファイルをサーバーのドキュメントルートにマウントします。

最後は、以下に示すように、NGINXにアクセスするサービスを作成します。

```
---
apiVersion: v1
kind:Service
metadata:
  name: nginx-service
spec:
  ports:
    - name: http
      port:80
      targetPort: 80
      protocol:TCP
    - name: https
      port:443
      targetPort:443
      protocol:TCP
  selector:
    app: nginx
  externalIPs:
    - XXX.XXX.XXX.XX
```

サービスは、httpsで外部IP（<https://XXX.XXX.XXX.XXX）にアクセスしてテストできます。アドレスバーの鍵が証明書が有効であることを示していることにご注意ください。>

<figure><img src="https://859776093-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FPL6k1aGsLiFiiJ3Y7zCl%2Fuploads%2FLz7EUo1xCZN8fkjm9nK0%2Fimage.png?alt=media&#x26;token=3eea67a5-d42e-4b7c-8b4d-8127c363a9fa" alt=""><figcaption></figcaption></figure>

### 外部シークレット

外部シークレットは、外部APIからのシークレットを同期してKubernetesに注入するKubernetesオペレータです。KeeperボルトからKubernetesにシークレットを同期するために外部シークレットをセットアップする方法の詳細については、こちらをご参照ください。

### 次の手順

この時点で、[Secrets Manager SDK](/keeperpam/jp/secrets-manager/developer-sdk-library.md)のいずれかを使用して、Keeper Secrets ManagerをK8sデプロイメントに統合できるようになりました。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.keeper.io/keeperpam/jp/secrets-manager/integrations/kubernetes.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
