kubernetes核心概念 Service(二)
实验环境
安装好k8s集群
Service类型:
ClusterIP(可在集群内部访问)
NodePort(可通过节点ip访问)
LoadBalancer
ExternalName
注意:
1. Service类型决定了客户访问Service代理的方法
2. Kube-proxy工作模式是service实现代理时的底层实现方式(ipvs)
一、Service类型-LoadBalancer
使用MetalLB/OpenELB实现LoadBalancer
1、概述
MetalLB可以为kubernetes集群中的Service提供网络负载均衡功能。
MetalLB两大功能为:
地址分配:MetalLB 可以为 LoadBalancer 类型的 Service 分配外部 IP 地址,类似于DHCP,此地址是对外发布的虚拟的群集ip
外部流量负载均衡:MetalLB 可以将外部流量负载均衡到集群中的多个节点,并将流量转发到相应的 Pod。通过群集ip访问的流量,将被负载均衡的调度到k8s群集的各个节点的service
注:
当使用云平台(阿里云、腾讯云、AWS等)的容器服务时,我们可以通过配置service为LoadBalancer模式来绑定云平台的负载均衡器,从而实现外网的访问。
对于自建kubernetes集群我们一般使用MetalLB来实现外部流量的访问。
2、工作原理
Metallb包含两个组件,Controller(Deployment方式部署)和Speaker(daemonset方式部署)。
具体的工作原理:
1)Controller负责监听service变化,当service配置为LoadBalancer模式时,从IP池中分配相应的IP。
2)Speaker则依据Service的变化,将外部流量引流到kubernetes集群node节点。
3)当业务流量通过到达指定的Node时,由Node上面运行的Kube-Proxy依据转发模式(iptables或ipvs)将流量转发到pod中。
小结:
1)MetalLB负责从主机维度实现负载均衡,而pod副本间的负载均衡是通过kube-proxy实现。
2)跟NodePort模式相比较,MetalLB使群集有了客户访问的统一入口,即群集ip。
3)NodePort:客户访问任意节点ip,都可以访问到service,kube-proxy再通过ipvs实现pod间的调度
4)MetalLB:客户通过访问的群集IP,客户请求被负载均衡的调度到任一节点service,kube-proxy再通过ipvs实现pod间的调度
3、修改kube-proxy代理模式
列出 Kubernetes 集群中 kube-system 命名空间下的所有 ConfigMap 资源
kubectl get configmap -n kube-system
编辑 kube-system 命名空间中的 kube-proxy ConfigMap
kubectl edit configmap kube-proxy -n kube-system
修改添加:
由原来的flase修改为true,原理同LVS中的DR模式关闭到群集地址的arp响应
重启 kube-system 命名空间中的 kube-proxy DaemonSet,使新的配置生效
kubectl rollout restart daemonset kube-proxy -n kube-system
4、MetalLB部署
官网安装步骤地址:Installation :: MetalLB, bare metal load-balancer for Kubernetes
浏览器中访问https://raw.githubusercontent.com/metallb/metallb/v0.14.9/config/manifests/metallb-native.yaml,看到内容后复制创建文件,再kubectl apply -f metallb-native.yaml部署应用
官网方法需要使用VPN连接后才能下载,这里使用下载好的文件部署
上传metallb-controller.tar和metallb_speaker.tar包到/root目录并导入(master1、worker1、worker2)
docker load -i metallb-controller.tar
docker load -i metallb_speaker.tar
上传metallb-native.yaml文件到/root目录(master1)
创建资源
kubectl apply -f metallb-native.yaml
列出 metallb-system 命名空间中的所有 Pod
kubectl get pod -n metallb-system
5、IP地址池准备
vim ippool.yaml
添加:
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: ippool
namespace: metallb-system
spec:
addresses:
- 192.168.10.240-192.168.10.250
创建资源
kubectl apply -f ippool.yaml
列出 metallb-system 命名空间中的所有 IPAddressPool 资源
kubectl get ipaddresspool -n metallb-system
输出字段解析:
NAME:IP 地址池的名称。
AUTO ASSIGN:是否自动分配 IP 地址。
AVOID BUGGY IPS:是否避免使用有问题的 IP 地址。
ADDRESSES:IP 地址池的范围。
6、开启二层通告
vim L2.yaml
添加:
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: example
namespace: metallb-system
创建资源
kubectl apply -f L2.yaml
7、发布Service类型为LoadBalancer的应用
创建Deployment控制器类型应用nginx-metallb及service,service类型为LoadBalancer
vim nginx-metallb.yaml
添加:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-metallb
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx-metallb1
image: nginx:1.20
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-metallb
spec:
ports:
- port: 8090
protocol: TCP
targetPort: 80
selector:
app: nginx
type: LoadBalancer
创建资源
kubectl apply -f nginx-metallb.yaml
kubectl get svc
字段解析:
EXTERNAL-IP:Service 的外部 IP 地址(仅适用于 LoadBalancer 类型)
在各节点上查看集群IP
ip a | grep 192.168.10.240
访问Service的外部IP
curl 192.168.10.240:8090
使用浏览器访问192.168.10.240:8090
通过nodeIP访问
使用浏览器访问192.168.10.11:30351
删除有关pod和service
kubectl delete -f nginx-metallb.yaml
二、ExternalName
1、ExternalName作用
把集群外部的服务引入到集群内部,实现了集群内部pod和集群外部的服务进行通信
ExternalName 类型的服务适用于外部服务使用域名的方式,缺点是不能指定端口
集群内的Pod会继承Node上的DNS解析规则,只要Node可以访问的服务,Pod中也可以访问到,这就实现了集群内服务访问集群外服务
2、将公网域名引入
vim externalname.yml
添加:
apiVersion: v1
kind: Service
metadata:
name: my-externalname
namespace: default
spec:
type: ExternalName
externalName: www.baidu.com
创建资源
kubectl apply -f externalname.yml
kubectl get svc
列出 kube-system 命名空间中的所有 Service 资源
kubectl get svc -n kube-system
安装dig命令软件bind-utils
yum -y install bind-utils
查询 Kubernetes 集群中 my-externalname Service 的 DNS A 记录,并指定 DNS 服务器为 10.96.0.10
dig -t A my-externalname.default.svc.cluster.local. @10.96.0.10
kubectl run -it --image busybox -- sh
nslookup www.baidu.com
nslookup my-externalname.default.svc.cluster.local.
三、sessionAffinity会话保持(会话粘滞)
1、Session Affinity简介
会话保持(Session Affinity),有时又称粘滞会话(Sticky Sessions),是负载均衡领域设计需要着力解决的重要问题之一,也是一个相对比较复杂的问题。
会话保持是指在负载均衡器上的一种机制,在完成负载均衡任务的同时,还负责一系列相关联的访问请求会分配到一台服务器上。
会话保持的作用:确保把来自同一客户的一个完整会话的请求转发至后台同一台服务器进行处理。
2、什么时候需要会话保持?
举个大家每天都会遇到的例子,大家在淘宝或者京东上购物时,从完成用户身份认证到浏览店铺,选择心仪商品加入购物车,一直到最后下单完成支付,需要经过很多次和服务器的交互过程才能完成整个交易。由于这几次交互过程从顺序上和逻辑上是密切相关的,服务器在进行这些交互过程的某一个交互步骤时需要一个上下文(Context),即上一次交互过程的输出,因此要求这些相关的交互过程都由一台服务器完成。
在这种情况下,假设负载均衡器仍然把这些相关交互session分散到不同的服务器实例上,就会带来很糟糕的用户体验,比如客户在浏览器上每点击一次,都会弹出登录页面。或者即使用户输入了正确的验证码,却仍然提示验证码错误。由于服务器处理实例不一样,也有可能造成客户放入购物车的物品丢失。
设置sessionAffinity为Clientip (类似nginx的ip_hash算法,lvs的sh算法)
(1)创建测试用deployment、service
vim sessionAffinity.yaml
添加:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-server1
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: c1
image: nginx:1.20
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
spec:
type: ClusterIP
ports:
- protocol: TCP
port: 80
targetPort: 80
selector:
app: nginx
创建资源
kubectl apply -f sessionAffinity.yaml
kubectl get pod
分别进入创建的两个pod,创建网页
kubectl exec -it nginx-server1-56f996dfc5-5dg5j -- bash
echo "web1" > /usr/share/nginx/html/index.html
kubectl exec -it nginx-server1-56f996dfc5-jzv72 -- bash
echo "web2" > /usr/share/nginx/html/index.html
查看发布service nginx-svc的集群IP
kubectl get svc
访问集群IP
curl 10.108.237.138
curl 10.108.237.138
(2)给服务打补丁,增加会话粘滞
查看service nginx-svc的详细信息
kubectl describe service nginx-svc
使用 kubectl patch 来修改 Kubernetes 中名为 nginx-svc 的 Service 的配置,将 sessionAffinity 设置为 ClientIP
kubectl patch svc nginx-svc -p '{"spec":{"sessionAffinity":"ClientIP"}}'
字段解析:
-p '{"spec":{"sessionAffinity":"ClientIP"}}':这是 patch 的内容,表示对 spec 部分进行修改,将 sessionAffinity 字段的值设置为 ClientIP
查看service nginx-svc的详细信息
kubectl describe svc nginx-svc
字段解析:
sessionAffinity:
这是 Kubernetes Service 的一个配置项,用于控制客户端请求的路由行为。
None(默认值):不启用会话亲和性,请求会被随机分配到后端 Pod。
ClientIP:启用基于客户端 IP 的会话亲和性。来自同一客户端 IP 的请求会被路由到同一个后端 Pod。
访问测试:
curl 10.108.237.138
一直是一个pod提供服务
将sessionAffinity设置回为None
kubectl patch svc nginx-svc -p '{"spec":{"sessionAffinity":"None"}}'
kubectl describe svc nginx-svc
访问测试:
curl 10.108.237.138