×

作为集群管理员,当您添加类型为LoadBalancer的服务时,您可以控制 MetalLB 如何分配 IP 地址。

请求特定 IP 地址

与其他一些负载均衡器实现一样,MetalLB 接受服务规范中的spec.loadBalancerIP字段。

如果请求的 IP 地址在任何地址池的范围内,MetalLB 将分配请求的 IP 地址。如果请求的 IP 地址不在任何范围内,MetalLB 将报告警告。

特定 IP 地址的服务 YAML 示例
apiVersion: v1
kind: Service
metadata:
  name: <service_name>
  annotations:
    metallb.universe.tf/address-pool: <address_pool_name>
spec:
  selector:
    <label_key>: <label_value>
  ports:
    - port: 8080
      targetPort: 8080
      protocol: TCP
  type: LoadBalancer
  loadBalancerIP: <ip_address>

如果 MetalLB 无法分配请求的 IP 地址,则服务的EXTERNAL-IP将报告<pending>,并且运行oc describe service <service_name>将包含以下示例事件。

MetalLB 无法分配请求的 IP 地址时的示例事件
  ...
Events:
  Type     Reason            Age    From                Message
  ----     ------            ----   ----                -------
  Warning  AllocationFailed  3m16s  metallb-controller  Failed to allocate IP for "default/invalid-request": "4.3.2.1" is not allowed in config

从特定池请求 IP 地址

要从特定范围分配 IP 地址,但您不关心具体的 IP 地址,则可以使用metallb.universe.tf/address-pool注释来请求来自指定地址池的 IP 地址。

来自特定池的 IP 地址的服务 YAML 示例
apiVersion: v1
kind: Service
metadata:
  name: <service_name>
  annotations:
    metallb.universe.tf/address-pool: <address_pool_name>
spec:
  selector:
    <label_key>: <label_value>
  ports:
    - port: 8080
      targetPort: 8080
      protocol: TCP
  type: LoadBalancer

如果您为<address_pool_name>指定的地址池不存在,MetalLB 将尝试从任何允许自动分配的池中分配 IP 地址。

接受任何 IP 地址

默认情况下,地址池配置为允许自动分配。MetalLB 将从这些地址池分配 IP 地址。

要接受来自任何配置为自动分配的池的任何 IP 地址,不需要特殊的注释或配置。

接受任何 IP 地址的服务 YAML 示例
apiVersion: v1
kind: Service
metadata:
  name: <service_name>
spec:
  selector:
    <label_key>: <label_value>
  ports:
    - port: 8080
      targetPort: 8080
      protocol: TCP
  type: LoadBalancer

共享特定 IP 地址

默认情况下,服务不共享 IP 地址。但是,如果您需要将服务位于单个 IP 地址上,则可以通过向服务添加metallb.universe.tf/allow-shared-ip注释来启用选择性 IP 共享。

apiVersion: v1
kind: Service
metadata:
  name: service-http
  annotations:
    metallb.universe.tf/address-pool: doc-example
    metallb.universe.tf/allow-shared-ip: "web-server-svc"  (1)
spec:
  ports:
    - name: http
      port: 80  (2)
      protocol: TCP
      targetPort: 8080
  selector:
    <label_key>: <label_value>  (3)
  type: LoadBalancer
  loadBalancerIP: 172.31.249.7  (4)
---
apiVersion: v1
kind: Service
metadata:
  name: service-https
  annotations:
    metallb.universe.tf/address-pool: doc-example
    metallb.universe.tf/allow-shared-ip: "web-server-svc"
spec:
  ports:
    - name: https
      port: 443
      protocol: TCP
      targetPort: 8080
  selector:
    <label_key>: <label_value>
  type: LoadBalancer
  loadBalancerIP: 172.31.249.7
1 metallb.universe.tf/allow-shared-ip注释指定相同的值。此值称为*共享密钥*。
2 为服务指定不同的端口号。
3 如果您必须指定externalTrafficPolicy: local,则指定相同的 Pod 选择器,以便服务将流量发送到同一组 Pod。如果您使用cluster外部流量策略,则 Pod 选择器不必相同。
4 可选:如果您指定了上述三个项目,MetalLB 可能会将服务位于同一 IP 地址上。为了确保服务共享 IP 地址,请指定要共享的 IP 地址。

默认情况下,Kubernetes 不允许多协议负载均衡器服务。此限制通常会使运行需要同时监听 TCP 和 UDP 的服务(如 DNS)成为不可能。为了解决 Kubernetes 与 MetalLB 的此限制,请创建两个服务

  • 对于一项服务,指定 TCP;对于第二项服务,指定 UDP。

  • 在两项服务中,指定相同的 Pod 选择器。

  • 指定相同的共享密钥和spec.loadBalancerIP值,以将 TCP 和 UDP 服务位于同一 IP 地址上。

使用 MetalLB 配置服务

您可以将负载均衡服务配置为使用地址池中的外部 IP 地址。

先决条件
  • 安装 OpenShift CLI (oc)。

  • 安装 MetalLB Operator 并启动 MetalLB。

  • 配置至少一个地址池。

  • 配置您的网络,以便将客户端流量路由到集群的主机网络。

步骤
  1. 创建一个<service_name>.yaml文件。在文件中,确保spec.type字段设置为LoadBalancer

    请参考示例,了解如何请求 MetalLB 分配给服务的外部 IP 地址。

  2. 创建服务

    $ oc apply -f <service_name>.yaml
    示例输出
    service/<service_name> created
验证
  • 描述服务

    $ oc describe service <service_name>
    示例输出
    Name:                     <service_name>
    Namespace:                default
    Labels:                   <none>
    Annotations:              metallb.universe.tf/address-pool: doc-example  (1)
    Selector:                 app=service_name
    Type:                     LoadBalancer  (2)
    IP Family Policy:         SingleStack
    IP Families:              IPv4
    IP:                       10.105.237.254
    IPs:                      10.105.237.254
    LoadBalancer Ingress:     192.168.100.5  (3)
    Port:                     <unset>  80/TCP
    TargetPort:               8080/TCP
    NodePort:                 <unset>  30550/TCP
    Endpoints:                10.244.0.50:8080
    Session Affinity:         None
    External Traffic Policy:  Cluster
    Events:  (4)
      Type    Reason        Age                From             Message
      ----    ------        ----               ----             -------
      Normal  nodeAssigned  32m (x2 over 32m)  metallb-speaker  announcing from node "<node_name>"
    1 如果您请求来自特定池的 IP 地址,则会显示此注释。
    2 服务类型必须指示LoadBalancer
    3 如果服务分配正确,则负载均衡器入口字段将指示外部 IP 地址。
    4 事件字段指示分配用于公告外部 IP 地址的节点名称。如果遇到错误,事件字段将指示错误原因。