Allowing containers to consume API objects

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 plugin.

Expose pod information to Containers using the Downward API

The Downward API contains such information as the pod’s name, project, and resource values. Containers can consume information from the downward API using environment variables or a volume plugin.

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.

Understanding how to consume container values using the downward API

You containers can consume API values using environment variables or a volume plugin. Depending on the method you choose, containers can consume:

  • Pod name

  • Pod project/namespace

  • Pod annotations

  • Pod labels

Annotations and labels are available using only a volume plugin.

Consuming container values using environment variables

When using a container’s environment variables, use the EnvVar type’s valueFrom field (of type EnvVarSource) to specify that the variable’s value should come from a FieldRef source instead of the literal value specified by the value field.

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 project/namespace

Procedure

  1. Create a new pod spec that contains the environment variables you want the container to consume:

    1. Create a pod.yaml file similar to the following:

      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
      20. # ...
    2. Create the pod from the pod.yaml file:

      1. $ oc create -f pod.yaml

Verification

  • Check the container’s logs for the MY_POD_NAME and MY_POD_NAMESPACE values:

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

Consuming container values using a volume plugin

You containers can consume API values using a volume plugin.

Containers can consume:

  • Pod name

  • Pod project/namespace

  • Pod annotations

  • Pod labels

Procedure

To use the volume plugin:

  1. Create a new pod spec that contains the environment variables you want the container to consume:

    1. Create a volume-pod.yaml file similar to the following:

      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
      39. # ...
    2. Create the pod from the volume-pod.yaml file:

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

Verification

  • Check the container’s logs and verify the presence of the configured fields:

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

    Example output

    1. cluster=downward-api-test-cluster1
    2. rack=rack-123
    3. zone=us-east-coast
    4. annotation1=345
    5. annotation2=456
    6. kubernetes.io/config.source=api

Understanding how to consume 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 environment variable or a volume plugin.

Consuming container resources using environment variables

When creating pods, you can use the Downward API to inject information about computing resource requests and limits using environment variables.

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

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

Procedure

  1. Create a new pod spec that contains the resources you want to inject:

    1. Create a pod.yaml file similar to the following:

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

      1. $ oc create -f pod.yaml

Consuming container resources using a volume plugin

When creating pods, you can use the Downward API to inject information about computing resource requests and limits using a volume plugin.

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

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

Procedure

  1. Create a new pod spec that contains the resources you want to inject:

    1. Create a pod.yaml file similar to the following:

      1. apiVersion: v1
      2. kind: Pod
      3. metadata:
      4. name: dapi-env-test-pod
      5. spec:
      6. containers:
      7. - name: client-container
      8. image: gcr.io/google_containers/busybox:1.24
      9. 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"]
      10. resources:
      11. requests:
      12. memory: "32Mi"
      13. cpu: "125m"
      14. limits:
      15. memory: "64Mi"
      16. cpu: "250m"
      17. volumeMounts:
      18. - name: podinfo
      19. mountPath: /etc
      20. readOnly: false
      21. volumes:
      22. - name: podinfo
      23. downwardAPI:
      24. items:
      25. - path: "cpu_limit"
      26. resourceFieldRef:
      27. containerName: client-container
      28. resource: limits.cpu
      29. - path: "cpu_request"
      30. resourceFieldRef:
      31. containerName: client-container
      32. resource: requests.cpu
      33. - path: "mem_limit"
      34. resourceFieldRef:
      35. containerName: client-container
      36. resource: limits.memory
      37. - path: "mem_request"
      38. resourceFieldRef:
      39. containerName: client-container
      40. resource: requests.memory
      41. # ...
    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.

Procedure

  1. Create a secret to inject:

    1. Create a secret.yaml file similar to the following:

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

      1. $ oc create -f secret.yaml
  2. Create a pod that references the username field from the above Secret object:

    1. Create a pod.yaml file similar to the following:

      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
      17. # ...
    2. Create the pod from the pod.yaml file:

      1. $ oc create -f pod.yaml

Verification

  • Check the container’s logs for the MY_SECRET_USERNAME value:

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

Consuming configuration maps using the Downward API

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

Procedure

  1. Create a config map with the values to inject:

    1. Create a **_configmap.yaml_** file similar to the following:

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

      1. $ oc create -f configmap.yaml
  2. Create a pod that references the above config map:

    1. Create a pod.yaml file similar to the following:

      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: Always
      17. # ...
    2. Create the pod from the pod.yaml file:

      1. $ oc create -f pod.yaml

Verification

  • Check the container’s logs for the MY_CONFIGMAP_VALUE value:

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

Referencing environment variables

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.

Procedure

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

    1. Create a pod.yaml file similar to the following:

      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
      16. # ...
    2. Create the pod from the **_pod.yaml_** file:

      1. $ oc create -f pod.yaml

Verification

  • 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.

Procedure

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

    1. Create a pod.yaml file similar to the following:

      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
      14. # ...
    2. Create the pod from the **_pod.yaml_** file:

      1. $ oc create -f pod.yaml

Verification

  • Check the container’s logs for the MY_NEW_ENV value:

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