配置负载平衡涉及配置 Kubernetes LoadBalancer 服务或 Ingress 资源以及 NCP 复制控制器。

可以通过配置类型为 LoadBalancer 的 Kubernetes 服务创建第 4 层负载平衡器,通过配置 Kubernetes Ingress 资源创建第 7 层负载平衡器。

要在 NCP 中配置负载平衡,请在 ncp-rc.yml 文件中:

  1. 设置 use_native_loadbalancer = True
  2. (可选)将 pool_algorithm 设置为 ROUND_ROBINLEAST_CONNECTION/IP_HASH。默认值为 ROUND_ROBIN
  3. (可选)将 service_size 设置为 SMALLMEDIUMLARGE。默认值为 SMALL

LEAST_CONNECTION/IP_HASH 算法意味着来自同一源 IP 地址的流量将被发送到相同的后端 pod。

有关不同大小的 NSX-T 负载平衡器支持内容的详细信息,请参见《NSX-T Data Center 管理指南》

创建负载平衡器后,无法通过更新配置文件来更改负载平衡器大小,但是可以通过 NSX Manager UI 或 API 进行更改。

设置第 4 层和第 7 层负载平衡的持久性

可以在 NCP ConfigMap 中使用参数 l4_persistencel7_persistence 指定持久性设置。可用于设置第 4 层持久性的选项为源 IP。可用于设置第 7 层持久性的选项为 cookie 和源 IP。默认值为 <None>。例如,
   # Choice of persistence type for ingress traffic through L7 Loadbalancer.
   # Accepted values:
   # 'cookie'
   # 'source_ip'
   l7_persistence = cookie

   # Choice of persistence type for ingress traffic through L4 Loadbalancer.
   # Accepted values:
   # 'source_ip'
   l4_persistence = source_ip

对于 Kubernetes LoadBalancer 服务,如果禁用了全局第 4 层持久性(即 l4_persistence 设置为 <None>),您还可以在服务规范上指定 sessionAffinity 以配置服务持久性行为。如果 l4_persistence 设置为 source_ip,则可以使用服务规范上的 sessionAffinity 自定义服务持久性超时。默认第 4 层持久性超时为 10800 秒,与 Kubernetes 文档 (https://kubernetes.io/docs/concepts/services-networking/service) 中指定的服务超时相同。具有默认持久性超时的所有服务将使用相同的 NSX-T 负载平衡器持久性配置文件。将为每个具有非默认持久性超时的服务创建专用的配置文件。

注: 如果 Ingress 的后端服务的服务类型为 LoadBalancer,则该服务的第 4 层虚拟服务器和 Ingress 的第 7 层虚拟服务器不能具有不同的持久性设置,例如,对于第 4 层,采用 source_ip,而对于第 7 层,采用 cookie。在这种情况下,这两个虚拟服务器的持久性设置必须相同( source_ipcookieNone),或者其中一个为 None(另一个的设置可以为 source_ipcookie)。下面列出了这种情况的一个示例:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: cafe-ingress
spec:
  rules:
  - host: cafe.example.com
    http:
      paths:
      - path: /tea
        backend:
          serviceName: tea-svc
          servicePort: 80
-----
apiVersion: v1
kind: Service
metadata:
  name: tea-svc <==== same as the Ingress backend above
  labels:
    app: tea
spec:
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
    name: tcp
  selector:
    app: tea
  type: LoadBalancer

Ingress

  • NSX-T Data Center 将分别为具有 TLS 规范和不具有 TLS 规范的 Ingress 创建一个第 7 层负载平衡器。
  • 所有 Ingress 都将获得单个 IP 地址。
  • ncp.ini[nsx_v3] 部分中的 external_ip_pools 选项指定的外部 IP 池为 Ingress 资源分配 IP 地址。将在此 IP 地址以及 HTTP 端口 80 和 HTTPS 端口 443 上公开负载平衡器。
  • ncp.ini[nsx_v3] 部分中的 external_ip_pools_lb 选项指定的外部 IP 池为 Ingress 资源分配 IP 地址。如果 external_ip_pools_lb 选项不存在,则使用 external_ip_pools 指定的池。将在此 IP 地址以及 HTTP 端口 80 和 HTTPS 端口 443 上公开负载平衡器。
  • 可以通过更改配置并重新启动 NCP 来更改为不同的 IP 池。
  • 可以为 TLS 指定默认证书。有关生成证书并将证书挂载到 NCP pod 的信息,请参见下文。
  • 将在 HTTP 虚拟服务器(端口 80)上托管不具有 TLS 规范的 Ingress。
  • 将在 HTTPS 虚拟服务器(端口 443)上托管具有 TLS 规范的 Ingress。负载平衡器将充当 SSL 服务器并终止客户端 SSL 连接。
  • 密钥和 Ingress 的创建顺序无关紧要。如果存在密钥对象且该对象正由某个 Ingress 引用,则将在 NSX-T Data Center 中导入证书。如果删除了密钥或删除了引用该密钥的最后一个 Ingress,则将删除与该密钥对应的证书。
  • 支持通过添加或移除 TLS 区域来修改 Ingress。从 Ingress 规范中移除 tls 密钥后,Ingress 规则将从 HTTPS 虚拟服务器(端口 443)传输到 HTTP 虚拟服务器(端口 80)。同样,将 tls 密钥添加到 Ingress 规范后,Ingress 规则将从 HTTP 虚拟服务器(端口 80)传输到 HTTPS 虚拟服务器(端口 443)。
  • 如果单个群集的 Ingress 定义中存在重复的规则,则只会应用第一个规则。
  • 每个群集只支持一个具有默认后端的 Ingress。不匹配任何 Ingress 规则的流量将被转发到默认后端。
  • 如果存在多个具有默认后端的 Ingress,则只会配置第一个输入。其他 Ingress 将被注释为出现错误。
  • 使用正则表达式字符“.”和“*”支持 URI 通配符匹配。例如,路径“/coffee/.*”匹配“/coffee/”及后跟零个、一个或多个字符,如“/coffee/”、“/coffee/a”、“/coffee/b”,但不匹配“/coffee”、“/coffeecup”或“/coffeecup/a”。
    Ingress 规范示例:
    kind: Ingress
    metadata:
      name: cafe-ingress
    spec:
      rules:
      - http:
          paths:
          - path: /coffee/.*    #Matches /coffee/, /coffee/a but NOT /coffee, /coffeecup, etc.
            backend:
              serviceName: coffee-svc
              servicePort: 80
  • 您可以通过将注释添加到 Ingress 资源来配置 URL 请求重写。例如,
    kind: Ingress
    metadata:
      name: cafe-ingress
      annotations:
        ingress.kubernetes.io/rewrite-target: /
    spec:
      rules:
      - host: cafe.example.com
        http:
          paths:
          - path: /tea
            backend:
              serviceName: tea-svc
              servicePort: 80
          - path: /coffee
            backend:
              serviceName: coffee-svc
              servicePort: 80

    路径 /tea/coffee 将在 URL 发送到后端服务之前重写到 /

  • 支持 Ingress 注释 kubernetes.io/ingress.allow-http
    • 如果注释设置为 false,将仅创建 HTTPS 规则。
    • 如果注释设置为 true 或缺失,将创建 HTTP 规则。此外,如果 Ingress 规范中存在 TLS 部分,则将创建 HTTPS 规则。
  • 错误作为注释添加到 Ingress 资源中。错误键为 ncp/error.loadbalancer,警告键为 ncp/warning.loadbalancer。可能的错误和警告包括:
    • ncp/error.loadbalancer: DEFAULT_BACKEND_IN_USE

      该错误表示具有默认后端的 Ingress 已存在。Ingress 将处于非活动状态。无论是否使用 TLS,对于一组 Ingress 而言,只能有一个默认后端。要解决此错误,请删除 Ingress 并使用正确的规范重新创建。

    • ncp/warning.loadbalancer: SECRET_NOT_FOUND

      该错误表示 Ingress 规范中指定的密钥不存在。Ingress 将部分处于活动状态。要解决此错误,请创建缺少的密钥。请注意,警告出现在注释中后,不会在 Ingress 资源的生命周期内将其清除。

    • ncp/warning.loadbalancer: INVALID_INGRESS
      此错误表示以下条件之一成立。Ingress 将处于非活动状态。要解决此错误,请删除 Ingress 并使用正确的规范重新创建。
      • Ingress 规则与同一 Kubernetes 群集中的另一 Ingress 规则冲突。
      • allow-http 注释设置为 False,且 Ingress 没有 TLS 区域。
      • Ingress 规则未指定 hostpath。此类 Ingress 规则具有与 Ingress 默认后端相同的功能。请改用 Ingress 默认后端。

类型为 LoadBalancer 的服务

  • NSX-T Data Center 将为每个服务端口创建一个第 4 层负载平衡器虚拟服务器和池。
  • TCP 和 UDP 均受支持。
  • 每个服务都将有一个唯一的 IP 地址。
  • 根据 LoadBalancer 定义中的 loadBalancerIP 字段,将从外部 IP 池中为服务分配一个 IP 地址。loadBalancerIP 字段可以为空,具有 IP 地址或具有 IP 池的名称或 ID。如果 loadBalancerIP 字段为空,则从 ncp.ini[nsx_v3] 部分中的 external_ip_pools_lb 选项指定的外部 IP 池中分配 IP。如果 external_ip_pools_lb 选项不存在,则使用 external_ip_pools 指定的池。将在此 IP 地址和服务端口上公开 LoadBalancer 服务。
  • 可以通过更改配置并重新启动 NCP 来更改为不同的 IP 池。
  • loadBalancerIP 指定的 IP 池必须具有标记 {"ncp/owner": cluster:<cluster>}

  • 错误作为注释添加到服务中。错误键为 ncp/error.loadbalancer。可能的错误包括:
    • ncp/error.loadbalancer: IP_POOL_NOT_FOUND

      该错误表示指定了 loadBalancerIP: <nsx-ip-pool>,但 <nsx-ip-pool> 不存在。服务将处于非活动状态。要解决此错误,请指定有效的 IP 池,然后删除并重新创建该服务。

    • ncp/error.loadbalancer: IP_POOL_EXHAUSTED

      该错误表示指定了 loadBalancerIP: <nsx-ip-pool>,但 IP 池已用尽其 IP 地址。服务将处于非活动状态。要解决此错误,请指定包含可用 IP 地址的 IP 池,然后删除并重新创建该服务。

    • ncp/error.loadbalancer: IP_POOL_NOT_UNIQUE

      此错误表示多个 IP 池具有 loadBalancerIP: <nsx-ip-pool> 指定的名称。服务将处于非活动状态。

    • ncp/error.loadbalancer: POOL_ACCESS_DENIED

      此错误表示 loadBalancerIP 指定的 IP 池不具有标记 {"ncp/owner": cluster:<cluster>} 或标记中指定的群集与 Kubernetes 群集的名称不匹配。

    • ncp/error.loadbalancer: LB_VIP_CONFLICT

      此错误表示 loadBalancerIP 字段中的 IP 与活动服务的 IP 相同。服务将处于非活动状态。

  • 支持自动缩放第 4 层负载平衡器。如果创建或修改 Kubernetes LoadBalancer 服务以便需要更多的虚拟服务器,而现有的第 4 层负载平衡器没有足够的容量,将创建新的第 4 层负载平衡器。NCP 也将删除不再连接虚拟服务器的第 4 层负载平衡器。默认情况下,将启用该功能。可以通过在 NCP ConfigMap 中将 l4_lb_auto_scaling 设置为 false 禁用此功能。

负载平衡器和网络策略

将流量从 NSX 负载平衡器虚拟服务器转发到 pod 时,源 IP 是 Tier-1 路由器上行链路端口的 IP 地址。此地址位于专用的 Tier-1 传输网络中,可能会导致基于 CIDR 的网络策略禁止本应允许的流量。要避免出现此问题,必须配置网络策略以使 Tier-1 路由器上行链路端口的 IP 地址包含在允许的 CIDR 块中。该内部 IP 地址将显示在 status.loadbalancer.ingress.ip 字段中,并在 Ingress 资源上显示为注释 (ncp/internal_ip_for_policy)。

例如,如果虚拟服务器的外部 IP 地址是 4.4.0.5,内部 Tier-1 路由器的上行链路端口的 IP 地址为 100.64.224.11,则状态为:
    status:
      loadBalancer:
      ingress:
      - ip: 4.4.0.5
      - ip: 100.64.224.11
Ingress 资源和 LoadBalancer 类型服务资源上的注释为:
    ncp/internal_ip_for_policy: 100.64.224.11
IP 地址 100.64.224.11 必须属于网络策略的 ipBlock 选择器中允许的 CIDR。例如,
    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    ...
    ingress:
    - from:
      - ipBlock:
         cidr: 100.64.224.11/32

用于生成 CA 签名证书的示例脚本

以下脚本可分别生成存储在文件 <filename>.crt 和 <finename>.key 中的 CA 签名证书和私钥。 genrsa 命令可生成 CA 密钥。应对 CA 密钥进行加密。您可以使用 aes256 等命令指定加密方法。
#!/bin/bash
host="www.example.com"
filename=server

openssl genrsa -out ca.key 4096
openssl req -key ca.key -new -x509 -days 365 -sha256 -extensions v3_ca -out ca.crt -subj "/C=US/ST=CA/L=Palo Alto/O=OS3/OU=Eng/CN=${host}"
openssl req -out ${filename}.csr -new -newkey rsa:2048 -nodes -keyout ${filename}.key -subj "/C=US/ST=CA/L=Palo Alto/O=OS3/OU=Eng/CN=${host}"
openssl x509 -req -days 360 -in ${filename}.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out ${filename}.crt -sha256

将默认证书和密钥挂载到 NCP Pod 中

生成证书和私钥后,请将其置于主机虚拟机上的目录 /etc/nsx-ujo 中。假设证书文件和密钥文件分别命名为 lb-default.crtlb-default.key,请编辑 ncp-rc.yaml 以便主机上的这些文件挂载到 pod 中。例如,
spec:
  ...
  containers:
  - name: nsx-ncp
    ...
    volumeMounts:
    ...
    - name: lb-default-cert
      # Mount path must match nsx_v3 option "lb_default_cert_path"
      mountPath: /etc/nsx-ujo/lb-default.crt
    - name: lb-priv-key
      # Mount path must match nsx_v3 option "lb_priv_key_path"
      mountPath: /etc/nsx-ujo/lb-default.key
  volumes:
  ...
  - name: lb-default-cert
    hostPath:
      path: /etc/nsx-ujo/lb-default.crt
  - name: lb-priv-key
    hostPath:
      path: /etc/nsx-ujo/lb-default.key