The essence of the Pod

A Pod packs one or more containers. Pod is the smallest execution unit of K8S. Pod is a process in K8S. Pod can wrap Docker, and can also wrap other types of containers. A Pod contains encapsulated containers, storage resources, network resources, and configurations that guide how the container operates.

The container can be understood as a bald container without hooks. K8S cannot mount it directly. By adding hooks (IP address) to the container (container), a Pod is formed, which is convenient for K8S to operate.

You can also think of Pod as a traditional virtual machine, where a container is a program running in a traditional virtual machine, except that the virtual machine is an entity and Pod is a logical concept.

K8S schedules containers by choreographing pods rather than manipulating them directly, and K8S cannot manipulate containers directly.

Shared resources in Pod

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

network

Pod has a unique IP address, multiple containers in Pod share an IP address and network ports and other network resources in Pod multiple containers can use localhost communication Pod container and external communication, Multiple containers need to coordinate network ports The container in Pod gets the same system hostname as the name configured for Pod

storage

Pod You can specify that all containers in a Pod group can access the storage volume to share data with each other. Shared volumes in Pod can be persisted to prevent data loss during container restart

The characteristics of the Pod

If you use kind: Pod’s YAMl file to create a Pod, the Pod cannot be automatically scheduled to another available server if the current node server has a problem.

You typically use KIND: Deployment’s YAML to create pods.

Deployment is a controller that can be used to create and manage pods. If creating multiple copies of Pod, scroll to update Pod.

When the node where the Pod is located has problems, the Deployment controller can start new pods on 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']
Copy the code

Mirror pull policy

If not specified, imagePullPolicy is Always, meaning that Kubelet will try to pull each image from the specified repository. If the container attribute imagePullPolicy is set to IfNotPresent, the local image is preferred. If the container attribute imagePullPolicy is set to IfNotPresent Never, the local image will always 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" ]
Copy the code

Pod common parameters

NodeSelector

Function: Bind a Pod to a Node

apiVersion: v1
kind: Pod
...
spec:
 nodeSelector:
   disktype: ssd
Copy the code

The Pod can only run on nodes that carry the “DiskType: SSD” Label. If the node does not have this Label, scheduling will fail.

NodeName

This field is normally set by the scheduler, but we can set it manually during testing to make the scheduler think the Pod has already been scheduled.

HostAliase

Set the contents of the /etc/hosts file for each Pod container

apiVersion: v1 kind: Pod ...... Spec: hostAliases: -ip: "10.20.20.20" Hostnames: - "test1.com" - "test2.com"Copy the code

Check the container

[root@master01 ~]# kubectl exec -it nginx -- bash
root@nginx:/# cat /etc/hosts
......
# Entries added by HostAliases.
10.20.20.20     test1.com       test2.com
Copy the code

shareProcessNamespace

Define the parameter shareProcessNamespace=true so that all containers in the Pod will share the PID Namespace

Create a Pod with two containers

[root@master01 ~]# 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
Copy the code

Viewing health

[root@master01 ~]# 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>
Copy the code

Enter a container called shell in Pod Nginx

[root@master01 ~]# 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
Copy the code

As you can see, the process of the nginx container is visible in the shell container

The preset parameter of Pod, PodPreset

A few common configurations can be preset, and PodPreset automatically attaches the common configuration to the corresponding Pod when users submit their own personalized Pod configuration.

Content defined in PodPreset will only be appended to the Pod API object itself before it is created, and will not affect any Pod controller definition.

For example, if we are now committing an nginx-Deployment, the Deployment object itself is never changed by PodPreset, only the pods created by this Deployment are modified.

If PodPreset is not enabled

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

Enable the PodPreset feature

Modify the [/ etc/kubernetes manifests/kube - apiserver. Yaml] the spec.containers.com mand: Modify the original - the runtime API/config = all = true for - - the runtime API/config = all = true, Settings. K8s. IO/v1alpha1 = true - new line -- enable-adit-plugins =PodPreset (preset) Kubelet systemctl restart kubeletCopy the code

Preset value Preset. Yaml

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

Pod configure nginx. Yaml

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

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
Copy the code

Create a Pod

[root@master01 ~]# kubectl apply -f nginx.yaml 
pod/nginx created
Copy the code

Check whether the Pod is injected

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

You can see that Pod is injected with env named TZ

Init container

The characteristics of

  1. The Init container runs before the application container starts in the Pod.
  2. A Pod can have one or more Init containers.
  3. Each Init container run must be completed.
  4. If the Init container fails, K8S will restart the Pod until the Init container succeeds.
  5. However, if the Pod corresponding restartPolicy value is Never, it will not restart.
  6. If a Pod has multiple Init containers, they run one by one in order. Each Init container must run successfully before the next one can run.
  7. The Init container can contain utilities or personalization code that are not present in the application container during installation. For example, there is no need to generate a new image FROM an image just to use a tool like sed, AWk, Python, or DIG during installation.
  8. The Init container can safely run these tools without compromising the security of the application image.
  9. The creator and deployer of an application image can work independently of each other rather than jointly building a single application image.
  10. The Init container can run in a different file system view than the application container in Pod. Therefore, the Init container has access to Secrets that the application container does not.
  11. Because the Init container must be run before the application container can be started, 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 within the Pod start in parallel.
  12. The Pod will not become Ready until all Init containers have succeeded.
  13. A change in the Init container image will cause the Pod to restart. A change in the application container image will only restart the application container.
  14. The Init container is executed once before each container copy in Pod is started.

How to use

  1. Define a Pod with two Init containers.
  2. Init containers are myService and myDB. Pod cannot start myapp-Container in the Spec area until both Init containers are started

Create Pod YAML file:

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 the 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"]Copy the code

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
Copy the code

To start the Pod, run the following command:

kubectl apply -f myapp.yaml
pod/myapp-pod created
Copy the code

Check its status:

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

Use the following command to see 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 [...]Copy the code

View the log of the Init container in Pod

$ kubectl logs myapp-pod -c init-myservice
$ kubectl logs myapp-pod -c init-mydb
Copy the code

At this point, the Init container will wait until it finds services named mydb and myService.

Create service for mydb and myService:

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

You can see that these Init containers finish executing, and then the Pod of my-app transitions to the Running state:

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

Myapp-pod can only be created if we start mydb and myService and Init container is complete.

Debug Pod

If the Pod is terminated, run the following command to check the cause

Kubectl describe pod pod Name kubectl get pod - o go - the template = '{{range. Status. ContainerStatuses}} {{" Container Name: . "}} {{name}} {{\ r \ nLastState: ""}} {{. LastState}} {{end}} 'name of the podCopy the code

conclusion

The Pod wraps the container, and K8S operates the container by manipulating the Pod.

A Pod can contain multiple application containers and multiple Init containers.

A Pod created manually does not have the ability to heal itself when a server node fails. A controller is required to solve this problem.