K8s 网络机制

概述

一、Service类型

NodePort

 LoadBalancer

 ExternalName

 二、容器网络机制

同一个 Node 内访问

 跨 Node 间 Pod 访问

 三、Service与Pod关系

Pod 的定义

Service 的定义

两者之间关系

四、Kube-proxy多种模式

Userspace 模式

iptables 模式

 ipvs 模式

五、Ingress

什么是ingress呢?

svc和ingress的区别?

Ingress Controller和ingress区别?

Ingress Controller和内置的Pod控制器有啥区别呢?

demo


概述

Service 作为 K8s 中的一等公民,其承载了核心容器网络的访问管理能力,包括:

  • 暴露/访问一组 Pod 的能力

  • Pod 访问集群内、集群外服务

  • 集群外客户端访问集群内 Pod 的服务

无论是作为应用的开发者还是使用者,一般都需要先经过 Service 才会访问到真正的目标 Pod。因此熟悉 Service 网络管理机制将会使我们更加深入理解 K8s 的容器编排原理,

本文将从 K8s 中容器网络、Service/Pod 关联、Service 类型、kube-proxy 模式、Ingress 等方面,说明 Service 的网络机制。

一、Service类型

类型应用场景
CLusterIPK8S集群内部相互访问
NodePortK8S集群外部实现访问
LoadBalancer云环境中使用,比如K8S在阿里云,腾讯云,京东云,华为云等。对应的云产品都有自己的负载均衡器产品
ExternerNameSVC代理的服务并不在K8S集群内部,而是在K8S集群外部

 

 ClusterIP

ClusterIP 表示在 K8s 集群内部通过 service.spec.clusterIP 进行访问,之后经过 kube-proxy 负载均衡到目标 Pod。

无头服务 (Headless Service):
当指定 Service 的 ClusterIP = None 时,则创建的 Service 不会生成 ClusterIP,这样 Service 域名在解析的时候,将直接解析到对应的后端 Pod (一个或多个),某些业务如果不想走 Service 默认的负载均衡,则可采用此种方式 直连 Pod。

// service.spec.publishNotReadyAddresses:表示是否将没有 ready 的 Pods 关联到 Service,默认为 false。设置此字段的主要场景是为 StatefulSet 的 Service 提供支持,使之能够为其 Pod 传播 SRV DNS 记录,以实现对等发现。

 当没有指定 service.type 时,默认类型为 ClusterIP。

apiVersion: v1kind: Servicemetadata:  name: headless-servicespec:  selector:    app: nginx  ports:    - protocol: TCP      port: 80      targetPort: 80  type: ClusterIP # 默认类型,可省略  clusterIP: None # 指定 ClusterIP = None  publishNotReadyAddresses: true # 是否关联未 ready pods

NodePort

当业务需要从 K8s 集群外访问内部服务时,通过 NodePort 方式可以先将访问流量转发到对应的 Node IP,然后再通过 service.spec.ports[].nodePort 端口,通过 kube-proxy 负载均衡到目标 Pod。

Service NodePort 默认端口范围:30000-32767,共 2768 个端口。
可通过 kube-apiserver 组件的 --service-node-port-range 参数进行配置。

[root@master231 ~]# vim /etc/kubernetes/manifests/kube-apiserver.yaml 
 ...
 spec:
  containers:
  - command:
    - kube-apiserver
    - --service-node-port-range=3000-50000  # 进行添加这一行即可

apiVersion: v1kind: Servicemetadata:  name: nodeport-servicespec:  selector:    app: nginx  ports:    - nodePort: 30800   #worker节点的端口映射      port: 8080        #对应的svc的port端口      protocol: TCP           targetPort: 80    #对应的pod端口  type: NodePort

 LoadBalancer

上面的 NodePort 方式访问内部服务,需要依赖具体的 Node 高可用,如果节点挂了则会影响业务访问,LoadBalancer 可以解决此问题。

具体来说,LoadBalancer 类型的 Service 创建后,由具体是云厂商或用户实现 externalIP (service.status.loadBalancer) 的分配,业务直接通过访问 externalIP,然后负载均衡到目标 Pod。

apiVersion: v1kind: Servicemetadata:  name: my-servicespec:  selector:    app.kubernetes.io/name: MyApp  ports:    - protocol: TCP      nodePort: 30931      port: 80      targetPort: 9376  clusterIP: 10.0.171.239  type: LoadBalancerstatus:  loadBalancer:    ingress:    - ip: 192.0.2.127

 ExternalName

当业务需要从 K8s 内部访问外部服务的时候,可以通过 ExternalName 的方式实现。Demo 如下

具体来说,service.spec.externalName 字段值会被解析为 DNS 对应的 CNAME 记录,之后就可以访问到外部对应的服务了​​​​​​

apiVersion: v1kind: Service  #无selector,无endpointsmetadata:  name: my-service    namespace: prodspec:  type: ExternalName  externalName: my.database.example.com

 二、容器网络机制

K8s 将一组逻辑上紧密相关的容器,统一抽象为 Pod 概念,以共享 Pod Sandbox 的基础信息,如 Namespace 命名空间、IP 分配、Volume 存储(如 hostPath/emptyDir/PVC)等,因此讨论容器的网络访问机制,实际上可以用 Pod 访问机制代替。

根据 Pod 在集群内的分布情况,可将 Pod 的访问方式主要分为两种:

  • 同一个 Node 内 Pod 访问

  • 跨 Node 间 Pod 访问

同一个 Node 内访问

同一个 Node 内访问,表示两个或多个 Pod 落在同一个 Node 宿主机上,这种 Pod 彼此间访问将不会跨 Node,通过本机网络即可完成通信。

具体来说,Node 上的运行时如 Docker/containerd 会在启动后创建默认的网桥 cbr0 (custom bridge),以连接当前 Node 上管理的所有容器 (containers)。当 Pod 创建后,会在 Pod Sandbox 初始化基础网络时,调用 CNI bridge 插件创建 veth-pair(两张虚拟网卡),一张默认命名 eth0 (如果 hostNetwork = false,则后续调用 CNI ipam 插件分配 IP)。另一张放在 Host 的 Root Network Namespace 内,然后连接到 cbr0。当 Pod 在同一个 Node 内通信访问的时候,直接通过 cbr0 即可完成网桥转发通信。

访问流程:

  • 首先运行时如 Docker/containerd 创建 cbr0;

  • Pod Sandbox 初始化调用 CNI bridge 插件创建 veth-pair(两张虚拟网卡);

  • 一张放在 Pod Sandbox 所在的 Network Namespace 内(CRI containerd 默认传的参数为 eth0);

  • 另一张放在 Host 的 Root Network Namespace 内,然后连接到 cbr0;

  • Pod 在同一个 Node 内访问直接通过 cbr0 网桥转发;

// docker中默认网桥名为docker 0,k8s中默认网桥名为cni 0

 跨 Node 间 Pod 访问

跨 Node 间访问,Pod 访问流量通过 veth-pair 打到 cbr0,之后转发到宿主机 eth0,之后通过 Node 之间的路由表 Route Table 进行转发。到达目标 Node 后进行相同的过程,最终转发到目标 Pod 上。

访问流程:

  • 用户访问某个 Pod 时,首先访问的是 Kubernetes 服务。
  • 服务通过 kube-proxy 将请求转发到后端的 Pod。
  • 由于服务是跨节点的,kube-proxy 会根据不同的访问策略(如 iptables 或 IPVS)选择后端的 Pod。如果 Pod 位于不同的节点,流量会通过节点之间的网络进行转发。

 三、Service与Pod关系

Pod 的定义

Pod 是 Kubernetes 中最小的部署单位。Pod 中包含一个或多个容器(通常是单个容器)。这些容器共享同一个网络命名空间。

特点:

  • 每个 Pod 会被 Kubernetes 分配一个 唯一的 IP 地址,这个 IP 地址仅在集群内部有效。
  • Pod 的生命周期是短暂的,一个 Pod 会随着应用的部署而创建,随着应用的销毁而被删除。
  • Pod 通常由 Deployment、StatefulSet 或 DaemonSet 等控制器进行管理,控制器负责确保
  • Pod 的数量和健康状态。

Service 的定义

Service 是一个抽象,它定义了一组具有相同功能的 Pod,并为这些 Pod 提供一个固定的访问入口。Pod 的 IP 地址是动态的,可能会因为 Pod 的重启或者节点的变动而变化,Service 通过对外提供一个稳定的访问接口来解决这个问题。 

特点:

  • ClusterIP:这是最常见的类型,它为 Service 分配一个虚拟 IP 地址,Pod 通过该 IP 地址暴露给其他 Pod 或客户端。
  • NodePort:在 ClusterIP 的基础上,Service 会在每个节点上开放一个静态端口,从而使服务可以通过 NodeIP:NodePort 进行访问。
  • LoadBalancer:在 NodePort 的基础上,Service 会向云提供商请求创建一个外部负载均衡器,从而为外部客户端提供访问。
  • Headless Service:如果没有为 Service 提供 ClusterIP(即 clusterIP: None),则 Service 仅提供一组 Pod 的 DNS 名称而没有虚拟 IP。这种类型常用于 StatefulSet 等需要稳定 DNS 的场景。

两者之间关系

Service 通过指定选择器 (selector) 去选择与目标 Pod 匹配的标签 (labels),找到目标 Pod 后,建立对应的 Endpoints 对象。当感知到 Service/Endpoints/Pod 对象变化时,创建或更新 Service 对应的 Endpoints,使得 Service selector 与 Pod labels 始终达到匹配的状态。

四、Kube-proxy多种模式

 在 Kubernetes 中,kube-proxy 是一种负责服务代理和负载均衡的关键组件,它允许 Kubernetes 集群中的 Pod 通过 Service 访问其他 Pod。kube-proxy 在多个网络模式下工作,控制流量如何从客户端发送到 Service 以及 Service 后端的 Pod。

Kubernetes 提供了三种 kube-proxy 的工作模式,每种模式使用不同的方式来管理流量的路由和负载均衡。以下是这三种模式的详细解释:

  • Userspace 模式
  • iptables 模式
  • ipvs 模式

Userspace 模式

这是kube-proxy的最早版本,也是 Kubernetes 在早期版本中使用的默认模式,这里不多讲解,感兴趣小伙伴可以自行百度。

iptables 模式

K8s 中当前默认的 kube-proxy 模式,核心逻辑是使用 iptables 中 PREROUTING 链 nat 表,实现 Service => Endpoints (Pod IP) 的负载均衡。

工作原理:

  • 在 iptables 模式下,kube-proxy 会通过管理 iptables 规则来处理流量的路由。当客户端请求一个 Service 时,kube-proxy 会将流量重定向到后端的 Pod。每个 Service 在 iptables 中都有一条规则,客户端的请求会根据规则被路由到某个 Pod。
  • iptables 可以将请求直接转发到 Pod,而不需要经过用户空间进程,因此性能得到了显著提高。

 ipvs 模式

ipvs是 Linux 内核提供的一个虚拟服务器模块,专门用于高效的负载均衡。相比iptables,ipvs提供了更强大、灵活的负载均衡能力。

工作原理:

  • 在 ipvs 模式下,kube-proxy 使用ipvs来实现负载均衡。ipvs为每个 Service 创建虚拟的 IP 地址(VIP),然后将流量根据负载均衡算法转发到后端的 Pod。
  • ipvs支持多种负载均衡算法,如轮询(Round Robin)、最少连接(Least Connection)、加权轮询(Weighted Round Robin)等。
模式工作原理优点缺点使用场景
iptables使用 Linux 内核的 iptables 规则来进行流量路由和负载均衡。性能优越,简化配置。随着规则数增多,性能会下降。负载均衡算法简单,通常是轮询。中小规模的集群,适合大多数生产环境。
ipvs使用 Linux 内核的 ipvs 模块来进行高效的负载均衡,支持多种负载均衡算法。高效负载均衡,支持更多的调度算法,性能优秀。配置复杂,需要内核支持 ipvs 模块。大规模集群,高流量环境,复杂负载均衡需求

五、Ingress

之前学习的svc资源,如果遇到多个服务要监听80端口时很明显无论哪种类型都无法实现,如果非要实现,就得在K8S集群外部部署一个LB设备,来代理到对应svc资源。而ingress就可以很好的解决这个问题。

什么是ingress呢?

  • 所谓的ingress指的是一种规则,基于用户访问的请求头路由到正确的svc。说白了就是7层代理
  • 可惜K8S只是实现了ingress定义规则,这个规则被记录到etcd中,但并没有具体实现此功能,因此需要自行安装相应的附加组件(ingress-nginx,trafik,...)

svc和ingress的区别?

  • ingress和svc的区别是,svc只能实现4层的代理。而ingress实现了7层的代理。

Ingress Controller和ingress区别?

  • ingress是定义域名到svc的解析规则,好比nginx.conf配置文件。
  • 而ingress-controller适用于执行规则的程序,好比nginx程序。

Ingress Controller和内置的Pod控制器有啥区别呢?

  • 内置的Pod控制器,比如ds,sts,deploy,jobs,cj,rs,rc等都是用来控制Pod的副本数量。
  • 而Ingress Controller是用来解析ingress规则的,两者并没有任何关系

demo

创建工作负载

[root@master231 ~]# cat deploy-apps.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-apps-v1
spec:
  replicas: 3
  selector:
    matchLabels:
      apps: v1
  template:
    metadata:
      labels:
        apps: v1
    spec:
      containers:
      - name: c1
        image: nginx:1.26.2
        ports:
        - containerPort: 80

---

apiVersion: v1
kind: Service
metadata:
  name: svc-apps
spec:
  selector:
    apps: v1
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80

创建ingress资源

[root@master231 ~]# cat 01-apps-ingress.yaml 
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: apps-ingress
spec:
  rules:
  - host: apps.cherry.com
    http:
      paths:
      - backend:
          service:
            name: svc-apps
            port:
              number: 80
        path: /
        pathType: ImplementationSpecific

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值