k8s入门篇二(部署Metallb 用户的负载均衡支持)

K8S 用户的负载均衡支持

简介

在私有网络上运行 Kubernetes,和御三家相比,对 LoadBalancer 类型的服务的支持应该是众多表面差异中最醒目的一个了。类型为 LoadBalancer 的服务在 Kubernetes 中并没有直接支持,NodePort 和 ExternalIP 方案让很多私有云用户成为了 K8S 世界中的二等公民。接下来介绍的 Metallb,就给私有 Kubernetes 用户带来了一个方便、可用(而且不太成熟)的软件解决方案。

该项目发布于 2017 年底,当前处于 Beta 阶段。

Metallb 会在 Kubernetes 内运行,监控服务对象的变化,一旦察觉有新的 LoadBalancer 服务运行,并且没有可申请的负载均衡器之后,就会完成两部分的工作:

地址分配

用户需要在配置中提供一个地址池,Metallb 将会在其中选取地址分配给服务。

地址广播

根据不同配置,Metallb 会以二层(ARP/NDP)或者 BGP 的方式进行地址的广播。

支持范围

不支持 IPVS

网络插件 兼容性
Calico 部分支持(有附加文档)
Flannel 支持
Kube-router 不支持(正在跟进)
Romana 支持(有附加文档)
Weave Net 支持

一个小测试

安装

Metallb 支持 Helm 和 YAML 两种安装方法,这里我们使用第二种:

kubectl apply -f https://raw.githubusercontent.com/google/metallb/v0.7.1/manifests/metallb.yaml

很简单,Metallb 就会开始安装,会生成自己的命名空间以及 RBAC 配置。

$ kubectl get pods -n metallb-system
NAME                         READY     STATUS    RESTARTS   AGE
controller-b7896bf94-g449l   1/1       Running   0          51m
speaker-mt6kd                1/1       Running   0          51m
speaker-sqbn4                1/1       Running   0          51m

配置

接下来我们要生成一个 Configmap 文件,为 Metallb 设置网址范围以及协议相关的选择和配置,这里以一个简单的二层配置为例:

apiVersion: v1
kind: ConfigMap
metadata:
  namespace: metallb-system
  name: config
data:
  config: |
    address-pools:
    - name: my-ip-space
      protocol: layer2
      addresses:
      - 10.211.55.240/28

注意:这里的 IP 地址范围需要跟集群实际情况相对应。

使用 kubectl apply 命令应用之后,使用 kubectl logs -f [metallb-controller-pod] 会看到配置更新过程。

测试

创建一个 Nginx 的服务,服务类型为 LoadBalancer

apiVersion: apps/v1beta2
kind: Deployment
metadata:
  name: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1
        ports:
        - name: http
          containerPort: 80

---
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: nginx
  type: LoadBalancer

服务创建运行之后,可以列出服务信息:

kubectl get svc
NAME       TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)         AGE
kube-dns   ClusterIP      10.96.0.10                53/UDP,53/TCP   7d
nginx      LoadBalancer   10.96.245.212   10.211.55.240   80:32207/TCP    54m

这里就发现,LoadBalancer 类型的服务,分配到了我们地址池中的第一个 IP。

用 curl http://10.211.55.240 验证,就会发现返回了 Nginx 的欢迎信息。

补充

除了这里提到的一点点简单配置之外,Metallb 的配置能力还是比较强大的,这点可以参考官网,其中谈及了不少较为务实的案例,另外还提到了部分 Issue 供用户参考。

 

前言

我们知道,Service 机制,以及 Kubernetes 里的 DNS 插件,都是在帮助我们解决同样一个问题,即:如何找到某一个容器;而 Service 是由 kube-proxy 组件,加上 iptables 来共同实现的;所谓 Service 的访问入口,其实就是每台宿主机上由 kube-proxy 生成的 iptables 规则,以及 kube-dns 生成的 DNS 记录。而一旦离开了这个集群,这些信息对用户来说,也就自然没有作用了

在使用 Kubernetes 的 Service 时,一个必须要面对和解决的问题就是:如何从外部(Kubernetes 集群之外),访问到 Kubernetes 里创建的 Service?

从外界连通 Service

三种方式

  • NodePort
  • ExternalIP
  • LoadBalance

这里 NodePort 和 externalIPs 是 K8S 集群本身就支持的特性,这两个方案让很多私有云用户成为了 K8S 世界中的二等公民,而 NodePort 也是我们最常用的;

而 kubernetes 没有为裸机群集提供网络负载均衡器(类型为 LoadBalancer 的服务)的实现,如果你的 K8S 集群没有在公有云的 IaaS 平台(GCP,AWS,Azure …)上运行,则 LoadBalancers 将在创建时无限期地保持 “挂起” 状态,也就是说只有公有云厂商自家的 kubernetes 支持 LoadBalancer,对 LoadBalancer 类型的服务的支持应该是众多表面差异中最醒目的一个了

纯软件解决方案: MetalLB

该项目发布于 2017 年底,当前处于 Beta 阶段,旨在解决上述中的不平衡,通过提供与标准网络设备集成的网络 LB 实现来纠正这种不平衡,以便裸机集群上的外部服务也 “尽可能” 地工作;即 MetalLB 能够帮助你在 kubernetes 中创建 LoadBalancer 类型的 kubernetes 服务

项目地址:https://github.com/google/metallb

版本说明:https://metallb.universe.tf/release-notes/

Metallb 会在 Kubernetes 内运行,监控服务对象的变化,一旦察觉有新的 LoadBalancer 服务运行,并且没有可申请的负载均衡器之后,就会完成两部分的工作:

  • 地址分配用户需要在配置中提供一个地址池,Metallb 将会在其中选取地址分配给服务。
  • 地址广播根据不同配置,Metallb 会以二层(ARP/NDP)或者 BGP 的方式进行地址的广播

基本原理图

安装部署演示

部署 Metallb 负载均衡器

Metallb 支持 Helm 和 YAML 两种安装方法(这里推荐第二种)

  • Helm
    $ helm install --name metallb stable/metallb
  • YAML
    $ kubectl apply -f https://raw.githubusercontent.com/google/metallb/v0.7.3/manifests/metallb.yaml

    很简单,Metallb 就会开始安装,会生成自己的命名空间以及 RBAC 配置

    [root@lee ~]# kubectl apply -f https://raw.githubusercontent.com/google/metallb/v0.7.3/manifests/metallb.yaml
    namespace/metallb-system created
    serviceaccount/controller created
    serviceaccount/speaker created
    clusterrole.rbac.authorization.k8s.io/metallb-system:controller created
    clusterrole.rbac.authorization.k8s.io/metallb-system:speaker created
    role.rbac.authorization.k8s.io/config-watcher created
    clusterrolebinding.rbac.authorization.k8s.io/metallb-system:controller created
    clusterrolebinding.rbac.authorization.k8s.io/metallb-system:speaker created
    rolebinding.rbac.authorization.k8s.io/config-watcher created
    daemonset.apps/speaker created
    deployment.apps/controller created
    
    [root@lee ~]# kubectl get pods -n metallb-system -owide
    NAME                                             READY   STATUS  RESTARTS   AGE   IP               NODE   NOMINATED NODE
    controller-765899887-bdwdk   1/1     Running   0          82s   10.0.0.22                lee    
    speaker-qldl6                                  1/1     Running   0          82s   192.168.50.124   lee

    目前还没有宣布任何内容,因为我们没有提供 ConfigMap,也没有提供负载均衡地址的服务;
    接下来我们要生成一个 ConfigMap文件,为 Metallb 设置网址范围以及协议相关的选择和配置

    提供 IP pool

    通过之前提到的原理图可知,需要创建一个 ConfigMap 文件,以提供 IP 池

    $ wget https://raw.githubusercontent.com/google/metallb/v0.7.3/manifests/example-layer2-config.yaml

    修改 ip 地址池和集群节点网段相同,且必须为一个 IP 区间

    apiVersion: v1
    kind: ConfigMap
    metadata:
      namespace: metallb-system
      name: config
    data:
      config: |
        address-pools:
        - name: my-ip-space
          protocol: layer2
          addresses:
          # 与集群节点网段相同
          -192.168.50.211-192.168.50.220

    IP 地址为 无占用

    [root@lee ~]# ping 192.168.50.211
    PING 192.168.50.211 (192.168.50.211) 56(84) bytes of data.
    From 192.168.50.124 icmp_seq=1 Destination Host Unreachable
    From 192.168.50.124 icmp_seq=2 Destination Host Unreachable
    From 192.168.50.124 icmp_seq=3 Destination Host Unreachable
    From 192.168.50.124 icmp_seq=4 Destination Host Unreachable
    ^C
    --- 192.168.50.211 ping statistics ---
    5 packets transmitted, 0 received,  4 errors, 100% packet loss, time 4001ms

    部署?example-layer2-config.yaml?文件

    $ kubectl apply -f example-layer2-config.yaml

    部署应用服务测试

    $ wget https://raw.githubusercontent.com/google/metallb/master/manifests/tutorial-2.yaml
    $ kubectl apply -f tutorial-2.yaml

    查看 yaml 文件配置,包含了一个 deployment 和一个 LoadBalancer 类型的 service,默认即可;

    查看 service 分配的 EXTERNAL-IP

    [root@lee ~]# kubectl get svc -owide
    NAME               TYPE             CLUSTER-IP     EXTERNAL-IP         PORT(S)        AGE   SELECTOR
    nginx           LoadBalancer   10.0.228.36      192.168.50.211     80:31796/TCP        65s   app=nginx

    ping 该 EXTERNAL-IP 地址,发现该地址可以访问了

    [root@lee ~]# ping 192.168.50.211
    PING 192.168.50.211 (192.168.50.211) 56(84) bytes of data.
    64 bytes from 192.168.50.211: icmp_seq=1 ttl=64 time=0.050 ms
    64 bytes from 192.168.50.211: icmp_seq=2 ttl=64 time=0.082 ms
    64 bytes from 192.168.50.211: icmp_seq=3 ttl=64 time=0.068 ms

    集群内访问该?EXTERNAL-IP?地址

    [root@lee ~]# curl 192.168.50.211
    ...............

    Thank you for using nginx.

    从集群外访问该 IP 地址

    Administrator at 16:47:09 / $ curl 192.168.50.211
      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
      100   612  100   612    0     0   597k      0 --:--:-- --:--:-- --:--:--  597k
    ................

    Thank you for using nginx.

    另外使用 Node IP NodePort 也可以访问

    Administrator at 16:47:09 / $ curl 192.168.50.124:31796
      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
      100   612  100   612    0     0   597k      0 --:--:-- --:--:-- --:--:--  597k
    ................

    Thank you for using nginx.

Work Blog » k8s入门篇二(部署Metallb 用户的负载均衡支持)
分享到:
赞(1) 打赏

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏