【k8s中svc、ep与pod的关系】
在 Kubernetes(K8s)中,服务(Service,简称 SVC)、端点(Endpoint,简称 EP)和
容器组(Pod)是关键概念,它们相互协作,共同实现应用的网络连接与服务发现。
它们的关系如下:

Pod
基础概念:Pod 是 K8s 中最小的可部署和可管理的计算单元,它可以包含一个或多个紧密相关的容器。
这些容器共享网络命名空间、存储卷等资源,它们被 K8s 作为一个整体进行调度和管理。例如,一个 
Web 应用的 Pod 可能包含一个运行 Web 服务器的容器和一个运行相关缓存服务的容器。
特点:每个 Pod 都有自己唯一的 IP 地址,然而,由于 Pod 本质上是短暂的,其 IP 地址并非持久不变。
当 Pod 由于某种原因(如节点故障、资源不足等)被重新调度到其他节点时,它会获得一个新的 IP 地址。
这就使得直接通过 Pod 的 IP 地址来访问应用变得不可靠。

Service(SVC)
基础概念:Service 定义了一组 Pod 的逻辑集合以及访问它们的策略,是一种抽象的方式来暴露 Pod 提供
的服务,为 Pod 提供了一个固定的 IP 地址和 DNS 名称,使得客户端可以稳定地访问这些 Pod,而无需关心
Pod 的实际 IP 地址变化。
作用:Service 提供了服务发现和负载均衡的功能。一方面,它可以将对 Service 的请求负载均衡到后端的多个
Pod 上,确保请求能够均匀分配,避免单个 Pod 负载过高。另一方面,它让客户端通过一个固定的入口来访问动态
变化的 Pod 集合,实现了服务发现的功能。比如,一个 Service 可以将外部对某个特定端口的 HTTP 请求转发到
后端一组运行 Web 应用的 Pod 上。


Endpoint(EP)
基础概念:
Endpoint 是 Service 所关联的 Pod 的实际 IP 地址和端口的列表,它是 K8s 自动维护的一个对象,
用于记录 Service 背后真正提供服务的 Pod 实例的网络位置。

与 Service 和 Pod 的关系:
当 Service 创建时,K8s 会根据 Service 定义的选择器(Selector)来查找与之匹配的 Pod,
并自动创建对应的 Endpoint 对象。这个 Endpoint 对象会实时跟踪这些 Pod 的变化。
如果有新的 Pod 加入或现有 Pod 离开,Endpoint 会相应地更新,确保 Service 始终能够
正确地将流量导向可用的 Pod。

三者关系总结如下:
Service 通过标签选择器(Label Selector)来关联一组具有相同标签的 Pod,
这些被关联的 Pod 就是 Service 的后端。而 Endpoint 则是这些后端 Pod 的实际网络端点的集合,
Service 通过 Endpoint 来知道将请求转发到哪些具体的 Pod 实例上。这种关系使得 K8s 集群中的应用
能够以一种可靠、可扩展的方式进行网络通信。

一、service的核心

1.1、service的作用

使用kubernetes集群运行工作负载时,由于Pod经常处于用后即焚状态,Pod经常被重新生成,
因此Pod对应的IP地址也会经常变化,导致无法直接访问Pod提供的服务,
Kubernetes中使用了Service来解决这一问题。

即在Pod前面使用Service对Pod进行代理,无论Pod怎样变化,只要有Label,
就可以让Service能够联系上Pod,
把Pod的IP地址添加到Service对应的端点列表(Endpoints)实现对PodIP跟踪,
进而实现通过Service访问Pod目的。


1.通过service为pod客户端提供访问pod方法,即可客户端访问pod
2.通过标签动态感知pod IP地址变化等
3.防止pod失联
4.定义访问pod访问策略
5.通过label-selector相关联
6.通过Service实现Pod的负载均衡(TCP/UDP 4层)
7.底层实现由kube-proxy通过userspace、iptables、ipvs三种代理模式

1.2、 kube-proxy的三种模式

1. kubernetes集群中有三层网络,一类是真实存在的,例如Node Network、Pod Network,提供真实IP地址;
 一类是虚拟的,例如ClusterNetwork或Service Network,提供虚拟IP地址,不会出现在接口上,
 仅会出现在Service当中。
 
2. kube-proxy始终watch(监控)kube-apiserver上关于Service相关的资源变动状态,
一旦获取相关信息kube-proxy都要把相关信息转化为当前节点之上的,
能够实现Service资源调度到特定Pod之上的规则,进而实现访问Service就能够获取Pod所提供的服务。

3. kube-proxy三种代理模式:UserSpace模式、iptables模式、ipvs模式

1.2.1 UserSpace模式

userspace 模式是 kube-proxy 使用的第一代模式,该模式在 kubernetes v1.0 版本开始支持使用。

userspace 模式的实现原理图示如下:

第五十七节  k8s 1.31.x 之 Service 学习_IP

kube-proxy会为每个 Service 随机监听一个端口(proxy port),并增加一条 iptables规则。

所以通过 ClusterlP:Port 访问 Service 的报文都redirect 到 proxy port,
kube-proxy 从它监听的 proxy port 收到报文以后,走 round robin(默认)或是
session afinity(会话亲和力,即同client IP 都走同一链路给同- pod 服务),分发给对应的 pod。

由于 userspace 模式会造成所有报文都走一遍用户态
(也就是 Service 请求会先从用户空间进入内核iptables,
然后再回到用户空间,由kube-proxy 完成后端Endpoints的选择和代理工作),
需要在内核空间和用户空间转换,流量从用户空间进出内核会带来性能损耗,
所以这种模式效率低、性能不高,不推荐使用。

第五十七节  k8s 1.31.x 之 Service 学习_IP_02

1.2.2 iptables模式

iptables 模式是 kube-proxy 使用的第二代模式,该模式在 kubernetes v1.1 版本开始支持,
从 v1.2 版本开始成为 kube-proxy 的默认模式。


iptables 模式的负载均衡模式是通过底层 netfilter/iptables 规则来实现的,
通过 Informer 机制 Watch 接口实时跟踪 Service 和 Endpoint 的变更事件,
并触发对 iptables 规则的同步更新。

iptables 模式的实现原理图示如下:

第五十七节  k8s 1.31.x 之 Service 学习_IP_03

通过图示我们可以发现在 iptables 模式下,kube-proxy 只是作为 controller,而不是 server,
真正服务的是内核的netfilter,体现用户态的是iptables。所以整体的效率会比userspace模式高。

下面我们使用一个例子来查看 iptables 模式下的转发规则。
新建nginx.yaml文件,并向文件中写入如下内容:

vim nginx.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  replicas: 2
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
        - name: my-nginx
          image: nginx
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: my-nginx
  labels:
    run: my-nginx
spec:
  ports:
    - port: 80
      protocol: TCP
  selector:
    run: my-nginx
---

kubectl apply -f nginx.yaml

在这个 YAML 文件中我们使用 Deployment 创建了两个 nginx pod 副本,
并定义了名为 my-nginx 的服务,选择所有标签为 run: my-nginx 的 pod,指定端口为 80。

kubectl get pod 
kubectl get ep
kubectl get svc

第五十七节  k8s 1.31.x 之 Service 学习_IP_04

iptables -L

第五十七节  k8s 1.31.x 之 Service 学习_Pod_05

2.3 ipvs模式

ipvs 模式被 kube-proxy 采纳为第三代模式,模式在 kubernetes v1.8 版本开始引入,
在 v1.9 版本中处于 beta 阶段,在 v1.11 版本中正式开始使用。

ipvs(IP Virtual Server) 实现了传输层负载均衡,也就是 4 层LAN交换,作为 Linux 内核的一部分。

ipvs运行在主机上,在真实服务器前充当负载均衡器。
ipvs 可以将基于 TCP 和 UDP 的服务请求转发到真实服务器上,
并使真实服务器上的服务在单个 IP 地址上显示为虚拟服务。

ipvs 模式的实现原理图示如下:

第五十七节  k8s 1.31.x 之 Service 学习_nginx_06

ipvs 和 iptables 都是基于 netfilter 的,那么 ipvs 模式有哪些更好的性能呢?

可以从以下4点对比看
1. ipvs 为大型集群提供了更好的可拓展性和性能。
2. ipvs 支持比 iptables 更复杂的负载均衡算法(包括:最小负载、最少连接、加权等)。
3. ipvs 支持服务器健康检查和连接重试等功能。
4. 可以动态修改 ipset 的集合,即使 iptables 的规则正在使用这个集合。
ipvs 依赖于 iptables。

ipvs 会使用 iptables 进行包过滤、airpin-masquerade tricks(地址伪装)、SNAT 等功能,
但是使用的是 iptables 的扩展 ipset,并不是直接调用 iptables 来生成规则链。
通过 ipset 来存储需要 DROP 或 masquerade 的流量的源或目标地址,用于确保iptables 规则的
数量是恒定的,这样我们就不需要关心有多少 Service 或是 Pod 了。

使用 ipset 相较于 iptables 有什么优点呢?
iptables 是线性的数据结构,而 ipset 引入了带索引的数据结构,当规则很多的时候,
ipset 依然可以很高效的查找和匹配。我们可以将 ipset 简单理解为一个 IP(段) 的集合,
这个集合的内容可以是 IP 地址、IP 网段、端口等,iptables 可以直接添加规则。
对这个“可变的集合进行操作”,这样就可以大大减少 iptables 规则的数量,从而减少性能损耗。

举一个例子,如果我们要禁止成千上万个 IP 访问我们的服务器,如果使用 iptables 就需要一条一条的
添加规则,这样会在 iptables 中生成大量的规则;如果用 ipset 就只需要将相关的 IP 地址(网段)加入
到 ipset 集合中,然后只需要设置少量的iptables 规则就可以实现这个目标。

下面的表格是 ipvs 模式下维护的 ipset 表集合:

第五十七节  k8s 1.31.x 之 Service 学习_Pod_07

ipvs 模式相关的常用参数有:
--cleanup-ipvs:值为 true 时清除在 ipvs 模式下创建的 ipvs 配置和 iptables 规则。
--proxy-mode:通过 --proxy-mode = ipvs 进行设置,隐式使用 ipvs NAT 模式进行服务端口映射。
--ipvs-scheduler:指定 ipvs 负载均衡算法,如果未配置,则默认为 round-robin(rr) 算法。
--ipvs-sync-period:刷新 ipvs 规则的最大间隔时间(比如 5s、1m),必须大于 0。
--ipvs-min-sync-period:刷新 ipvs 规则的最小间隔时间间隔(比如 5s、1m),必须大于 0。
--ipvs-sync-period:刷新 ipvs 规则的最大时间间隔,必须大于 0,默认值为 30s。

--ipvs-exclude-cidrs:清除 ipvs 规则时 ipvs 代理不应触及的 CIDR 的逗号分隔列表,
   因为 ipvs 代理无法区分 kube-proxy 创建的 ipvs 规则和用户原始 ipvs 规则,
   如果在环境中使用 ipvs 代理模式和自己的 ipvs 规则,则应指定此参数,否则将清除原始规则。
查看proxy目前是以iptables模式  还是以ipvs模式运行,可以使用以下方法查看
默认安装完k8s集群后的模式是iptables模式,需要手动改为ipvs模式,不然会出现
k8s集群汇总kube-proxy过段时间后ping不通。

kubectl get configmap
kubectl edit configmap kube-proxy -n kube-system
---
ipvs:
      excludeCIDRs: null
      minSyncPeriod: 0s
      scheduler: ""
      strictARP: true
      syncPeriod: 0s
      tcpFinTimeout: 0s
      tcpTimeout: 0s
      udpTimeout: 0s
    kind: KubeProxyConfiguration
    logging:
      flushFrequency: 0
      options:
        json:
          infoBufferSize: "0"
        text:
          infoBufferSize: "0"
      verbosity: 0
    metricsBindAddress: ""
    mode: "ipvs"
----

【扩展】
二进制安装k8s参数配置需 
strictARP: true,
mode: "ipvs"
-------------*********---
查看kube-proxy二进制文件
ps -ef | grep kube-proxy
路径在此
cd  /var/lib/kube-proxy/config.conf
find  /  -name  "kube-proxy"

第五十七节  k8s 1.31.x 之 Service 学习_Pod_08

第五十七节  k8s 1.31.x 之 Service 学习_IP_09

改kube-proxy为ipvs模式后,需要重启kube-proxy的pod
#查看pod运行模式
kubectl get deploy -n kube-system
kubectl get ds -n kube-system
#重启pod
kubectl rollout restart ds kube-proxy -n kube-system
kubectl get pod -n kube-system -o wide

ping 192.168.80.73看是否正常通信
---
ping 192.168.80.73
PING 192.168.80.73 (192.168.80.73) 56(84) bytes of data.
64 bytes from 192.168.80.73: icmp_seq=1 ttl=64 time=0.738 ms
64 bytes from 192.168.80.73: icmp_seq=2 ttl=64 time=0.453 ms
64 bytes from 192.168.80.73: icmp_seq=3 ttl=64 time=0.491 ms

第五十七节  k8s 1.31.x 之 Service 学习_nginx_10

第五十七节  k8s 1.31.x 之 Service 学习_Pod_11

第五十七节  k8s 1.31.x 之 Service 学习_Pod_12

1.3 kube-proxy的参数

kube-proxy 其它启动参数有:
--bind-address:kube-proxy 绑定主机的 IP 地址,默认值为 0.0.0.0,表示绑定所有 IP 地址。
--cleanup:设置为 true 表示在清除 iptables 规则和 ipvs 规则后退出。
--cluster-cidr:集群中 Pod 的 CIDR 地址范围,用于桥接集群外部流量到内部。
--config:kube-proxy 的主配置文件。
--config-sync-period:从 API Server 更新配置的时间间隔,必须大于 0,默认值为 15m0s。
--conntrack-max-per-core:跟踪每个 CPU core 的 NAT 连接的最大数量(设置为 0 表示无限制,
    并忽略 conntrack-min 的值),默认值为 32768。
--conntrack-min:最小 conntrack 条目的分配数量,默认值为 131072。
--conntrack-tcp-timeout-close-wait:当 TCP 连接处于 CLOSE_WAIT 状态时的 NAT 超时时间,
    默认值为 1h0m0s。
--conntrack-tcp-timeout-established:建立 TCP 连接的超时时间,设置为 0 表示无限制,
    默认值为 24h0m0s。
--healthz-bind-address:healthz 服务绑定主机 IP 地址,设置为 0.0.0.0 表示使用
    所有 IP 地址,默认值为 0.0.0.0:10256。
--healthz-port:healthz 服务监听的主机端口号,设置为 0 表示不启用,默认值为 10256。
--hostname-override:设置本 Node 在集群中的主机名,不设置时将使用本机 hostname。
--kube-api-burst:每秒发送到 API Server 的请求的数量,默认值为 10。
--kubeconfig:kubeconfig 配置文件路径,在配置文件中包括 Master 地址信息及必要的认证信息。
--masquerade-all:设置为 true 表示使用纯 iptables 代理,所有网络包都将进行 SNAT 转换。
--master:API Server 的地址。
--metrics-bind-address:Metrics Server 的监听地址,设置为 0.0.0.0 表示使用所有 IP 地址,
    默认值为 127.0.0.1:10249。
--proxy-mode:代理模式,可选项为 userspace、iptables、ipvs,默认值为 iptables,
   当操作系统内核版本或 iptables 版本不够新时,将自动降级为 userspace 模式。

二、 service的类型

如何确保Service能够正确地将流量路由到目标Pod?

1. 使用正确的标签选择器(Label Selector):
确保 Service 的标签选择器能够准确地匹配到目标 Pod。Service 通过标签选择器来关联一组 Pod,
这些 Pod 是其服务的后端。

2. 确保 Pod 的健康状态:
K8s 的服务发现和负载均衡机制通常只会将流量路由到健康的 Pod。因此,要确保 Pod 中的容器是健康的,
避免将流量路由到故障或不可用的 Pod。可以使用 K8s 的健康检查机制,如 Liveness Probe 和 
Readiness Probe。

3. 合理的网络策略(Network Policy):
网络策略可以控制 Pod 之间的网络流量,确保 Service 能将流量路由到允许访问的 Pod。
如果存在网络策略,需要保证其不会阻止 Service 到 Pod 的流量。

4. 检查 Service 和 Endpoint 状态:
使用 kubectl get svc 和 kubectl get ep 命令检查 Service 和 Endpoint 的状态。
这将显示 Service 的详细信息和关联的 Endpoint 信息,你可以查看是否有正确的后端 Pod 被关联。

5. 监控和日志:利用 K8s 的监控工具(如 Prometheus)和日志系统(如 EFK Stack)来监控 Service 
和 Pod 的性能和状态。例如,通过 Prometheus 可以收集和分析诸如请求延迟、请求成功率等指标,
帮助你判断是否存在流量路由问题。同时,日志系统可以帮助你查看服务端和客户端的错误日志,找出
潜在问题。

6. 总结:
准确使用标签选择器,确保 Service 能正确关联到目标 Pod。
利用健康检查机制确保 Pod 处于健康状态,以便接收流量。
制定合理的网络策略,保证网络的连通性。
定期检查 Service 和 Endpoint 状态,使用监控和日志工具辅助问题排查。

2.1 service的类型

1. ClusterlP
 默认,分配一个集群内部可以访问的虚拟IP。
2. NodePort
 在每个Node上分配一个端口作为外部访问入口nodePort端口范围为:30000-32767。
3. LoadBalancer
 工作在特定的Cloud Provider上,例如GoogleCloud,AWS,OpenStack。
4. ExternalName
 表示把集群外部的服务引入到集群内部中来,即实现了集群内部pod和集群外部的通信。

2.2 service的参数

port:
 访问service使用的端口
targetPort:
 Pod中容器端囗
nodePort:
通过Node实现外网用户访问k8s集群内service(30000-32767)

2.3 service的创建

Service的创建在工作中有两种方式,一是命令行创建,二是通过资源清单文件YAML文件创建。

2.3.1 ClusterIP 类型

ClusterIP根据是否生成ClusterIP又可分为普通Service和Headless Service(无头服务)

1. 普通Service:
为Kubernetes的Service分配一个集群内部可访问的固定的虚拟IP(Cluster IP), 实现集群内的。

2. Headless Service: (无头服务)
该服务不会分配Cluster IP, 也不通过kube-proxy做反向代理和负载均衡。
而是通过DNS为每个pod提供一个域名,这样我们能访问到每个单独的pod。
普通ClusterIP 类型
集群IP模式,只能在集群内部进行访问,如master跟node节点上,将某一类相同标签的pod映射出
分配一个service的ip来进行访问。

如下图所示,
 使用Deployment资源创建了3个pod,将这三个pod的80端口映射为8000端口,
 并提供一个Service的ip来访问这些pod,这时我们在集群中的任意节点(即Master或者Node节上)
 通过Service的IP加端口就能负载均衡访问到这3个pod。

第五十七节  k8s 1.31.x 之 Service 学习_Pod_13

【直接命令行模式创建pod】
定义一个名为my-dep的Deployment资源,里面包含有3个pod副本,每个pod中含有一个nginx容器

kubectl create deployment my-dep --image=hub.mirrorify.net/library/nginx:latest --replicas=3

kubectl get deploy,pod

kubectl get svc
没有svc,需要手动创建,
默认是--type-ClusterIP模式
kubectl expose deploy  my-dep  --port=8000  --target-port=80  --type=ClusterIP  --protocol=TCP

curl -I 10.100.118.147:8000

第五十七节  k8s 1.31.x 之 Service 学习_Pod_14

第五十七节  k8s 1.31.x 之 Service 学习_Pod_15

#查看创建的pod名
kubectl get pods
kubectl get svc

#依次修改每个pod的html页面

修改第1个pod
kubectl exec  -it  my-dep-5f9f5544bb-5jvtr  --  /bin/bash 
echo 'this is 1 page' > /usr/share/nginx/html/index.html

修改第2个pod
kubectl exec  -it  my-dep-5f9f5544bb-bkksj  --  /bin/bash 
echo 'this is 2 page' > /usr/share/nginx/html/index.html

修改第3个pod
kubectl exec  -it   my-dep-5f9f5544bb-cwxrm  --  /bin/bash 
echo 'this is 3 page' > /usr/share/nginx/html/index.html

kubectl get svc
#访问Service服务3次,看看反馈的结果
curl http://10.100.118.147:8000
可以看到每次访问的pod都不一样,实现了负载均衡

第五十七节  k8s 1.31.x 之 Service 学习_IP_16

【使用yaml 环境创建】
vim my-dp.yaml
---
apiVersion: apps/v1 #版本信息使用kubectl explain deployment查看
kind: Deployment
metadata:
  name: nginx-dep
spec:
  replicas: 2 #定义2个pod副本 
  selector:
    matchLabels:
      app: nginx-dep #匹配的pod标签名

  template:
    metadata:
      name: nginx
      labels:
        app: nginx-dep # pod的标签名,要跟matchLabels里定义的一致
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
  namespace: default
  labels:
    app: nginx-svc
spec:
  clusterIP: 10.96.0.222 #指定ClusterIP,不写此行会自动分配一个Service的ip
  type: ClusterIP #可以不写此行,默认为ClusterIP模式
  selector:
    app: nginx-dep #关联的pod的标签名
  ports:
  - port: 8000
    protocol: TCP
    targetPort: 80


kubectl apply -f my-dp.yaml
kubectl get pod,svc

第五十七节  k8s 1.31.x 之 Service 学习_IP_17

第五十七节  k8s 1.31.x 之 Service 学习_nginx_18

#  查看pod 标签
kubectl get pods --show-labels 
kubectl get pod -l app=nginx-dep 
kubectl get svc,deploy,ep

第五十七节  k8s 1.31.x 之 Service 学习_IP_19

【使用Service域名访问】

#得到Service名字my-dep
kubectl get svc 
#查看pod
kubectl get pods 
#进入容器
kubectl exec -it nginx-dep-65b4947c7c-fpvlc -- /bin/bash 

容器内测试
curl http://nginx-svc:8000
echo > /dev/tcp/10.96.0.222/8000

curl nginx-svc:8000

此时的nginx-svc:8000中的nginx为服务名,default为命名空间,svc表示service
可简写为nginx-svc:8000,需要进入容器中访问才能用这种方式,因为有coredns解析,
但在集群节点上无法使用,集群节点只能用Service_ip:8000的方式访问,因为没有dns解析。

第五十七节  k8s 1.31.x 之 Service 学习_Pod_20

第五十七节  k8s 1.31.x 之 Service 学习_IP_21

第五十七节  k8s 1.31.x 之 Service 学习_Pod_22

Headless Service 无头服务
"Headless Service" 翻译过来就是“无头服务”,它表示的是创建的 Service Service没有
设置Cluster IP,因为它的创建非常简单,只需要设置service.spec.clusterIP=None即可。

它属于一种特殊类型的集群服务,通常应用于以下两种情况中:
自定义负载均衡策略,即:不使用 Service 默认的负载均衡策略
(默认的策略是通过服务转发连符合要求的任一一个 Pod 上)。
获取属于相同标签选择器下的所有 Pod 列表,所以通过 Headless Service 
可以获取到所有符合相关要求的 Pod 列表,然后可以通过自定义负载均衡器
让客户端的连接转发到一个、多个、或是所有的 Pod 上,典型的应用就是:StatefulSet。

Headless Service 的特点如下:
1. 在集群内部没有一个特定的 Cluster IP 地址
2. kube-proxy 不会处理 Headless Service
3. 没有负载均衡和路由功能
4. 根据服务是否有标签选择器进行 DNS 配置

是否定义标签选择器主要影响 DNS 配置:
设置了 Selector:Endpoints Controller 在 apiService 中会创建 Endpoints 记录,
并且修改 DNS 配置返回 A 记录,这样就可以获取到 Headless Service 对应的所有 Pod 的
IP 地址。
没有设置 Selector:不会有 Endpoints 记录。

所以 Headless Service 自定义负载均衡的实现逻辑是:
通过标签选择器获取到所有符合标签的的 IP 地址列表,然后自定义服务响应的方式。
【测试】
vim nginx-deployment.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 3 # 创建 3 个 nginx Pod 副本
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: registry.cn-hangzhou.aliyuncs.com/ywflyfish/nginx:latest
        ports:
        - containerPort: 80  # 指定开放 80 端口
---
apiVersion: v1
kind: Service
metadata:
  name: headless-service
spec:
  clusterIP: None # 注意:无头服务,这里一定要设置为 None
  selector:
    app: nginx-selector
  ports:
  - protocol: TCP
    port: 8080
    targetPort: 80
---

kubectl apply -f nginx-deployment.yaml
kubectl get svc

第五十七节  k8s 1.31.x 之 Service 学习_nginx_23

kubectl get deploy,pod,ep

第五十七节  k8s 1.31.x 之 Service 学习_IP_24

【访问headless-service的pod】
DNS服务监视Kubernetes APl,为每一个Service创建DNS记录用于域名解析headless service
需要DNS来解决访问问题

DNS记录格式为:<service-name>.<namespace-name>.svc.cluster.local

kubectl get svc -n kube-system -o wide

dig -t A headless-service.default.svc.cluster.local. @10.96.0.10

kubectl exec -it nginx-757b9469fd-46999 -- /bin/bash
cat /etc/resolv.conf
---
nameserver 10.96.0.10
pod内部的dns是外部svc地址

第五十七节  k8s 1.31.x 之 Service 学习_Pod_25

第五十七节  k8s 1.31.x 之 Service 学习_nginx_26

2.3.2 NodePort 类型

在每台集群节点上都映射端口,这样访问集群任意节点的端口就能访问到pod提供的服务,
这就不限集群中了,集群外也能访问。


下面我们来创建一个该类型的Service服务体验一下
定义一个名为my-dep的Deployment资源,里面包含有3个pod副本,每个pod中含有一个nginx容器

kubectl create deployment my-dep --image=nginx

kubectl get deploy

第五十七节  k8s 1.31.x 之 Service 学习_nginx_27

创建Service,指定类型为NodePort

kubectl expose deploy my-dep --port=8000 --target-port=80 --type=NodePort --protocol=TCP

kubectl get svc 

web访问
http://192.168.80.71:30779/

第五十七节  k8s 1.31.x 之 Service 学习_Pod_28

第五十七节  k8s 1.31.x 之 Service 学习_IP_29

注意,这个30779端口在任何一台集群节点上都开放了,该端口是随机暴露的,
默认范围在30000-32767之间
如果觉得访问集群节点加端口的方式不很方便,可以使用Nginx做负载均衡,
或者Ingress控制器做负载均衡。

ifconfig
ipvsadm -Ln
可以进一步看到30779路由规则,走的是容器IP地址,也就是docker的IP

第五十七节  k8s 1.31.x 之 Service 学习_nginx_30

第五十七节  k8s 1.31.x 之 Service 学习_nginx_31

使用yaml文件创建方式:
vim nginx-svc2.yml
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc2
  namespace: default
  labels:
    app: nginx-svc2
spec:
  type: NodePort #这里改为NodePort模式
  selector:
    app: nginx-dep #关联的pod的标签名
  ports:
  - port: 8000
    protocol: TCP
    targetPort: 80

#应用yaml清单
kubectl apply -f nginx-svc2.yml
kubectl get svc,deploy,ep

第五十七节  k8s 1.31.x 之 Service 学习_Pod_32

第五十七节  k8s 1.31.x 之 Service 学习_Pod_33

如果不想使用集群IP加端口的方式访问,可以部署一台Nginx作为负载均衡器,这样能更加规范化

我们也可以编辑之前ClusterIP类型创建的名为my-dep的Service,将其改为ClusterIP模式

#编辑名为nginx-svc的Service
kubectl edit service nginx-svc

type: NodePort #修改type为NodePort

#或者

kubectl patch service nginx-svc -p '{"spec": {"type":"NodePort"}}

2.3.3 k8s对接外部MySQL8.x

官网下载包 https://downloads.mysql.com/archives/community/

第五十七节  k8s 1.31.x 之 Service 学习_Pod_34

第五十七节  k8s 1.31.x 之 Service 学习_IP_35

第五十七节  k8s 1.31.x 之 Service 学习_Pod_36

将下载好的安装包上传到rocky 8.10主机

解压
mkdir mysql8.4
tar -xvf tar -xvf mysql-8.4.2-1.el8.x86_64.rpm-bundle.tar
mv mysql-* mysql8.4
cd mysql8.4

安装mysql8.4数据库,依赖会自动下载安装
yum localinstall mysql-community-*

启动MySQL
service mysqld start  
chkconfig mysqld on

从日志 查看 安装 密码:
cat  /var/log/mysqld.log  |grep password
找到 root密码 FydAUaM(S2ov
-----
登录
mysql -uroot -p
FydAUaM(S2ov


重置登录密码
set password = 'Lyc123456.0';
flush privileges;
use mysql;
update user set host = '%' where user = 'root';
select user,host from mysql.user;
flush privileges;
exit;

第五十七节  k8s 1.31.x 之 Service 学习_IP_37

第五十七节  k8s 1.31.x 之 Service 学习_IP_38

重新登录MySQL
 mysql -uroot -p 
 ---> 数据root密码:Lyc123456.0

刷新表权限
ALTER USER 'root'@'%' IDENTIFIED BY 'Lyc123456.0' PASSWORD EXPIRE NEVER;
use mysql;
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'Lyc123456.0';
flush privileges;

如果提示mysql_native_password没开启,需要在my.cnf文件中添加
vim  /etc/my.cnf
---
添加
mysql_native_password=ON
---
service mysqld restart 
然后重新登录
mysql -uroot -p 
---> 数据root密码:Lyc123456.0
 可以执行SHOW PLUGINS,查看表权限打开情况

建一个测试库:
create database 34dbtest;

第五十七节  k8s 1.31.x 之 Service 学习_nginx_39

第五十七节  k8s 1.31.x 之 Service 学习_nginx_40

第五十七节  k8s 1.31.x 之 Service 学习_Pod_41

第五十七节  k8s 1.31.x 之 Service 学习_nginx_42

第五十七节  k8s 1.31.x 之 Service 学习_IP_43

第五十七节  k8s 1.31.x 之 Service 学习_nginx_44

【无头服务】
无头服务,是headless的翻译,一种特殊的Service类型,
不会自动分配ClusterIP和虚拟DNS名称。相反,它会为
每个Pod分配一个独立的DNS名称,以便于直接访问每个Pod。

这种Service通常用于StatefulSet等有状态的应用程序,例如
数据库集群、ZooKeeper集群等,可以直接访问每个Pod来
进行读写操作。

当需要在Pod级别控制网络流量时,也可以使用Headless Service。

总之,Headless Service适用于需要访问Pod的个别IP和端口时,
或需要使用自定义负载均衡逻辑时。

例如,
StatefulSet中的数据库集群就可以使用Headless Service,以便于在读写时直接访问每个pod。
【 ep 】
Endpoint:

Service 和 Endpoint 之间有啥关系呢?

Service:在k8s中,pod之间通信是一般通过service名称完成的.
Endpoint:pod和service之间的关联关系,是通过endpoint实现的。

Endpoints(简写:ep)表示了一个Service对应的所有Pod副本的访问地址,
而Endpoints Controller负责生成和维护所有Endpoints对象的控制器,
它负责监听Service和对应的Pod副本的变化。

第五十七节  k8s 1.31.x 之 Service 学习_IP_45

k8s 对接外部MySQL:

Service(svc)是根据Endpoint(ep),去连接对应的服务,
这就好办了
Service --> Endpoint --> Pod
k8s 对接外部MySQL:
Service(svc)是根据 Endpoint(ep),去连接对应的服务,这就好办了
Service --> Endpoint --> Pod

#定义一个server资源
vim mysql_service.yaml
---
apiVersion: v1
kind: Service
metadata:
  name: mysql #svc的name
  namespace: default #定义的namespace空间下
spec:
  type: ClusterIP
  ports:
   - port: 3306
---


# 定义一个ep资源
vim mysql_endpoints.yaml
---
apiVersion: v1
kind: Endpoints
metadata:
  name: mysql
  namespace: default
subsets:
  - addresses:
    - ip: 192.168.80.74 #定义的外部数据库【根据外部连接MySQL的IP更改】
    ports:
    - port: 3306
----

#创建一个svc资源
kubectl apply -f mysql_service.yaml
kubectl describe svc -n default mysql

# 更新ep资源
kubectl apply -f mysql_endpoints.yaml
#再次查询,发现ep已经记录MySQL的连接地址了
kubectl describe svc -n default mysql 

kubectl get svc 
kubectl get ep

第五十七节  k8s 1.31.x 之 Service 学习_nginx_46

第五十七节  k8s 1.31.x 之 Service 学习_nginx_47

k8s集群中启动一个centos容器进行验证:
vim centos7-test.yaml
---
apiVersion: v1
kind: Pod
metadata:
  name: centos-test
  labels:
    role: centos7
spec:
  containers:
    - name: centos7-1
      image: registry.cn-shanghai.aliyuncs.com/ywflyfish/centos7jdk8ssh:v1
      ports:
        - containerPort: 22
          hostPort: 50022
          protocol: TCP

创建pod
kubectl apply -f centos7-test.yaml

下载镜像:
docker pull registry.cn-shanghai.aliyuncs.com/ywflyfish/centos7jdk8ssh:v1
kubectl get pod

第五十七节  k8s 1.31.x 之 Service 学习_IP_48

确保集群走的通信模式是ipvs
kubectl edit configmap kube-proxy -n kube-system
改kube-proxy为ipvs模式后,需要重启kube-proxy的pod

查看pod运行模式
kubectl get deploy -n kube-system
kubectl get ds -n kube-system

重启pod
kubectl rollout restart ds kube-proxy -n kube-system
kubectl get pod -n kube-system -o wide


进入容器
kubectl exec -it centos-test -- /bin/bash
cat /etc/resolv.conf
---
nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local
pod内部的dns是外部svc地址


装mysql 客户端工具
yum install mariadb -y


测试:
mysql -uroot -h mysql.default.svc.cluster.local -p
Lyc123456.0

第五十七节  k8s 1.31.x 之 Service 学习_nginx_49

第五十七节  k8s 1.31.x 之 Service 学习_nginx_50

【总结】
安装其他类似的应用也一样操作,
需要定义一个server资源,
然后再定义一个ep,
将server与pod进行关联。

三、 LoadBalancer 之 metallb负载

集群外访问过程
·用户
   域名
·云服务提供商提供LB服务
  NodelP:Port(service lP)
  Pod IP:端口

第五十七节  k8s 1.31.x 之 Service 学习_IP_51

【部署metallb流程】
部署metallb---> 创建开放IP地址池--> 开启2层地址ipvs转发---> 部署ingress nginx--> 
----> metallb LoadBalancer-->部署测试服务

3.1 metallb介绍

官网

https://metallb.universe.tf/installation/

MetalLB 挂接到您的 Kubernetes 集群中,并提供一个网络 load-balancer 实现。
简而言之,它允许您创建 Kubernetes 服务类型LoadBalancer在不运行的集群中 在云提供商上,
因此不能简单地挂接到付费产品 提供负载均衡器。

MetalLB两大功能为:
·地址分配,类似于DHCP
·外部通告,一旦MetalLB为服务分配了外部IP地址,它就需要使群集之外的网络意识到该IP在群集中“存在”。

MetalLB使用标准路由协议来O实现此目的: ARP,NDP或BGP。

metallb安装之前对环境有要求,k8s修改如下配置

kubectl edit configmap -n kube-system kube-proxy
-------------
     40     ipvs:
     41       excludeCIDRs: null
     42       minSyncPeriod: 0s
     43       scheduler: ""
     44       strictARP: true
     45       syncPeriod: 0s
     54           infoBufferSize: "0"
     55         text:
     56           infoBufferSize: "0"
     57       verbosity: 0
     58     metricsBindAddress: ""
     59     mode: "ipvs"


重新启动kube-proxy
kubectl rollout restart daemonset kube-proxy -n kube-system

第五十七节  k8s 1.31.x 之 Service 学习_nginx_52

二进制部署k8s集群用这个方法修改

vim /opt/kubernetes/cfg/kube-proxy-config.yml
---
kind: KubeProxyConfiguration
apiVersion: kubeproxy.config.k8s.io/v1alpha1
bindAddress: 0.0.0.0
metricsBindAddress: 0.0.0.0:10249
clientConnection:
 kubeconfig: /opt/kubernetes/cfg/kube-proxy.kubeconfig
hostnameOverride: flyfish101
clusterCIDR: 10.244.0.0/16
mode: ipvs   #模式IPVS
ipvs:
 scheduler: "rr"
 strictARP: true   #打卡强制模式
iptables:
 masqueradeAll: true
---
service kube-proxy restart

3.2 metallb下载安装

wget https://raw.githubusercontent.com/metallb/metallb/v0.14.9/config/manifests/metallb-native.yaml
kubectl apply -f  metallb-native.yaml

kubectl get pod -n metallb-system -o wide

第五十七节  k8s 1.31.x 之 Service 学习_IP_53

3.3 创建metallb地址池

# 创建metallb地址池
vim IPAddressPool.yaml
---
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: first-pool
  namespace: metallb-system
spec:
  addresses:
  - 192.168.80.221-192.168.80.229
---

# 打开2层网络地址转发
vim metallb-L2.yaml
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: example
  namespace: metallb-system
spec:
  ipAddressPools:
  - first-pool
----

kubectl apply -f IPAddressPool.yaml
kubectl apply -f metallb-L2.yaml

kubectl get ipaddresspool -n metallb-system 
---
irst-pool   true          false             ["192.168.80.221-192.168.80.229"]

第五十七节  k8s 1.31.x 之 Service 学习_IP_54

3.4 部署ingress nginx

vim metallb-nginx.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  namespace: default
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - name: http
          containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx
  namespace: default
spec:
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: nginx
  type: LoadBalancer   # service类型为LoadBalancer


# 执行部署
kubectl apply -f metallb-nginx.yaml

第五十七节  k8s 1.31.x 之 Service 学习_IP_55

kubectl get ns
kubectl get pod -n default -o wide

直接curl对应的pod,通信正常
curl -i http://10.244.32.99

第五十七节  k8s 1.31.x 之 Service 学习_IP_56

kubectl get svc

直接curl对应的pod,通信正常
curl -i http://192.168.80.221

网页web登录下试试
http://192.168.80.221

也可以直接访问对应机器IP+端口号访问
例如本次nginx对应的pod在32机器上,我们试试
192.168.80.32:31959

第五十七节  k8s 1.31.x 之 Service 学习_Pod_57

第五十七节  k8s 1.31.x 之 Service 学习_Pod_58

第五十七节  k8s 1.31.x 之 Service 学习_Pod_59

四、 ExternalName 别名服务类型

ExternalName: 将外部的服务引用到k8s集群内部,也称别名服务。
ExternalName Service是一种特殊类型的 Service,主要用于访问位于集群外部的服务。

它没有选择器 Selector,也没有定义任何端口 Port 或是 Endpoints。

它的作用是返回集群外服务的域名:
1. 把集群外部的服务引入到集群内部中来,实现了集群内部pod和集群外部的服务进行通信
2. ExternalName 类型的服务适用于外部服务使用域名的方式,缺点是不能指定端口
3. 还有一点要注意:
      集群内的Pod会继承Node上的DNS解析规则。
      所以只要Node可以访问的服务,Pod中也可以访问到,这就实现了集群内服务访问集群外服务。
      

工作原理:会在coredns上相关域名上生成cname记录。

使用背景:让使用者像调用内部服务一样使用外部服务
实际场景使用,可以引用外部的数据库服务,以IP或者端口方式
dig -t a www.baidu.com 10.0.0.2

第五十七节  k8s 1.31.x 之 Service 学习_IP_60

vim externalname-svc.yaml
---
apiVersion: v1
kind: Service
metadata:
  name: en-svc
  namespace: default
spec:
  type: ExternalName  #type类型需要选择ExternalName
  externalName: www.baidu.com #externalName中填写外部服务对应的域名
---

kubectl apply -f externalname-svc.yaml
kubectl get svc

第五十七节  k8s 1.31.x 之 Service 学习_nginx_61

DNS 解析:

dig -t A en-svc.default.svc.cluster.local. @10.0.0.2

第五十七节  k8s 1.31.x 之 Service 学习_nginx_62

kubectl run -it expod --image=busybox:1.28
nslookup www.baidu.com
nslookup en-svc.default.svc.cluster.local

第五十七节  k8s 1.31.x 之 Service 学习_IP_63

4.1 不同namespace服务名引入

第五十七节  k8s 1.31.x 之 Service 学习_IP_64

1. 创建ns1命名空间和相关deploy, pod,service

vim ns1-nginx.yaml
---
apiVersion: v1 
kind: Namespace 
metadata: 
  name: ns1 # 创建ns1命名空间
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy-nginx 
  namespace: ns1 # 属于ns1命名空间
spec:
  replicas: 1 
  selector:
    matchLabels:
      app: nginx 
  template: 
    metadata:
      labels:
        app: nginx 
    spec:
      containers: 
      - name: nginx
        image: nginx:1.15-alpine
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: svc1 # 服务名
  namespace: ns1 # 属于ns1命名空间
spec:
  selector:
    app: nginx
  clusterIP: None # 无头service
  ports:
  - port: 80 
    targetPort: 80 
---
kind: Service
apiVersion: v1
metadata:
  name: external-svc1
  namespace: ns1 # 属于ns1命名空间
spec:
  type: ExternalName
  externalName: svc2.ns2.svc.cluster.local # 将ns2空间的svc2服务引入到ns1命名空间
----

kubectl apply -f ns1-nginx.yaml
kubectl get pod -n ns1
kubectl get svc -n ns1

第五十七节  k8s 1.31.x 之 Service 学习_nginx_65

2. 创建ns2命名空间和相关deploy, pod,service

vim ns2-nginx.yaml
----
apiVersion: v1 
kind: Namespace 
metadata: 
  name: ns2 # 创建ns2命名空间
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy-nginx 
  namespace: ns2 # 属于ns2命名空间
spec:
  replicas: 1 
  selector:
    matchLabels:
      app: nginx 
  template: 
    metadata:
      labels:
        app: nginx 
    spec:
      containers: 
      - name: nginx
        image: nginx:1.15-alpine
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: svc2 # 服务名
  namespace: ns2 # 属于ns2命名空间
spec:
  selector:
    app: nginx
  clusterIP: None # 无头service
  ports:
  - port: 80 
    targetPort: 80 
---
kind: Service
apiVersion: v1
metadata:
  name: external-svc2
  namespace: ns2 # 属于ns2命名空间
spec:
  type: ExternalName
  externalName: svc1.ns1.svc.cluster.local # 将ns1空间的svc1服务引入到ns2命名空间
---

kubectl apply -f ns2-nginx.yaml
kubectl get pod -n ns2
kubectl get svc -n ns2

第五十七节  k8s 1.31.x 之 Service 学习_IP_66

kubectl get ns

kubectl get pod -n ns1 -o wide
kubectl get pod -n ns2 -o wide

第五十七节  k8s 1.31.x 之 Service 学习_nginx_67

进ns1 的pod 测试
kubectl exec -it deploy-nginx-6958dbd4d5-2tjhh -n ns1 -- sh
---
nslookup svc1

#解析 svc2 的域名
nslookup svc2.ns2.svc.cluster.local 

# 将 ns2里的svc2服务引到了ns1里的名字,也可以访问
nslookup external-svc1.ns1.svc.cluster.local. 

exit

第五十七节  k8s 1.31.x 之 Service 学习_IP_68

进ns2 的pod 测试
kubectl exec -it deploy-nginx-6958dbd4d5-4m859 -n ns2 -- sh
---
nslookup svc2

#解析 svc1 的域名
nslookup svc1.ns1.svc.cluster.local

 # 将 ns1里的svc1服务引到了ns2里的名字,也可以访问
nslookup external-svc2.ns2.svc.cluster.local.

exit

第五十七节  k8s 1.31.x 之 Service 学习_IP_69

五、sessionAffinity

5.1 什么是sessionAffinity

sessionAffinity是指在Kubernetes中,用于控制外部流量如何在后端Pod之间分发的一种机制。
它确保来自同一客户端的请求始终被路由到同一个后端Pod上,从而保持会话的一致性。

【工作原理】
sessionAffinity主要有两种模式:

None:这是默认设置,负载均衡器会根据负载均衡算法(如轮询、最少连接数等)将每个新的请求
      独立地分发到后端的Pods上,与之前的请求无关。

ClientIP:基于客户端的IP地址来将来自同一个客户端的请求路由到同一个后端Pod上。这样可以确保
         来自同一个客户端的多次请求都被发送到同一个后端Pod上,保持会话一致性。
         
         
【应用场景】
sessionAffinity通常用于需要保持会话状态的应用程序,如基于HTTP的应用程序。例如,
在购物网站上从用户认证到浏览商品、添加购物车、下单支付等过程中,确保这些交互过程由
同一台服务器完成,避免因会话分散到不同服务器而导致用户体验下降的问题。

5.2 实验测试

设置sessionAffinity 为 Clientip
 (类似nginx的ip_hash算法,LVS的sh算法)
使用yaml 创建环境
vim nginx-deploy.yaml
---
apiVersion: apps/v1 #版本信息使用kubectl explain deployment查看
kind: Deployment
metadata:
  name: nginx-deploy
spec: 
  replicas: 2 #定义2个pod副本 
  selector:
    matchLabels:
      app: nginx-deploy #匹配的pod标签名
 
  template: 
    metadata:
      name: nginx 
      labels:
        app: nginx-deploy # pod的标签名,要跟matchLabels里定义的一致
    spec:
      containers: 
      - name: nginx 
        image: nginx:latest
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
  namespace: default
  labels:
    app: nginx-svc
 
spec:
  clusterIP: #指定ClusterIP,不写此行会自动分配一个Service的ip
  type: ClusterIP #可以不写此行,默认为ClusterIP模式
  selector:
    app: nginx-deploy #关联的pod的标签名
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
---

kubectl apply -f nginx-deploy.yaml
kubectl get pod,svc
kubectl get pod -A

第五十七节  k8s 1.31.x 之 Service 学习_IP_70

第五十七节  k8s 1.31.x 之 Service 学习_Pod_71

默认使用None模式

#查看创建的pod名
kubectl get pods

#依次修改每个pod的html页面,注意进入容器后使用ctrl+d退出容器
kubectl exec -it nginx-deploy-6d64457d77-2vdt8  -- /bin/sh
echo 'web1' > /usr/share/nginx/html/index.html
exit

#修改第二个pod
...
kubectl exec -it nginx-deploy-6d64457d77-86xrp -- /bin/sh
echo 'web2' > /usr/share/nginx/html/index.html
exit

第五十七节  k8s 1.31.x 之 Service 学习_Pod_72

第五十七节  k8s 1.31.x 之 Service 学习_IP_73

kubectl get svc

查看每次显示返回的内容 
curl http://10.107.247.164
----
[root@lyc-80-31 yaml]# curl http://10.107.247.164
web1
[root@lyc-80-31 yaml]# curl http://10.107.247.164
web2
----
可以看到每次访问的pod都不一样

第五十七节  k8s 1.31.x 之 Service 学习_IP_74

使用ClientIP模式

修改pod 模式为ClientIP :
kubectl patch svc nginx-svc -p '{"spec":{"sessionAffinity":"ClientIP"}}'

kubectl describe svc nginx-svc

第五十七节  k8s 1.31.x 之 Service 学习_nginx_75

ClientIP模式下测试,注意返回内容

curl http://10.107.247.164
---
可以看到ClientIP模式下,访问的pod始终都是同一个,不会变。

第五十七节  k8s 1.31.x 之 Service 学习_IP_76