K8s-Service
Service在很多情况下只是一个概念,真正起作用的其实是kube-proxy服务进程,每个Node节点上都运行着一个kube-proxy服务进程。当创建Service的时候会通过api-server向etcd写入创建的service的信息,而kube-proxy会基于监听的机制发现这种Service的变动,然后它会将最新的Service信息转成对应的访问规则。
▶ kube-proxy的三种工作模式
• userspace模式(用户空间模式,最早版本,已淘汰)
原理:kube-proxy在节点用户空间监听端口,收到流量后,在用户态做转发,再把包转发给后端Pod
特点:
1.逻辑简单,早期k8s使用
2.支持健康检查后端Pod
缺点:
1.性能很差,流量要在内核态<--->用户态来回拷贝,上下文切换开销大
2.并发高的时候延迟高
• iptables模式(默认模式,广泛使用)
原理:kube-proxy不直接管流量,再节点内核写入大量iptables规则。内核直接匹配流量并转发,不需要经过kube-proxy进程。
特点:
1.流量在内核转发,性能远高于userspace
2.无需额外依赖,Linux原生iptables,开箱即用
3.支持随即负载均衡(默认随机选后端Pod)
缺点:
1.Service数量多的时候,iptables规则爆炸,规则数量巨大,更新慢。
2.负载均衡策略单一,只有随机,不支持轮询,加权等。
3.没有后端Pod健康探测(Pod挂了,需要控制器删除endpoint,才会删除规则
• ipvs模式(高性能模式,生产大规模集群推荐)
原理:ipvs是Linux内核模块,kube-proxy调用ipvs,在内核创建虚拟服务。ipvs专门做四层负载均衡。
需要提前加载内核模块ip_vs
特点:
1.性能最高,ipvs是专门负载均衡模块,大量Service场景下,规则更新速度远快于iptables
2.内置多种负载均衡算法:rr(轮询)、wrr(加权轮询)、lc(最小连接)、sh(源地址哈希)等。
3.支持会话保持
缺点:
1.需要操作系统内核开启ipvs模块,部分精简系统默认没加载
2.配置相对复杂一些
3.ipvs只负责四层转发,端口映射、过滤还是要依赖少量iptables辅助规则
• 表格对比
模式| 转发位置| 负载均衡算法| 大规模 Service 性能| 现状
---|---|---|---|---
userspace| 用户态| 随机| 差| 废弃
iptables| 内核 iptables| 随机| 一般,规则膨胀| 默认,中小集群
ipvs| 内核 ipvs 模块| rr/wrr/lc/sh 等多种| 优秀| 大规模生产推荐
▶ Service的四种类型
• ClusterIP:
默认值,它是k8s系统自动分配的虚拟IP,只能在集群内部访问。
yaml文件:
…………
…………
spec:
selector:
app: nginx-pod
clusterIP: 10.96.0.10 #不可以乱写
#(kubectl get cm kubeadm-config -n kube-system -o yaml | grep -E "podSubnet|serviceSubnet")查看集群ip范围
type: ClusterIP
ports:
- port: 80
targetPort: 80
#### • NodePort:
将Service通过指定的Node上的端口暴露给外部,通过此办法,就可以在集群外部访问服务。
yaml文件:
………………
………………
type: NodePort
ports:
- port: 80
nodePort: 30002
targetPort: 80
• LoadBalancer:
使用外接负载均衡器完成到服务的负载分发,注意此模式需要外部云环境支持
• ExternalName:
把集群外部服务引入集群内部,直接使用。
yaml文件:
apiVersion: v1
kind: Service
metadata:
name: svc-externalname
namespace: demo
spec:
type: ExternalName
externamName: www.baidu.com
可以用dig查看解析详情
▶ Endpoint
Endpoint是k8s中的一个资源对象,存储在etcd中,用来记录一个service对应的所有pod的访问地址,它是根据service配置文件中的selector描述产生的。
命令:
kubectl -n demo get endpoints -o wide
▶ HeadLiness(无头服务)
这类服务不会分配ClusterIP,如果想要访问service,只能通过service的域名进行查询,域名的规则是:服务名.名称空间.svc.cluster.local
yaml创建:clusterIP:None即可创建
获取集群DNS服务器地址:
kubectl get svc -n kube-system kube-dns
使用dig命令查看域名解析到的ip:
yum install bind-utils -y
dig @10.96.0.10 服务名.命名空间.svc.cluster.local
▶ Ingress
• 工作原理:
1.用户编写ingress规则,说明哪个域名对应k8s集群的哪个Service
2.ingress控制器动态感知ingress服务规则的变化,然后生成一段对应的Nginx反向代理配置
3.ingress控制器会将生成的Nginx配置写入到一个运行着的Nginx服务中,并动态更新
4.到此为止,其实真正在工作的就是一个Nginx了,内部配置了用户自定义的请求转发规则
• 部署Ingress
第七节: service详解 - WOLITA,有ingress-deploy的yaml文件,六百多行
kubectl create -f ingress-deploy.yaml即可
• 使用验证Ingress
1.部署deployment和service,**注意标签匹配**
2.Http代理
vim ingress-http
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-http
namespace: demo
spec:
ingressClassName: nginx
rules:
- host: nginx.itedu.com
http:
paths:
- pathType: Prefix #前缀匹配
path: /
backend:
service:
name: nginx-service #注意标签一致
port:
number: 80
查看:
kubectl get -n demo ingress ingress-http
查看ingress的80对应的外网端口:
kubectl -n ingress-nginx get svc
### 3.Https代理
生成自签名的证书:
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/C=CN/ST=BJ/L=BJ/O=nginx/CN=itedu.com"
创建密钥:
kubectl create secret tls tls-secret --key tls.key --cert tls.crt
创建ingress-https.yaml:
多一块儿内容:
…………
spec:
ingressClassName: nginx
tls:
- hosts:
- nginx.itedu.com
- tomcat.itedu.com
secretName: tls-secret #指定密钥