k8s的服务与负载均衡

Service的定义

在k8s中, Service是一种kuberenets对象, 它的作用是将运行在一个或一组 Pod 上的网络应用程序公开为网络服务的方法

端口

在service中,主要有三种端口:

  • port :Service 对外暴露的端口(集群内部访问用的 ClusterIP:port,或 NodePort/LoadBalancer 的端口)。
  • targetPort :Pod 容器内实际监听的端口。(target端口如果不写就是和port一个端口)
  • nodePort :如果 Service 类型是 NodePort/LoadBalancer,会在宿主机节点开放一个固定端口(30000–32767 默认范围)。

selector

在service中, 既然要组织一组pod来提供服务, 那么必须要提供一种表示来匹配pod, 那么这里就是使用了selector.

1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: v1
kind: Service
metadata:
name: my-nginx
labels:
run: my-nginx
spec:
ports:
- port: 80
protocol: TCP
selector:
run: my-nginx

如上述代码就是一个简单的service定义, 里面通过run:my-nginx来匹配符合标签的pod, 来加入service之中

endpointslice

在定义service的时候, 如果使用了selector, 那么会自动生成EndpointSlice对象, 每个 EndpointSlice 里包含若干个 Pod/Endpoint 的信息,例如:

  • 地址 (addresses) → Pod 的 IP
  • 端口 (ports) → Pod 容器的端口(对应 Service 的 targetPort)
  • 条件 (conditions) → Pod 是否 Ready、Serving、Terminating 等
  • 拓扑信息 (topology) → 节点、区域等信息,方便拓扑感知调度

服务类型

Kubernetes Service 类型允许指定你所需要的 Service 类型。

可用的 type 值及其行为有:

  • ClusterIP通过集群的内部 IP 公开 Service,选择该值时 Service 只能够在集群内部访问。这也是没有为 Service 显式指定 type 时使用的默认值。可以使用 Ingress或者 Gateway API 向公共互联网公开服务。
  • NodePort通过每个节点上的 IP 和静态端口(NodePort)公开 Service。为了让 Service 可通过节点端口访问,Kubernetes 会为 Service 配置集群 IP 地址,相当于你请求了 type: ClusterIP 的 Service。
  • LoadBalancer使用云平台的负载均衡器向外部公开 Service。Kubernetes 不直接提供负载均衡组件;你必须将 Kubernetes 集群与云平台集成, 比如阿里云
  • ExternalName将服务映射到 externalName 字段的内容(例如,映射到主机名 api.foo.bar.example)。该映射将集群的 DNS 服务器配置为返回具有该外部主机名值的 CNAME 记录。集群不会为之创建任何类型代理。

service的使用

在实际使用service的时候, service并不是实际存在的实体, 比如pod这种, 而是一种抽象的概念. 如下图是一个k8s网络的示意图

k8s架构

Pod的创建

controller-manager (比如 DeploymentController、ReplicaSetController)会监听 apiserver 中 Pod/ReplicaSet/Deployment 的变化, 来动态的管理pod的数量. 分别是几种情况:

  • kubectl发送的直接创建pod请求:

    • 首先api-service 会作合法性判断, 通过后会第一时间把对象存入etcd
    • scheduler (kube-scheduler)通过 watch 监听 apiserver 中的 Pending Pod 。会根据调度策略(资源可用性、亲和性/反亲和性、污点和容忍度等)为 Pod 选定一个合适的 Node。选好后 scheduler 向 apiserver 发送 绑定请求 ,把 Pod.spec.nodeName 设置为选中的节点。apiserver 更新 etcd,Pod 状态还是 Pending,但已经绑定到某个 Node。
    • 目标节点上的 kubelet 会 watch apiserver 上自己节点的 Pod 对象, 发现有一个新 Pod 分配到本节点,于是开始创建流程. 包括创建puase容器, 调用CNI分配网络,拉取镜像,启动业务容器. 在完成这些过程中, kubelet会定期向api-service汇报自己的状态
    • api-service会接受来自 kubelet 报告的状态, 并且更新etcd. 同时control-manager中的endpoints-controller会在service创建, pod状态变化时候扫描集群里所有 Pod, 来做标签匹配. 满足所有条件的 Pod → 被写入 EndpointSlice
  • pod的创建被包裹在deployment或者statefulset之中:

    • 首先api-service 会作合法性判断, 通过后会第一时间把deployment或者statefulset对象存入etcd
    • 这时候controller-manager中的deployment-controller或者statefulset-controller会监听apiserver中deployment或者statefulset的变化, 两者通常会实现一个ReplicaSet。而ReplicaSetController 监听 ReplicaSet 的变化后, 也会触发相应的Pod创建流程, 之后的流程就走到了scheduler,kubelet等组件.
  • Pod丢失或者宕机:

    • controller-manager 发定期访问api-service来检查pod状态, 一旦发生确实, 就进入创建的过程. 详细见上面第二步

Service的网络:

作者

kosa-as

发布于

2026-01-04

更新于

2026-01-05

许可协议

评论