首页 > 其他分享 >kubernetes-POD的基本原理

kubernetes-POD的基本原理

时间:2024-08-11 15:49:12浏览次数:9  
标签:容器 pause kubernetes 基本原理 nginx POD Pod pod

目录

什么是POD?

kubernetes中的一切都可以理解为是一种资源对象,POD,rc,service,都可以理解是 一种资源对象。POD的组成示意图如下,由一个叫”pause“的根容器,加上一个或多个用户自定义的容器构造。pause的状态带便了这一组容器的状态,POD里多个业务容器共享POD的Ip和数据卷。在kubernetes环境下,POD是容器的载体,所有的容器都是在POD中被管理,一个或多个容器放在POD里作为一个单元方便管理

POD有以下特点:

  • 一个POD可以理解为一个应用实例,提供服务;
  • POD中容器始终部署在同一个Node上;
  • POD中容器共享网络,存储资源;
  • Kubernetes直接管理POD,而不是容器;

在POD的生命周期中,POD被创建后,被分配一个唯一的ID(UID),调度到节点上,并一致维持期望的状态直到被终结(根据重启策略)或者被删除。如果node死掉了,分配到了这个node上的POD,在经过一个超时时间后会被重新调度到其他node节点上。一个给定的POD(如UID定义的)不会被“重新调度”到新的节点上,而是被一个同样的POD取代,如果期望的话甚至可以是相同的名字,但是会有一个新的UID(查看replication controller获取详情)。

为什么使用POD作为最小单元,而不是container

直接部署一个容器看起来更简单,但是这里也有更好的原因为什么在容器基础上抽象一层呢?根本原因是为了管理容器,kubernetes需要更多的信息,比如重启策略,它定义了容器终止后要采取的策略;或者是一个可用性探针,从应用程序的角度去探测是否一个进程还存活着。基于这些原因,kubernetes架构师决定使用一个新的实体,也就是POD,而不是重载容器的信息添加更多属性,用来在逻辑上包装一个或者多个容器的管理所需要的信息。

为什么允许一个POD里有多个容器

POD里的容器运行在一个逻辑上的"主机"上,它们使用相同的网络名称空间 (即同一POD里的容器使用相同的ip和相同的端口段区间) 和相同的IPC名称空间。它们也可以共享存储卷。这些特性使它们可以更有效的通信,并且POD可以使你把紧密耦合的应用容器作为一个单元来管理。也就是说当多个应用之间是紧耦合关系时,可以将多个应用一起放在一个POD中,同个POD中的多个容器之间互相访问可以通过localhost来通信(可以把POD理解成一个虚拟机,共享网络和存储卷)。
因此当一个应用如果需要多个运行在同一主机上的容器时,为什么不把它们放在同一个容器里呢?首先,这样何故违反了一个容器只负责一个应用的原则。这点非常重要,如果我们把多个应用放在同一个容器里,这将使解决问题变得非常麻烦,因为它们的日志记录混合在了一起,并且它们的生命周期也很难管理。因此一个应用使用多个容器将更简单,更透明,并且使应用依赖解偶。并且粒度更小的容器更便于不同的开发团队共享和复用。

POD中如何管理多个容器

POD中可以同时运行多个进程(作为容器运行)协同工作,同一个POD中的容器会自动的分配到同一个 node 上,同一个POD中的容器共享资源、网络环境和依赖,它们总是被同时调度。
POD中共享的环境包括Linux的namespace,cgroup和其他可能的隔绝环境,这一点跟Docker容器一致。在POD的环境中,每个容器中可能还有更小的子隔离环境。POD中的容器共享IP地址和端口号,它们之间可以通过localhost互相发现。它们之间可以通过进程间通信,需要明白的是同一个POD下的容器是通过lo网卡进行通信。例如SystemV信号或者POSIX共享内存。不同POD之间的容器具有不同的IP地址,不能直接通过IPC通信。POD中的容器也有访问共享volume的权限,这些volume会被定义成POD的一部分并挂载到应用容器的文件系统中。
总而言之。POD中可以共享两种资源:网络 和 存储

  1. 网络:每个POD都会被分配一个唯一的IP地址。POD中的所有容器共享网络空间,包括IP地址和端口。POD内部的容器可以使用localhost互相通信。POD中的容器与外界通信时,必须分配共享网络资源(例如使用宿主机的端口映射)。
  2. 存储:可以POD指定多个共享的Volume。POD中的所有容器都可以访问共享的volume。Volume也可以用来持久化POD中的存储资源,以防容器重启后文件丢失。

POD的yaml格式定义配置文件说明

apiVersion: v1                   # 必选,版本号
kind: Pod                        # 必选,Pod
metadata:                        # 必选,元数据
  name: nginx-pod                # 必选,Pod名称
  namespace: default             # 必选,Pod所属的命名空间
  labels:                        # 可选,自定义标签,Map格式
    app: nginx                   # 标签键值对
  annotations:                   # 可选,自定义注解
    description: "Nginx web server"  # 注解,用于描述该Pod
spec:                            # 必选,Pod中容器的详细属性
  containers:                    # 必选,Pod中容器列表
  - name: nginx                  # 必选,容器名称
    image: nginx:1.21.6          # 必选,容器的镜像地址和名称
    imagePullPolicy: IfNotPresent # 获取镜像的策略
    command: ["/bin/sh", "-c"]   # 容器的启动命令列表(覆盖)
    args: ["echo Hello Kubernetes!"]  # 容器的启动命令参数列表
    workingDir: /usr/share/nginx/html  # 容器的工作目录
    volumeMounts:                # 挂载到容器内部的存储卷配置
    - name: nginx-config-volume  # 引用Pod.spec.volumes[]中定义的共享存储卷的名称
      mountPath: /etc/nginx      # 存储卷在容器内挂载的绝对路径
      readOnly: true             # 设置为只读模式
    ports:                       # 容器需要暴露的端口列表
    - name: http                 # 端口名称
      containerPort: 80          # 容器需要监听的端口号
      hostPort: 8080             # 容器所在主机需要监听的端口号
  env:                           # 容器运行前需设置的环境变量列表
  - name: NGINX_PORT             # 环境变量名称
    value: "80"                  # 环境变量的值
  resources:                     # 资源限制和请求的设置
    limits:                      # 资源限制的设置
      cpu: "500m"                # CPU限制,单位为Core数
      memory: "512Mi"            # 内存限制,单位为MiB
    requests:                    # 资源请求的设置
      cpu: "250m"                # CPU请求,容器启动的初始可用数量
      memory: "256Mi"            # 内存请求,容器启动的初始可用数量
  livenessProbe:                 # 对Pod中容器的健康检查设置
    httpGet:                     # 设置为 HttpGet 检查方式
      path: /                    # URL路径
      port: 80                   # 对应端口
    initialDelaySeconds: 10      # 容器启动完成后首次探测的时间,单位为秒
    timeoutSeconds: 5            # 健康检查探测的超时时间,单位为秒
    periodSeconds: 15            # 健康检查的定期探测时间间隔,单位为秒
    successThreshold: 1          # 成功探测几次后认为健康
    failureThreshold: 3          # 失败探测几次后认为不健康
  securityContext:               # 安全上下文设置
    privileged: false            # 是否使用特权模式
  restartPolicy: Always           # Pod的重启策略
  nodeSelector:                  # NodeSelector调度,指定Pod调度到具有特定标签的Node上
    disktype: ssd                # 标签的键值对
  imagePullSecrets:              # Pull镜像时使用的Secret名称
  - name: myregistrykey          # Secret名称
  hostNetwork: false             # 是否使用主机网络模式
  volumes:                       # 在该Pod上定义的共享存储卷列表
  - name: nginx-config-volume    # 共享存储卷名称
    configMap:                   # 类型为ConfigMap的存储卷
      name: nginx-config         # 绑定的ConfigMap名称
      items:                     # 如果仅需挂载ConfigMap对象中的指定Key时使用
      - key: nginx.conf
        path: nginx.conf

如何使用Pod

通常把POD分为两类:

  • 自主式POD :这种POD本身是不能自我修复的,当POD被创建后(不论是由你直接创建还是被其他Controller),都会被Kuberentes调度到集群的Node上。直到POD的进程终止、被删掉、因为缺少资源而被驱逐、或者Node故障之前这个POD都会一直保持在那个Node上。POD不会自愈。如果POD运行的Node故障,或者是调度器本身故障,这个POD就会被删除。同样的,如果POD所在Node缺少资源或者POD处于维护状态,POD也会被驱逐。
  • 控制器管理的POD:Kubernetes使用更高级的称为Controller的抽象层,来管理POD实例。Controller可以创建和管理多个POD,提供副本管理、滚动升级和集群级别的自愈能力。例如,如果一个Node故障,Controller就能自动将该节点上的POD调度到其他健康的Node上。虽然可以直接使用POD,但是在Kubernetes中通常是使用Controller来管理POD的。如下图:

每个POD都有一个特殊的被称为"根容器"的Pause 容器。 Pause容器对应的镜像属于Kubernetes平台的一部分,除了Pause容器,每个POD还包含一个或者多个紧密相关的用户业务容器。

Kubernetes设计这样的POD概念和特殊组成结构有什么用意呢?
原因一:在一组容器作为一个单元的情况下,难以对整体的容器简单地进行判断及有效地进行行动。比如一个容器死亡了,此时是算整体挂了么?那么引入与业务无关的Pause容器作为POD的根容器,以它的状态代表着整个容器组的状态,这样就可以解决该问题。
原因二:POD里的多个业务容器共享Pause容器的IP,共享Pause容器挂载的Volume,这样简化了业务容器之间的通信问题,也解决了容器之间的文件共享问题。

POD的持久性和终止

Pod的持久性

  • Pod在设计上就不是作为持久化实体的。在调度失败、节点故障、缺少资源或者节点维护的状态下都会死掉会被驱逐。通常,用户不需要手动直接创建Pod,而是应该使用controller(例如Deployments),即使是在创建单个Pod的情况下。Controller可以提供集群级别的自愈功能、复制和升级管理。

Pod的终止

  • 因为Pod作为在集群的节点上运行的进程,所以在不再需要的时候能够优雅的终止掉是十分必要的(比起使用发送KILL信号这种暴力的方式)。用户需要能够放松删除请求,并且知道它们何时会被终止,是否被正确的删除。用户想终止程序时发送删除pod的请求,在pod可以被强制删除前会有一个宽限期,会发送一个TERM请求到每个容器的主进程。一旦超时,将向主进程发送KILL信号并从API server中删除。如果kubelet或者container manager在等待进程终止的过程中重启,在重启后仍然会重试完整的宽限期。

示例流程如下:

  1. 用户发送删除Pod的命令,默认宽限期是30秒;
  2. 在Pod超过该宽限期后API server就会更新Pod的状态为"dead";
  3. 在客户端命令行上显示的Pod状态为"terminating";
  4. 跟第三步同时,当kubelet发现pod被标记为"terminating"状态时,开始停止pod进程:
  • 如果在pod中定义了preStop hook,在停止pod前会被调用。如果在宽限期过后,preStop hook依然在运行,第二步会再增加2秒的宽限期;
  • 向Pod中的进程发送TERM信号;
  1. 跟第三步同时,该Pod将从该service的端点列表中删除,不再是replication controller的一部分。关闭的慢的pod将继续处理load balancer转发的流量;
  2. 过了宽限期后,将向Pod中依然运行的进程发送SIGKILL信号而杀掉进程。
  3. Kublete会在API server中完成Pod的的删除,通过将优雅周期设置为0(立即删除)。Pod在API中消失,并且在客户端也不可见。

删除宽限期默认是30秒。 kubectl delete命令支持 --grace-period= 选项,允许用户设置自己的宽限期。如果设置为0将强制删除pod。在kubectl>=1.5版本的命令中,你必须同时使用 --force 和 --grace-period=0 来强制删除pod。
Pod的强制删除是通过在集群和etcd中将其定义为删除状态。当执行强制删除命令时,API server不会等待该pod所运行在节点上的kubelet确认,就会立即将该pod从API server中移除,这时就可以创建跟原pod同名的pod了。这时,在节点上的pod会被立即设置为terminating状态,不过在被强制删除之前依然有一小段优雅删除周期。【需要注意:如果删除一个pod后,再次查看发现pod还在,这是因为在deployment.yaml文件中定义了副本数量!还需要删除deployment才行。即:"kubectl delete pod pod-name -n namespace" && "kubectl delete deployment deployment-name -n namespace"】

Pause

Pause容器,又叫Infra容器。我们检查node节点的时候会发现每个node节点上都运行了很多的pause容器,例如如下:

[root@master01 ~]# docker ps |grep pause
b64743cdafc3   registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.5   "/pause"                  3 seconds ago    Up 2 seconds              k8s_POD_coredns-5db5696c7-hzmz8_kube-system_e6731c9d-b869-478c-bd92-4ab0269100d0_16
11cda9acfeeb   registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.5   "/pause"                  3 seconds ago    Up 3 seconds              k8s_POD_cluster-test-8b47d69f5-ztp8g_default_f799a8b6-7f57-4545-9cca-10a65125e2c0_9
9f9aa4eb7b44   registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.5   "/pause"                  4 seconds ago    Up 4 seconds              k8s_POD_metrics-server-6bf7dcd649-vbswr_kube-system_ee301025-6f64-4b1d-a45a-93ee54ed677e_8
d6033bb2d90f   registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.5   "/pause"                  28 seconds ago   Up 27 seconds             k8s_POD_calico-node-vwgvd_kube-system_d9db971a-dc40-4330-bf87-826fcb13654e_12

image.pngkubernetes中的pause容器主要为每个业务容器提供以下功能:

  • 在pod里担任与其他容器namespace共享的基础;
  • 启用pid命名空间,开启init进程,负责处理僵尸进程。

(注意:这里虽然开启了PID名称空间共享,但是在Kubelet中--docker-disable-shared-pid=true关闭了PID共享,所以Pod中的每个容器都将具有自己的PID 1,并且每个容器将需要自己处理僵尸进程)

我们首先在节点上运行一个pause容器

[root@node01 ~]# docker run -d --name pause --ipc=shareable -p 8880:80 registry.cn-hangzhou.aliyuncs.com/google_containers/pause-amd64:3.1
c535b224ad280c600c761483543128b1a10a12776b8deceb35bda750c8a9a10a

然后再运行一个nginx容器,nginx将为localhost:2368创建一个代理。

[root@node01 ~]# cat <<EOF >> nginx.conf
error_log stderr;
events { worker_connections  1024; }
http {
    access_log /dev/stdout combined;
    server {
        listen 80 default_server;
        server_name example.com www.example.com;
        location / {
            proxy_pass http://127.0.0.1:2368;
        }
    }
}
EOF

[root@node01 ~]# docker run -d --name nginx -v `pwd`/nginx.conf:/etc/nginx/nginx.conf --net=container:pause --ipc=container:pause --pid=container:pause nginx
8651621e55ac24d8470eb43077397af08ca1e0090301b6f9bb30902535e5936e

然后再为ghost创建一个应用容器

[root@oracle ~]# docker run -d --name ghost --net=container:pause --ipc=container:pause --pid=container:pause ghost:2.7.1
Unable to find image 'ghost:2.7.1' locally
2.7.1: Pulling from library/ghost
Digest: sha256:727f18f41e0835f673c23d037ee3f56f3bfeaca8e7bfbabdd803107c2e35839f
Status: Downloaded newer image for ghost:2.7.1
c479167c5577994b9c455343e88f9d9a14762f4c1840851aaf56429ed131ff5c

解析:

  • pause 容器将内部的80端口映射到了宿主机的8880端口;
  • pause容器在宿主机上设置好了网络namespace后,nginx容器加入到该网络namespace中;
  • nginx容器启动的时候指定了–net=container:pause;
  • ghost容器启动的时候同样加入到了该网络namespace中;
  • 这样三个容器就共享了网络,互相之间就可以使用localhost直接通信,
  • –ipc=contianer:pause –pid=container:pause就是三个容器的ipc和pid处于同一个namespace中,init进程为pause;

这时我们进入到ghost容器中查看进程情况。

[root@node01 ~]# docker exec -it ghost /bin/bash
root@c535b224ad28:/var/lib/ghost# ps axu
USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root          1  0.0  0.0   1012     4 ?        Ss   03:48   0:00 /pause
root          6  0.0  0.0  32472   780 ?        Ss   03:53   0:00 nginx: master process nginx -g daemon off;
systemd+     11  0.0  0.1  32932  1700 ?        S    03:53   0:00 nginx: worker process
node         12  0.4  7.5 1259816 74868 ?       Ssl  04:00   0:07 node current/index.js
root         77  0.6  0.1  20240  1896 pts/0    Ss   04:29   0:00 /bin/bash
root         82  0.0  0.1  17496  1156 pts/0    R+   04:29   0:00 ps axu

在ghost容器中同时可以看到pause和nginx容器的进程,并且pause容器的PID是1。而在kubernetes中容器的PID=1的进程即为容器本身的业务进程。

Pod中共享的名称空间:

  • PID命名空间:Pod中的不同应用程序可以看到其他应用程序的进程ID;
  • 网络命名空间:Pod中的多个容器能够访问同一个IP和端口范围;
  • IPC命名空间:Pod中的多个容器能够使用SystemV IPC或POSIX消息队列进行通信;
  • UTS命名空间:Pod中的多个容器共享一个主机名;Volumes(共享存储卷):
  • Pod中的各个容器可以访问在Pod级别定义的Volumes;

标签:容器,pause,kubernetes,基本原理,nginx,POD,Pod,pod
From: https://www.cnblogs.com/Unstoppable9527/p/18353501

相关文章

  • CertBot搭配DNSPod
    CertBot搭配DNSPodsummary:cetbot搭配dnspod实现自动注册ssl证书和自动续期......
  • 【云原生之kubernetes实战】在k8s环境下部署Note Mark笔记工具
    【云原生之kubernetes实战】在k8s环境下部署NoteMark笔记工具一、NoteMark介绍1.1NoteMark简介1.2NoteMark特点1.3NoteMark使用场景二、本次实践介绍2.1本次实践简介2.2本次环境规划2.2k8s存储介绍三、检查k8s环境3.1检查工作节点状态3......
  • 【K8s】专题九:Kubernetes 常用命令汇总
    以下内容均来自个人笔记并重新梳理,如有错误欢迎指正!如果对您有帮助,烦请点赞、关注、订阅、转发!欢迎扫码关注个人公众号!目录写在前边一、集群相关1、查看集群信息2、查看集群服务3、查看集群组件4、查看集群版本5、查看集群API版本二、节点相关1、查看节点状态2......
  • Kubernetes-POD的健康检查
    目录简介什么是探针LivenessProbe(存活探针)ReadinessProbe(就绪探针)StartupProbe(启动探针)什么时候使用探针?何时使用存活探针(LivenessProbe)何时使用就绪探针(Read inessProbe)何时使用启动探针(StartupProbe)容器探测方法exechttpGettcpSocket容器探测使用livenessProbe使用exec使......
  • Kubernetes-POD的健康检查
    目录简介什么时候使用探针?何时使用存活探针(LivenessProbe)何时使用就绪探针(Read inessProbe)何时使用启动探针(StartupProbe)容器探测方法exechttpGettcpSocket容器探测使用livenessProbe使用exec使用httpGet使用tcpSocketreadinessProbe使用exec使用httpGet使用tcpSocket使用start......
  • 【Kubernetes】k8s集群存储卷(pvc存储卷)
    目录一.pvc存储卷1.PV2.PVC3.StorageClass4.PV和PVC的生命周期二.实战演练1.创建静态pv1.1.配置nfs1.2.创建pv1.3.创建pvc1.4.结合pod,将pv、pvc一起运行2.创建动态pv2.1.上传2.2.创建ServiceAccount,用来管理NFSProvisioner在k8s集群中运行的权限,设置nfs-......
  • 【云原生】Kubernetes中如何对etcd进行备份和还原,确保k8s集群的稳定和健壮
    ✨✨欢迎大家来到景天科技苑✨✨......
  • 通义千问-podcast播客AI转译与NotebookLM
    通义千问-podcast播客AI转译与NotebookLM背景通义千问的播客链接转写功能通义千问的播客链接转写功能是一个高效、便捷的工具,旨在帮助用户将播客链接中的音频内容自动转换为文字形式,并提取关键信息。这一功能主要面向播客爱好者、学习者和知识工作者,使得他们能够更加灵活地处理和......
  • Kubernetes-POD的QoS
    目录背景问题分析进一步排查问题原因Pod的QoS服务质量等级结论背景今天开发团队反馈,测试环境中部分业务功能无法正常使用。经过初步排查,发现某个业务Pod在一天内重启了10次,因此需要进一步调查原因。问题分析首先,我查看了Pod的日志,发现JVM并未抛出任何错误,服务却直接重启了。这......
  • Kubernetes-kubeapps-install
    Helminstall[root@rocky01~]#curl-fsSL-oget_helm.shhttps://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3[root@rocky01~]#chmod700get_helm.sh&&./get_helm.shKubeappsinstall[root@rocky01~]#helmrepoaddbitnamihttp......