k8s私有集群loadBalancer
一.介绍
几种service类型介绍:https://zhuanlan.zhihu.com/p/157565821
1.为什么要用LoadBalancer
1.keepalived和loadbalancer的区别
node节点如果不想暴露端口,需要使用keepalived,但是这和k8s中的loadbalancer一样的原理。但如果要加入一个新的node,keepalived需要改动配置,loadbalancer不用,故障转移是自动的,此时新节点将接管发生故障的节点的IP地址所有权。
2.AWS自带loadbalancer图解
3.什么时候用
一般在机房或者云上使用ECS自建Kubernetes集群是无法使用 LoadBalancer 类型的 Service 。因为 Kubernetes 本身没有为裸机群集提供网络负载均衡器的实现。
自建的 Kubernetes 集群暴露让外网访问,目前只能使用 NodePort 或 Ingress 等的方法进行服务暴露。NodePort 缺点是每个暴露的服务需要占用所有节点的某个端口。Ingress 是一个不错的解方法。
有没有方法,让自建的 Kubernetes 集群也能使用 LoadBalancer 类型的 Service ?这就用到了MetaLB
2.loaderblancer和Metallb不同
公有云的会提供一个负载均衡器,自带ip。和keepalived思路相同
而metallb是不提供负载均衡器的,它是借助浮动ip的思路,为loadblancer类型的svc分配一个外界可访问的ip,这个ip需要用户自己提供。
二.MetalLB
1.概念
MetalLB 会在 Kubernetes 内运行,监控服务对象的变化,一旦监测到有新的 LoadBalancer 服务运行,并且没有可申请的负载均衡器之后,就会完成地址分配和外部声明两部分的工作。
2.地址分配
在云厂商提供的 Kubernetes 集群中,Service 声明使用 LoadBalancer时,云平台会自动分配一个负载均衡器的IP地址给你,应用可以通过这个地址来访问。
使用 MetalLB 时,MetalLB 会自己为用户的 LoadBalancer 类型 Service 分配 IP 地址,当然该 IP 地址不是凭空产生的,需要用户在配置中提供一个 IP 地址池,Metallb 将会在其中选取地址分配给服务。
3.外部声明
一旦 MetalLB 为服务分配了IP地址,它需要对外宣告此 IP 地址,并让外部主机可以路由到此 IP。
外部声明有两种模式:
Layer 2 模式
BGP 模式
1、Layer 2 模式
Layer 2 模式下,每个 Service 会有集群中的一个 Node 来负责。服务的入口流量全部经由单个节点,然后该节点的 Kube-Proxy 会把流量再转发给服务的 Pods。也就是说,该模式下 MetalLB 并没有真正提供负载均衡器。尽管如此,MetalLB 提供了故障转移功能,如果持有 IP 的节点出现故障,则默认 10 秒后即发生故障转移,IP 会被分配给其它健康的节点。
优缺点:
优点:
是它的通用性:它可以在任何以太网网络上运行,不需要特殊的硬件。
缺点:
Layer 2 模式下存在单节点瓶颈,服务所有流量都经过一个Node节点。这意味着服务的入口带宽被限制为单个节点的带宽。
由于 Layer 2 模式需要 ARP/NDP 客户端配合,当故障转移发生时,MetalLB 会发送 ARP 包来宣告 MAC 地址和 IP 映射关系的变化,地址分配略为繁琐。
2、BGP 模式
BGP 模式下,集群中所有node都会跟上联路由器建立BGP连接,并且会告知路由器应该如何转发service的流量。
优缺点:
优点:
BGP模式下才是一个真正的 LoadBalancer,通过BGP协议正确分布流量,不再需要一个Leader节点。
缺点:
不能优雅处理故障转移,当持有服务的节点宕掉后,所有活动连接的客户端将收到 Connection reset by peer。
需要上层路由器支持BGP。而且因为BGP单session的限制,如果Calico也是使用的BGP模式,就会有冲突从而导致metallb无法正常工作。
4.环境要求
Kubernetes 1.13.0 版本或更高版本的集群。
Kubernetes 集群网络组件需要支持 MetalLB 服务,具体参考: https://metallb.universe.tf/installation/network-addons/
MetalLB 需要能分配IPv4地址。
根据操作模式的不同,可能需要一个或多个能够使用BGP的路由器。
参考文件(两个部署文件结合参考):
https://blog.csdn.net/weixin_43357497/article/details/109056990
https://article.itxueyuan.com/Zo8enW
https://www.cnblogs.com/fengjian2016/p/11936651.html
部署如下:
1.kubectl apply -f https://raw.githubusercontent.com/google/metallb/v0.8.3/manifests/metallb.yaml
2.创建configmap,用于指定ip地址池
3.创建自定义svc(type类型为loadbanlance,会选取ip地址池中ip)和deployment,每要新建不同的服务,都需要指定不同的svc和deployment(上面两步是固定的)
三.ingress
1.理解
参考:
https://segmentfault.com/a/1190000019908991/
https://blog.51cto.com/u_15382481/5205194
https://www.cnblogs.com/ll409546297/p/16734507.html
k8s 对外暴露服务(service)主要有两种方式:NotePort, LoadBalance, 此外externalIPs也可以使各类service对外提供服务。
但是当集群服务很多的时候,NodePort方式最大的缺点是会占用很多集群机器的端口;
LB方式最大的缺点则是每个service一个LB又有点浪费和麻烦,并且需要k8s之外的支持; 而ingress则只需要一个NodePort或者一个LB就可以满足所有service对外服务的需求。可以简单理解为service的service。工作机制大致可以用下图表示:
1.Ingress概念
1.Ingress是k8s资源,是集群内服务暴露到外部的一种方式
2.它和 Service 的不同之处在于,Service 只可以支持 4 层的负载均衡,而 Ingress 是支持 7 层的负载均衡,支持 http 和 https,包括通过主机名的访问
3.Ingress 只是一个统称,其由 Ingress 和 Ingress Controller 两部分组成
- Ingress 用作将原来需要手动配置的规则,抽象成一个 Ingress 对象,使用 YAML 格式的文件来创建和管理。
- Ingress Controller 和k8s api交互,动态感知上一步yaml文件的变化,进而生成或改变底层nginx.conf配置文件。包括nginx、haproxy、F5等,官方推荐使用nginx
2.为什么用ingress
1.为什么不用nginx?这是因为在 K8S 集群中,如果每加入一个服务,我们都在 Nginx 中添加域名映射,比较麻烦,只用在ingress配置文件中写即可
2.客户端访问集群时,要用http七层协议,只有ingress能够提供
总:ingress的yaml配置文件关联自定义的svc,自定义的svc关联具体pod应用,因此相当于svc的svc,ingress controller通过api检测ingress配置文件对底层nginx.conf改动更新
3.普通svc模式和ingress模式
4.ingress结合例子
如下(ingress是和自定义的svc关联)
#apiVersion:networking.k8s.io/v1的格式
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: minimal-ingress
annotations:
#在生成的nginx配置中,采用loacation ~表示正则匹配
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- http:
paths:
- path: /testpath
pathType: Prefix
backend:
service:
name: test
port:
number: 80
#apiVersion:networking.k8s.io/v1beta1的格式
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: ingress-test
namespace: ratel-test1
spec:
rules:
- host: ingress.test.com
http:
paths:
- backend:
serviceName: ingress-test
servicePort: 80
path: /
5.ingress-controller
ingress-controller 是实现反向代理和负载均衡的程序,其功能是为了使 ingress 工作,通过解析 ingress 的规则来实现请求转发。集群内可以有多个 ingress-controller。
一般来说,ingress-controller的形式都是一个pod,里面跑着daemon程序和反向代理程序。daemon负责不断监控集群的变化,根据ingress对象(yaml文件)的配置存储在pod中生成nginx.conf文件
2.部署方式
需要考虑2方面
- ingress-controller是作为pod来运行的,以什么方式部署比较好
- ingress解决了把如何请求路由到集群内部,那它自己怎么暴露给外部比较好
几种部署和暴露方式:
-
方式一:Deployment+LoadBalancer模式的svc
如果要把ingress部署在公有云,那用这种方式比较合适。用Deployment部署ingress-controller,创建一个type为LoadBalancer的service关联这组pod。大部分公有云,都会为LoadBalancer的service自动创建一个负载均衡器,通常还绑定了公网地址。只要把域名解析指向该地址,就实现了集群服务的对外暴露。
-
方式二:Deployment+NodePort模式的svc
同样用deployment模式部署ingress-controller,并创建对应的服务,但是type为NodePort。这样,ingress就会暴露在集群节点ip的特定端口上。由于nodeport暴露的端口是随机端口,一般会在前面再搭建一套负载均衡器来转发请求。该方式一般用于宿主机是相对固定的环境ip地址不变的场景。 NodePort方式暴露ingress虽然简单方便,但是NodePort多了一层NAT,在请求量级很大时可能对性能会有一定影
-
方式三:DaemonSet+HostNetwork+nodeSelector
用DaemonSet结合nodeselector来部署ingress-controller到特定的node上,然后使用HostNetwork直接把该pod与宿主机node的网络打通,直接使用宿主机的80/433端口就能访问服务。这时,ingress-controller所在的node机器就很类似传统架构的边缘节点,比如机房入口的nginx服务器。该方式整个请求链路最简单,性能相对NodePort模式更好。缺点是由于直接利用宿主机节点的网络和端口,一个node只能部署一个ingress-controller pod。比较适合大并发的生产环境使用。
3.方式三部署
ingress-nginx和k8s版本对照参考:https://github.com/kubernetes/ingress-nginx
https://www.cnblogs.com/ll409546297/p/16734507.html
-
service部署
apiVersion: v1 kind: Service metadata: name: xbd-nacos spec: ports: - port: 8848 targetPort: 8848 selector: app: xbd-nacos type: ClusterIP
-
安装 ingress-nginx-controller
#下载固定文件 https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.3/deploy/static/provider/cloud/deploy.yaml
修改如下:
#修改1 image: k8s.gcr.io/ingress-nginx/controller:v1.1.3@sha256:31f47c1e202b39fadecf822a9b76370bd4baed199a005b3e7d4d1455f4fd3fe2 改成 image: registry.aliyuncs.com/google_containers/nginx-ingress-controller:v1.1.3
#修改2 image: k8s.gcr.io/ingress-nginx/kube-webhook-certgen:v1.1.1@sha256:64d8c73dca984af206adf9d6d7e46aa550362b1d7a01f3a0a91b20cc67868660 改成(这个镜像存在两处) image: registry.aliyuncs.com/google_containers/kube-webhook-certgen:v1.1.1
#修改3 kind: Deployment 改成 kind: DaemonSet # 保证每个节点都存在 加入 spec: hostNetwork: true # 宿主网络开启 containers:
-
编写ingress
-
ingressClassName的值使用
kubectl get IngressClass
命令获取,或进入ingress controller.yaml中查看name值 -
ingressclass资源的name同级加上
ingressclass.kubernetes.io/is-default-class: "true"
,ingress资源中可不写ingressClassName或者 kubernetes.io/ingress.class 注解
#ingress.yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: #annotations: # kubernetes.io/ingress.class: "nginx-ingress-inst-1" name: xbd-nacos-ing spec: #使用ingressClassName或kubernetes.io/ingress.class都可以 ingressClassName: "nginx" rules: - host: xbd.nacos.com http: paths: - path: / pathType: Prefix backend: service: name: xbd-nacos #对应的svc名称 port: number: 8848
-
-
本地修改host文件进行测试
#daemonset默认每台node都会有,此时可以再加一层keepalvied实现对node的负载均衡,当然可以通过daemonset的标签选择指定到固定node上 nodeip xbd.nacos.com
4.多ingress部署
当k8s集群上有dev、test、prod3套环境,可以为每套环境部署一套ingress,只需要将ingress controller.yaml中的namespace区分开来,然后ingress引用即可。
参考:https://blog.51cto.com/fengwan/5710057?u_atoken=c9eb2e48-9018-4ae0-abe9-780926232c9a&u_asession=01gKnKLypWJU5Kwc4htuENC-yE6v5EmY9DnocWl5NyMB56lHsEsEl1VeKBSdmWnWs9X0KNBwm7Lovlpxjd_P_q4JsKWYrT3W_NKPr8w6oU7K8OBNh4vUL6n4MQLUj_5hQ1kGIqlTZZ8pFMErCyu9Vi4GBkFo3NEHBv0PZUm6pbxQU&u_asig=05ReNMps794XZLa2116BvqUZh9BtisbcIN4aqrDmz7onfTUchNS6lABe-YOV2-mG2hUXbONpFYvDvemVViIgEtwCTpRrISTLfrq645iZ_5wMo0bXgZ1sDjrCW1Fc5-EWNj-Fq7oXyn4kpjLA3BSihwJeuuwIn2ekuitYXJGu6s-Cb9JS7q8ZD7Xtz2Ly-b0kmuyAKRFSVJkkdwVUnyHAIJzbd1bQdxpV9DuX2VxqDrHSSnLhiTaHjCf5_NGKSfXV2SxnxGQL5Y3qOEIZ5dvISBau3h9VXwMyh6PgyDIVSG1W8VWCBImsYhMVkjEGU1EyH3GDD_i-YTWy21aCLL7cNYZvLW4--x4BsgGNGHQKHEp4vj1M7QAHXTTOjicVA1YbsamWspDxyAEEo4kbsryBKb9Q&u_aref=bw0pZCsswowvf0JlwA44raYr5HQ%3D