k 8 sのセキュリティ情報(secret)及び構成情報(configmap)管理


アプリケーションの起動中に、データベースにアクセスするユーザー名パスワードや鍵などの機密情報が必要になる場合があります.これらの情報をコンテナミラーに直接保存するのは明らかに不適切であり,Kubernetesが提供する解決策はSecretである.
Secretは、機密情報をプロファイルに直接保存することを避けるために、暗号化された方法でデータを格納します.SecretはVolumeとしてPodにmountされ、コンテナはSecretの機密データをファイルで使用することができる.また、コンテナは、これらのデータを環境変数として使用することもできます.
SecretはコマンドラインまたはYAMLで作成できます.たとえば、Secretには次の情報が含まれます.
  • ユーザ名admin
  • パスワード123456
  • Secretの作成
    Secretを作成するには、次の4つの方法があります.
  • は、--from-literal:
    kubectl create secret generic mysecret --from-literal=username=admin --from-literal=password=123456
    各--from-literalによって1つの情報エントリに対応する.
  • は、--from-file:
    echo -n admin > ./username
    echo -n 123456 > ./password
    kubectl create secret generic mysecret --from-file=./username --from-file=./password
    ファイルコンテンツごとに1つの情報エントリに対応する.
  • は、--from-env-file:
    cat << EOF > env.txt
    username=admin
    password=123456
    EOF
    kubectl create secret generic mysecret --from-env-file=env.txt
    ファイルenv.txtの各行Key=Valueで情報エントリを対応します.
  • YAMLプロファイル経由:
    apiVersion: v1
    kind: Secret
    metadata:
    name: mysecret
    data:
    username: YWRtaW4=
    password: MTIzNDU2
  • ファイル内の機密データはbase 64によって符号化された結果でなければならない.
    [root@k8s-master ~]# echo -n admin |base64
    YWRtaW4=
    [root@k8s-master ~]# echo -n 123456 | base64
    MTIzNDU2

    kubectl applyを実行してSecretを作成します.
    # kubectl apply -f mysecrete.yml
    secret/mysecret created

    これらを使用して作成したSecret.
    表示Secreはkubectl get secretで存在するsecretを表示できます.
    [root@k8s-master ~]# kubectl get secrets 
    NAME                  TYPE                                  DATA   AGE
    default-token-5l66h   kubernetes.io/service-account-token   3      14d
    mysecret              Opaque                                2      20s

    2つのデータエントリが表示され、kubectl describe secretはエントリのKeyを表示します.
    [root@k8s-master ~]# kubectl describe secrets mysecret 
    Name:         mysecret
    Namespace:    default
    Labels:       
    Annotations:  
    Type:         Opaque
    
    Data
    ====
    password:  6 bytes
    username:  5 bytes
    [root@k8s-master ~]# 

    Valueも表示したい場合は、kubectl edit secret mysecretを使用します.
    apiVersion: v1
    data:
      password: MTIzNDU2
      username: YWRtaW4=
    kind: Secret
    metadata:
      annotations:
        kubectl.kubernetes.io/last-applied-configuration: |
          {"apiVersion":"v1","data":{"password":"MTIzNDU2","username":"YWRtaW4="},"kind":"Secret","metadata":{"annotations":{},"name":"mysecret","namespace":"default"}}
      creationTimestamp: "2019-10-14T08:26:43Z"
      name: mysecret
      namespace: default
      resourceVersion: "13845"
      selfLink: /api/v1/namespaces/default/secrets/mysecret
      uid: a713292c-6fea-4065-b5ae-239f8fe9a76f
    type: Opaque
    ~              

    次に、base 64を介してValueを逆符号化する.
    [root@k8s-master ~]# echo -n MTIzNDU2 |base64 --decode 
    123456
    
    # echo -n YWRtaW4=  |base64 --decode                  
    admin[root@k8s-master ~]# 

    PodでSecretを使用する方法.
    volume方式使用Secret
    Podは、Volumeまたは環境変数によってSecretを使用することができる.
    Podのプロファイルは次のとおりです.
    apiVersion: v1
    kind: Pod
    metadata:
      name: mypod
    spec:
      containers:
      - name: mypod
        image: busybox
        args:
          - /bin/sh
          - -c 
          - sleep 10;touch /tmp/healthy;sleep 30000
        volumeMounts:
        - name: foo
          mountPath: /etc/foo
          readOnly: true
      volumes:
      - name: foo
        secret:
          secretName: mysecret

    ①volume fooを定義し、ソースはsecret mysecretです.
    ②foo mountをコンテナパス/etc/fooに、readOnlyとして読み書き権限を指定します.
    Podを作成し、コンテナでSecretを読み込みます.
    [root@k8s-master ~]# kubectl apply -f mypod.yml
    pod/mypod created
    [root@k8s-master ~]# kubectl exec -it mypod sh 
    / # ls /etc/foo/
    password  username
    / # cat /etc/foo/username 
    admin/ # 
    / # cat /etc/foo/password 
    123456/ # 
    / # 
    / # exit

    Kubernetesは、指定したパス/etc/fooの下で機密データごとにファイルを作成します.ファイル名はデータエントリのKeyです.ここでは/etc/foo/usernameと/etc/foo/passwordです.Valueはファイルに明文で保存されます.
    プロファイルを次のように変更するなど、データを格納するファイル名をカスタマイズすることもできます.
    
    apiVersion: v1
    kind: Pod
    metadata:
      name: mypod
    spec:
      containers:
      - name: mypod
        image: busybox
        args:
          - /bin/sh
          - -c 
          - sleep 10;touch /tmp/healthy;sleep 30000
        volumeMounts:
        - name: foo
          mountPath: /etc/foo
          readOnly: true
      volumes:
      - name: foo
        secret:
          secretName: mysecret
          items:
          - key: username
            path: my-group/my-username
          - key: password
            path: my-group/my-password

    このとき、データは/etc/foo/my-group/my-usernameおよび/etc/foo/my-group/my-passwordにそれぞれ格納されます.
    Volume方式で使用されるSecretは動的更新をサポートします.Secretが更新されると、コンテナ内のデータも更新されます.
    passwordをabcdefに更新し、base 64をYWJjZGVmに符号化する
    [root@k8s-master ~]# cat mysecrete.yml 
    apiVersion: v1
    kind: Secret
    metadata:
      name: mysecret
    data:
      username: YWRtaW4=
      password: YWJjZGVm

    Secretを更新します.
    [root@k8s-master ~]# kubectl apply -f mysecrete.yml
    secret/mysecret configured

    待機すると、新しいpasswordがコンテナに同期します.
    /etc/foo/..2019_10_14_09_42_09.863448745/my-group # cat my-password 
    abcdef/etc/foo/..2019_10_14_09_42_09.863448745/my-group # 

    環境変数方式使用Secret
    VolumeでSecretを使用すると、コンテナはファイルからデータを読み込む必要があります.少し面倒ですが、Kubernetesでは環境変数でSecretを使用することもサポートされています.
    Podプロファイルの例は次のとおりです.
    apiVersion: v1
    kind: Pod
    metadata:
      name: mypod
    spec:
      containers:
      - name: mypod
        image: busybox
        args:
          - /bin/sh
          - -c
          - sleep 10; touch /tmp/healthy; sleep 30000
        env:
          - name: SECRET_USERNAME
            valueFrom:
              secretKeyRef:
                name: mysecret
                key: username
          - name: SECRET_PASSWORD
            valueFrom:
              secretKeyRef:
                name: mysecret
                key: password

    Podを作成し、Secretを読み込みます.
    [root@k8s-master ~]# kubectl apply -f mysql-env.yml
    pod/mypod created
    [root@k8s-master ~]# kubectl exec -it mypod sh
    / # echo $SECRET_USERNAME
    admin
    / # echo $SECRET_PASSWORD
    123456
    / # 

    環境変数SECRET_USERNAMEとSECRET_PASWORDはSecretのデータの読み込みに成功しました.
    環境変数によるSecretの読み取りは便利ですが、Secretの動的更新はサポートされていません.
    SecretはPodにパスワード、Token、秘密鍵などの機密データを提供することができる.アプリケーションの構成情報などの非機密データについては、ConfigMapを使用できます.
    コンフィギュレーションの管理
    SecretはPodにパスワード、Token、秘密鍵などの機密データを提供することができる.アプリケーションの構成情報などの非機密データについては、ConfigMapを使用できます.
    ConfigMapの作成と使用方法はSecretと非常に似ており、主な違いはデータが明文で保存されていることです.
    Secretと同様に、ConfigMapは4つの作成方法をサポートしています.
  • は、--from-literal:
    kubectl create configmap myconfigmap --from-literal=config1=xxx --from-literal=config2=yyy
    各--from-literalによって1つの情報エントリに対応する.
  • は、--from-file:
    echo -n xxx > ./config1
    echo -n yyy > ./config2
    kubectl create configmap myconfigmap --from-file=./config1 --from-file=./config2
    ファイルコンテンツごとに1つの情報エントリに対応する.
  • は、--from-env-file:
    cat << EOF > env.txt
    config1=xxx
    config2=yyy
    EOF
    kubectl create configmap myconfigmap --from-env-file=env.txt
    ファイルenv.txtの各行Key=Valueで情報エントリを対応します.
  • YAMLプロファイル:
    apiVersion: v1
    kind: ConfigMap
    metadata:
    name: myconfigmap1
    data:
    config1: xxx
    config2: yyy
    ファイル内のデータをそのまま明文で入力します.

  • Secretと同様に、PodはVolumeまたは環境変数でSecretを使用することもできます.
    Volume方式:
    apiVersion: v1
    kind: Pod
    metadata:
      name: mypod
    spec:
      containers:
      - name: mypod
        image: busybox
        args:
          - /bin/sh
          - -c
          - sleep 10; touch /tmp/healthy; sleep 30000
        volumeMounts:
        - name: foo
          mountPath: /etc/foo
          readOnly: true
      volumes:
      - name: foo
        configMap:
          name: myconfigmap

    環境変数の方法:
    apiVersion: v1
    kind: Pod
    metadata:
      name: mypod
    spec:
      containers:
      - name: mypod
        image: busybox
        args:
          - /bin/sh
          - -c
          - sleep 10; touch /tmp/healthy; sleep 30000
        env:
          - name: CONFIG_1
            valueFrom:
              configMapKeyRef:
                name: myconfigmap
                key: config1
          - name: CONFIG_2
            valueFrom:
              configMapKeyRef:
                name: myconfigmap
                key: config2

    ほとんどの場合、コンフィギュレーション情報はファイル形式で提供されるため、コンフィギュレーションMapの作成には通常--from-fileまたはYAML方式が採用され、コンフィギュレーションMapの読み取りには通常Volume方式が採用される.
    たとえば、Podにログを記録する方法の構成情報を渡します.
    class: logging.handlers.RotatingFileHandler
    formatter: precise
    level: INFO
    filename: %hostname-%timestamp.log

    --from-file形式でファイルlogging.confに保存し、コマンドを実行できます.
    # kubectl create configmap myconfigmap2 --from-file=./logging.conf 

    kubectl create configmap myconfigmap--from-file=./logging.conf YAMLプロファイルを使用する場合、その内容は次のとおりです.
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: myconfigmap3
    data:
      logging.conf: |
        class: logging.handlers.RotatingFileHandler
        formatter: precise
        level: INFO
        filename: %hostname-%timestamp.log

    Keylogging.confの後ろの|記号を書き落とさないように注意してください.
    ConfigMapを作成して表示するには、次の手順に従います.
    [root@k8s-master ~]# kubectl apply -f myconfigmap2.yml
    configmap/myconfigmap3 created
    [root@k8s-master ~]# kubectl get configmaps myconfigmap3 
    NAME           DATA   AGE
    myconfigmap3   1      2m39s
    [root@k8s-master ~]# kubectl describe configmaps myconfigmap3
    Name:         myconfigmap3
    Namespace:    default
    Labels:       
    Annotations:  kubectl.kubernetes.io/last-applied-configuration:
                    {"apiVersion":"v1","data":{"logging.conf":"class: logging.handlers.RotatingFileHandler
    formatter: precise
    level: INFO
    filename: %hostna... Data ==== logging.conf: ---- class: logging.handlers.RotatingFileHandler formatter: precise level: INFO filename: %hostname-%timestamp.log Events: [root@k8s-master ~]#

    このコンフィギュレーションファイルは、Podで次のように使用されます.
    apiVersion: extensions/v1beta1
    kind: Deployment
    metadata:
      name: nginx-configmap
    spec:
      replicas: 1
      template:
        metadata:
          labels:
            app: nginx-configmap
        spec:
          containers:
          - name: nginx-configmap
            image: nginx
            ports:
            - containerPort: 80
            volumeMounts:     
            - name: config-volume4
              mountPath: /tmp/config4
          volumes:
          - name: config-volume4
            configMap:
              name: myconfigmap

    ①volumeで設定情報を格納するファイルの相対パスをmyapp/logging.confと指定します.
    ②volume mountをコンテナの/etcディレクトリに移動します.
    Podを作成し、構成情報を読み込みます.
    構成情報は/etc/myapp/logging.confファイルに保存されています.Secretと同様に、Volume形式のConfigMapもダイナミックな更新をサポートし、自分で実践しています.
    小結はPodに構成情報を伝達する.情報を暗号化する必要がある場合は、Secretを使用します.一般的な構成情報の場合は、ConfigMapを使用します.
    SecretとConfigMapは4つの定義方法をサポートしています.Podはそれらを使用する場合、Volume方式または環境変数方式を選択できますが、動的更新はVolume方式のみサポートされています.