摘要
本文内容转自网络,个人学习记录使用,请勿传播
Service
Service
存在的意义
k8s集群中部署的服务对外提供访问可以通过NodePort
的方式对外暴露端口,
k8s集群中部署的pod随着日常的部署、变更、故障经常会发生变化,如果需要将pod组成的服务对外提供访问就需要动态的感知pod的变化并提供统一、固定的入口来对外提供用户访问。
k8s
中service
的引入就是为了解决感知pod
动态变化,并对外提供统一入口的解决方案。
service
可以通过标签选择器来识别一组pod
,为同一组pod
提供统一入口(服务发现)service
可以感知pod
的变化,防止pod
失联serivce
可以定义一组pod
的访问策略(负载均衡)
Pod
与Service
的关系
service
通过标签选择器来关联一组pod
service
使用iptables
或者ipvs
来为一组pod
提供负载均衡能力k8s
通过kube-proxy
来实现service
创建service
1 | # 启动一个deploy |
多端口的service
定义
service
定义多个端口的时候,需要通过name
进行区分
1 | apiVersion: v1 |
Service的三种类型
ClusterIP:
k8s集群内部使用NodePort:
在node节点上开放随机端口,对外暴露服务LoadBalancer:
通过调用公有云lb服务对外暴露应用
ClusterIP
service的模式类型,为一组服务提供一个固定的集群IP(VIP),默认只能在集群内部访问。
1 | spec: |
NodePort
在集群中每个节点上通过kube-proxy启用一个端口来暴露服务,可以在集群外部访问。也会分配一个稳定内部集群IP地址。
访问地址:
<任意NodeIP>:<NodePort>
默认端口范围:
30000-32767
1 | spec: |
- NodePort 会在每个node节点上监听端口提供对外访问,通常来说我们需要在外部增加一个负载均衡设备来代理多台node
LoadBalancer
与NodePort类似,会在每个节点上启用一个端口来暴露服务。除此之外,Kubernetes
会通过api请求底层云平台(例如阿里云、腾
讯云、AWS等)上的负载均衡器,将每个Node([NodeIP]:[NodePort]
)作为后端添加进去。
Service的代理模式
service有两种代理模式,传统的方式使用iptables代理模式,近期增加了对ipvs的支持
- iptables:通过linux系统的iptables对流量进行转发
- ipvs:通过内核ipvs负载均衡模块对流量进行转发
- 在kubernetes v1.8 中引入了 ipvs模式,在 v1.9 中处于 beta 阶段,在 v1.11 中已经正式可用了。
- iptables 模式在 v1.1 中就添加支持了,从 v1.2版本开始 iptables 就是 kube-proxy 默认的操作模式
- ipvs 和iptables 都是基于netfilter的。ipvs 会使用 iptables 进行包过滤、SNAT、masquared。
具体来说,ipvs 将使用ipset来存储需要DROP或masquared的流量的源或目标地址,
以确保 iptables 规则的数量是恒定的,这样我们就不需要关心我们有多少服务了。
iptables的流量转发实现
1 | $ kubectl get svc |
如何修改代理模式
kube-proxy
默认使用iptables
模式
1 | kubectl logs kube-proxy-jwnwd -n kube-system | grep Proxier |
kubeadm部署修改为ipvs模式
1 | $ kubectl edit configmap kube-proxy -n kube-system |
内核加载ipvs模块
1 | ipvs_mode_dir="/usr/lib/modules/$(uname -r)/kernel/net/netfilter/ipvs" |
二进制方式部署的集群修改ipvs模式
1 | # 二进制方式部署的集群需要修改kube-proxy的配置文件 |
iptables与ipvs对比
模式 | 优点 | 缺点 |
---|---|---|
iptables | 灵活、功能强大,在k8s中应用的较早,更稳定 | 当条目过多会导致性能下降(规则的遍历匹配和更新,呈线性时延) |
只有一种调度算法 | ||
ipvs | 工作在内核态,有更好的性能 | 在 |
调度算法非常丰富(rr、wrr、lc、wlc、ip hash等) |
CoreDNS
k8s集群内部的DNS服务器,目前为k8s集群默认使用的DNS组件服务,CoreDNS服务一直监听Kubernetes API,会为每一个Service创建CNS记录,用于记录域名解析。
- CoreDNS可以在集群内服务间调用场景提供名字解析服务
1 | # CoreDNS yaml文件地址 |
- ClusterIP A级路格式:
<service-name>.<namespace-name>.svc.cluster.local
- 示例:my-svc.my-namespace.svc.cluster.local
Ingress
Ingress
- 将集群内部的服务通过7层规则对外部提供服务的规则集合
- k8s集群中的一个抽象资源,提供一个暴露集群中应用的外部访问入口的定义方法
Ingress Controller
- 通过读取Ingress规则实现流量分发策略并完成流量的接入、分发
- 根据
Ingress
定义的规则生成具体的路由规则,并对Pod提供负载均衡
为了弥补NodePort不足而生
- NodePort只支持四层负载均衡
- 一个端口只能给一个服务使用,端口需要提前做规划
- 端口多了之后维护困难
Pod和Ingress的关系
Ingress Controller
Ingress
管理的负载均衡器,为集群提供全局的负载均衡能力
Ingress Controller
有很多实现
- k8s官方维护的nginx
Haproxy Ingress
Istio Ingress
Kong Ingress
Traefik Ingress
Ingress官方文档:文档地址
部署Ingress Controller
Ingress-nginx官方文档:文档地址
1 | $ wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.48.1/deploy/static/provider/cloud/deploy.yaml -O k8s-ingress-controller.yaml |
创建Service
1 | kubectl expose deploy nginx-taint --name nginx-taint --port=8080 --target-port=80 --type=ClusterIP --dry-run=client -o yaml > nginx-taint-service.yaml |
1 | apiVersion: v1 |
1 | # 如果报错Internal error occurred: failed calling webhook "validate.nginx.ingress.kubernetes.io" |
创建Ingress
规则
1 | kubectl create ingress nginx-taint --default-backend=nginx-taint:8080 --rule="test1.isme.com/*=nginx-taint:8080" --dry-run=client -o yaml > nginx-taint-ingress.yaml |
1 | apiVersion: networking.k8s.io/v1 |
1 | $ kubectl apply -f nginx-taint-ingress.yaml |
本地绑定host到任意一个节点ip上,然后通过浏览器访问验证
1 | # 将ingress转发端口设置成pod端口 |
1 | $ kubectl describe ingress nginx-taint |
配置https规则
自签https证书
1 | cat > ca-config.json <<EOF |
将证书保存到Secret中
1 | $ kubectl create secret tls test2-isme-com --cert=test2.isme.com.pem --key=test2.isme.com-key.pem |
Ingress
配置tls
1 | apiVersion: networking.k8s.io/v1 |
访问验证
Ingress Controller
工作原理
Ingress Controller
通过与Kubernetes API
交互,动态的去感知集群中Ingress
规则变化,通过Ingress
定义的规则,如:那个域名对应哪个service;生成流量转发规则,然后应用到具体实现的应用上,如:nginx,然后加载配置生效,最终完成7层负载流量转发以及规则动态更新的问题。
1 | 浏览器 -> 公网负载均衡器 -> ingress controller -> 分布在各个节点上的Pod |
Ingress Controller
如何通过Ingress
规则找到Service
对应的Pod
Ingress
规则中转发的Service
端口可以是Service
的端口,也可以是Pod
的端口Service
是四层接入层,通过端口进行转发,每一个端口对应一个服务的多副本Pod
- 同一个
Service
可以创建多个端口映射,代理服务的多个或同一个端口 Ingress
规则实际上是通过Service
加端口信息,找到对应代理的后端服务多副本Pod
并进行转发
Service
多端口配置
1 | # 多端口映射service,service开启多个端口可以代理不同或同一个端口 |
1 | $ kubectl get svc |
Ingress
配置
1 | # 不同域名对应不同端口 |
1 | $ kubectl get ingress |
最终2个域名都可以访问到同一个服务