K8s actual combat (III) | essence of pod

Time:2021-9-21

preface

The previous section released a container into k8s, but the actual operation is pod, so why pod instead of container.

Update history

The essence of pod

The pod packs one or more containers.
Pod is the smallest execution unit of k8s.
Pod is a process in k8s.
Pod can package docker and other types of containers.
Pod contains encapsulated containers, storage resources, network resources, and configurations that guide how containers work.

The container can be understood as a bare container without hook. K8s cannot directly mount it. A pod is formed by adding hooks (IP addresses) to the container (container), which is convenient for k8s to operate.

Pod can also be understood as a traditional virtual machine, and the container is a program running in the traditional virtual machine, but the virtual machine is an entity, and pod is a logical concept.

K8s schedules containers by arranging pods instead of directly operating containers. K8s cannot directly manipulate containers.

Shared resources in pod

Pod provides shared network, storage resources and namespace for multiple containers running in it.

network

The pod has a unique IP address. Multiple containers in the pod share network resources such as an IP address and network port
Multiple containers in pod can communicate using localhost
When the container in the pod communicates with the outside, multiple containers need to coordinate the network ports
The container in the pod gets the same system host name as the name configured for the pod

storage

Pod specifies a set of storage volumes
Multiple containers in the pod can access the storage volume to share data with each other
The shared volumes in the pod can be saved permanently to prevent the container from restarting and losing data

Characteristics of pod

If you use the yaml file of kind: pod to create a pod, the pod cannot be automatically scheduled to other available servers after the current node server has a problem.

Generally, the yaml of kind: deployment is used to create a pod.

Deployment is a controller that can be used to create and manage pods. If you create a multi copy pod, scroll to update the pod.

When the node where the pod is located has a problem, the deployment controller can start a new pod at other nodes in the cluster.

Pod template

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  containers:
  - name: myapp-container
    image: busybox
    command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 3600']

Image pull strategy

Without specifying, imagepullpolicy is always, that is, kubelet   Attempts to pull each mirror from the specified repository.
If container properties   imagePullPolicy   Set to   Ifnotpresent, the local image will be used preferentially.
If container properties   imagePullPolicy   Set to   IfNotPresent    Never, the local image will be used.

apiVersion: v1
kind: Pod
metadata:
  name: private-image-test-1
spec:
  containers:
    - name: uses-private-image
      image: nginx
      imagePullPolicy: Always
      command: [ "echo", "SUCCESS" ]

Common parameters of pod

NodeSelector

Function: bind pod to node

apiVersion: v1
kind: Pod
...
spec:
 nodeSelector:
   disktype: ssd

This pod can only run on nodes with a “disktype: SSD” label. If there is no node with this label, the scheduling will fail.

NodeName

This field is generally set by the scheduler, but we can manually set this field during testing to make the scheduler think that the pod has been scheduled.

HostAliase

Set the contents of the / etc / hosts file of each container in the pod

apiVersion: v1
kind: Pod
......
spec:
  hostAliases:
  - ip: "10.20.20.20"
    hostnames:
    - "test1.com"
    - "test2.com"

Go into the container and check it

[[email protected] ~]# kubectl exec -it nginx -- bash
[email protected]:/# cat /etc/hosts
......
# Entries added by HostAliases.
10.20.20.20     test1.com       test2.com

shareProcessNamespace

If the parameter shareprocessnamespace = true is defined, all containers in the pod will share the PID namespace

Create a pod with two containers

[[email protected] ~]# cat nginx.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  shareProcessNamespace: true
  containers:
  - name: nginx
    image: nginx
  - name: shell
    image: busybox
    stdin: true
    tty: true

View operation

[[email protected] ~]# kubectl get pods -o wide
NAME    READY   STATUS    RESTARTS   AGE    IP               NODE     NOMINATED NODE   READINESS GATES
nginx   2/2     Running   0          117s   192.10.137.131   work03   <none>           <none>

Enter the container named shell in pod nginx

[[email protected] ~]# kubectl attach -it nginx -c shell
If you don't see a command prompt, try pressing enter.
/ # ps aux
PID   USER     TIME  COMMAND
    1 root      0:00 /pause
    6 root      0:00 nginx: master process nginx -g daemon off;
   33 101       0:00 nginx: worker process
   34 root      0:00 sh
   39 root      0:00 ps aux

As you can see, the process of nginx container can be seen in the shell container

Preset parameter of pod podpreset

We can preset some general configurations. When users submit their own personalized pod configuration, podpreset can automatically attach the general configuration to the corresponding pod.

The content defined in podpreset will only be appended to the pod API object itself before it is created, and will not affect the definition of any pod controller.

For example, if we are submitting an nginx deployment, the deployment object itself will never be changed by podpreset, and only all pods created by the deployment will be modified.

When the podpreset attribute is not enabled

# kubectl get podpresets
error: the server doesn't have a resource type "podpresets"

Enable the podpreset property

modify
[/etc/kubernetes/manifests/kube-apiserver.yaml] 
Medium
spec.containers.command: 
modify原
- --runtime-config=api/all=true
by
- --runtime-config=api/all=true,settings.k8s.io/v1alpha1=true
Add a new line
- --enable-admission-plugins=PodPreset

All 3 masters restart kubelet
systemctl restart kubelet

Preset.yaml

apiVersion: settings.k8s.io/v1alpha1
kind: PodPreset
metadata:
  name: allow-tz-env
spec:
  selector:
    matchLabels:
  env:
    - name: TZ
      value: Asia/Shanghai

Pod configuration nginx.yaml

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx

Create podpreset

# kubectl get podpreset
No resources found in default namespace.

# kubectl apply -f podpreset.yaml
podpreset.settings.k8s.io/allow-tz-env created

# kubectl get podpreset
NAME           CREATED AT
allow-tz-env

Create pod

[[email protected] ~]# kubectl apply -f nginx.yaml 
pod/nginx created

Check whether the pod is injected

# kubectl get pod nginx -o yaml 
... omitted
spec:
  containers:
  - env:
    - name: TZ
      value: Asia/Shanghai
    image: nginx
    imagePullPolicy: Always
    name: nginx
    resources: {}
... omitted

You can see that pod is injected with env named TZ

Init container

characteristic

  1. The init container runs before the application container in the pod starts.
  2. A pod can have one or more init containers.
  3. Each init container run must be completed.
  4. If the init container fails to run, k8s will continue to restart the pod until the init container runs successfully.
  5. However, if the restart policy value corresponding to pod is never, it will not restart.
  6. If a pod has multiple init containers, these containers will run one by one in order. Each init container must run successfully before the next one can run.
  7. The init container can contain some utilities or personalization code that does not exist in the application container during installation. For example, it is not necessary to generate a new image from an image just to use tools like sed, awk, python, or dig during installation.
  8. The init container can safely run these tools to prevent them from reducing the security of the application image.
  9. The creator and deployer of the application image can work independently, and there is no need to jointly build a separate application image.
  10. The init container can run in a file system view different from the application container in the pod. Therefore, the init container can have access to secrets, but the application container cannot.
  11. Because the init container must run before the application container starts, the init container provides a mechanism to block or delay the start of the application container until a set of prerequisites are met. Once the preconditions are met, all application containers in the pod will start in parallel.
  12. Until all init containers fail, pod will not become   Ready   Status.
  13. The change of init container image will cause the pod to restart, and the change of application container image will only restart the application container.
  14. Before each container copy in pod starts, init container will be executed once.

How to use

  1. Define a pod with 2 init containers.
  2. The init containers are myservice and mydb. After both init containers are started, pod can start the application container myapp container in the spec area

Create yaml file for Pod:

cat myapp.yaml

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  containers:
  - name: myapp-container
    image: busybox:1.28
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
  initContainers:
  - name: init-myservice
    image: busybox:1.28
    command: ['sh', '-c', "until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done"]
  - name: init-mydb
    image: busybox:1.28
    command: ['sh', '-c', "until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done"]

Create yaml files for mydb and myservice:

cat myservice.yaml

kind: Service
apiVersion: v1
metadata:
  name: myservice
spec:
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376
---
kind: Service
apiVersion: v1
metadata:
  name: mydb
spec:
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9377

To start this pod, execute the following command:

kubectl apply -f myapp.yaml
pod/myapp-pod created

Check its status:

kubectl get -f myapp.yaml
NAME        READY     STATUS     RESTARTS   AGE
myapp-pod   0/1       Init:0/2   0          6m

Use the following command to view more details:

kubectl describe -f myapp.yaml

Name:          myapp-pod
Namespace:     default
[...]
Labels:        app=myapp
Status:        Pending
[...]
Init Containers:
  init-myservice:
[...]
    State:         Running
[...]
  init-mydb:
[...]
    State:         Waiting
      Reason:      PodInitializing
    Ready:         False
[...]
Containers:
  myapp-container:
[...]
    State:         Waiting
      Reason:      PodInitializing
    Ready:         False
[...]

View the log of init container in pod

$ kubectl logs myapp-pod -c init-myservice
$ kubectl logs myapp-pod -c init-mydb

At this point, the init container will wait until a service named mydb and myservice is found.

Create a service for mydb and myservice:

$ kubectl create -f services.yaml
service "myservice" created
service "mydb" created

You can see that these init containers are executed, and then the pod of my app is transferred to running status:

$ kubectl get -f myapp.yaml
NAME        READY     STATUS    RESTARTS   AGE
myapp-pod   1/1       Running   0          9m

Myapp pod can be created only after we start mydb and myservice and the init container is completed.

Debug Pod

If the pod is terminated, you can view the reason through the following command

Kubectl describe pod pod name

Kubectl get Pod - o go template = '{range. Status. Containerstatuses}' "container name:"} {. Name} {"\ R \ nlaststate:"} {. Laststate} {{end}} 'pod name

Conclusion

The pod packages the container, and k8s operates the container by operating the pod.
Pod can contain multiple application containers and multiple init containers.
When the server node fails, the manually created pod has no self-healing ability, and the controller needs to be used to solve this problem.

Contact me

WeChat official account: zuolinux_ com

K8s actual combat (III) | essence of pod