k8s 踩坑记 - 2
有新的冒险伙伴加入!
MetalLB
(在这一部分,我会尝试用较为“官方”的措辞来总结;而在正文部分,我还是会用大白话说)
MetalLB是一个控制平面组件,它可以在BareMetal环境下,为Service的LoadBalancer语义提供一个实现
它可以通过ARP(IPv4)/NDP(IPv6)协议(在L2模式下)或者BGP协议(在BGP模式下)来宣告VIP(Virtual IP)
从而使入口端流量流向leader(在L2模式下)或者进行路由层面的负载均衡(在BGP模式下)
这家伙在说些什么呢……(自我批判)
总之,k8s本身并不提供LoadBalancer语义的具体实现。通常情况下,云厂商售卖的云服务器中提供了它的实现,而我们的本地裸机如果想要使用type: LoadBalancer,就需要自己安装一个了,MetalLB就是其中一种。简单点来讲,安装了MetalLB,集群就可以“假装自己在云上”。
需要注意的是,MetalLB本身并不负责流量转发,它只负责“将流量引入集群”,实际的转发工作由kube-proxy和CNI这类组件负责
它也只控制入口流量的流向,如上文所述,kube-proxy等等这些组件会负责后续的转发,确保(至少如果我没配置错的话)流量送到正确的地方
在L2模式下,入口的所有流量首先会被送到Leader,尽管这听起来配不上它的“LoadBalancer”的名头,但它仍然属于负载均衡的一部分;在BGP模式下,这玩意就能充分发挥优势,真正地在路由层面进行分流了
在L2模式下,它会选出一个leader节点,如果这个leader节点挂掉,它就会选出下一个……这就是“漂移”,一定程度上减轻了单点故障的影响,为集群带来了一点稳定性
“可恶,集群阵!”
“就一个节点也能叫「集群」吗?”
——《东方K8S》
在学习初期,我曾经使用NodePort来暴露Service,并且当时的我认为使用NodePort和使用LoadBalancer和MetalLB是没有区别的。彳亍吧,使用NodePort在单节点的集群用来暴露服务或者用来测试确实是可行的,但是这么做的缺点会很快暴露出来:
- 无法暴露低位端口(80/443),因为
NodePort有限制(当然很有可能是设计上就不打算让我们这么做) - 在Service越来越多时,
NodePort的管理将会变得异常困难 - 最致命的一点……
NodePort暴露出来的服务是 节点相关 而非 集群相关 的,这意味着我们需要访问 节点 来访问暴露的服务……嘶……
Ingress
好吧,其实如果单独讲“Ingress”的话,可能会引起歧义……它可以指“被ingress-controller读取并执行的一种资源”,也可以指“Kubernetes Ingress这一套东西” 当然这节的节标题指的是后者
Ingress(体系)提供了第七层的路由抽象,所以可以提供第七层负载均衡,ingress资源当然本身不负责转发流量,而是影响ingress-controller的行为 废话 ;从某种意义上来说ingress-controller自身不负责转发流量(?),但是奈何它与更加底层的实现(例如nginx,这些实现最终提供了流量转发)紧紧耦合了起来,所以其实ingress-controller自身确实承担了转发流量的工作
概念补齐
控制平面与数据平面
曾经,我以为,控制平面和数据平面的划分是以节点为单位的
但是实际上大错特错,控制平面应当是负责调控节点运行状态的“组件集合”,例如kube-apiserver,etcd,诸如此类,它们互相协作,就好像一个”平面“。由于以上原因,”平面”的划分并不是以节点为单位的,这些组件甚至可以分布在不同的节点上(通常以Pod形式)。综上,”平面“的分类是以逻辑而非物理位置方面来划分的。控制平面负责决策,而数据平面负责执行实际工作。
不过要注意,master节点和worker节点并不等同于控制平面和数据平面,根据上文,很容易知道这两对东西甚至不在同一个级别上。但是话又说回来了,让worker跑控制平面的组件似乎有些反直觉……?
果然还是要来点干货啊
MetalLB
下面是MetalLB资源的配置文件(假设metallb命名空间存在 废话 )
1 | apiVersion: metallb.io/v1beta1 |
Ingress-nginx
由于我们配置了MetalLB,所以我们现在可以使用LoadBalancer来暴露我们的Ingress服务了!但是等等昂,我们需要让Ingress知道这一点……我们先创建一个文件,ingress_value.yaml:
1 | controller: |
然后使用下面的命令,将我们的配置应用到Ingress,让Ingress见识一下我们新提的LoadBalancer语义实现:
1 | helm upgrade ingress-app ingress-nginx/ingress-nginx -n=the-namespace -f ingress_value.yaml |
下面贴出了我将/dashboard的path代理到my-headlamp服务的Ingress配置
1 | apiVersion: networking.k8s.io/v1 |
(哦对了,别忘了更改headlamp的baseURL):
1 | config: |
1 | helm upgrade headlamp headlamp/headlamp -n=the-namespace -f headlamp_patch.yaml |