Increase visibility into IT operations to detect and resolve technical issues before they impact your business.

Learn More Go to Insights

Engage with our Red Hat Product Security team, access security updates, and ensure your environments are not exposed to any known security vulnerabilities. Product Security Center

Keep your systems secure with Red Hat's specialized responses to security vulnerabilities. View Responses Expand section "1.3.3. Understanding how to use pod disruption budgets to specify the number of pods that must be up" Collapse section "1.3.3. Understanding how to use pod disruption budgets to specify the number of pods that must be up" Expand section "2.3. Placing pods relative to other pods using affinity and anti-affinity rules" Collapse section "2.3. Placing pods relative to other pods using affinity and anti-affinity rules" Expand section "4.1. Viewing and listing the nodes in your OpenShift Container Platform cluster" Collapse section "4.1. Viewing and listing the nodes in your OpenShift Container Platform cluster" Expand section "4.8. Allocating resources for nodes in an OpenShift Container Platform cluster" Collapse section "4.8. Allocating resources for nodes in an OpenShift Container Platform cluster" Expand section "5.5.2. Understanding how to consume container values using the downward API" Collapse section "5.5.2. Understanding how to consume container values using the downward API" Expand section "5.5.3. Understanding how to consume container resources using the downward API" Collapse section "5.5.3. Understanding how to consume container resources using the downward API" Expand section "5.7. Executing remote commands in an OpenShift Container Platform container" Collapse section "5.7. Executing remote commands in an OpenShift Container Platform container" Expand section "6.1. Viewing system event information in an OpenShift Container Platform cluster" Collapse section "6.1. Viewing system event information in an OpenShift Container Platform cluster" Expand section "6.2. Estimating the number of pods your OpenShift Container Platform nodes can hold" Collapse section "6.2. Estimating the number of pods your OpenShift Container Platform nodes can hold" Expand section "6.4. Configuring cluster memory to meet container memory and risk requirements" Collapse section "6.4. Configuring cluster memory to meet container memory and risk requirements"

1.1. Using pods

A pod is one or more containers deployed together on one host, and the smallest compute unit that can be defined, deployed, and managed.

Pods are the rough equivalent of a machine instance (physical or virtual) to a Container. Each pod is allocated its own internal IP address, therefore owning its entire port space, and Containers within pods can share their local storage and networking. Pods have a lifecycle; they are defined, then they are assigned to run on a node, then they run until their Container(s) exit or they are removed for some other reason. Pods, depending on policy and exit code, might be removed after exiting, or can be retained in order to enable access to the logs of their Containers. OpenShift Container Platform treats pods as largely immutable; changes cannot be made to a pod definition while it is running. OpenShift Container Platform implements changes by terminating an existing pod and recreating it with modified configuration, base image(s), or both. Pods are also treated as expendable, and do not maintain state when recreated. Therefore pods should usually be managed by higher-level controllers, rather than directly by users. For the maximum number of pods per OpenShift Container Platform node host, see the Cluster Limits.

OpenShift Container Platform leverages the Kubernetes concept of a pod , which is one or more containers deployed together on one host, and the smallest compute unit that can be defined, deployed, and managed. The following is an example definition of a pod that provides a long-running service, which is actually a part of the OpenShift Container Platform infrastructure: the integrated container image registry. It demonstrates many features of pods, most of which are discussed in other topics and thus only briefly mentioned here:

Pod object definition (YAML)

kind: Pod
apiVersion: v1
metadata:
  name: example
  namespace: default
  selfLink: /api/v1/namespaces/default/pods/example
  uid: 5cc30063-0265780783bc
  resourceVersion: '165032'
  creationTimestamp: '2019-02-13T20:31:37Z'
  labels:                  1
    app: hello-openshift
  annotations:
    openshift.io/scc: anyuid
spec:
  restartPolicy: Always      2
  serviceAccountName: default
  imagePullSecrets:
    - name: default-dockercfg-5zrhb
  priority: 0
  schedulerName: default-scheduler
  terminationGracePeriodSeconds: 30
  nodeName: ip-10-0-140-16.us-east-2.compute.internal
  securityContext:     3
    seLinuxOptions:
      level: 's0:c11,c10'
  containers:          4
    - resources: {}
      terminationMessagePath: /dev/termination-log
      name: hello-openshift
      securityContext:
        capabilities:
          drop:
            - MKNOD
        procMount: Default
      ports:
        - containerPort: 8080
          protocol: TCP
      imagePullPolicy: Always
      volumeMounts:             5
        - name: default-token-wbqsl
          readOnly: true
          mountPath: /var/run/secrets/kubernetes.io/serviceaccount
      terminationMessagePolicy: File
      image: registry.redhat.io/openshift4/ose-ogging-eventrouter:v4.3 6
  serviceAccount: default     7
  volumes:                    8
    - name: default-token-wbqsl
      secret:
        secretName: default-token-wbqsl
        defaultMode: 420
  dnsPolicy: ClusterFirst
status:
  phase: Pending
  conditions:
    - type: Initialized
      status: 'True'
      lastProbeTime: null
      lastTransitionTime: '2019-02-13T20:31:37Z'
    - type: Ready
      status: 'False'
      lastProbeTime: null
      lastTransitionTime: '2019-02-13T20:31:37Z'
      reason: ContainersNotReady
      message: 'containers with unready status: [hello-openshift]'
    - type: ContainersReady
      status: 'False'
      lastProbeTime: null
      lastTransitionTime: '2019-02-13T20:31:37Z'
      reason: ContainersNotReady
      message: 'containers with unready status: [hello-openshift]'
    - type: PodScheduled
      status: 'True'
      lastProbeTime: null
      lastTransitionTime: '2019-02-13T20:31:37Z'
  hostIP: 10.0.140.16
  startTime: '2019-02-13T20:31:37Z'
  containerStatuses:
    - name: hello-openshift
      state:
        waiting:
          reason: ContainerCreating
      lastState: {}
      ready: false
      restartCount: 0
      image: openshift/hello-openshift
      imageID: ''
  qosClass: BestEffort
Pods can be "tagged" with one or more labels, which can then be used to select and manage groups of pods in a single operation. The labels are stored in key/value format in the metadata hash. One label in this example is registry=default . The pod restart policy with possible values Always , OnFailure , and Never . The default value is Always . OpenShift Container Platform defines a security context for containers which specifies whether they are allowed to run as privileged containers, run as a user of their choice, and more. The default context is very restrictive but administrators can modify this as needed. containers specifies an array of one or more container definitions. The container specifies where external storage volumes are mounted within the container. In this case, there is a volume for storing access to credentials the registry needs for making requests against the OpenShift Container Platform API. Each container in the pod is instantiated from its own container image. Pods making requests against the OpenShift Container Platform API is a common enough pattern that there is a serviceAccount field for specifying which service account user the pod should authenticate as when making the requests. This enables fine-grained access control for custom infrastructure components. The pod defines storage volumes that are available to its container(s) to use. In this case, it provides an ephemeral volume for the registry storage and a secret volume containing the service account credentials. This pod definition does not include attributes that are filled by OpenShift Container Platform automatically after the pod is created and its lifecycle begins. The Kubernetes pod documentation has details about the functionality and purpose of pods.

1.2. Viewing pods

As an administrator, you can view the pods in your cluster and to determine the health of those pods and the cluster as a whole.

1.2.1. About pods

OpenShift Container Platform leverages the Kubernetes concept of a pod , which is one or more containers deployed together on one host, and the smallest compute unit that can be defined, deployed, and managed. Pods are the rough equivalent of a machine instance (physical or virtual) to a container. You can view a list of pods associated with a specific project or view usage statistics about pods.

1.2.2. Viewing pods in a project

You can view a list of pods associated with the current project, including the number of replica, the current status, number or restarts and the age of the pod.

Procedure

To view the pods in a project: Change to the project:

$ oc project <project-name>
  • Run the following command:

    $ oc get pods

    For example:

    $ oc get pods -n openshift-console
    NAME                       READY   STATUS    RESTARTS   AGE
    console-698d866b78-bnshf   1/1     Running   2          165m
    console-698d866b78-m87pm   1/1     Running   2          165m

    Add the -o wide flags to view the pod IP address and the node where the pod is located.

    $ oc get pods -o wide
    NAME                       READY   STATUS    RESTARTS   AGE    IP            NODE                           NOMINATED NODE
    console-698d866b78-bnshf   1/1     Running   2          166m   10.128.0.24   ip-10-0-152-71.ec2.internal    <none>
    console-698d866b78-m87pm   1/1     Running   2          166m   10.129.0.23   ip-10-0-173-237.ec2.internal   <none>
  • 1.2.3. Viewing pod usage statistics

    You can display usage statistics about pods, which provide the runtime environments for Containers. These usage statistics include CPU, memory, and storage consumption.

    Prerequisites

    • You must have cluster-reader permission to view the usage statistics. Metrics must be installed to view the usage statistics.

    Procedure

    To view the usage statistics: Run the following command:

    $ oc adm top pods

    For example:

    $ oc adm top pods -n openshift-console
    NAME                         CPU(cores)   MEMORY(bytes)
    console-7f58c69899-q8c8k     0m           22Mi
    console-7f58c69899-xhbgg     0m           25Mi
    downloads-594fcccf94-bcxk8   3m           18Mi
    downloads-594fcccf94-kv4p6   2m           15Mi
  • Run the following command to view the usage statistics for pods with labels:

    $ oc adm top pod --selector=''

    You must choose the selector (label query) to filter on. Supports = , == , and != .

  • 1.3. Configuring an OpenShift Container Platform cluster for pods

    As an administrator, you can create and maintain an efficient cluster for pods. By keeping your cluster efficient, you can provide a better environment for your developers using such tools as what a pod does when it exits, ensuring that the required number of pods is always running, when to restart pods designed to run only once, limit the bandwidth available to pods, and how to keep pods running during disruptions.

    1.3.1. Configuring how pods behave after restart

    A pod restart policy determines how OpenShift Container Platform responds when Containers in that pod exit. The policy applies to all Containers in that pod. The possible values are: Always - Tries restarting a successfully exited Container on the pod continuously, with an exponential back-off delay (10s, 20s, 40s) until the pod is restarted. The default is Always . OnFailure - Tries restarting a failed Container on the pod with an exponential back-off delay (10s, 20s, 40s) capped at 5 minutes. Never - Does not try to restart exited or failed Containers on the pod. Pods immediately fail and exit. After the pod is bound to a node, the pod will never be bound to another node. This means that a controller is necessary in order for a pod to survive node failure:

    Condition Controller Type Restart Policy

    Pods that are expected to terminate (such as batch computations) OnFailure or Never Pods that are expected to not terminate (such as web servers) Replication Controller Always . Pods that must run one-per-machine Daemonset If a Container on a pod fails and the restart policy is set to OnFailure , the pod stays on the node and the Container is restarted. If you do not want the Container to restart, use a restart policy of Never . If an entire pod fails, OpenShift Container Platform starts a new pod. Developers must address the possibility that applications might be restarted in a new pod. In particular, applications must handle temporary files, locks, incomplete output, and so forth caused by previous runs. Kubernetes architecture expects reliable endpoints from cloud providers. When a cloud provider is down, the kubelet prevents OpenShift Container Platform from restarting. If the underlying cloud provider endpoints are not reliable, do not install a cluster using cloud provider integration. Install the cluster as if it was in a no-cloud environment. It is not recommended to toggle cloud provider integration on or off in an installed cluster. For details on how OpenShift Container Platform uses restart policy with failed Containers, see the Example States in the Kubernetes documentation.

    1.3.2. Limiting the bandwidth available to pods

    You can apply quality-of-service traffic shaping to a pod and effectively limit its available bandwidth. Egress traffic (from the pod) is handled by policing, which simply drops packets in excess of the configured rate. Ingress traffic (to the pod) is handled by shaping queued packets to effectively handle data. The limits you place on a pod do not affect the bandwidth of other pods.

    Procedure

    To limit the bandwidth on a pod: Write an object definition JSON file, and specify the data traffic speed using kubernetes.io/ingress-bandwidth and kubernetes.io/egress-bandwidth annotations. For example, to limit both pod egress and ingress bandwidth to 10M/s:

    Limited Pod Object Definition

    "kind": "Pod", "spec": { "containers": [ "image": "openshift/hello-openshift", "name": "hello-openshift" "apiVersion": "v1", "metadata": { "name": "iperf-slow", "annotations": { "kubernetes.io/ingress-bandwidth": "10M", "kubernetes.io/egress-bandwidth": "10M" Create the pod using the object definition:

    $ oc create -f <file_or_dir_path>

    1.3.3. Understanding how to use pod disruption budgets to specify the number of pods that must be up

    A pod disruption budget is part of the Kubernetes API, which can be managed with oc commands like other object types. They allow the specification of safety constraints on pods during operations, such as draining a node for maintenance. PodDisruptionBudget is an API object that specifies the minimum number or percentage of replicas that must be up at a time. Setting these in projects can be helpful during node maintenance (such as scaling a cluster down or a cluster upgrade) and is only honored on voluntary evictions (not on node failures). A PodDisruptionBudget object’s configuration consists of the following key parts: A label selector, which is a label query over a set of pods. An availability level, which specifies the minimum number of pods that must be available simultaneously, either: minAvailable is the number of pods must always be available, even during a disruption. maxUnavailable is the number of Pods can be unavailable during a disruption. A maxUnavailable of 0% or 0 or a minAvailable of 100% or equal to the number of replicas, is permitted, but can block nodes from being drained. You can check for pod disruption budgets across all projects with the following:

    $ oc get poddisruptionbudget --all-namespaces
    NAMESPACE         NAME          MIN-AVAILABLE   SELECTOR
    another-project   another-pdb   4               bar=foo
    test-project      my-pdb        2               foo=bar

    The PodDisruptionBudget is considered healthy when there are at least minAvailable pods running in the system. Every pod above that limit can be evicted. Depending on your pod priority and preemption settings, lower-priority pods might be removed despite their pod disruption budget requirements.

    1.3.3.1. Specifying the number of pods that must be up with pod disruption budgets

    You can use a PodDisruptionBudget object to specify the minimum number or percentage of replicas that must be up at a time.

    Procedure

    To configure a pod disruption budget: Create a YAML file with the an object definition similar to the following:

    apiVersion: policy/v1beta1 1
    kind: PodDisruptionBudget
    metadata:
      name: my-pdb
    spec:
      minAvailable: 2  2
      selector:  3
        matchLabels:
          foo: bar
    1
    PodDisruptionBudget is part of the policy/v1beta1 API group. The minimum number of pods that must be available simultaneously. This can be either an integer or a string specifying a percentage, for example, 20% . A label query over a set of resources. The result of matchLabels and matchExpressions are logically conjoined.

    apiVersion: policy/v1beta1 1
    kind: PodDisruptionBudget
    metadata:
      name: my-pdb
    spec:
      maxUnavailable: 25% 2
      selector: 3
        matchLabels:
          foo: bar
    1
    PodDisruptionBudget is part of the policy/v1beta1 API group. The maximum number of pods that can be unavailable simultaneously. This can be either an integer or a string specifying a percentage, for example, 20% . A label query over a set of resources. The result of matchLabels and matchExpressions are logically conjoined. Run the following command to add the object to project:

    $ oc create -f </path/to/file> -n <project_name>

    1.3.4. Preventing pod removal using critical pods

    There are a number of core components that are critical to a fully functional cluster, but, run on a regular cluster node rather than the master. A cluster might stop working properly if a critical add-on is evicted. Pods marked as critical are not allowed to be evicted.

    Procedure

    To make a pod critical: Create a pod specification or edit existing pods to include the system-cluster-critical priority class:

    spec:
      template:
        metadata:
          name: critical-pod
        priorityClassName: system-cluster-critical 1
    1
    Default priority class for pods that should never be evicted from a node. Alternatively, you can specify system-node-critical for pods that are important to the cluster but can be removed if necessary. Create the pod:

    $ oc create -f <file-name>.yaml

    1.4. Automatically scaling pods

    As a developer, you can use a horizontal pod autoscaler (HPA) to specify how OpenShift Container Platform should automatically increase or decrease the scale of a replication controller or deployment configuration, based on metrics collected from the pods that belong to that replication controller or deployment configuration.

    1.4.1. Understanding horizontal pod autoscalers

    You can create a horizontal pod autoscaler to specify the minimum and maximum number of pods you want to run, as well as the CPU utilization or memory utilization your pods should target.

    Important

    Autoscaling for Memory Utilization is a Technology Preview feature only. After you create a horizontal pod autoscaler, OpenShift Container Platform begins to query the CPU and/or memory resource metrics on the pods. When these metrics are available, the horizontal pod autoscaler computes the ratio of the current metric utilization with the desired metric utilization, and scales up or down accordingly. The query and scaling occurs at a regular interval, but can take one to two minutes before metrics become available. For replication controllers, this scaling corresponds directly to the replicas of the replication controller. For deployment configurations, scaling corresponds directly to the replica count of the deployment configuration. Note that autoscaling applies only to the latest deployment in the Complete phase. OpenShift Container Platform automatically accounts for resources and prevents unnecessary autoscaling during resource spikes, such as during start up. Pods in the unready state have 0 CPU usage when scaling up and the autoscaler ignores the pods when scaling down. Pods without known metrics have 0% CPU usage when scaling up and 100% CPU when scaling down. This allows for more stability during the HPA decision. To use this feature, you must configure readiness checks to determine if a new pod is ready for use. In order to use horizontal pod autoscalers, your cluster administrator must have properly configured cluster metrics.

    1.4.1.1. Supported metrics

    The following metrics are supported by horizontal pod autoscalers:

    Table 1.1. Metrics

    Metric Description API version

    CPU utilization Number of CPU cores used. Can be used to calculate a percentage of the pod’s requested CPU. autoscaling/v1 , autoscaling/v2beta2 Memory utilization Amount of memory used. Can be used to calculate a percentage of the pod’s requested memory. autoscaling/v2beta2

    Important

    For memory-based autoscaling, memory usage must increase and decrease proportionally to the replica count. On average: An increase in replica count must lead to an overall decrease in memory (working set) usage per-pod. A decrease in replica count must lead to an overall increase in per-pod memory usage. Use the OpenShift Container Platform web console to check the memory behavior of your application and ensure that your application meets these requirements before using memory-based autoscaling.

    1.4.2. Creating a horizontal pod autoscaler for CPU utilization

    You can create a horizontal pod autoscaler (HPA) for an existing DeploymentConfig or ReplicationController object that automatically scales the Pods associated with that object in order to maintain the CPU usage you specify. The HPA increases and decreases the number of replicas between the minimum and maximum numbers to maintain the specified CPU utilization across all Pods. When autoscaling for CPU utilization, you can use the oc autoscale command and specify the minimum and maximum number of Pods you want to run at any given time and the average CPU utilization your Pods should target. If you do not specify a minimum, the Pods are given default values from the OpenShift Container Platform server. To autoscale for a specific CPU value, create a HorizontalPodAutoscaler object with the target CPU and Pod limits.

    Prerequisites

    In order to use horizontal pod autoscalers, your cluster administrator must have properly configured cluster metrics. You can use the oc describe PodMetrics <pod-name> command to determine if metrics are configured. If metrics are configured, the output appears similar to the following, with Cpu and Memory displayed under Usage .

    $ oc describe PodMetrics openshift-kube-scheduler-ip-10-0-135-131.ec2.internal
    Name:         openshift-kube-scheduler-ip-10-0-135-131.ec2.internal
    Namespace:    openshift-kube-scheduler
    Labels:       <none>
    Annotations:  <none>
    API Version:  metrics.k8s.io/v1beta1
    Containers:
      Name:  wait-for-host-port
      Usage:
        Memory:  0
      Name:      scheduler
      Usage:
        Cpu:     8m
        Memory:  45440Ki
    Kind:        PodMetrics
    Metadata:
      Creation Timestamp:  2019-05-23T18:47:56Z
      Self Link:           /apis/metrics.k8s.io/v1beta1/namespaces/openshift-kube-scheduler/pods/openshift-kube-scheduler-ip-10-0-135-131.ec2.internal
    Timestamp:             2019-05-23T18:47:56Z
    Window:                1m0s
    Events:                <none>

    Procedure

    To create a horizontal pod autoscaler for CPU utilization: Perform one of the following one of the following: To scale based on the percent of CPU utilization, create a HorizontalPodAutoscaler object for an existing DeploymentConfig:

    $ oc autoscale dc/<dc-name> \1
      --min <number> \2
      --max <number> \3
      --cpu-percent=<percent> 4
    1
    Specify the name of the DeploymentConfig. The object must exist. Optionally, specify the minimum number of replicas when scaling down. Specify the maximum number of replicas when scaling up. Specify the target average CPU utilization over all the Pods, represented as a percent of requested CPU. If not specified or negative, a default autoscaling policy is used. To scale based on the percent of CPU utilization, create a HorizontalPodAutoscaler object for an existing ReplicationController:

    $ oc autoscale rc/<rc-name> 1
      --min <number> \2
      --max <number> \3
      --cpu-percent=<percent> 4
    1
    Specify the name of the ReplicationController. The object must exist. Specify the minimum number of replicas when scaling down. Specify the maximum number of replicas when scaling up. Specify the target average CPU utilization over all the Pods, represented as a percent of requested CPU. If not specified or negative, a default autoscaling policy is used. To scale for a specific CPU value, create a YAML file similar to the following for an existing DeploymentConfig or ReplicationController: Create a YAML file similar to the following:

    apiVersion: autoscaling/v2beta2 1
    kind: HorizontalPodAutoscaler
    metadata:
      name: cpu-autoscale 2
      namespace: default
    spec:
      scaleTargetRef:
        apiVersion: v1 3
        kind: ReplicationController 4
        name: example 5
      minReplicas: 1 6
      maxReplicas: 10 7
      metrics: 8
      - type: Resource
        resource:
          name: cpu 9
          target:
            type: Utilization 10
            averageValue: 500m 11
    1
    Use the autoscaling/v2beta2 API. Specify a name for this horizontal pod autoscaler object. Specify the API version of the object to scale: For a ReplicationController, use v1 , For a DeploymentConfig, use apps.openshift.io/v1 . Specify the kind of object to scale, either ReplicationController or DeploymentConfig . Specify the name of the object to scale. The object must exist. Specify the minimum number of replicas when scaling down. Specify the maximum number of replicas when scaling up. Use the metrics parameter for memory utilization. Specify cpu for CPU utilization. Set to Utilization . Set the type to averageValue . Create the horizontal pod autoscaler:

    $ oc create -f <file-name>.yaml
  • Verify that the horizontal pod autoscaler was created:

    $ oc get hpa cpu-autoscale
    NAME            REFERENCE                       TARGETS         MINPODS   MAXPODS   REPLICAS   AGE
    cpu-autoscale   ReplicationController/example   173m/500m       1         10        1          20m
  • For example, the following command creates a horizontal pod autoscaler that maintains between 3 and 7 replicas of the Pods that are controlled by the image-registry DeploymentConfig in order to maintain an average CPU utilization of 75% across all Pods.

    $ oc autoscale dc/image-registry --min 3 --max 7 --cpu-percent=75
    deploymentconfig "image-registry" autoscaled

    The command creates a horizontal pod autoscaler with the following definition:

    $ oc edit hpa frontend -n openshift-image-registry
    apiVersion: autoscaling/v1
    kind: HorizontalPodAutoscaler
    metadata:
      creationTimestamp: "2020-02-21T20:19:28Z"
      name: image-registry
      namespace: default
      resourceVersion: "32452"
      selfLink: /apis/autoscaling/v1/namespaces/default/horizontalpodautoscalers/frontend
      uid: 1a934a22-925d-431e-813a-d00461ad7521
    spec:
      maxReplicas: 7
      minReplicas: 3
      scaleTargetRef:
        apiVersion: apps.openshift.io/v1
        kind: DeploymentConfig
        name: image-registry
      targetCPUUtilizationPercentage: 75
    status:
      currentReplicas: 5
      desiredReplicas: 0

    The following example shows autoscaling for the image-registry DeploymentConfig. The initial deployment requires 3 Pods. The HPA object increased that minimum to 5 and will increase the Pods up to 7 if CPU usage on the Pods reaches 75%:

    $ oc get dc image-registry
    NAME             REVISION   DESIRED   CURRENT   TRIGGERED BY
    image-registry   1          3         3         config
    $ oc autoscale dc/image-registry --min=5 --max=7 --cpu-percent=75
    horizontalpodautoscaler.autoscaling/image-registry autoscaled
    $ oc get dc image-registry
    NAME             REVISION   DESIRED   CURRENT   TRIGGERED BY
    image-registry   1          5         5         config

    1.4.3. Creating a horizontal pod autoscaler object for memory utilization

    You can create a horizontal pod autoscaler (HPA) for an existing DeploymentConfig or ReplicationController object that automatically scales the Pods associated with that object in order to maintain the average memory utilization you specify, either a direct value or a percentage of requested memory. The HPA increases and decreases the number of replicas between the minimum and maximum numbers to maintain the specified memory utilization across all Pods. For memory utilization, you can specify the minimum and maximum number of Pods and the average memory utilization your Pods should target. If you do not specify a minimum, the Pods are given default values from the OpenShift Container Platform server.

    Important

    Autoscaling for memory utilization is a Technology Preview feature only. Technology Preview features are not supported with Red Hat production service level agreements (SLAs), might not be functionally complete, and Red Hat does not recommend to use them for production. These features provide early access to upcoming product features, enabling customers to test functionality and provide feedback during the development process. For more information on Red Hat Technology Preview features support scope, see https://access.redhat.com/support/offerings/techpreview/ .

    Prerequisites

    In order to use horizontal pod autoscalers, your cluster administrator must have properly configured cluster metrics. You can use the oc describe PodMetrics <pod-name> command to determine if metrics are configured. If metrics are configured, the output appears similar to the following, with Cpu and Memory displayed under Usage .

    $ oc describe PodMetrics openshift-kube-scheduler-ip-10-0-129-223.compute.internal -n openshift-kube-scheduler
    Name:         openshift-kube-scheduler-ip-10-0-129-223.compute.internal
    Namespace:    openshift-kube-scheduler
    Labels:       <none>
    Annotations:  <none>
    API Version:  metrics.k8s.io/v1beta1
    Containers:
      Name:  scheduler
      Usage:
        Cpu:     2m
        Memory:  41056Ki
      Name:      wait-for-host-port
      Usage:
        Memory:  0
    Kind:        PodMetrics
    Metadata:
      Creation Timestamp:  2020-02-14T22:21:14Z
      Self Link:           /apis/metrics.k8s.io/v1beta1/namespaces/openshift-kube-scheduler/pods/openshift-kube-scheduler-ip-10-0-129-223.compute.internal
    Timestamp:             2020-02-14T22:21:14Z
    Window:                5m0s
    Events:                <none>

    Procedure

    To create a horizontal pod autoscaler for memory utilization: Create a YAML file for one of the following: To scale for a specific memory value, create a HorizontalPodAutoscaler object similar to the following for an existing DeploymentConfig or ReplicationController:

    apiVersion: autoscaling/v2beta2 1
    kind: HorizontalPodAutoscaler
    metadata:
      name: hpa-resource-metrics-memory 2
      namespace: default
    spec:
      scaleTargetRef:
        apiVersion: v1 3
        kind: ReplicationController 4
        name: example 5
      minReplicas: 1 6
      maxReplicas: 10 7
      metrics: 8
      - type: Resource
        resource:
          name: memory 9
          target:
            type: AverageValue 10
            averageValue: 500Mi 11
    1
    Use the autoscaling/v2beta2 API. Specify a name for this horizontal pod autoscaler object. Specify the API version of the object to scale: For a ReplicationController, use v1 , For a DeploymentConfig, use apps.openshift.io/v1 . Specify the kind of object to scale, either ReplicationController or DeploymentConfig . Specify the name of the object to scale. The object must exist. Specify the minimum number of replicas when scaling down. Specify the maximum number of replicas when scaling up. Use the metrics parameter for memory utilization. Specify memory for memory utilization. Set the type to AverageValue . Specify averageValue and a specific memory value. To scale for a percentage, create a HorizontalPodAutoscaler object similar to the following:

    apiVersion: autoscaling/v2beta2 1
    kind: HorizontalPodAutoscaler
    metadata:
      name: memory-autoscale 2
      namespace: default
    spec:
      scaleTargetRef:
        apiVersion: apps.openshift.io/v1 3
        kind: DeploymentConfig 4
        name: example 5
      minReplicas: 1 6
      maxReplicas: 10 7
      metrics: 8
      - type: Resource
        resource:
          name: memory 9
          target:
            type: Utilization 10
            averageUtilization: 50 11
    1
    Use the autoscaling/v2beta2 API. Specify a name for this horizontal pod autoscaler object. Specify the API version of the object to scale: For a ReplicationController, use v1 , For a DeploymentConfig, use apps.openshift.io/v1 . Specify the kind of object to scale, either ReplicationController or DeploymentConfig . Specify the name of the object to scale. The object must exist. Specify the minimum number of replicas when scaling down. Specify the maximum number of replicas when scaling up. Use the metrics parameter for memory utilization. Specify memory for memory utilization. Set to Utilization . Specify averageUtilization and a target average memory utilization over all the Pods, represented as a percent of requested memory. The target pods must have memory requests configured. Create the horizontal pod autoscaler:

    $ oc create -f <file-name>.yaml

    For example:

    $ oc create -f hpa.yaml
    horizontalpodautoscaler.autoscaling/hpa-resource-metrics-memory created
  • Verify that the horizontal pod autoscaler was created:

    $ oc get hpa hpa-resource-metrics-memory
    NAME                          REFERENCE                       TARGETS         MINPODS   MAXPODS   REPLICAS   AGE
    hpa-resource-metrics-memory   ReplicationController/example   2441216/500Mi   1         10        1          20m
    $ oc describe hpa hpa-resource-metrics-memory
    Name:                        hpa-resource-metrics-memory
    Namespace:                   default
    Labels:                      <none>
    Annotations:                 <none>
    CreationTimestamp:           Wed, 04 Mar 2020 16:31:37 +0530
    Reference:                   ReplicationController/example
    Metrics:                     ( current / target )
      resource memory on pods:   2441216 / 500Mi
    Min replicas:                1
    Max replicas:                10
    ReplicationController pods:  1 current / 1 desired
    Conditions:
      Type            Status  Reason              Message
      ----            ------  ------              -------
      AbleToScale     True    ReadyForNewScale    recommended size matches current size
      ScalingActive   True    ValidMetricFound    the HPA was able to successfully calculate a replica count from memory resource
      ScalingLimited  False   DesiredWithinRange  the desired count is within the acceptable range
    Events:
      Type     Reason                   Age                 From                       Message
      ----     ------                   ----                ----                       -------
      Normal   SuccessfulRescale        6m34s               horizontal-pod-autoscaler  New size: 1; reason: All metrics below target
  • 1.4.4. Understanding horizontal pod autoscaler status conditions

    You can use the status conditions set to determine whether or not the horizontal pod autoscaler (HPA) is able to scale and whether or not it is currently restricted in any way. The HPA status conditions are available with the v2beta1 version of the autoscaling API. The HPA responds with the following status conditions: The AbleToScale condition indicates whether HPA is able to fetch and update metrics, as well as whether any backoff-related conditions could prevent scaling. A True condition indicates scaling is allowed. A False condition indicates scaling is not allowed for the reason specified. The ScalingActive condition indicates whether the HPA is enabled (for example, the replica count of the target is not zero) and is able to calculate desired metrics. A True condition indicates metrics is working properly. A False condition generally indicates a problem with fetching metrics. The ScalingLimited condition indicates that the desired scale was capped by the maximum or minimum of the horizontal pod autoscaler. A True condition indicates that you need to raise or lower the minimum or maximum replica count in order to scale. A False condition indicates that the requested scaling is allowed.

    $ oc describe hpa cm-test
    Name:                           cm-test
    Namespace:                      prom
    Labels:                         <none>
    Annotations:                    <none>
    CreationTimestamp:              Fri, 16 Jun 2017 18:09:22 +0000
    Reference:                      ReplicationController/cm-test
    Metrics:                        ( current / target )
      "http_requests" on pods:      66m / 500m
    Min replicas:                   1
    Max replicas:                   4
    ReplicationController pods:     1 current / 1 desired
    Conditions: 1
      Type              Status    Reason              Message
      ----              ------    ------              -------
      AbleToScale       True      ReadyForNewScale    the last scale time was sufficiently old as to warrant a new scale
      ScalingActive     True      ValidMetricFound    the HPA was able to successfully calculate a replica count from pods metric http_request
      ScalingLimited    False     DesiredWithinRange  the desired replica count is within the acceptable range
    Events:
    1
    The horizontal pod autoscaler status messages. The following is an example of a pod that is unable to scale:

    Conditions:
      Type         Status  Reason          Message
      ----         ------  ------          -------
      AbleToScale  False   FailedGetScale  the HPA controller was unable to get the target's current scale: no matches for kind "ReplicationController" in group "apps"
    Events:
      Type     Reason          Age               From                       Message
      ----     ------          ----              ----                       -------
      Warning  FailedGetScale  6s (x3 over 36s)  horizontal-pod-autoscaler  no matches for kind "ReplicationController" in group "apps"

    The following is an example of a pod that could not obtain the needed metrics for scaling:

    Conditions:
      Type                  Status    Reason                    Message
      ----                  ------    ------                    -------
      AbleToScale           True     SucceededGetScale          the HPA controller was able to get the target's current scale
      ScalingActive         False    FailedGetResourceMetric    the HPA was unable to compute the replica count: unable to get metrics for resource cpu: no metrics returned from heapster

    The following is an example of a pod where the requested autoscaling was less than the required minimums:

    Conditions:
      Type              Status    Reason              Message
      ----              ------    ------              -------
      AbleToScale       True      ReadyForNewScale    the last scale time was sufficiently old as to warrant a new scale
      ScalingActive     True      ValidMetricFound    the HPA was able to successfully calculate a replica count from pods metric http_request
      ScalingLimited    False     DesiredWithinRange  the desired replica count is within the acceptable range

    1.4.4.1. Viewing horizontal pod autoscaler status conditions

    You can view the status conditions set on a pod by the horizontal pod autoscaler (HPA). The horizontal pod autoscaler status conditions are available with the v2beta1 version of the autoscaling API.

    Prerequisites

    In order to use horizontal pod autoscalers, your cluster administrator must have properly configured cluster metrics. You can use the oc describe PodMetrics <pod-name> command to determine if metrics are configured. If metrics are configured, the output appears similar to the following, with Cpu and Memory displayed under Usage .

    $ oc describe PodMetrics openshift-kube-scheduler-ip-10-0-135-131.ec2.internal
    Name:         openshift-kube-scheduler-ip-10-0-135-131.ec2.internal
    Namespace:    openshift-kube-scheduler
    Labels:       <none>
    Annotations:  <none>
    API Version:  metrics.k8s.io/v1beta1
    Containers:
      Name:  wait-for-host-port
      Usage:
        Memory:  0
      Name:      scheduler
      Usage:
        Cpu:     8m
        Memory:  45440Ki
    Kind:        PodMetrics
    Metadata:
      Creation Timestamp:  2019-05-23T18:47:56Z
      Self Link:           /apis/metrics.k8s.io/v1beta1/namespaces/openshift-kube-scheduler/pods/openshift-kube-scheduler-ip-10-0-135-131.ec2.internal
    Timestamp:             2019-05-23T18:47:56Z
    Window:                1m0s
    Events:                <none>

    Procedure

    To view the status conditions on a pod, use the following command with the name of the pod:

    $ oc describe hpa <pod-name>

    For example:

    $ oc describe hpa cm-test

    The conditions appear in the Conditions field in the output.

    Name:                           cm-test
    Namespace:                      prom
    Labels:                         <none>
    Annotations:                    <none>
    CreationTimestamp:              Fri, 16 Jun 2017 18:09:22 +0000
    Reference:                      ReplicationController/cm-test
    Metrics:                        ( current / target )
      "http_requests" on pods:      66m / 500m
    Min replicas:                   1
    Max replicas:                   4
    ReplicationController pods:     1 current / 1 desired
    Conditions: 1
      Type              Status    Reason              Message
      ----              ------    ------              -------
      AbleToScale       True      ReadyForNewScale    the last scale time was sufficiently old as to warrant a new scale
      ScalingActive     True      ValidMetricFound    the HPA was able to successfully calculate a replica count from pods metric http_request
      ScalingLimited    False     DesiredWithinRange  the desired replica count is within the acceptable range

    1.4.5. Additional resources

    For more information on replication controllers and deployment controllers, see Understanding Deployments and DeploymentConfigs .

    1.5. Providing sensitive data to pods

    Some applications need sensitive information, such as passwords and user names, that you do not want developers to have. As an administrator, you can use Secret objects to provide this information without exposing that information in clear text.

    1.5.1. Understanding secrets

    The Secret object type provides a mechanism to hold sensitive information such as passwords, OpenShift Container Platform client configuration files, private source repository credentials, and so on. Secrets decouple sensitive content from the pods. You can mount secrets into Containers using a volume plug-in or the system can use secrets to perform actions on behalf of a pod. Key properties include: Secret data can be referenced independently from its definition. Secret data volumes are backed by temporary file-storage facilities (tmpfs) and never come to rest on a node. Secret data can be shared within a namespace.

    YAML Secret Object Definition

    apiVersion: v1
    kind: Secret
    metadata:
      name: test-secret
      namespace: my-namespace
    type: Opaque 1
    data: 2
      username: dmFsdWUtMQ0K 3
      password: dmFsdWUtMg0KDQo=
    stringData: 4
      hostname: myapp.mydomain.com 5
    Indicates the structure of the secret’s key names and values. The allowable format for the keys in the data field must meet the guidelines in the DNS_SUBDOMAIN value in the Kubernetes identifiers glossary . The value associated with keys in the data map must be base64 encoded. Entries in the stringData map are converted to base64 and the entry will then be moved to the data map automatically. This field is write-only; the value will only be returned via the data field. The value associated with keys in the stringData map is made up of plain text strings. You must create a secret before creating the pods that depend on that secret. When creating secrets: Create a secret object with secret data. Update the pod’s service account to allow the reference to the secret. Create a pod, which consumes the secret as an environment variable or as a file (using a secret volume).

    1.5.1.1. Types of secrets

    The value in the type field indicates the structure of the secret’s key names and values. The type can be used to enforce the presence of user names and keys in the secret object. If you do not want validation, use the opaque type, which is the default. Specify one of the following types to trigger minimal server-side validation to ensure the presence of specific key names in the secret data: kubernetes.io/service-account-token . Uses a service account token. kubernetes.io/basic-auth . Use with Basic Authentication. kubernetes.io/ssh-auth . Use with SSH Key Authentication. kubernetes.io/tls . Use with TLS certificate authorities. Specify type: Opaque if you do not want validation, which means the secret does not claim to conform to any convention for key names or values. An opaque secret, allows for unstructured key:value pairs that can contain arbitrary values. You can specify other arbitrary types, such as example.com/my-secret-type . These types are not enforced server-side, but indicate that the creator of the secret intended to conform to the key/value requirements of that type. For examples of different secret types, see the code samples in Using Secrets .

    1.5.1.2. Example secret configurations

    The following are sample secret configuration files.

    YAML Secret That Will Create Four Files

    apiVersion: v1
    kind: Secret
    metadata:
      name: test-secret
    data:
      username: dmFsdWUtMQ0K     1
      password: dmFsdWUtMQ0KDQo= 2
    stringData:
      hostname: myapp.mydomain.com 3
      secret.properties: |-     4
        property1=valueA
        property2=valueB
    File contains decoded values. File contains decoded values. File contains the provided string. File contains the provided data.

    YAML of a Pod Populating Files in a Volume with Secret Data

    apiVersion: v1
    kind: Pod
    metadata:
      name: secret-example-pod
    spec:
      containers:
        - name: secret-test-container
          image: busybox
          command: [ "/bin/sh", "-c", "cat /etc/secret-volume/*" ]
          volumeMounts:
              # name must match the volume name below
              - name: secret-volume
                mountPath: /etc/secret-volume
                readOnly: true
      volumes:
        - name: secret-volume
          secret:
            secretName: test-secret
      restartPolicy: Never

    YAML of a Pod Populating Environment Variables with Secret Data

    apiVersion: v1
    kind: Pod
    metadata:
      name: secret-example-pod
    spec:
      containers:
        - name: secret-test-container
          image: busybox
          command: [ "/bin/sh", "-c", "export" ]
            - name: TEST_SECRET_USERNAME_ENV_VAR
              valueFrom:
                secretKeyRef:
                  name: test-secret
                  key: username
      restartPolicy: Never

    YAML of a Build Config Populating Environment Variables with Secret Data

    apiVersion: v1
    kind: BuildConfig
    metadata:
      name: secret-example-bc
    spec:
      strategy:
        sourceStrategy:
          - name: TEST_SECRET_USERNAME_ENV_VAR
            valueFrom:
              secretKeyRef:
                name: test-secret
                key: username

    1.5.1.3. Secret data keys

    Secret keys must be in a DNS subdomain.

    1.5.2. Understanding how to create secrets

    As an administrator you must create a secret before developers can create the pods that depend on that secret. When creating secrets: Create a secret object with secret data. Update the pod’s service account to allow the reference to the secret. Create a pod, which consumes the secret as an environment variable or as a file (using a secret volume).

    1.5.2.1. Secret creation restrictions

    To use a secret, a pod needs to reference the secret. A secret can be used with a pod in three ways: To populate environment variables for Containers. As files in a volume mounted on one or more of its Containers. By kubelet when pulling images for the pod. Volume type secrets write data into the Container as a file using the volume mechanism. Image pull secrets use service accounts for the automatic injection of the secret into all pods in a namespaces. When a template contains a secret definition, the only way for the template to use the provided secret is to ensure that the secret volume sources are validated and that the specified object reference actually points to an object of type Secret . Therefore, a secret needs to be created before any pods that depend on it. The most effective way to ensure this is to have it get injected automatically through the use of a service account. Secret API objects reside in a namespace. They can only be referenced by pods in that same namespace. Individual secrets are limited to 1MB in size. This is to discourage the creation of large secrets that could exhaust apiserver and kubelet memory. However, creation of a number of smaller secrets could also exhaust memory.

    1.5.2.2. Creating an opaque secret

    As an administrator, you can create a opaque secret, which allows for unstructured key:value pairs that can contain arbitrary values.

    Procedure

    1. Create a secret object in a YAML file on master. For example:

      apiVersion: v1
      kind: Secret
      metadata:
        name: mysecret
      type: Opaque 1
      data:
        username: dXNlci1uYW1l
        password: cGFzc3dvcmQ=
      1
      Specifies an opaque secret. Use the following command to create a secret object:

      $ oc create -f <filename>

    Then: Update the service account for the pod where you want to use the secret to allow the reference to the secret. Create the pod, which consumes the secret as an environment variable or as a file (using a secret volume).

    1.5.3. Understanding how to update secrets

    When you modify the value of a secret, the value (used by an already running pod) will not dynamically change. To change a secret, you must delete the original pod and create a new pod (perhaps with an identical PodSpec). Updating a secret follows the same workflow as deploying a new Container image. You can use the kubectl rolling-update command. The resourceVersion value in a secret is not specified when it is referenced. Therefore, if a secret is updated at the same time as pods are starting, then the version of the secret will be used for the pod will not be defined. Currently, it is not possible to check the resource version of a secret object that was used when a pod was created. It is planned that pods will report this information, so that a controller could restart ones using a old resourceVersion . In the interim, do not update the data of existing secrets, but create new ones with distinct names.

    1.5.4. About using signed certificates with secrets

    To secure communication to your service, you can configure OpenShift Container Platform to generate a signed serving certificate/key pair that you can add into a secret in a project. A service serving certificate secret is intended to support complex middleware applications that need out-of-the-box certificates. It has the same settings as the server certificates generated by the administrator tooling for nodes and masters.

    Service pod specification configured for a service serving certificates secret.

    apiVersion: v1
      kind: Service
      metadata:
        name: registry
        annotations:
          service.alpha.openshift.io/serving-cert-secret-name: registry-cert1
    							Specify the name for the certificate
    					Other pods can trust cluster-created certificates (which are only signed for internal DNS names), by using the CA bundle in the /var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt file that is automatically mounted in their pod.
    					The signature algorithm for this feature is x509.SHA256WithRSA. To manually rotate, delete the generated secret. A new certificate is created.
    				

    1.5.4.1. Generating signed certificates for use with secrets

    To use a signed serving certificate/key pair with a pod, create or edit the service to add the service.alpha.openshift.io/serving-cert-secret-name annotation, then add the secret to the pod.

    Procedure

    To create a service serving certificate secret: Edit the pod specification for your service. Add the service.alpha.openshift.io/serving-cert-secret-name annotation with the name you want to use for your secret.

    kind: Service
    apiVersion: v1
    metadata:
      name: my-service
      annotations:
          service.alpha.openshift.io/serving-cert-secret-name: my-cert 1
    spec:
      selector:
        app: MyApp
      ports:
      - protocol: TCP
        port: 80
        targetPort: 9376

    The certificate and key are in PEM format, stored in tls.crt and tls.key respectively. Create the service:

    $ oc create -f <file-name>.yaml
  • View the secret to make sure it was created:

    $ oc get secrets
    NAME                         TYPE                                  DATA      AGE
    my-cert                  kubernetes.io/tls                     2         9m
    $ oc describe secret my-service-pod
    Name:         my-service-pod
    Namespace:    openshift-console
    Labels:       <none>
    Annotations:  kubernetes.io/service-account.name: builder
                  kubernetes.io/service-account.uid: ab-11e9-988a-0eb4e1b4a396
    Type:  kubernetes.io/service-account-token
    ca.crt:     5802 bytes
    namespace:  17 bytes
    token:      eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Ii
    wia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJvcGVuc2hpZnQtY29uc29sZSIsImt1YmVyb
    cnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJhYmE4Y2UyZC00MzVlLTExZTktOTg4YS0wZWI0ZTFiNGEz
    OTYiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6b3BlbnNoaWZ
  • Edit your pod specification with that secret.

    apiVersion: v1
    kind: Pod
    metadata:
      name: my-service-pod
    spec:
      containers:
      - name: mypod
        image: redis
        volumeMounts:
        - name: foo
          mountPath: "/etc/foo"
      volumes:
      - name: foo
        secret:
          secretName: my-cert
          items:
          - key: username
            path: my-group/my-username
            mode: 511

    When it is available, your pod will run. The certificate will be good for the internal service DNS name, <service.name>.<service.namespace>.svc. The certificate/key pair is automatically replaced when it gets close to expiration. View the expiration date in the service.alpha.openshift.io/expiry annotation on the secret, which is in RFC3339 format. In most cases, the service DNS name <service.name>.<service.namespace>.svc is not externally routable. The primary use of <service.name>.<service.namespace>.svc is for intracluster or intraservice communication, and with re-encrypt routes.

  • 1.5.5. Troubleshooting secrets

    If a service certificate generation fails with (service’s service.alpha.openshift.io/serving-cert-generation-error annotation contains):

    secret/ssl-key references serviceUID 62ad25ca-d703-11e6-9d6f-0e9c0057b608, which does not match 77b6dd80-d716-11e6-9d6f-0e9c0057b60

    The service that generated the certificate no longer exists, or has a different serviceUID . You must force certificates regeneration by removing the old secret, and clearing the following annotations on the service service.alpha.openshift.io/serving-cert-generation-error , service.alpha.openshift.io/serving-cert-generation-error-num :

    $ oc delete secret <secret_name>
    $ oc annotate service <service_name> service.alpha.openshift.io/serving-cert-generation-error-
    $ oc annotate service <service_name> service.alpha.openshift.io/serving-cert-generation-error-num-
    Note

    The command removing annotation has a - after the annotation name to be removed.

    1.6. Using device plug-ins to access external resources with pods

    Device plug-ins allow you to use a particular device type (GPU, InfiniBand, or other similar computing resources that require vendor-specific initialization and setup) in your OpenShift Container Platform pod without needing to write custom code.

    1.6.1. Understanding device plug-ins

    The device plug-in provides a consistent and portable solution to consume hardware devices across clusters. The device plug-in provides support for these devices through an extension mechanism, which makes these devices available to Containers, provides health checks of these devices, and securely shares them.

    Important

    OpenShift Container Platform supports the device plug-in API, but the device plug-in Containers are supported by individual vendors. A device plug-in is a gRPC service running on the nodes (external to the kubelet ) that is responsible for managing specific hardware resources. Any device plug-in must support following remote procedure calls (RPCs):

    service DevicePlugin {
          // GetDevicePluginOptions returns options to be communicated with Device
          // Manager
          rpc GetDevicePluginOptions(Empty) returns (DevicePluginOptions) {}
          // ListAndWatch returns a stream of List of Devices
          // Whenever a Device state change or a Device disappears, ListAndWatch
          // returns the new list
          rpc ListAndWatch(Empty) returns (stream ListAndWatchResponse) {}
          // Allocate is called during container creation so that the Device
          // Plug-in can run device specific operations and instruct Kubelet
          // of the steps to make the Device available in the container
          rpc Allocate(AllocateRequest) returns (AllocateResponse) {}
          // PreStartcontainer is called, if indicated by Device Plug-in during
          // registration phase, before each container start. Device plug-in
          // can run device specific operations such as reseting the device
          // before making devices available to the container
          rpc PreStartcontainer(PreStartcontainerRequest) returns (PreStartcontainerResponse) {}
    }
    Example device plug-ins

    1.6.1.1. Methods for deploying a device plug-in

    • Daemonsets are the recommended approach for device plug-in deployments. Upon start, the device plug-in will try to create a UNIX domain socket at /var/lib/kubelet/device-plugin/ on the node to serve RPCs from Device Manager. Since device plug-ins must manage hardware resources, access to the host file system, as well as socket creation, they must be run in a privileged security context. More specific details regarding deployment steps can be found with each device plug-in implementation.

    1.6.2. Understanding the Device Manager

    Device Manager provides a mechanism for advertising specialized node hardware resources with the help of plug-ins known as device plug-ins. You can advertise specialized hardware without requiring any upstream code changes.

    Important

    OpenShift Container Platform supports the device plug-in API, but the device plug-in Containers are supported by individual vendors. Device Manager advertises devices as Extended Resources . User pods can consume devices, advertised by Device Manager, using the same Limit/Request mechanism, which is used for requesting any other Extended Resource . Upon start, the device plug-in registers itself with Device Manager invoking Register on the /var/lib/kubelet/device-plugins/kubelet.sock and starts a gRPC service at /var/lib/kubelet/device-plugins/<plugin>.sock for serving Device Manager requests. Device Manager, while processing a new registration request, invokes ListAndWatch remote procedure call (RPC) at the device plug-in service. In response, Device Manager gets a list of Device objects from the plug-in over a gRPC stream. Device Manager will keep watching on the stream for new updates from the plug-in. On the plug-in side, the plug-in will also keep the stream open and whenever there is a change in the state of any of the devices, a new device list is sent to the Device Manager over the same streaming connection. While handling a new pod admission request, Kubelet passes requested Extended Resources to the Device Manager for device allocation. Device Manager checks in its database to verify if a corresponding plug-in exists or not. If the plug-in exists and there are free allocatable devices as well as per local cache, Allocate RPC is invoked at that particular device plug-in. Additionally, device plug-ins can also perform several other device-specific operations, such as driver installation, device initialization, and device resets. These functionalities vary from implementation to implementation.

    1.6.3. Enabling Device Manager

    Enable Device Manager to implement a device plug-in to advertise specialized hardware without any upstream code changes. Device Manager provides a mechanism for advertising specialized node hardware resources with the help of plug-ins known as device plug-ins. Obtain the label associated with the static Machine Config Pool CRD for the type of node you want to configure. Perform one of the following steps: View the Machine Config:

    # oc describe machineconfig <name>

    For example:

    # oc describe machineconfig 00-worker
    oc describe machineconfig 00-worker
    Name:         00-worker
    Namespace:
    Labels:       machineconfiguration.openshift.io/role=worker 1
    1 1
    Label required for the device manager.

    Procedure

    1. Create a Custom Resource (CR) for your configuration change.

      Sample configuration for a Device Manager CR

      apiVersion: machineconfiguration.openshift.io/v1
      kind: KubeletConfig
      metadata:
        name: devicemgr 1
      spec:
        machineConfigPoolSelector:
          matchLabels:
             machineconfiguration.openshift.io: devicemgr 2
        kubeletConfig:
          feature-gates:
            - DevicePlugins=true 3
      Assign a name to CR. Enter the label from the Machine Config Pool. Set DevicePlugins to 'true`. Create the device manager:

      $ oc create -f devicemgr.yaml
      letconfig.machineconfiguration.openshift.io/devicemgr created
    2. Ensure that Device Manager was actually enabled by confirming that /var/lib/kubelet/device-plugins/kubelet.sock is created on the node. This is the UNIX domain socket on which the Device Manager gRPC server listens for new plug-in registrations. This sock file is created when the Kubelet is started only if Device Manager is enabled.

    1.7. Including pod priority in pod scheduling decisions

    You can enable pod priority and preemption in your cluster. Pod priority indicates the importance of a pod relative to other pods and queues the pods based on that priority. Pod preemption allows the cluster to evict, or preempt, lower-priority pods so that higher-priority pods can be scheduled if there is no available space on a suitable node Pod priority also affects the scheduling order of pods and out-of-resource eviction ordering on the node. To use priority and preemption, you create priority classes that define the relative weight of your pods. Then, reference a priority class in the pod specification to apply that weight for scheduling. Preemption is controlled by the disablePreemption parameter in the scheduler configuration file, which is set to false by default.

    1.7.1. Understanding pod priority

    When you use the Pod Priority and Preemption feature, the scheduler orders pending pods by their priority, and a pending pod is placed ahead of other pending pods with lower priority in the scheduling queue. As a result, the higher priority pod might be scheduled sooner than pods with lower priority if its scheduling requirements are met. If a pod cannot be scheduled, scheduler continues to schedule other lower priority pods.

    1.7.1.1. Pod priority classes

    You can assign pods a priority class, which is a non-namespaced object that defines a mapping from a name to the integer value of the priority. The higher the value, the higher the priority. A priority class object can take any 32-bit integer value smaller than or equal to 1000000000 (one billion). Reserve numbers larger than one billion for critical pods that should not be preempted or evicted. By default, OpenShift Container Platform has two reserved priority classes for critical system pods to have guaranteed scheduling.

    $ oc get priorityclasses
    NAME                      CREATED AT
    cluster-logging           2019-03-13T14:45:12Z
    system-cluster-critical   2019-03-13T14:01:10Z
    system-node-critical      2019-03-13T14:01:10Z
    • system-node-critical - This priority class has a value of 2000001000 and is used for all pods that should never be evicted from a node. Examples of pods that have this priority class are sdn-ovs , sdn , and so forth. A number of critical components include the system-node-critical priority class by default, for example: master-api master-controller master-etcd sdn-ovs system-cluster-critical - This priority class has a value of 2000000000 (two billion) and is used with pods that are important for the cluster. Pods with this priority class can be evicted from a node in certain circumstances. For example, pods configured with the system-node-critical priority class can take priority. However, this priority class does ensure guaranteed scheduling. Examples of pods that can have this priority class are fluentd, add-on components like descheduler, and so forth. A number of critical components include the system-cluster-critical priority class by default, for example: fluentd metrics-server descheduler cluster-logging - This priority is used by Fluentd to make sure Fluentd pods are scheduled to nodes over other apps. If you upgrade your existing cluster, the priority of your existing pods is effectively zero. However, existing pods with the scheduler.alpha.kubernetes.io/critical-pod annotation are automatically converted to system-cluster-critical class. Fluentd cluster logging pods with the annotation are converted to the cluster-logging priority class.

    1.7.1.2. Pod priority names

    After you have one or more priority classes, you can create pods that specify a priority class name in a pod specification. The priority admission controller uses the priority class name field to populate the integer value of the priority. If the named priority class is not found, the pod is rejected.

    1.7.2. Understanding pod preemption

    When a developer creates a pod, the pod goes into a queue. If the developer configured the pod for pod priority or preemption, the scheduler picks a pod from the queue and tries to schedule the pod on a node. If the scheduler cannot find space on an appropriate node that satisfies all the specified requirements of the pod, preemption logic is triggered for the pending pod. When the scheduler preempts one or more pods on a node, the nominatedNodeName field of higher-priority pod specification is set to the name of the node, along with the nodename field. The scheduler uses the nominatedNodeName field to keep track of the resources reserved for pods and also provides information to the user about preemptions in the clusters. After the scheduler preempts a lower-priority pod, the scheduler honors the graceful termination period of the pod. If another node becomes available while scheduler is waiting for the lower-priority pod to terminate, the scheduler can schedule the higher-priority pod on that node. As a result, the nominatedNodeName field and nodeName field of the pod specification might be different. Also, if the scheduler preempts pods on a node and is waiting for termination, and a pod with a higher-priority pod than the pending pod needs to be scheduled, the scheduler can schedule the higher-priority pod instead. In such a case, the scheduler clears the nominatedNodeName of the pending pod, making the pod eligible for another node. Preemption does not necessarily remove all lower-priority pods from a node. The scheduler can schedule a pending pod by removing a portion of the lower-priority pods. The scheduler considers a node for pod preemption only if the pending pod can be scheduled on the node.

    1.7.2.1. Pod preemption and other scheduler settings

    If you enable pod priority and preemption, consider your other scheduler settings:

    Pod priority and pod disruption budget
    A pod disruption budget specifies the minimum number or percentage of replicas that must be up at a time. If you specify pod disruption budgets, OpenShift Container Platform respects them when preempting pods at a best effort level. The scheduler attempts to preempt pods without violating the pod disruption budget. If no such pods are found, lower-priority pods might be preempted despite their pod disruption budget requirements.
    Pod priority and pod affinity
    Pod affinity requires a new pod to be scheduled on the same node as other pods with the same label. If a pending pod has inter-pod affinity with one or more of the lower-priority pods on a node, the scheduler cannot preempt the lower-priority pods without violating the affinity requirements. In this case, the scheduler looks for another node to schedule the pending pod. However, there is no guarantee that the scheduler can find an appropriate node and pending pod might not be scheduled. To prevent this situation, carefully configure pod affinity with equal-priority pods.

    1.7.2.2. Graceful termination of preempted pods

    When preempting a pod, the scheduler waits for the pod graceful termination period to expire, allowing the pod to finish working and exit. If the pod does not exit after the period, the scheduler kills the pod. This graceful termination period creates a time gap between the point that the scheduler preempts the pod and the time when the pending pod can be scheduled on the node. To minimize this gap, configure a small graceful termination period for lower-priority pods.

    1.7.3. Configuring priority and preemption

    You apply pod priority and preemption by creating a priority class object and associating pods to the priority using the priorityClassName in your pod specifications.

    Sample priority class object

    apiVersion: scheduling.k8s.io/v1beta1
    kind: PriorityClass
    metadata:
      name: high-priority 1
    value: 1000000 2
    globalDefault: false 3
    description: "This priority class should be used for XYZ service pods only." 4
    The name of the priority class object. The priority value of the object. Optional field that indicates whether this priority class should be used for pods without a priority class name specified. This field is false by default. Only one priority class with globalDefault set to true can exist in the cluster. If there is no priority class with globalDefault:true , the priority of pods with no priority class name is zero. Adding a priority class with globalDefault:true affects only pods created after the priority class is added and does not change the priorities of existing pods. Optional arbitrary text string that describes which pods developers should use with this priority class.

    Procedure

    To configure your cluster to use priority and preemption: Create one or more priority classes: Specify a name and value for the priority. Optionally specify the globalDefault field in the priority class and a description. Create a pod specification or edit existing pods to include the name of a priority class, similar to the following:

    Sample pod specification with priority class name

    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        env: test
    spec:
      containers:
      - name: nginx
        image: nginx
        imagePullPolicy: IfNotPresent
      priorityClassName: high-priority 1
    Specify the priority class to use with this pod. Create the pod:

    $ oc create -f <file-name>.yaml

    You can add the priority name directly to the pod configuration or to a pod template.

    1.7.4. Disabling priority and preemption

    You can disable the pod priority and preemption feature. After the feature is disabled, the existing pods keep their priority fields, but preemption is disabled, and priority fields are ignored. If the feature is disabled, you cannot set a priority class name in new pods.

    Important

    Critical pods rely on scheduler preemption to be scheduled when a cluster is under resource pressure. For this reason, Red Hat recommends not disabling preemption. DaemonSet pods are scheduled by the DaemonSet controller and not affected by disabling preemption.

    Procedure

    To disable the preemption for the cluster: Edit the Scheduler Operator Custom Resource to add the disablePreemption: true parameter:

    oc edit scheduler cluster
    apiVersion: config.openshift.io/v1
    kind: Scheduler
    metadata:
      creationTimestamp: '2019-03-12T01:45:02Z'
      generation: 1
      name: example
      resourceVersion: '1882034'
      selfLink: /apis/config.openshift.io/v1/schedulers/example
      uid: 743701e9-4468-11e9-bd34-02a7fe1bf828
    spec:
      disablePreemption: true

    1.8. Placing pods on specific nodes using node selectors

    A node selector specifies a map of key-value pairs. The rules are defined using custom labels on nodes and selectors specified in pods. For the pod to be eligible to run on a node, the pod must have the indicated key-value pairs as the label on the node. If you are using node affinity and node selectors in the same pod configuration, see the important considerations below.

    1.8.1. Using node selectors to control pod placement

    You can use node selector labels on pods to control where the pod is scheduled. With node selectors, OpenShift Container Platform schedules the pods on nodes that contain matching labels. To add node selectors to an existing pod, add a node selector to the controlling object for that node, such as a ReplicaSet, Daemonset, or StatefulSet. Any existing pods under that controlling object are recreated on a node with a matching label. If you are creating a new pod, you can add the node selector directly to the pod spec. You can add labels to a node or MachineConfig, but the labels will not persist if the node or machine goes down. Adding the label to the MachineSet ensures that new nodes or machines will have the label. You cannot add a node selector directly to an existing scheduled pod.

    Prerequisite

    To add a node selector to existing pods, determine the controlling object for that pod. For example, the router-default-66d5cf9464-m2g75 pod is controlled by the router-default-66d5cf9464 ReplicaSet:

    $ oc describe pod router-default-66d5cf9464-7pwkc
    Name:               router-default-66d5cf9464-7pwkc
    Namespace:          openshift-ingress
    Controlled By:      ReplicaSet/router-default-66d5cf9464

    The web console lists the controlling object under ownerReferences in the pod YAML:

      ownerReferences:
        - apiVersion: apps/v1
          kind: ReplicaSet
          name: router-default-66d5cf9464
          uid: d81dd094-da26-11e9-a48a-128e7edf0312
          controller: true
          blockOwnerDeletion: true

    Procedure

    1. Add labels to a node by using a MachineSet or editing the node directly: Use a MachineSet to add labels to nodes managed by the MachineSet when a node is created: Run the following command to add a node selector to a MachineSet:

      $ oc patch MachineSet <name> --type='json' -p='[{"op":"add","path":"/spec/template/spec/metadata/labels", "value":{"<key>"="<value>","<key>"="<value>"}}]'  -n openshift-machine-api

      For example:

      $ oc patch MachineSet abc612-msrtw-worker-us-east-1c  --type='json' -p='[{"op":"add","path":"/spec/template/spec/metadata/labels", "value":{"type":"user-node","region":"east"}}]'  -n openshift-machine-api
    2. Verify that the label is added to the MachineSet by using the oc edit command: For example:

      $ oc edit MachineSet abc612-msrtw-worker-us-east-1c -n openshift-machine-api

      Example MachineSet object

      apiVersion: machine.openshift.io/v1beta1
      kind: MachineSet
      spec:
        template:
          metadata:
          spec:
            metadata:
              labels:
                region: east
                type: user-node
      									Add labels directly to a node:
      											Edit the Node object for the node:
      										

      $ oc label nodes <name> <key>=<value>

      For example, to label a node:

      $ oc label nodes ip-10-0-142-25.ec2.internal type=user-node region=east
    3. Verify that the label is added to the node:

      $ oc get nodes -l type=user-node,region=east

      Example output

      NAME                          STATUS   ROLES    AGE   VERSION
      ip-10-0-142-25.ec2.internal   Ready    worker   17m   v1.18.3+002a51f
      Add the matching node selector a pod: To add a node selector to existing and future pods, add a node selector to the controlling object for the pods:

      Example ReplicaSet object

      kind: ReplicaSet
      spec:
        template:
          metadata:
            creationTimestamp: null
            labels:
              ingresscontroller.operator.openshift.io/deployment-ingresscontroller: default
              pod-template-hash: 66d5cf9464
          spec:
            nodeSelector:
              beta.kubernetes.io/os: linux
              node-role.kubernetes.io/worker: ''
              type: user-node 1
      Add the node selector. To add a node selector to a specific pod, add the selector to the Pod object directly:

      Example Pod object

      apiVersion: v1
      kind: Pod
      spec:
        nodeSelector:
          <key>: <value>
      									For example:
      								

      Example Pod object with a node selector

      apiVersion: v1
      kind: Pod
      spec:
        nodeSelector:
          region: east
          type: user-node