k8s workload controller

Posted by cody44 on Wed, 05 Jan 2022 13:56:04 +0100

k8s workload controller

Workloads are applications running on kubernetes.
Whether your load is a single component or multiple components working together, you can run it in a set of Pods in Kubernetes. In Kuberneres, pod represents a set of containers running on the cluster.

Kubernetes Pods has a defined life cycle. For example, when a Pod runs in your cluster and a fatal error occurs on the node where the Pod runs, all Pods on that node will fail. Kubernetes regards such failures as the final state: even if the node returns to normal operation later, you need to create a new Pod to restore the application.

However, in order to make life a little easier for users, you don't need to manage each Pod directly. Instead, you can use load resources to manage a set of Pods for you. These resource configuration controllers ensure that the number of Pods of the appropriate type and running state is correct and consistent with the state you specify.

Common workload controllers:

  • Deployment
  • StatefulSet
  • DaemonSet
  • Job
  • CronJob

Deployment

A Deployment provides declarative update capabilities for Pods and ReplicaSets.

You are responsible for describing the target state in the Deployment, and the Deployment controller changes the actual state to the desired state at a controlled rate. You can define a Deployment to create a new ReplicaSet, or delete an existing Deployment and adopt its resources through the new Deployment.

Deployment is very suitable for managing stateless applications on your cluster. All pod s in deployment are equivalent to each other and are replaced when necessary.

Create Deployment

[root@master kubenetres]# vim deploy.yml
[root@master kubenetres]# cat deploy.yml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy
  labels:
    app: nginx
spec: 
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template: 
    metadata: 
      labels:
        app: nginx
    spec: 
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80

[root@master kubenetres]# kubectl apply -f deploy.yml 
deployment.apps/deploy created
[root@master kubenetres]# kubectl get pod
NAME                      READY   STATUS    RESTARTS      AGE
deploy-8d545c96d-6vmnd    1/1     Running   0             49s
deploy-8d545c96d-l4kx4    1/1     Running   0             49s
deploy-8d545c96d-nk25r    1/1     Running   0             49s      

In this example:

  • A deployment named deploy (indicated by the. metadata.name field) was created
  • This deployment creates three (indicated by the replicas field) copies of the pod
  • The selector field defines how Deployment finds Pods to manage. Here, you can select the tag (app: nginx) defined in the Pod template. However, more complex selection rules are also possible, as long as the Pod template itself meets the given rules.
  • The template field contains the following subfields:
    • Pod is labeled app: nginx using the labels field.
    • The Pod template specification (i.e. the. template.spec field) instructs Pods to run an nginx container that runs version 1.14.2 of nginx Docker Hub Mirror.
    • Create a container and name it nginx using the name field.

ReplicaSet

The purpose of ReplicaSet is to maintain a stable set of Pod replicas that are running at any time. Therefore, it is usually used to ensure the availability of a given number of identical pods.

How ReplicaSet works

RepicaSet is defined by a set of fields, including a selection operator that identifies the set of available pods, a value used to indicate the number of copies that should be maintained, a Pod template used to specify that a new Pod should be created to meet the conditions for the number of copies, and so on. Each ReplicaSet uses the provided Pod template when it creates a new Pod as needed.

ReplicaSet via metadata. On Pod The ownerReferences field is connected to the affiliated Pod, which gives the master resource of the current object. The Pod obtained by the ReplicaSet contains the identification information of the master ReplicaSet in its ownerReferences field. It is through this connection that ReplicaSet knows the state of the Pod set it maintains and plans its operation behavior accordingly.

The ReplicaSet uses its selection operator to identify the Pod set to obtain. If a Pod does not have an OwnerReference or its OwnerReference is not a controller, and it matches the selection operator of a ReplicaSet, the Pod is immediately obtained by the ReplicaSet.

When to use ReplicaSet

ReplicaSet ensures that a specified number of Pod replicas are running at any time. However, Deployment is a more advanced concept that manages the ReplicaSet and provides declarative updates and many other useful functions to the Pod. Therefore, we recommend using Deployment instead of directly using ReplicaSet, unless you need to customize the update business process or do not need to update at all.

This actually means that you may never need to manipulate the ReplicaSet object: instead, use Deployment and define your application in the spec section.

[root@master kubenetres]# vim replicaset.yml 
[root@master kubenetres]# cat replicaset.yml 
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: replicaset
  labels:
    app: httpd
    tier: frontend
spec:
  replicas: 3
  selector:
    matchLabels:
      tier: frontend
  template:
    metadata:
      labels:
        tier: frontend
    spec:
      containers:
      - name: httpd
        image: httpd:latest

View the currently deployed ReplicaSet

[root@master mainfest]# kubectl apply -f replicaset.yaml 
replicaset.apps/replicaset created
[root@master kubenetres]# kubectl apply -f replicaset.yml 
replicaset.apps/replicaset created
[root@master kubenetres]# kubectl get rs 
NAME                DESIRED   CURRENT   READY   AGE
deploy-8d545c96d    3         3         3       2m16s
replicaset          3         3         0       10s
[[root@master kubenetres]# kubectl get pod
NAME                      READY   STATUS              RESTARTS      AGE
deploy-8d545c96d-6vmnd    1/1     Running             0             2m39s
deploy-8d545c96d-l4kx4    1/1     Running             0             2m39s
deploy-8d545c96d-nk25r    1/1     Running             0             2m39s
httpd1-57c7b6f7cb-sk86h   1/1     Running             5 (21h ago)   2d22h
nginx1-7cf8bc594f-8j8tv   1/1     Running             2 (21h ago)   25h
replicaset-2v8rh          1/1     Running             0             33s
replicaset-5r5mb          0/1     ContainerCreating   0             33s
replicaset-rc4zq          0/1     ContainerCreating   0             33s
test                      1/1     Running             1 (21h ago)   21h

DaemonSet

DaemonSet ensures that all (or some) nodes run a copy of a Pod. When nodes join the cluster, a Pod will also be added for them. When nodes are removed from the cluster, these pods will also be recycled. Deleting DaemonSet will delete all pods it creates.

Some typical usage of DaemonSet:

  • Run the cluster daemon on each node
  • Run the log collection daemon on each node
  • Run the monitoring daemon on each node

A simple usage is to start a daemon set on all nodes for each type of daemon. A slightly more complex usage is to deploy multiple daemonsets for the same daemon; Each has different flags, and has different memory and CPU requirements for different hardware types.

Create DaemonSet

You can describe the DaemonSet in the YAML file. For example, the following daemon The YAML file describes a runtime

[root@master kubenetres]# vi daemonset.yml
[root@master kubenetres]# cat daemonset.yml 
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd-elasticsearch
  namespace: kube-system
  labels:
    k8s-app: fluentd-logging
spec:
  selector:
    matchLabels:
      name: fluentd-elasticsearch
  template:
    metadata:
      labels:
        name: fluentd-elasticsearch
    spec:
      tolerations:
      # this toleration is to have the daemonset runnable on master nodes
      # remove it if your masters can't run pods
      - key: node-role.kubernetes.io/master
        operator: Exists
        effect: NoSchedule
      containers:
      - name: fluentd-elasticsearch
        image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2
        resources:
          limits:
            memory: 200Mi
          requests:
            cpu: 100m
            memory: 200Mi
        volumeMounts:
        - name: varlog
          mountPath: /var/log
        - name: varlibdockercontainers
          mountPath: /var/lib/docker/containers
          readOnly: true
      terminationGracePeriodSeconds: 30
      volumes:
      - name: varlog
        hostPath:
          path: /var/log
      - name: varlibdockercontainers
        hostPath:
          path: /var/lib/docker/containers

Create view

[root@master kubenetres]# kubectl apply -f daemonset.yml 
daemonset.apps/fluentd-elasticsearch created
[root@master kubenetres]# kubectl get pod -n kube-system
NAME                                         READY   STATUS              RESTARTS       AGE
coredns-6d8c4cb4d-pqvll                      1/1     Running             11 (21h ago)   5d5h
coredns-6d8c4cb4d-txmm6                      1/1     Running             11 (21h ago)   5d5h
etcd-master.example.com                      1/1     Running             11 (21h ago)   5d5h
fluentd-elasticsearch-9hcxh                  0/1     ContainerCreating   0              20s
fluentd-elasticsearch-wqtv5                  0/1     ContainerCreating   0              20s
fluentd-elasticsearch-xk92n                  0/1     ContainerCreating   0              20s

How is Daemon Pods scheduled

Scheduling via default scheduler

FEATURE STATE: Kubernetes v1.23 [stable]

The daemon set ensures that all eligible nodes run a copy of the Pod. Typically, the node running the Pod is selected by the Kubernetes scheduler. However, the DaemonSet Pods are created and scheduled by the DaemonSet controller. This brings the following problems:

  • Inconsistency of Pod behavior: normal pods are in Pending state when waiting for scheduling after being created, and DaemonSet Pods will not be in Pending state after being created. This confuses users.
  • Pod preemption is handled by the default scheduler. After preemption is enabled, the DaemonSet controller will make scheduling decisions without considering pod priority and preemption.

ScheduleDaemonSetPods allows you to schedule DaemonSets using the default scheduler instead of the DaemonSet controller by placing NodeAffinity conditions instead of Add the spec.nodeName condition to the DaemonSet Pods. The default scheduler then binds the Pod to the target host. If the node affinity configuration of the DaemonSet Pod already exists, it is replaced (the original node affinity configuration is considered before selecting the target host). The DaemonSet controller performs these operations only when creating or modifying the DaemonSet Pod and does not change the spec.template of the DaemonSet.

nodeAffinity:
  requiredDuringSchedulingIgnoredDuringExecution:
    nodeSelectorTerms:
    - matchFields:
      - key: metadata.name
        operator: In
        values:
        - target-host-name

In addition, the system automatically adds node kubernetes. IO / unscheduled: NoSchedule tolerance to DaemonSet Pods. When scheduling the DaemonSet Pod, the default scheduler ignores the unscheduled node.

Jobs

The Job will create one or more Pods and will continue to retry the execution of Pods until the specified number of Pods are successfully terminated. With the successful completion of Pods, the Job tracks the number of successfully completed Pods. When the number reaches the specified success threshold, the task (i.e. Job) ends. Deleting a Job will clear all the created Pods. Suspending a Job will delete all the active Pods of the Job until the Job is resumed again.

In a simple usage scenario, you will create a Job object to run a Pod in a reliable way until it is completed. When the first Pod fails or is deleted (for example, because the node hardware fails or restarts), the Job object will start a new Pod.

You can also use Job to run multiple pods in parallel.

[root@master kubenetres]# vi jobs.yaml
[root@master kubenetres]# cat jobs.yaml 
apiVersion: batch/v1
kind: Job
metadata:
  name: pi
spec:
  template:
    spec:
      containers:
      - name: pi
        image: perl
        command: ["perl",  "-Mbignum=bpi", "-wle", "print bpi(2000)"]
      restartPolicy: Never
  backoffLimit: 4

Run view

[root@master kubenetres]# kubectl apply -f jobs.yaml 
job.batch/pi created
[root@master kubenetres]# kubectl describe jobs/pi
Name:             pi
Namespace:        default
Selector:         controller-uid=8d4b7a4d-0e9f-476d-ac0c-b05389e85e57
Labels:           controller-uid=8d4b7a4d-0e9f-476d-ac0c-b05389e85e57
                  job-name=pi
Annotations:      batch.kubernetes.io/job-tracking: 
Parallelism:      1
Completions:      1
Completion Mode:  NonIndexed
Start Time:       Fri, 24 Dec 2021 08:03:23 -0500
Pods Statuses:    1 Active / 0 Succeeded / 0 Failed
Pod Template:
  Labels:  controller-uid=8d4b7a4d-0e9f-476d-ac0c-b05389e85e57
           job-name=pi
  Containers:
   pi:
    Image:      perl
    Port:       <none>
    Host Port:  <none>
    Command:
      perl
      -Mbignum=bpi
      -wle
      print bpi(2000)
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Events:
  Type    Reason            Age   From            Message
  ----    ------            ----  ----            -------
  Normal  SuccessfulCreate  23s   job-controller  Created pod: pi-dblxb

CronJob

FEATURE STATE: Kubernetes v1.21 [stable]

CronJob creates Jobs based on interval repeat scheduling.

A CronJob object is like a line in a crontab (cron table) file. It is written in Cron format and executes jobs periodically at a given scheduling time.

be careful:

All CronJob schedule s are based on Kube controller manager Time zone.

If your control plane runs Kube controller manager in a Pod or a bare container, the time zone set for the container will determine the time zone used by the controller of Cron Job.

When creating a manifest for CronJob resources, ensure that the name provided is a legal DNS subdomain name The name cannot exceed 52 characters. This is because the CronJob controller will automatically append 11 characters after the Job name provided, and there is a limit that the maximum length of the Job name cannot exceed 63 characters.

CronJob is used to perform periodic actions, such as backup, report generation, etc. Each of these tasks should be configured to repeat periodically (e.g. daily / weekly / monthly); you can define the time interval at which the task starts to execute.

The following CronJob sample list prints out the current time and greeting messages every minute:

[root@master kubenetres]# vi cronjob.yml
[root@master kubenetres]# cat cronjob.yml 
apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: hello
spec:
  schedule: "*/1 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: hello
            image: busybox
            imagePullPolicy: IfNotPresent
            command:
            - /bin/sh
            - -c
            - date; echo Hello from the Kubernetes cluster
          restartPolicy: OnFailure

Run view

[root@master kubenetres]# kubectl apply -f cronjob.yml 
Warning: batch/v1beta1 CronJob is deprecated in v1.21+, unavailable in v1.25+; use batch/v1 CronJob
cronjob.batch/hello created[root@master mainfest]# kubectl apply -f cronjob.yaml 
cronjob.batch/hello created

[root@master kubenetres]# kubectl get pods
NAME                      READY   STATUS              RESTARTS      AGE
hello-27339185-2z8qj      0/1     Completed           0             16s
[root@master kubenetres]# kubectl logs hello-27339185-2z8qj
Fri Dec 24 13:05:01 UTC 2021
Hello from the Kubernetes cluster

Cron schedule syntax

# ┌ --------- minutes (0 - 59)
# │ ┌ --------- hours (0 - 23)
# One day of the month (1 - 31)
# │ │ │ ┌ --------- month (1 - 12)
# One day of the week (0 - 6) (Sunday to Monday; on some systems, 7 is also Sunday)
# │ │ │ │ │
# │ │ │ │ │
# │ │ │ │ │
# * * * * *
# ┌ --------- minutes (0 - 59)
# │ ┌ --------- hours (0 - 23)
# One day of the month (1 - 31)
# │ │ │ ┌ --------- month (1 - 12)
# One day of the week (0 - 6) (Sunday to Monday; on some systems, 7 is also Sunday)
# │ │ │ │ │
# │ │ │ │ │
# │ │ │ │ │
# * * * * *
inputdescribeamount to
@yearly (or @annually)Run once a year at midnight on January 10 0 1 1 *
@monthlyRun once at midnight on the first day of each month0 0 1 * *
@weeklyRun every Sunday at midnight0 0 * * 0
@daily (or @midnight)Run at midnight every day0 0 * * *
@hourlyAt the beginning of every hour0 * * * *

Topics: Operation & Maintenance Docker Kubernetes