Chapter 13. Self Awareness

Some applications need to be self-aware and require information about themselves. The Self Awareness pattern describes the Kubernetes Downward API that provides a simple mechanism for introspection and metadata injection to applications.

Problem

For the majority of use cases, cloud-native applications are stateless and disposable without an identity relevant to other applications. However, sometimes even these kinds of applications need to have information about themselves and the environment they are running in. That may include information known only at runtime, such as the Pod name, Pod IP address, and the hostname on which the application is placed. Or, other static information defined at Pod level such as the specific resource requests and limits, or some dynamic information such as annotations and labels that could be altered by the user at runtime.

For example, depending on the resources made available to the container, you may want to tune the application thread-pool size, or change the garbage collection algorithm or memory allocation. You may want to use the Pod name and the hostname while logging information, or while sending metrics to a central server. You may want to discover other Pods in the same namespace with a specific label and join them into a clustered application. For these and other use cases, Kubernetes provides the Downward API.

Solution

The requirements that we’ve described and the following solution are not specific only to containers but are present in any dynamic environment where the metadata of resources changes. For example, AWS offers Instance Metadata and User Data services that can be queried from any EC2 instance to retrieve metadata about the EC2 instance itself. Similarly, AWS ECS provides APIs that can be queried by the containers and retrieve information about the container cluster.

The Kubernetes approach is even more elegant and easier to use. The Downward API allows passing metadata about the Pod to the containers and the cluster through environment variables and files. These are the same mechanisms we used for passing application-related data from ConfigMaps and Secrets. But in this case, the data is not created by us. Instead, we specify the keys that interests us, and Kubernetes populates the values dynamically. Figure 13-1 gives an overview of how the Downward API injects resource and runtime information into interested Pods.

Application introspection mechanisms
Figure 13-1. Application introspection mechanisms

The main point here is that with the Downward API, the metadata is injected into your Pod and made available locally. The application does not need to use a client and interact with the Kubernetes API and can remain Kubernetes-agnostic. Let’s see how easy it is to request metadata through environment variables in Example 13-1.

Example 13-1. Environment variables from Downward API
apiVersion: v1
kind: Pod
metadata:
  name: random-generator
spec:
  containers:
  - image: k8spatterns/random-generator:1.0
    name: random-generator
    env:
    - name: POD_IP
      valueFrom:
        fieldRef:                     1
          fieldPath: status.podIP
    - name: MEMORY_LIMIT
      valueFrom:
        resourceFieldRef:
          container: random-generator 2
  resource: limits.memory
1

The environment variable POD_IP is set from the properties of this Pod and come into existence at Pod startup time.

2

The environment variable MEMORY_LIMIT is set to the value of the memory resource limit of this container; the actual limit declaration is not shown here.

In this example we use fieldRef to access Pod-level metadata. The keys shown in Table 13-1 are available for fieldRef.fieldPath both as environment variables and downwardAPI volumes.

Table 13-1. Downward API information available in fieldRef.fieldPath
Name Description

spec.nodeName

Name of node hosting the Pod

status.hostIP

IP address of node hosting the Pod

metadata.name

Pod name

metadata.namespace

Namespace in which the Pod is running

status.podIP

Pod IP address

spec.serviceAccountName

ServiceAccount that is used for the Pod

metadata.uid

Unique ID of the Pod

metadata.labels['key']

Value of the Pod’s label key

metadata.annotations['key']

Value of the Pod’s annotation key

Similarly to fieldRef, we can use resourceFieldRef to access metadata specific to a container belonging to the Pod. This metadata is specific to a container which can be specified with resourceFieldRef.container. When used as environment variable then by default the current container is used. The possible keys for resourceFieldRef.resource are shown in Table 13-2.

Table 13-2. Downward API information available in resourceFieldRef.resource
Name Description

requests.cpu

A container’s CPU request

limits.cpu

A container’s CPU limit

limits.memory

A container’s memory request

requests.memory

A container’s memory limit

A user can change certain metadata such as labels and annotations while a Pod is running. Unless the Pod is restarted, environment variables will not reflect such a change. But downwardAPI volumes can reflect updates to labels and annotations. In addition to the individual fields described previously, downwardAPI volumes can capture all Pod labels and annotations into files with metadata.labels and metadata.annotations references. Example 13-2 shows how such volumes can be used.

Example 13-2. Downward API through volumes
apiVersion: v1
kind: Pod
metadata:
  name: random-generator
spec:
  containers:
  - image: k8spatterns/random-generator:1.0
    name: random-generator
    volumeMounts:
    - name: pod-info                    1
      mountPath: /pod-info
  volumes:
  - name: pod-info
    downwardAPI:
      items:
      - path: labels                    2
        fieldRef:
          fieldPath: metadata.labels
      - path: annotations               3
        fieldRef:
          fieldPath: metadata.annotations
1

Values from the Downward API can be mounted as files into the Pod.

2

The file labels contain all labels, line by line, in the format name=value. This file gets updated when labels are changing.

3

The annotations file holds all annotations in the same format as the labels.

With volumes, if the metadata changes while the Pod is running, it is reflected in the volume files. But it is still up to the consuming application to detect the file change and read the updated data accordingly. If such a functionality is not implemented in the application, a Pod restart still might be required.

Discussion

On many occasions, an application needs to be self-aware and have information about itself and the environment in which it is running. Kubernetes provides nonintrusive mechanisms for introspection and metadata injection. One of the downsides of the Downward API is that it offers a fixed number of keys that can be referenced. If your application needs more data, especially about other resources or cluster-related metadata, it has be queried on the API Server.

This technique is used by many applications that query the API Server to discover other Pods in the same namespace that have certain labels or annotations. Then the application may form a cluster with the discovered Pods and sync state, for example. It is also used by monitoring applications to discover Pods of interest and then start instrumenting them.

Many client libraries are available for different languages to interact with the Kubernetes API Server to obtain more self-referring information that goes beyond what the Downward API provides.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset