PodPod 是 K8s 的最小调度单位里面可以有一个或多个容器这些容器共享网络、存储等资源。Pod 里的容器共享什么资源是否共享说明网络 namespace共享同一个 Pod 内容器共用 IP、端口空间可以用localhost通信UTS namespace共享主机名相同IPC namespace共享可以用共享内存、信号量存储卷 Volume可共享多个容器可以挂同一个 volumePID 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 最终跑在节点上。节点一般可以根据职责分为两类——控制节点和工作节点工作负载DeploymentDeployment 是 K8s 里最常用的工作负载控制器用来管理无状态Pod 的副本StatefulSetStatefulSet 是专门用来管理有状态Pod的工作负载控制器StatefulSet 和 Deployment 的核心区别维度DeploymentStatefulSetPod 身份随机名字可互换固定名字如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-proxyVIP 转发负载均衡由客户端自己做适合 gRPC 客户端自己维护连接池客户端(集群内部的其他Pod)如何知道DNS的Key(FQDN)的——通过配置文件提前配置有状态的Pod是不是就一定不能用Deployemnt——不一定如果不考虑可用性Pod是单实例的话那用Deployment也可以。核心决定性因素在于——Pod 挂掉重建后能不能还以原来的身份挂回原来分配给它的那个卷。单副本情况下不需要做多副本的区分所以可以Service——把IP:Port路由到具体的PodService服务 是 Kubernetes 中用于为 Pod 提供稳定网络访问入口和负载均衡的核心组件它抽象了 Pod 的网络访问方式使得外部客户端或其他 Pod 可以通过 Service 访问后端 Pod而无需关心 Pod 的具体 IP 地址或生命周期。Service本身也只是规则真正处理流量的是kube-proxy。负责K8s的四层路由Service的所有类型K8s 里Service 的spec.type官方只有 4 种类型作用外部能否访问典型场景ClusterIP分配一个集群内部虚拟 IP不能默认仅集群内集群内服务互访默认类型NodePort在ClusterIP的基础上在每个节点上开一个端口能节点IP:端口测试、简单暴露、无云 LBLoadBalancer向云/基础设施申请外部负载均衡器能外部LB IP:端口生产环境暴露服务ExternalName用 DNS CNAME 指向外部域名不代理流量只做 DNS 映射集群内访问外部服务另外还有两个容易混淆的概念Headless Service不是独立类型而是ClusterIP: None的特殊 ClusterIP。ExternalIPsspec.externalIPs字段不是 Service 类型。Ingress不是 Service 类型是七层入口通常后端再接 Service。ClusterIPClusterIP 是 K8s 给 Service 分配的一个集群内部虚拟 IP用来在集群内稳定地访问一组 Pod。查看机器中的所有Service和其ClusterIProotknowledgeskilltest:/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查看机器中的所有Podrootknowledgeskilltest:/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 nonename为coredns开头的就是负责将FQDN转化为IP的组件对于普通Service其会将FQDN解析为ClusterIP对于Headless Service其会将FQDN解析为后端Pod IP列表StatefulSet 工作负载下的POD会有稳定的POD名也会有稳定的FQDNcoreDNS能将其转化为单个Pod 的IPneme为kube-proxy开头的就是负责将ClusterIP/NodePort流量转发到具体Pod的组件NodePort在每个节点上开放同一个端口把这个端口收到的流量转发到 Service 后面的 Pod。一个端口对应一个Service注意启用了NodePort后整个Service一般依旧会有一个ClusterIP——NodePort负责对外ClusterIP负责对内LoadBalancer本质上是NodePort 的上一层封装在 NodePort 基础上再向云厂商或基础设施申请一个独立的负载均衡器 IP。刚需公网IPQLB怎么知道过来请求到底要访问哪个NodePortA一个云 LB 可以为多个端口创建一个监听器每个监听器分别映射到对应的后端——一个IP不同但是Port相同的IP:Port列表。K8s 原生 LoadBalancer 的语义是“一个 Service 一个 LB”——所以一个LoadBalancer虽然可以对应多个NodePort但是其后端都是同一组Pod。也就是说不存在只使用一个公网IPLoadBalancer就完成多个Service的暴露的情况。或者说K8s原生中没有LB这个对象有的只是LoadBalancer这种Service类型因此也就没有LB-Service的一对多关系。但是云厂商天生就需要对LB和公网IP做管理因此实现一套这样的逻辑成本相对低——而且用户也有需求。所以其实在云上完全可以用 一个公网 IP 一个负载均衡器LB不用 Ingress就对外提供多个服务。限制就是必须依靠不同的端口来区分不同的服务。Ingress——把HTTP 请求域名、路径路由到ServiceIngress 是 K8s 里的一种 API 对象用来定义“外部 HTTP/HTTPS 流量怎么进入集群、路由到哪些 Service”。它本身只是规则真正处理流量的是 Ingress Controller(一组以DaemonSet工作负载形式部署的Pod)。负责K8s的七层路由rootknowledgeskilltest:/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 typeLoadBalancer / NodePort - Ingress Controller Pod └── TCP 承载到达四层 └── Nginx / Traefik / Envoy 解析 HTTP七层 - 根据 Ingress 规则选择后端 - 通过 TCP 连接发往后端 Pod IP:Port四层 Service / Endpoint 提供服务发现可能不经过 ClusterIP - 业务应用解析 HTTP处理业务七层