$ kubectl apply -f openelb.yaml namespace/openelb-system created customresourcedefinition.apiextensions.k8s.io/bgpconfs.network.kubesphere.io created customresourcedefinition.apiextensions.k8s.io/bgppeers.network.kubesphere.io created customresourcedefinition.apiextensions.k8s.io/eips.network.kubesphere.io created serviceaccount/kube-keepalived-vip created serviceaccount/openelb-admission created role.rbac.authorization.k8s.io/leader-election-role created role.rbac.authorization.k8s.io/openelb-admission created clusterrole.rbac.authorization.k8s.io/kube-keepalived-vip created clusterrole.rbac.authorization.k8s.io/openelb-admission created clusterrole.rbac.authorization.k8s.io/openelb-manager-role created rolebinding.rbac.authorization.k8s.io/leader-election-rolebinding created rolebinding.rbac.authorization.k8s.io/openelb-admission created clusterrolebinding.rbac.authorization.k8s.io/kube-keepalived-vip created clusterrolebinding.rbac.authorization.k8s.io/openelb-admission created clusterrolebinding.rbac.authorization.k8s.io/openelb-manager-rolebinding created service/openelb-admission created deployment.apps/openelb-manager created job.batch/openelb-admission-create created job.batch/openelb-admission-patch created mutatingwebhookconfiguration.admissionregistration.k8s.io/openelb-admission created validatingwebhookconfiguration.admissionregistration.k8s.io/openelb-admission created
$ kubectl get crd NAME CREATED AT bgpconfs.network.kubesphere.io 2022-05-19T06:37:19Z bgppeers.network.kubesphere.io 2022-05-19T06:37:19Z eips.network.kubesphere.io 2022-05-19T06:37:19Z
$ kubectl get ns openelb-system -o wide NAME STATUS AGE openelb-system Active 2m27s
实际上主要工作的负载就是这两个jobs.batch和这一个deployment
1 2 3 4 5 6 7 8 9 10 11 12 13 14
$ kubectl get pods -n openelb-system NAME READY STATUS RESTARTS AGE openelb-admission-create-57tzm 0/1 Completed 05m11s openelb-admission-patch-j5pl4 0/1 Completed 05m11s openelb-manager-5cdc8697f9-h2wd6 1/1 Running 05m11s
$ kubectl get deploy -n openelb-system NAME READY UP-TO-DATE AVAILABLE AGE openelb-manager 1/1115m38s
$ kubectl get jobs.batch -n openelb-system NAME COMPLETIONS DURATION AGE openelb-admission-create1/111s 11m openelb-admission-patch 1/112s 11m
apiVersion:v1 kind:Service metadata: name:nginx-lb-service namespace:nginx-quic spec: allocateLoadBalancerNodePorts:false externalTrafficPolicy:Cluster internalTrafficPolicy:Cluster selector: app:nginx-lb ports: -protocol:TCP port:80# match for service access port targetPort:80# match for pod access port type:LoadBalancer
---
apiVersion:v1 kind:Service metadata: name:nginx-lb2-service namespace:nginx-quic spec: allocateLoadBalancerNodePorts:false externalTrafficPolicy:Cluster internalTrafficPolicy:Cluster selector: app:nginx-lb ports: -protocol:TCP port:80# match for service access port targetPort:80# match for pod access port type:LoadBalancer
---
apiVersion:v1 kind:Service metadata: name:nginx-lb3-service namespace:nginx-quic spec: allocateLoadBalancerNodePorts:false externalTrafficPolicy:Cluster internalTrafficPolicy:Cluster selector: app:nginx-lb ports: -protocol:TCP port:80# match for service access port targetPort:80# match for pod access port type:LoadBalancer
然后我们检查部署状态:
1 2 3 4 5 6 7 8 9 10 11 12
$ kubectl apply -f nginx-quic-lb.yaml namespace/nginx-quic unchanged deployment.apps/nginx-lb created service/nginx-lb-service created service/nginx-lb2-service created service/nginx-lb3-service created
$ kubectl get svc -n nginx-quic NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx-lb-service LoadBalancer 10.88.17.248 10.31.88.101 80:30643/TCP 58m nginx-lb2-service LoadBalancer 10.88.13.220 10.31.88.102 80:31114/TCP 58m nginx-lb3-service LoadBalancer 10.88.18.110 10.31.88.103 80:30485/TCP 58m
$ ip neigh | grep 10.31.88.113 10.31.88.113 dev eth0 lladdr 52:54:00:74:eb:11 STALE $ arp -a | grep 10.31.88.113 ? (10.31.88.113) at 52:54:00:74:eb:11 [ether] on eth0
apiVersion:v1 kind:Service metadata: name:nginx-lb3-service namespace:nginx-quic annotations: lb.kubesphere.io/v1alpha1:openelb protocol.openelb.kubesphere.io/v1alpha1:layer2 eip.openelb.kubesphere.io/v1alpha2:eip-layer2-pool spec: allocateLoadBalancerNodePorts:true externalTrafficPolicy:Cluster internalTrafficPolicy:Cluster selector: app:nginx-lb ports: -protocol:TCP port:80# match for service access port targetPort:80# match for pod access port type:LoadBalancer # 使用 loadBalancerIP 字段从而指定VIP loadBalancerIP:10.31.88.113
修改完成之后我们重新部署,openelb会自动生效并且将服务的EXTERNAL-IP变更为新IP。
1 2 3 4 5
$ kubectl get svc -n nginx-quic -o wide NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR nginx-lb-service LoadBalancer 10.88.17.248 10.31.88.101 80:30643/TCP 18h app=nginx-lb nginx-lb2-service LoadBalancer 10.88.13.220 10.31.88.102 80:31114/TCP 18h app=nginx-lb nginx-lb3-service LoadBalancer 10.88.18.110 10.31.88.113 80:30485/TCP 18h app=nginx-lb
需要特别注意的是bgpconf这里配置的监听端口,OpenELB在默认情况下会同时监听IPv4和IPv6网络栈,因此需要确保集群开启了IPv6网络栈,否则会无法正确建立BGP连接。pod内的报错日志类似"listen tcp6 [::]:17900: socket: address family not supported by protocol"
$ kubectl apply -f openelb/openelb-bgp.yaml bgpconf.network.kubesphere.io/default created bgppeer.network.kubesphere.io/bgppeer-openwrt-plus created $ kubectl get bgpconf NAME AGE default 16s $ kubectl get bgppeer NAME AGE bgppeer-openwrt-plus 20s
apiVersion:v1 kind:Service metadata: name:nginx-lb2-service namespace:nginx-quic annotations: lb.kubesphere.io/v1alpha1:openelb protocol.openelb.kubesphere.io/v1alpha1:bgp eip.openelb.kubesphere.io/v1alpha2:eip-bgp-pool spec: allocateLoadBalancerNodePorts:false externalTrafficPolicy:Cluster internalTrafficPolicy:Cluster selector: app:nginx-lb ports: -protocol:TCP port:80# match for service access port targetPort:80# match for pod access port type:LoadBalancer
---
apiVersion:v1 kind:Service metadata: name:nginx-lb3-service namespace:nginx-quic annotations: lb.kubesphere.io/v1alpha1:openelb protocol.openelb.kubesphere.io/v1alpha1:bgp eip.openelb.kubesphere.io/v1alpha2:eip-bgp-pool spec: allocateLoadBalancerNodePorts:false externalTrafficPolicy:Cluster internalTrafficPolicy:Cluster selector: app:nginx-lb ports: -protocol:TCP port:80# match for service access port targetPort:80# match for pod access port type:LoadBalancer loadBalancerIP:10.89.100.100
$ kubectl get eip -A NAME CIDR USAGE TOTAL eip-bgp-pool 10.89.0.1-10.89.255.254 2 65534 eip-layer2-pool 10.31.88.101-10.31.88.200 1 100 $ kubectl get svc -n nginx-quic NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx-lb-service LoadBalancer 10.88.15.40 10.31.88.101 80:30972/TCP 2m48s nginx-lb2-service LoadBalancer 10.88.60.227 10.89.0.1 80:30425/TCP 2m48s nginx-lb3-service LoadBalancer 10.88.11.160 10.89.100.100 80:30597/TCP 2m48s
再查看路由器上面的路由表,可以看到两个BGP模式的VIP有多个下一条路由,则说明ECMP开启成功
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
tiny-openwrt-plus# show ip route Codes: K - kernel route, C - connected, S - static, R - RIP, O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP, T - Table, v - VNC, V - VNC-Direct, A - Babel, F - PBR, f - OpenFabric, > - selected route, * - FIB route, q - queued, r - rejected, b - backup t - trapped, o - offload failure
K>* 0.0.0.0/0 [0/0] via 10.31.254.254, eth0, 12:56:32 C>* 10.31.0.0/16 is directly connected, eth0, 12:56:32 B>* 10.89.0.1/32 [20/0] via 10.31.88.1, eth0, weight 1, 00:00:28 * via 10.31.88.11, eth0, weight 1, 00:00:28 * via 10.31.88.12, eth0, weight 1, 00:00:28 B>* 10.89.100.100/32 [20/0] via 10.31.88.1, eth0, weight 1, 00:00:28 * via 10.31.88.11, eth0, weight 1, 00:00:28 * via 10.31.88.12, eth0, weight 1, 00:00:28