找回密码
 立即注册
首页 业界区 业界 博客园出海记-K8S集群优化:一次命中注定的失败 ...

博客园出海记-K8S集群优化:一次命中注定的失败

鞍汉 7 天前
1.jpeg

在上一篇出海记博文提到,本想试试 Cilium 的一个高科技,却试验失败。
这个高科技就是,Cilium 可以实现一个“魔法”,给 Kubernetes LoadBalancer Service 分配一个虚拟 IP,当内网中的机器访问这个 IP 时,Cilium 会选举1台节点服务器,填上它的 MAC 地址,瞒天过海地与请求方进行通信。如果用上这个科技,就可以用 Kubernetes Service 取代阿里云负载均衡作为 control-plane 的负载均衡,省钱又环保。
上次试验失败后,心里有些不甘心,又继续折腾。本想着成功后能发篇博文分享胜利经验,没想到现实很骨感——失败其实是注定的,因为忽略了一个关键点——云上的网络是一个虚拟世界,基于 ARP 协议的巧妙玩法,在现实(虚拟现实)面前行不通。
于是,这篇原本打算分享胜利经验的出海记博文被迫降级为分享失败经验。
以下是试验 Cilium L2 Announcements 失败过程的分享。
首先,在阿里云专有网络 VPC 中预留 172.21.48.240/28 网段给 Cilium LoadBalancer 使用
2.png

接着,更新 cilium 的部署,开启 cilium 与负载均衡相关的特性
  1. cilium upgrade --version 1.18.1 \
  2.   --namespace kube-system \
  3.   --set bpf.masquerade=true \
  4.   --set kubeProxyReplacement=true \
  5.   --set l2announcements.enabled=true \
  6.   --set l2NeighDiscovery.enabled=true \
  7.   --set externalIPs.enabled=true
复制代码
相比之前的 cilium 部署,多了3个配置选项
  1. --set l2announcements.enabled=true
  2. --set l2NeighDiscovery.enabled=true
  3. --set externalIPs.enabled=true
复制代码
部署完成后,检查一下配置是否生效
  1. ~ # cilium config view | grep enable-l2
  2. enable-l2-announcements                           true
  3. enable-l2-neigh-discovery                         true
  4. ~ # kubectl -n kube-system exec ds/cilium -- cilium-dbg status --verbose | grep externalIPs                                                                                                        2 ↵
  5. - externalIPs:    Enabled
复制代码
都生效了。
接下来,部署用于转发请求到 api-server 的 LoadBalancer Service,清单文件 lb-service.yaml 内容如下
  1. apiVersion: v1
  2. kind: Service
  3. metadata:
  4.   annotations:
  5.     io.cilium/lb-ipam-ips: 172.21.48.240
  6.   labels:
  7.     component: kube-apiserver
  8.     tier: control-plane
  9.   name: kube-api
  10.   namespace: kube-system
  11. spec:
  12.   selector:
  13.     component: kube-apiserver
  14.     tier: control-plane
  15.   ports:
  16.   - name: https
  17.     port: 6443
  18.     protocol: TCP
  19.     targetPort: 6443
  20.   type: LoadBalancer
复制代码
下单部署这个 service
  1. # kubectl apply -f lb-service.yaml   
  2. service/kube-api created
复制代码
查看部署情况
  1. ~ # kubectl get svc --field-selector spec.type=LoadBalancer -n kube-system
  2. NAME       TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
  3. kube-api   LoadBalancer   10.107.192.67   <pending>     6443:31920/TCP   31s
复制代码
这个 kube-api service 监听于 6443 端口,将转发请求给 control-plane 的 api-server,看上去是一个称职的 control-plane 负载均衡,但它现在只是一个摆设,中看不中用,因为只有 CLUSTER-IP,没有 EXTERNAL-IP,只能在 k8s 集群内部访问,而要作为 control-plane 负载均衡,需要能通过节点服务器所在的网络访问。
再接下来,部署 CiliumLoadBalancerIPPool,清单中 cidr 对应的是阿里云 VPC 预留的网段,清单文件 lb-ip-pool.yaml 内容如下
  1. apiVersion: "cilium.io/v2alpha1"
  2. kind: CiliumLoadBalancerIPPool
  3. metadata:
  4.   name: api-server
  5.   annotations:
  6. spec:
  7.   blocks:
  8.   - cidr: "172.21.48.240/28"
复制代码
下单部署
  1. ~ # kubectl apply -f lb-ip-pool.yaml
  2. ciliumloadbalancerippool.cilium.io/api-server created
复制代码
查看部署结果
  1. ~ # kubectl get CiliumLoadBalancerIPPool
  2. NAME         DISABLED   CONFLICTING   IPS AVAILABLE   AGE
  3. api-server   false      False         16              77s
  4. ~ # kubectl get svc --field-selector spec.type=LoadBalancer -n kube-system
  5. NAME       TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)          AGE
  6. kube-api   LoadBalancer   10.107.192.67   172.21.48.240   6443:31920/TCP   17m
复制代码
这时你会发现 kube-api service 的  EXTERNAL-IP 被分配了一个节点所在网络(阿里云VPC)的 IP 地址,这个 IP 是通过部署清单中的 io.cilium/lb-ipam-ips: 172.21.48.240 指定的,如果没有指定,会从 CiliumLoadBalancerIPPool  cidr 指定的网段中分配一个。
我们试试在其中一台节点服务器上访问这个 IP 与 6443 端口
  1. ~ # curl -k https://172.21.48.240:6443/livez
  2. ok
复制代码
竟然可以访问了,我们只是部署了 CiliumLoadBalancerIPPool,其他什么也没做,是 cilium 根据我下的菜单(清单文件),知道我的口味,把一切都包办了。
现在,k8s 集群中的任一节点都可以通过 172.21.48.240 访问负载均衡,不管是 control-plane 还是 worker 节点,
但仅仅这样是不够的,比如向集群加入新节点或者节点服务器重启时, 怎么访问这台负载均衡?
我们还需要再下一个菜单,开启 cilium 的魔法能力 —— L2 Announcements,让同一个内网中没有加入集群的服务器也能访问负载均衡,清单文件 lb-l2-announcements.yaml 内容如下
  1. apiVersion: "cilium.io/v2alpha1"
  2. kind: CiliumL2AnnouncementPolicy
  3. metadata:
  4.   name: control-plane
  5. spec:
  6.   serviceSelector:
  7.     matchLabels:
  8.       component: kube-apiserver
  9.       tier: control-plane
  10.   nodeSelector:
  11.     matchExpressions:
  12.     - key: node-role.kubernetes.io/control-plane
  13.       operator: Exists
  14.   loadBalancerIPs: true
  15.   externalIPs: true
复制代码
注:serviceSelector 需要对应之前部署的 LoadBalancer Service
下单部署
  1. ~ # kubectl apply -f lb-l2-announcements.yaml
  2. ciliuml2announcementpolicy.cilium.io/control-plane created
复制代码
查看部署情况
  1. # kubectl get CiliumL2AnnouncementPolicy                                                         
  2. NAME            AGE
  3. control-plane   29s
复制代码
查看 lease 是否生效
  1. ~ # kubectl -n kube-system get lease | grep "cilium-l2announce"
  2. cilium-l2announce-kube-system-kube-api   kube-cp-03
复制代码
查看 l2-announce 是否正常
  1. ~ # kubectl -n kube-system get pod -l 'app.kubernetes.io/name=cilium-agent' -o wide | grep kube-cp-03                                                                              1 ↵
  2. cilium-sgjv9   1/1     Running   8 (21m ago)   14d   172.21.49.58   kube-cp-03   <none>           <none>
复制代码
  1. ~# kubectl -n kube-system exec pod/cilium-sgjv9 -- cilium-dbg shell -- db/show l2-announce
  2. IP              NetworkInterface
  3. 172.21.48.240   eth0
复制代码
确认 L2 Announcements 已部署成功。
找一台内网中没有加入 k8s 集群的服务器测试一下,看是否可以访问负载均衡的 6443 端口
  1. ~ # telnet 172.21.48.240 6443
  2. Trying 172.21.48.240...
复制代码
连不上,L2 Announcements 没起作用。
用 arping 命令测试一下 APR 解析是否正常
  1. ~ # arping 172.21.48.240
  2. ARPING 172.21.48.240
  3. 58 bytes from ee:ff:ff:ff:ff:ff (172.21.48.240): index=0 time=59.783 usec
  4. 58 bytes from ee:ff:ff:ff:ff:ff (172.21.48.240): index=1 time=69.028 usec
  5. 58 bytes from ee:ff:ff:ff:ff:ff (172.21.48.240): index=2 time=88.491 usec
复制代码
ARP 解析虽然成功了,但却是一个很奇怪的 MAC 地址 ee:ff:ff:ff:ff:ff。一开始以为是 cilium-agent 在搞鬼,但后来试着 arping 一个根本不存在的内网 IP,竟然也是这个 MAC 地址!原来,阿里云 VPC 中的任何内网 IP 都是这样解析。这时才意识到,问题应该与身在云上有关。
后来在网上找到一篇博文 阿里云ecs服务器arp映射表与实际mac地址不一致的疑问 终于真相大白:
发工单后回答说:
ecs底层是虚拟化的网络,不是传统的物理网络。表项的学习是通过arp代理实现,为了避免大量ARP学习影响组件性能,所以看到的都是同一个MAC ee:ff:ff:ff:ff:ff ,是正常的现象。
原来,阿里云 VPC 的虚拟网络并未完全遵循标准的 ARP 协议,Cilium 巧妙的 L2 Announcements 方案如同“无根之木”,在云平台这个虚拟世界的“物理定律”下,其失效是必然的。所以,这次失败是命中注定的。
参考:

  • L2 Announcements / L2 Aware LB (Beta)
  • HA Cilium Load Balancer for Kubernetes Control Plane provisioned by ClusterAPI
  • Migrating from MetalLB to Cilium
  • Complete Guide: Cilium L2 Announcements for LoadBalancer Services in Bare-Metal Kubernetes

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册