Pod

Pod 是 K8s 的最小调度单位,里面可以有一个或多个容器,这些容器共享网络、存储等资源。

Pod 里的容器共享什么
资源是否共享说明
网络 namespace共享同一个 Pod 内容器共用 IP、端口空间,可以用 localhost 通信
UTS namespace共享主机名相同
IPC namespace共享可以用共享内存、信号量
存储卷 Volume可共享多个容器可以挂同一个 volume
PID namespace默认不共享设置 shareProcessNamespace: true 才共享
MNT namespace默认不共享每个容器有自己的 rootfs

所以同一个 Pod 里:

  • 容器之间可以用 localhost 访问
  • 端口不能冲突
  • 主机名一样
  • 文件系统默认各自独立
  • 可以通过 volume 共享数据

通常一个 Pod 里放几个容器?

大多数情况:一个 Pod 一个主容器。

多容器常见于:

  • sidecar:日志收集、代理
  • init container:启动前初始化
  • adapter:格式转换

它们生命周期和调度绑定在一起。

设计时,多个容器是否放在一个Pod内的关键考虑因素
维度适合同 Pod 的信号应该拆开的信号
网络必须用 localhost 通信,共享端口空间通过 Service、API、消息队列通信即可
存储必须共享同一个 volume,低延迟读写同一批文件用 PVC、对象存储、数据库交换数据即可
生命周期一起创建、一起删除,生命周期基本一致一个长期运行,一个按任务创建销毁
调度必须调度到同一节点可以分散到不同节点
安全隔离两者可信程度相同,安全要求一致一个跑不可信代码,需要强隔离
扩缩容副本数和扩缩容节奏一致一个要扩,一个不用扩,或比例不同
资源边界可以共享同一套资源限制和 QoS需要独立 CPU/内存 limits、独立 QoS
失败影响一个挂掉可以接受影响另一个一个崩溃不应影响另一个

Node

节点(Node)就是 K8s 集群里的一台工作机器(虚拟机or物理机),Pod 最终跑在节点上。
节点一般可以根据职责分为两类——控制节点和工作节点

工作负载

Deployment

Deployment 是 K8s 里最常用的工作负载控制器,用来管理无状态 Pod 的副本

StatefulSet

StatefulSet 是专门用来管理有状态Pod的工作负载控制器

StatefulSet 和 Deployment 的核心区别

维度DeploymentStatefulSet
Pod 身份随机名字,可互换固定名字,如 web-0、web-1
网络标识通常用 Service 负载均衡每个 Pod 有稳定 DNS
存储通常无状态,共享存储可选每个 Pod 独立 PVC
启动顺序并行启动默认按顺序启动
扩缩顺序随意有序扩缩
更新顺序滚动更新,任意替换默认逆序更新
适用无状态、可水平扩展有状态、需要稳定标识和存储

Deployment + 普通 Service的K8s内部请求链路

客户端
  -> DNS: web.default.svc.cluster.local
  -> 得到 ClusterIP: 10.96.0.10
  -> 向 ClusterIP 发请求
  -> 节点内核按 kube-proxy 规则 DNAT
  -> 转发到任意一个 Ready Pod(如 web-7d8f9c-abcde)

特点:

  • Pod 名字随机,客户端不关心连的是哪个
  • Service 做负载均衡
  • Pod 挂了、扩缩容,EndpointSlice 更新,规则自动变

StatefulSet + Headless Service的K8s内部请求链路

客户端
  -> DNS: web.default.svc.cluster.local
  -> 得到所有 Pod IP 列表:[10.244.0.5, 10.244.0.6, 10.244.0.7]
  -> 客户端自己选一个 Pod IP
  -> 直连 Pod

特点:

  • 没有 ClusterIP
  • 不经过 kube-proxy VIP 转发
  • 负载均衡由客户端自己做
  • 适合 gRPC 客户端自己维护连接池

客户端(集群内部的其他Pod)如何知道DNS的Key(FQDN)的?——通过配置文件提前配置

有状态的Pod是不是就一定不能用Deployemnt?——不一定,如果不考虑可用性,Pod是单实例的话,那用Deployment也可以。核心决定性因素在于——Pod 挂掉重建后,能不能还以原来的身份,挂回原来分配给它的那个卷。单副本情况下不需要做多副本的区分,所以可以

Service——把IP:Port路由到具体的Pod

Service(服务) 是 Kubernetes 中用于为 Pod 提供稳定网络访问入口和负载均衡的核心组件,它抽象了 Pod 的网络访问方式,使得外部客户端或其他 Pod 可以通过 Service 访问后端 Pod,而无需关心 Pod 的具体 IP 地址或生命周期。Service本身也只是规则,真正处理流量的是kube-proxy。负责K8s的四层路由

Service的所有类型

K8s 里 Service 的 spec.type 官方只有 4 种:

类型作用外部能否访问典型场景
ClusterIP分配一个集群内部虚拟 IP不能,默认仅集群内集群内服务互访,默认类型
NodePort在ClusterIP的基础上在每个节点上开一个端口能,节点IP:端口测试、简单暴露、无云 LB
LoadBalancer向云/基础设施申请外部负载均衡器能,外部LB IP:端口生产环境暴露服务
ExternalName用 DNS CNAME 指向外部域名不代理流量,只做 DNS 映射集群内访问外部服务

另外还有两个容易混淆的概念:

  • Headless Service:不是独立类型,而是 ClusterIP: None 的特殊 ClusterIP。
  • ExternalIPs:spec.externalIPs 字段,不是 Service 类型。
  • Ingress:不是 Service 类型,是七层入口,通常后端再接 Service。

ClusterIP

ClusterIP 是 K8s 给 Service 分配的一个集群内部虚拟 IP,用来在集群内稳定地访问一组 Pod。

查看机器中的所有Service和其ClusterIP

root@knowledgeskilltest:/home/zn# kubectl get services --all-namespaces
NAMESPACE                  NAME                               TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                  AGE
default                    kubernetes                         ClusterIP   10.96.0.1       <none>        443/TCP                  8d
dynamic-test-runtime       dynamic-test-admission-projector   ClusterIP   10.96.211.7     <none>        9443/TCP                 6d1h
dynamic-test-runtime       dynamic-test-run                   ClusterIP   None            <none>        <none>                   6d1h
dynamic-test               dynamic-test-api                   ClusterIP   10.96.65.96     <none>        8010/TCP                 6d18h
dynamic-test               dynamic-test-gateway               ClusterIP   10.96.4.159     <none>        9444/TCP                 6d18h
dynamic-test               dynamic-test-projector             ClusterIP   10.96.122.184   <none>        8443/TCP                 6d18h
dynamic-test               minio                              ClusterIP   10.96.225.52    <none>        9000/TCP,9001/TCP        6d19h
dynamic-test               mock-event-sink                    ClusterIP   10.96.170.115   <none>        8443/TCP                 6d18h
dynamic-test               mock-model-provider                ClusterIP   10.96.252.70    <none>        8443/TCP                 6d18h
dynamic-test               mysql                              ClusterIP   10.96.3.129     <none>        3306/TCP                 6d19h
dynamic-test               registry                           ClusterIP   10.96.250.62    <none>        5000/TCP                 6d1h
dynamic-test               skillhub-mock                      ClusterIP   10.96.4.147     <none>        8443/TCP                 6d18h
kube-system                kube-dns                           ClusterIP   10.96.0.10      <none>        53/UDP,53/TCP,9153/TCP   8d
opensandbox-dynamic-test   opensandbox-ingress-gateway        ClusterIP   10.96.184.95    <none>        80/TCP                   7d
opensandbox-dynamic-test   opensandbox-server                 ClusterIP   10.96.152.62    <none>        8443/TCP                 6d23h

可以看到dynamic-test-run 这个Service其ClusterIP为None,这种Service 就是前文提到的Headless Service

查看机器中的所有Pod

root@knowledgeskilltest:/home/zn# kubectl get pods -A -o wide
NAMESPACE                  NAME                                                 READY   STATUS      RESTARTS   AGE     IP             NODE                         NOMINATED NODE   READINESS GATES
dynamic-test-runtime       dynamic-test-admission-projector-7b967f54d8-vjs6j    1/1     Running     0          5d20h   10.244.0.165   dynamic-test-control-plane   <none>           <none>
dynamic-test-runtime       dynamic-test-admission-projector-7b967f54d8-x286g    1/1     Running     0          5d20h   10.244.0.164   dynamic-test-control-plane   <none>           <none>
dynamic-test-runtime       dynamic-test-run-0                                   1/1     Running     0          43h     10.244.0.18    dynamic-test-control-plane   <none>           <none>
dynamic-test-runtime       dynamic-test-run-1                                   1/1     Running     0          42h     10.244.0.22    dynamic-test-control-plane   <none>           <none>
dynamic-test-runtime       dynamic-test-run-2                                   1/1     Running     0          42h     10.244.0.21    dynamic-test-control-plane   <none>           <none>
dynamic-test-runtime       dynamic-test-runtime-reaper-7dbcddcb78-bzn9q         1/1     Running     0          5d20h   10.244.0.167   dynamic-test-control-plane   <none>           <none>
dynamic-test-runtime       dynamic-test-runtime-reaper-7dbcddcb78-kwlx5         1/1     Running     0          5d20h   10.244.0.163   dynamic-test-control-plane   <none>           <none>
dynamic-test               dynamic-test-api-556d6cbbbb-8949c                    1/1     Running     0          23h     10.244.0.36    dynamic-test-control-plane   <none>           <none>
dynamic-test               dynamic-test-assistant-96bfc89bd-4252m               1/1     Running     0          7d16h   10.244.0.123   dynamic-test-control-plane   <none>           <none>
dynamic-test               dynamic-test-image-74f65fdc7d-8f6xd                  1/1     Running     0          47h     10.244.0.238   dynamic-test-control-plane   <none>           <none>
dynamic-test               dynamic-test-migration-8bgfk                         0/1     Completed   0          7d17h   10.244.0.59    dynamic-test-control-plane   <none>           <none>
dynamic-test               dynamic-test-model-gateway-747dc9c58f-r5bps          1/1     Running     0          43h     10.244.0.6     dynamic-test-control-plane   <none>           <none>
dynamic-test               dynamic-test-projector-6d5684d6f9-67wpj              1/1     Running     0          7d16h   10.244.0.118   dynamic-test-control-plane   <none>           <none>
dynamic-test               dynamic-test-projector-6d5684d6f9-sbvjw              1/1     Running     0          7d16h   10.244.0.119   dynamic-test-control-plane   <none>           <none>
dynamic-test               dynamic-test-registry-d66678795-8spdp                1/1     Running     0          7d      10.244.0.135   dynamic-test-control-plane   <none>           <none>
dynamic-test               dynamic-test-relay-5c74788d86-x6drs                  1/1     Running     0          7d16h   10.244.0.121   dynamic-test-control-plane   <none>           <none>
dynamic-test               minio-59c78bffbd-kqqbp                               1/1     Running     0          7d17h   10.244.0.41    dynamic-test-control-plane   <none>           <none>
dynamic-test               mock-event-sink-7c966d5f7c-gzcmh                     1/1     Running     0          7d16h   10.244.0.107   dynamic-test-control-plane   <none>           <none>
dynamic-test               mock-model-provider-857bd94db8-8cq2h                 1/1     Running     0          44h     10.244.0.250   dynamic-test-control-plane   <none>           <none>
dynamic-test               mysql-6fcfccb8f8-92mld                               1/1     Running     0          7d17h   10.244.0.37    dynamic-test-control-plane   <none>           <none>
dynamic-test               skillhub-mock-5d785786c9-kz4bn                       1/1     Running     0          7d16h   10.244.0.114   dynamic-test-control-plane   <none>           <none>
ingress-nginx              ingress-nginx-controller-b6b495bc9-rrnrs             1/1     Running     0          4m22s   10.244.0.44    dynamic-test-control-plane   <none>           <none>
kube-system                coredns-559f6c778d-4wdfq                             1/1     Running     0          9d      10.244.0.3     dynamic-test-control-plane   <none>           <none>
kube-system                coredns-559f6c778d-mzqb8                             1/1     Running     0          9d      10.244.0.4     dynamic-test-control-plane   <none>           <none>
kube-system                etcd-dynamic-test-control-plane                      1/1     Running     0          9d      172.18.0.2     dynamic-test-control-plane   <none>           <none>
kube-system                kindnet-kkmdv                                        1/1     Running     0          9d      172.18.0.2     dynamic-test-control-plane   <none>           <none>
kube-system                kube-apiserver-dynamic-test-control-plane            1/1     Running     0          9d      172.18.0.2     dynamic-test-control-plane   <none>           <none>
kube-system                kube-controller-manager-dynamic-test-control-plane   1/1     Running     0          9d      172.18.0.2     dynamic-test-control-plane   <none>           <none>
kube-system                kube-proxy-vhnbx                                     1/1     Running     0          9d      172.18.0.2     dynamic-test-control-plane   <none>           <none>
kube-system                kube-scheduler-dynamic-test-control-plane            1/1     Running     0          9d      172.18.0.2     dynamic-test-control-plane   <none>           <none>
local-path-storage         local-path-provisioner-75f7fc7dc5-lh46q              1/1     Running     0          9d      10.244.0.2     dynamic-test-control-plane   <none>           <none>
opensandbox-dynamic-test   opensandbox-controller-manager-5d44fcc5f7-r7gvp      1/1     Running     0          2d      10.244.0.186   dynamic-test-control-plane   <none>           <none>
opensandbox-dynamic-test   opensandbox-ingress-gateway-656fb874c-sf8tv          1/1     Running     0          2d      10.244.0.187   dynamic-test-control-plane   <none>           <none>
opensandbox-dynamic-test   opensandbox-server-7b497b4b5c-nzm7s                  2/2     Running     0          46h     10.244.0.244   dynamic-test-control-plane   <none>           <none>

name为coredns开头的,就是负责将FQDN转化为IP的组件

  • 对于普通Service,其会将FQDN解析为ClusterIP
  • 对于Headless Service,其会将FQDN解析为后端Pod IP列表
  • StatefulSet 工作负载下的POD,会有稳定的POD名,也会有稳定的FQDN,coreDNS能将其转化为单个Pod 的IP

neme为kube-proxy开头的,就是负责将ClusterIP/NodePort流量转发到具体Pod的组件

NodePort

在每个节点上开放同一个端口,把这个端口收到的流量,转发到 Service 后面的 Pod。一个端口对应一个Service
注意启用了NodePort后,整个Service一般依旧会有一个ClusterIP——NodePort负责对外,ClusterIP负责对内

LoadBalancer

本质上是 NodePort 的上一层封装:在 NodePort 基础上,再向云厂商或基础设施申请一个独立的负载均衡器 IP。刚需公网IP

Q:LB怎么知道过来请求到底要访问哪个NodePort?
A:一个云 LB 可以为多个端口创建一个监听器,每个监听器分别映射到对应的后端——一个IP不同,但是Port相同的IP:Port列表。

K8s 原生 LoadBalancer 的语义是“一个 Service 一个 LB”——所以一个LoadBalancer虽然可以对应多个NodePort,但是其后端都是同一组Pod。也就是说不存在只使用一个公网IP+LoadBalancer就完成多个Service的暴露的情况。或者说K8s原生中,没有LB这个对象,有的只是LoadBalancer这种Service类型,因此也就没有LB-Service的一对多关系。

但是云厂商天生就需要对LB和公网IP做管理,因此实现一套这样的逻辑成本相对低——而且用户也有需求。

所以其实在云上,完全可以用 一个公网 IP + 一个负载均衡器(LB),不用 Ingress,就对外提供多个服务。限制就是必须依靠不同的端口来区分不同的服务。

Ingress——把HTTP 请求(域名、路径)路由到Service

Ingress 是 K8s 里的一种 API 对象,用来定义“外部 HTTP/HTTPS 流量怎么进入集群、路由到哪些 Service”。它本身只是规则,真正处理流量的是 Ingress Controller(一组以DaemonSet工作负载形式部署的Pod)。负责K8s的七层路由

root@knowledgeskilltest:/home/zn# kubectl get pods -A -o wide | grep ingress
ingress-nginx              ingress-nginx-controller-b6b495bc9-rrnrs             1/1     Running     0          7m21s   10.244.0.44    dynamic-test-control-plane   <none>           <none>

这个筛选出来的Pod就是ingress Controller实例,它里面通常跑着 ingress-nginx 的 controller 逻辑和 Nginx 进程。真正直接承接外部 HTTP/HTTPS 请求、按 Ingress 规则转发的,就是这个 Pod 里的 Nginx。

Ingress Controller的Service一般是前文中提到的LoadBalancer或者NodePort,通过IP(一般LB是公网,NodePort是内网)提供一个4层入口,然后Ingress Controller内部的nginx再解析 Host/Path,将请求根据Ingress规则反向代理到到后端 Service 对应的 Pod(四层)

外部流量路径

外部用户
  -> DNS 解析到入口 IP
  -> 四层入口:云 LB / Service type=LoadBalancer / NodePort 
  -> Ingress Controller Pod
       └── TCP 承载到达(四层)
       └── Nginx / Traefik / Envoy 解析 HTTP(七层)
  -> 根据 Ingress 规则选择后端
  -> 通过 TCP 连接发往后端 Pod IP:Port(四层)
       Service / Endpoint 提供服务发现,可能不经过 ClusterIP
  -> 业务应用解析 HTTP,处理业务(七层)
Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐