Downward API

Overview

The downward API is a mechanism that allows containers to consume information about API objects without coupling to OKD. Such information includes the pod’s name, namespace, and resource values. Containers can consume information from the downward API using environment variables or a volume plug-in.

Selecting Fields

Fields within the pod are selected using the **FieldRef** API type. **FieldRef** has two fields:

FieldDescription

fieldPath

The path of the field to select, relative to the pod.

apiVersion

The API version to interpret the fieldPath selector within.

Currently, the valid selectors in the v1 API include:

SelectorDescription

metadata.name

The pod’s name. This is supported in both environment variables and volumes.

metadata.namespace

The pod’s namespace.This is supported in both environment variables and volumes.

metadata.labels

The pod’s labels. This is only supported in volumes and not in environment variables.

metadata.annotations

The pod’s annotations. This is only supported in volumes and not in environment variables.

status.podIP

The pod’s IP. This is only supported in environment variables and not volumes.

The **apiVersion** field, if not specified, defaults to the API version of the enclosing pod template.

Consuming Container Values Using the Downward API

Using Environment Variables

One mechanism for consuming the downward API is using a container’s environment variables. The **EnvVar** type’s **valueFrom** field (of type **EnvVarSource**) is used to specify that the variable’s value should come from a **FieldRef** source instead of the literal value specified by the **value** field. In the future, additional sources may be supported; currently the source’s **fieldRef** field is used to select a field from the downward API.

Only constant attributes of the pod can be consumed this way, as environment variables cannot be updated once a process is started in a way that allows the process to be notified that the value of a variable has changed. The fields supported using environment variables are:

  • Pod name

  • Pod namespace

    1. Create a ***pod.yaml*** file:

      1. apiVersion: v1
      2. kind: Pod
      3. metadata:
      4. name: dapi-env-test-pod
      5. spec:
      6. containers:
      7. - name: env-test-container
      8. image: gcr.io/google_containers/busybox
      9. command: [ "/bin/sh", "-c", "env" ]
      10. env:
      11. - name: MY_POD_NAME
      12. valueFrom:
      13. fieldRef:
      14. fieldPath: metadata.name
      15. - name: MY_POD_NAMESPACE
      16. valueFrom:
      17. fieldRef:
      18. fieldPath: metadata.namespace
      19. restartPolicy: Never
    2. Create the pod from the ***pod.yaml*** file:

      1. $ oc create -f pod.yaml
    3. Check the container’s logs for the **MY_POD_NAME** and **MY_POD_NAMESPACE** values:

      1. $ oc logs -p dapi-env-test-pod

Using the Volume Plug-in

Another mechanism for consuming the downward API is using a volume plug-in. The downward API volume plug-in creates a volume with configured fields extended into files. The **metadata** field of the **VolumeSource** API object is used to configure this volume. The plug-in supports the following fields:

  • Pod name

  • Pod namespace

  • Pod annotations

  • Pod labels

Example 1. Downward API Volume Plug-in Configuration

  1. spec:
  2. volumes:
  3. - name: podinfo
  4. downwardAPI:: (1)
  5. items: (2)
  6. -name: "labels" (3)
  7. fieldRef:
  8. fieldPath: metadata.labels (4)
1The metadata field of the volume source configures the downward API volume.
2The items field holds a list of fields to extend into the volume.
3The name of the file to extend the field into.
4The selector of the field to extend.

For example:

  1. Create a ***volume-pod.yaml*** file:

    1. kind: Pod
    2. apiVersion: v1
    3. metadata:
    4. labels:
    5. zone: us-east-coast
    6. cluster: downward-api-test-cluster1
    7. rack: rack-123
    8. name: dapi-volume-test-pod
    9. annotations:
    10. annotation1: "345"
    11. annotation2: "456"
    12. spec:
    13. containers:
    14. - name: volume-test-container
    15. image: gcr.io/google_containers/busybox
    16. command: ["sh", "-c", "cat /tmp/etc/pod_labels /tmp/etc/pod_annotations"]
    17. volumeMounts:
    18. - name: podinfo
    19. mountPath: /tmp/etc
    20. readOnly: false
    21. volumes:
    22. - name: podinfo
    23. downwardAPI:
    24. defaultMode: 420
    25. items:
    26. - fieldRef:
    27. fieldPath: metadata.name
    28. path: pod_name
    29. - fieldRef:
    30. fieldPath: metadata.namespace
    31. path: pod_namespace
    32. - fieldRef:
    33. fieldPath: metadata.labels
    34. path: pod_labels
    35. - fieldRef:
    36. fieldPath: metadata.annotations
    37. path: pod_annotations
    38. restartPolicy: Never
  2. Create the pod from the ***volume-pod.yaml*** file:

    1. $ oc create -f volume-pod.yaml
  3. Check the container’s logs and verify the presence of the configured fields:

    1. $ oc logs -p dapi-volume-test-pod
    2. cluster=downward-api-test-cluster1
    3. rack=rack-123
    4. zone=us-east-coast
    5. annotation1=345
    6. annotation2=456
    7. kubernetes.io/config.source=api

Consuming Container Resources Using the Downward API

When creating pods, you can use the downward API to inject information about computing resource requests and limits so that image and application authors can correctly create an image for specific environments.

You can do this using both the environment variable and volume plug-in methods.

Using Environment Variables

  1. When creating a pod configuration, specify environment variables that correspond to the contents of the **resources** field in the **spec.container** field:

    1. ....
    2. spec:
    3. containers:
    4. - name: test-container
    5. image: gcr.io/google_containers/busybox:1.24
    6. command: [ "/bin/sh", "-c", "env" ]
    7. resources:
    8. requests:
    9. memory: "32Mi"
    10. cpu: "125m"
    11. limits:
    12. memory: "64Mi"
    13. cpu: "250m"
    14. env:
    15. - name: MY_CPU_REQUEST
    16. valueFrom:
    17. resourceFieldRef:
    18. resource: requests.cpu
    19. - name: MY_CPU_LIMIT
    20. valueFrom:
    21. resourceFieldRef:
    22. resource: limits.cpu
    23. - name: MY_MEM_REQUEST
    24. valueFrom:
    25. resourceFieldRef:
    26. resource: requests.memory
    27. - name: MY_MEM_LIMIT
    28. valueFrom:
    29. resourceFieldRef:
    30. resource: limits.memory
    31. ....

    If the resource limits are not included in the container configuration, the downward API defaults to the node’s CPU and memory allocatable values.

  2. Create the pod from the ***pod.yaml*** file:

    1. $ oc create -f pod.yaml

Using the Volume Plug-in

  1. When creating a pod configuration, use the **spec.volumes.downwardAPI.items** field to describe the desired resources that correspond to the **spec.resources** field:

    1. ....
    2. spec:
    3. containers:
    4. - name: client-container
    5. image: gcr.io/google_containers/busybox:1.24
    6. command: ["sh", "-c", "while true; do echo; if [[ -e /etc/cpu_limit ]]; then cat /etc/cpu_limit; fi; if [[ -e /etc/cpu_request ]]; then cat /etc/cpu_request; fi; if [[ -e /etc/mem_limit ]]; then cat /etc/mem_limit; fi; if [[ -e /etc/mem_request ]]; then cat /etc/mem_request; fi; sleep 5; done"]
    7. resources:
    8. requests:
    9. memory: "32Mi"
    10. cpu: "125m"
    11. limits:
    12. memory: "64Mi"
    13. cpu: "250m"
    14. volumeMounts:
    15. - name: podinfo
    16. mountPath: /etc
    17. readOnly: false
    18. volumes:
    19. - name: podinfo
    20. downwardAPI:
    21. items:
    22. - path: "cpu_limit"
    23. resourceFieldRef:
    24. containerName: client-container
    25. resource: limits.cpu
    26. - path: "cpu_request"
    27. resourceFieldRef:
    28. containerName: client-container
    29. resource: requests.cpu
    30. - path: "mem_limit"
    31. resourceFieldRef:
    32. containerName: client-container
    33. resource: limits.memory
    34. - path: "mem_request"
    35. resourceFieldRef:
    36. containerName: client-container
    37. resource: requests.memory
    38. ....

    If the resource limits are not included in the container configuration, the downward API defaults to the node’s CPU and memory allocatable values.

  2. Create the pod from the ***volume-pod.yaml*** file:

    1. $ oc create -f volume-pod.yaml

Consuming Secrets Using the Downward API

When creating pods, you can use the downward API to inject Secrets so image and application authors can create an image for specific environments.

Using Environment Variables

  1. Create a secret.yaml file:

    1. apiVersion: v1
    2. kind: Secret
    3. metadata:
    4. name: mysecret
    5. data:
    6. password: cGFzc3dvcmQ=
    7. username: ZGV2ZWxvcGVy
    8. type: kubernetes.io/basic-auth
  2. Create a Secret from the secret.yaml file:

    1. oc create -f secret.yaml
  3. Create a ***pod.yaml*** file that references the username field from the above Secret:

    1. apiVersion: v1
    2. kind: Pod
    3. metadata:
    4. name: dapi-env-test-pod
    5. spec:
    6. containers:
    7. - name: env-test-container
    8. image: gcr.io/google_containers/busybox
    9. command: [ "/bin/sh", "-c", "env" ]
    10. env:
    11. - name: MY_SECRET_USERNAME
    12. valueFrom:
    13. secretKeyRef:
    14. name: mysecret
    15. key: username
    16. restartPolicy: Never
  4. Create the pod from the ***pod.yaml*** file:

    1. $ oc create -f pod.yaml
  5. Check the container’s logs for the **MY_SECRET_USERNAME** value:

    1. $ oc logs -p dapi-env-test-pod

Consuming ConfigMaps Using the Downward API

When creating pods, you can use the downward API to inject ConfigMap values so image and application authors can create an image for specific environments.

Using Environment Variables

  1. Create a ***configmap.yaml*** file:

    1. apiVersion: v1
    2. kind: ConfigMap
    3. metadata:
    4. name: myconfigmap
    5. data:
    6. mykey: myvalue
  2. Create a ConfigMap from the ***configmap.yaml*** file:

    1. oc create -f configmap.yaml
  3. Create a ***pod.yaml*** file that references the above ConfigMap:

    1. apiVersion: v1
    2. kind: Pod
    3. metadata:
    4. name: dapi-env-test-pod
    5. spec:
    6. containers:
    7. - name: env-test-container
    8. image: gcr.io/google_containers/busybox
    9. command: [ "/bin/sh", "-c", "env" ]
    10. env:
    11. - name: MY_CONFIGMAP_VALUE
    12. valueFrom:
    13. configMapKeyRef:
    14. name: myconfigmap
    15. key: mykey
    16. restartPolicy: Never
  4. Create the pod from the ***pod.yaml*** file:

    1. $ oc create -f pod.yaml
  5. Check the container’s logs for the **MY_CONFIGMAP_VALUE** value:

    1. $ oc logs -p dapi-env-test-pod

Environment Variable References

When creating pods, you can reference the value of a previously defined environment variable by using the $() syntax. If the environment variable reference can not be resolved, the value will be left as the provided string.

Using Environment Variable References

  1. Create a ***pod.yaml*** file that references an existing environment variable:

    1. apiVersion: v1
    2. kind: Pod
    3. metadata:
    4. name: dapi-env-test-pod
    5. spec:
    6. containers:
    7. - name: env-test-container
    8. image: gcr.io/google_containers/busybox
    9. command: [ "/bin/sh", "-c", "env" ]
    10. env:
    11. - name: MY_EXISTING_ENV
    12. value: my_value
    13. - name: MY_ENV_VAR_REF_ENV
    14. value: $(MY_EXISTING_ENV)
    15. restartPolicy: Never
  2. Create the pod from the ***pod.yaml*** file:

    1. $ oc create -f pod.yaml
  3. Check the container’s logs for the **MY_ENV_VAR_REF_ENV** value:

    1. $ oc logs -p dapi-env-test-pod

Escaping Environment Variable References

When creating a pod, you can escape an environment variable reference by using a double dollar sign. The value will then be set to a single dollar sign version of the provided value.

  1. Create a ***pod.yaml*** file that references an existing environment variable:

    1. apiVersion: v1
    2. kind: Pod
    3. metadata:
    4. name: dapi-env-test-pod
    5. spec:
    6. containers:
    7. - name: env-test-container
    8. image: gcr.io/google_containers/busybox
    9. command: [ "/bin/sh", "-c", "env" ]
    10. env:
    11. - name: MY_NEW_ENV
    12. value: $$(SOME_OTHER_ENV)
    13. restartPolicy: Never
  2. Create the pod from the ***pod.yaml*** file:

    1. $ oc create -f pod.yaml
  3. Check the container’s logs for the **MY_NEW_ENV** value:

    1. $ oc logs -p dapi-env-test-pod