Guides

How to get started, and accomplish tasks, using Kubernetes.

Edit This Page

Using the Downward API to Convey Pod Properties

It is sometimes useful for a container to have information about itself, but we want to be careful not to over-couple containers to Kubernetes. The downward API allows containers to consume information about themselves or the system and expose that information how they want it, without necessarily coupling to the Kubernetes client or REST API.

An example of this is a “legacy” app that is already written assuming that a particular environment variable will hold a unique identifier. While it is often possible to “wrap” such applications, this is tedious and error prone, and violates the goal of low coupling. Instead, the user should be able to use the Pod’s name, for example, and inject it into this well-known variable.

Capabilities

The following information is available to a Pod through the downward API:

More information will be exposed through this same API over time.

Exposing pod information into a container

Containers consume information from the downward API using environment variables or using a volume plugin.

Environment variables

Most environment variables in the Kubernetes API use the value field to carry simple values. However, the alternate valueFrom field allows you to specify a fieldRef to select fields from the pod’s definition, and a resourceFieldRef to select fields from one of its container’s definition.

The fieldRef field is a structure that has an apiVersion field and a fieldPath field. The fieldPath field is an expression designating a field of the pod. The apiVersion field is the version of the API schema that the fieldPath is written in terms of. If the apiVersion field is not specified it is defaulted to the API version of the enclosing object.

The fieldRef is evaluated and the resulting value is used as the value for the environment variable. This allows users to publish their pod’s name in any environment variable they want.

The resourceFieldRef is a structure that has a containerName field, a resource field, and a divisor field. The containerName is the name of a container, whose resource (cpu or memory) information is to be exposed. The containerName is optional for environment variables and defaults to the current container. The resource field is an expression designating a resource in a container, and the divisor field specifies an output format of the resource being exposed. If the divisor is not specified, it defaults to “1” for cpu and memory. The table shows possible values for cpu and memory resources for resource and divisor settings:

Setting Cpu Memory
resource limits.cpu, requests.cpu limits.memory, requests.memory
divisor 1(cores), 1m(millicores) 1(bytes), 1k(kilobytes), 1M(megabytes), 1G(gigabytes), 1T(terabytes), 1P(petabytes), 1E(exabytes), 1Ki(kibibyte), 1Mi(mebibyte), 1Gi(gibibyte), 1Ti(tebibyte), 1Pi(pebibyte), 1Ei(exbibyte)

Example

This is an example of a pod that consumes its name and namespace via the downward API:

dapi-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: dapi-test-pod
spec:
  containers:
    - name: test-container
      image: gcr.io/google_containers/busybox
      command: [ "/bin/sh", "-c", "env" ]
      env:
        - 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
  restartPolicy: Never

This is an example of a pod that consumes its container’s resources via the downward API:

dapi-container-resources.yaml
apiVersion: v1
kind: Pod
metadata:
  name: dapi-test-pod
spec:
  containers:
    - name: test-container
      image: gcr.io/google_containers/busybox:1.24
      command: [ "/bin/sh", "-c", "env" ]
      resources:
        requests:
          memory: "32Mi"
          cpu: "125m"
        limits:
          memory: "64Mi"
          cpu: "250m"
      env:
        - name: MY_CPU_REQUEST
          valueFrom:
            resourceFieldRef:
              resource: requests.cpu
        - name: MY_CPU_LIMIT
          valueFrom:
            resourceFieldRef:
              resource: limits.cpu
        - name: MY_MEM_REQUEST
          valueFrom:
            resourceFieldRef:
              resource: requests.memory
        - name: MY_MEM_LIMIT
          valueFrom:
            resourceFieldRef:
              resource: limits.memory
  restartPolicy: Never

Downward API volume

Using a similar syntax it’s possible to expose pod information to containers using plain text files. Downward API are dumped to a mounted volume. This is achieved using a downwardAPI volume type and the different items represent the files to be created. fieldPath references the field to be exposed. For exposing a container’s resources limits and requests, containerName must be specified with resourceFieldRef.

Downward API volume permits to store more complex data like metadata.labels and metadata.annotations. Currently key/value pair set fields are saved using key="value" format:

key1="value1"
key2="value2"

In future, it will be possible to specify an output format option.

Downward API volumes can expose:

The downward API volume refreshes its data in step with the kubelet refresh loop. When labels will be modifiable on the fly without respawning the pod containers will be able to detect changes through mechanisms such as inotify.

In future, it will be possible to specify a specific annotation or label.

Projecting keys to specific paths and file permissions

You can project keys to specific paths and specific permissions on a per-file basis. The Secrets user guide explains the syntax.

Example

This is an example of a pod that consumes its labels and annotations via the downward API volume, labels and annotations are dumped in /etc/labels and in /etc/annotations, respectively:

volume/dapi-volume.yaml
apiVersion: v1
kind: Pod
metadata:
  name: kubernetes-downwardapi-volume-example
  labels:
    zone: us-est-coast
    cluster: test-cluster1
    rack: rack-22
  annotations:
    build: two
    builder: john-doe
spec:
  containers:
    - name: client-container
      image: gcr.io/google_containers/busybox
      command: ["sh", "-c", "while true; do if [[ -e /etc/labels ]]; then cat /etc/labels; fi; if [[ -e /etc/annotations ]]; then cat /etc/annotations; fi; sleep 5; done"]
      volumeMounts:
        - name: podinfo
          mountPath: /etc
          readOnly: false
  volumes:
    - name: podinfo
      downwardAPI:
        items:
          - path: "labels"
            fieldRef:
              fieldPath: metadata.labels
          - path: "annotations"
            fieldRef:
              fieldPath: metadata.annotations

This is an example of a pod that consumes its container’s resources via the downward API volume.

volume/dapi-volume-resources.yaml
apiVersion: v1
kind: Pod
metadata:
  name: kubernetes-downwardapi-volume-example
spec:
  containers:
    - name: client-container
      image: gcr.io/google_containers/busybox:1.24
      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"]
      resources:
        requests:
          memory: "32Mi"
          cpu: "125m"
        limits:
          memory: "64Mi"
          cpu: "250m"
      volumeMounts:
        - name: podinfo
          mountPath: /etc
          readOnly: false
  volumes:
    - name: podinfo
      downwardAPI:
        items:
          - path: "cpu_limit"
            resourceFieldRef:
              containerName: client-container
              resource: limits.cpu
          - path: "cpu_request"
            resourceFieldRef:
              containerName: client-container
              resource: requests.cpu
          - path: "mem_limit"
            resourceFieldRef:
              containerName: client-container
              resource: limits.memory
          - path: "mem_request"
            resourceFieldRef:
              containerName: client-container
              resource: requests.memory

For a more thorough example, see environment variables.

Default values for container resource limits

If cpu and memory limits are not specified for a container, the downward API will default to the node allocatable value for cpu and memory.

Analytics Create an Issue Edit this Page