Kekeの日記

エンジニア、読書なんでも

KubernetesのDownwardAPI

f:id:bobchan1915:20181007184738p:plain

本記事

本記事はKuberenetesのDownward APIを使ってみて学習します。

目次

Downward API

なぜ Downward というの?

KuberenetesのWorkloadsリソースの概念は非常に階層的になっていて、上位のものが下位のものを管理しています。

以下のような階層になっています(上にいけばいくほど上位なものです)。

たとえば

  • Deployment
  • ReplicaSets
  • Pod

だったり、

  • CronJob
  • Job
  • Pod

のような関係性です。またリソースではありませんがPodはいくつかのコンテナによって構成されるため

  • Pod
  • Container[]

のような階層があると言えます。今回はこの関係性について注目します。

このようにPodはReplicaSetsに管理され(情報を渡し)、ReplicaSetsはDeploymentに管理され(情報を渡し)たりする関係がUpwardであり、Downwardはその逆です。

Downwardとはクラスタの概念的な外部からアトミックな構成要素であるコンテナまで内部にもぐるような概念です。

一例としてPodがコンテナに情報を渡したりします。

またイメージ図を書きました。

f:id:bobchan1915:20181007184738p:plain

そしてPodからコンテナに情報が渡せるAPIのことをDownward APIといいます。

どのように使えるの

2種類の方法で使うことができます。

  • 環境変数としてセットする
  • DownwardAPIVolunmFileとしてセットする

環境変数としてロードする

Podフィールドを環境変数のために使う

以下のようにDownload APIを使えます。

たとえばPodのマニフェストファイルに以下のように定義します。

pods/inject/dapi-envars-pod.yaml  
apiVersion: v1
kind: Pod
metadata:
  name: dapi-envars-fieldref
spec:
  containers:
    - name: test-container
      image: k8s.gcr.io/busybox
      command: [ "sh", "-c"]
      args:
      - while true; do
          echo -en '\n';
          printenv MY_NODE_NAME MY_POD_NAME MY_POD_NAMESPACE;
          printenv MY_POD_IP MY_POD_SERVICE_ACCOUNT;
          sleep 10;
        done;
      env:
        - name: MY_NODE_NAME
          valueFrom:
            fieldRef:
              fieldPath: spec.nodeName
        - name: MY_POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: MY_POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        - name: MY_POD_IP
          valueFrom:
            fieldRef:
              fieldPath: status.podIP
        - name: MY_POD_SERVICE_ACCOUNT
          valueFrom:
            fieldRef:
              fieldPath: spec.serviceAccountName
  restartPolicy: Never

ここでDownload APIを使っているのはspec.env[].valueFrom.fieldRefで取得した値をenvとしてロードしています。

Podの情報へのアクセス方法ですがmetadaata.namespec.nodeNameのようにPodにアクセスしてください。

特にspecなどでアクセスするものはスケジュールされたあとに書き込まれるものです。

コンテナのフィールドを環境変数として使う

ここで先ほどとは異なり、valueFrom.resouceFieldRefになっています。

ここではcontainerNameで指定してコンテナのリソースを例えばrequest.cpuのように指定することになります。

valueFrom:
            resourceFieldRef:
              containerName: test-container
              resource: requests.cpu
apiVersion: v1
kind: Pod
metadata:
  name: dapi-envars-resourcefieldref
spec:
  containers:
    - name: test-container
      image: k8s.gcr.io/busybox:1.24
      command: [ "sh", "-c"]
      args:
      - while true; do
          echo -en '\n';
          printenv MY_CPU_REQUEST MY_CPU_LIMIT;
          printenv MY_MEM_REQUEST MY_MEM_LIMIT;
          sleep 10;
        done;
      resources:
        requests:
          memory: "32Mi"
          cpu: "125m"
        limits:
          memory: "64Mi"
          cpu: "250m"
      env:
        - name: MY_CPU_REQUEST
          valueFrom:
            resourceFieldRef:
              containerName: test-container
              resource: requests.cpu
        - name: MY_CPU_LIMIT
          valueFrom:
            resourceFieldRef:
              containerName: test-container
              resource: limits.cpu
        - name: MY_MEM_REQUEST
          valueFrom:
            resourceFieldRef:
              containerName: test-container
              resource: requests.memory
        - name: MY_MEM_LIMIT
          valueFrom:
            resourceFieldRef:
              containerName: test-container
              resource: limits.memory
  restartPolicy: Never

他にも以下の様な項目がある。

spec:
  containers:
  - env:
    - name: MY_NODE_NAME
      valueFrom:
        fieldRef:
          fieldPath: spec.nodeName
    # Kubernetes 1.7+
    - name: MY_NODE_IP
      valueFrom:
        fieldRef:
          fieldPath: status.hostIP
    - name: MY_POD_NAME
      valueFrom:
        fieldRef:
          fieldPath: metadata.name
    - name: MY_POD_NAMESPACE
      valueFrom:
        fieldRef:
          fieldPath: metadata.namespace
    - name: MY_POD_IP
      valueFrom:
        fieldRef:
          fieldPath: status.podIP
    - name: MY_POD_SERVICE_ACCOUNT
      valueFrom:
        fieldRef:
          fieldPath: spec.serviceAccountName
    # Kubernetes 1.8+
    - name: MY_POD_UID
      valueFrom:
        fieldRef:
          fieldPath: metadata.uid
    - name: MY_CPU_REQUEST
      valueFrom:
        resourceFieldRef:
          containerName: <CONTAINER_NAME>
          resource: requests.cpu
    - name: MY_CPU_LIMIT
      valueFrom:
        resourceFieldRef:
          containerName: <CONTAINER_NAME>
          resource: limits.cpu
    - name: MY_MEM_REQUEST
      valueFrom:
        resourceFieldRef:
          containerName: <CONTAINER_NAME>
          resource: requests.memory
    - name: MY_MEM_LIMIT
      valueFrom:
        resourceFieldRef:
          containerName: <CONTAINER_NAME>
          resource: limits.memory

DownwardAPIVolunmFileを使ってロードする

DownwardAPIVolunmFileはVolumeリソースの一部です。

提供されているAPIのバージョンはv1/coreです。

DownwardAPIVolunmFileはPodのフィールドを含むファイルを作るのに必要な情報を定義

しています。

以下のようなフィールドを持っています。

フィールド名 説明 必須?
fieldRef ObjectFieldSelector Podのフィールドを選択できる。指定できるのはannotationsnamenamespaceだけです。 ⭕️
mode integer モードビットである。chmodのように権限を管理する。0~0777の間で指定できる。何も指定しないとdefaultModeになる。
path string どこに作成されるかを相対パスで指定し..は使ってはいけない。 ⭕️
resouceFieldRef Containerフィールドを選択できる。 現在ではlimits.cpurequests.cpurequests.memoryがサポートされている ⭕️

以下の用に直接書いてもよいです。

volumes:
  - name: podinfo
    downwardAPI:
      items:
        - path: "nodename"
          fieldRef:
            fieldPath: spec.nodeName

しかし、わざわざリソースにするほどでもないので普通に環境変数として渡した方がクリアです。

参考文献

Expose Pod Information to Containers Through Environment Variables - Kubernetes

akomljen.com