Ingress 和负载均衡


OpenShift Container Platform 4.20

在 OpenShift Container Platform 中公开服务并管理外部流量

Red Hat OpenShift Documentation Team

摘要

本文档介绍如何配置路由、管理入口流量,并在 OpenShift Container Platform 中实施各种负载均衡解决方案。

第 1 章 配置路由

1.1. 路由配置

1.1.1. 创建基于 HTTP 的路由

创建一个路由,以通过公共 URL 托管您的应用程序。根据应用程序的网络安全配置,路由可以是安全的或不受保护的。基于 HTTP 的路由是一个不受保护的路由,它使用基本的 HTTP 路由协议,并在未安全的应用程序端口上公开服务。

以下流程描述了如何使用 hello-openshift 应用程序创建基于 HTTP 的简单路由,作为示例。

前提条件

  • 已安装 OpenShift CLI(oc)。
  • 以管理员身份登录。
  • 您有一个 web 应用,用于公开端口和侦听端口上流量的 TCP 端点。

流程

  1. 运行以下命令,创建一个名为 hello-openshift 的项目:

    $ oc new-project hello-openshift
    Copy to Clipboard Toggle word wrap
  2. 运行以下命令,在项目中创建 pod:

    $ oc create -f https://raw.githubusercontent.com/openshift/origin/master/examples/hello-openshift/hello-pod.json
    Copy to Clipboard Toggle word wrap
  3. 运行以下命令,创建名为 hello-openshift 的服务:

    $ oc expose pod/hello-openshift
    Copy to Clipboard Toggle word wrap
  4. 运行以下命令,创建一个没有安全安全的路由到 hello-openshift 应用程序:

    $ oc expose svc hello-openshift
    Copy to Clipboard Toggle word wrap

验证

  • 要验证您创建的路由资源,请运行以下命令:

    $ oc get routes -o yaml <name of resource> 
    1
    Copy to Clipboard Toggle word wrap
    1
    在本例中,路由名为 hello-openshift

创建的未安全路由的 YAML 定义示例

apiVersion: route.openshift.io/v1
kind: Route
metadata:
  name: hello-openshift
spec:
  host: www.example.com 
1

  port:
    targetPort: 8080 
2

  to:
    kind: Service
    name: hello-openshift
Copy to Clipboard Toggle word wrap

1
host 字段是指向该服务的别名 DNS 记录。此字段可以是任何有效的 DNS 名称,如 www.example.com。DNS 名称必须遵循 DNS952 子域惯例。如果没有指定,则会自动生成路由名称。
2
targetPort 字段是由此路由指向的服务选择的 pod 上的目标端口。
注意

要显示您的默认入口域,请运行以下命令:

$ oc get ingresses.config/cluster -o jsonpath={.spec.domain}
Copy to Clipboard Toggle word wrap

1.1.2. 为 Ingress Controller 分片创建路由

通过使用路由,您可以通过 URL 托管应用程序。Ingress Controller 分片有助于在一组 Ingress Controller 之间平衡传入的流量负载。它还可以将流量隔离到特定的 Ingress Controller。例如,A 公司的流量使用一个 Ingress Controller,B 公司的流量则使用另外一个 Ingress Controller。

以下流程描述了如何为 Ingress Controller 分片创建路由,使用 hello-openshift 应用程序作为示例。

先决条件

  • 已安装 OpenShift CLI(oc)。
  • 您以项目管理员身份登录。
  • 您有一个 web 应用来公开端口,以及侦听端口流量的 HTTP 或 TLS 端点。
  • 您已为分片配置了 Ingress Controller。

流程

  1. 运行以下命令,创建一个名为 hello-openshift 的项目:

    $ oc new-project hello-openshift
    Copy to Clipboard Toggle word wrap
  2. 运行以下命令,在项目中创建 pod:

    $ oc create -f https://raw.githubusercontent.com/openshift/origin/master/examples/hello-openshift/hello-pod.json
    Copy to Clipboard Toggle word wrap
  3. 运行以下命令,创建名为 hello-openshift 的服务:

    $ oc expose pod/hello-openshift
    Copy to Clipboard Toggle word wrap
  4. 创建名为 hello-openshift-route.yaml 的路由定义:

    为分片创建的路由的 YAML 定义

    apiVersion: route.openshift.io/v1
    kind: Route
    metadata:
      labels:
        type: sharded 
    1
    
      name: hello-openshift-edge
      namespace: hello-openshift
    spec:
      subdomain: hello-openshift 
    2
    
      tls:
        termination: edge
      to:
        kind: Service
        name: hello-openshift
    Copy to Clipboard Toggle word wrap

    1
    标签键及其对应标签值必须与 Ingress Controller 中指定的标签值匹配。在本例中,Ingress Controller 具有标签键和值 type: sharded
    2
    路由将使用 subdomain 字段的值公开。指定 subdomain 字段时,您必须保留主机名未设置。如果您同时指定了 hostsubdomain 字段,则路由将使用 host 字段的值,并忽略 subdomain 字段。
  5. 通过运行以下命令,使用 hello-openshift-route.yaml 创建到 hello-openshift 应用程序的路由:

    $ oc -n hello-openshift create -f hello-openshift-route.yaml
    Copy to Clipboard Toggle word wrap

验证

  • 使用以下命令获取路由的状态:

    $ oc -n hello-openshift get routes/hello-openshift-edge -o yaml
    Copy to Clipboard Toggle word wrap

    生成的 Route 资源应类似以下示例:

    输出示例

    apiVersion: route.openshift.io/v1
    kind: Route
    metadata:
      labels:
        type: sharded
      name: hello-openshift-edge
      namespace: hello-openshift
    spec:
      subdomain: hello-openshift
      tls:
        termination: edge
      to:
        kind: Service
        name: hello-openshift
    status:
      ingress:
      - host: hello-openshift.<apps-sharded.basedomain.example.net> 
    1
    
        routerCanonicalHostname: router-sharded.<apps-sharded.basedomain.example.net> 
    2
    
        routerName: sharded 
    3
    Copy to Clipboard Toggle word wrap

    1
    Ingress Controller 或路由器的主机名用于公开路由。host 字段的值由 Ingress Controller 自动决定,并使用它的域。在本例中,Ingress Controller 的域为 <apps-sharded.basedomain.example.net>
    2
    Ingress Controller 的主机名。如果没有设置主机名,则路由可以使用子域。当您指定子域时,会自动使用公开路由的 Ingress Controller 域。当路由由多个 Ingress Controller 公开时,路由由多个 URL 托管。
    3
    Ingress Controller 的名称。在本例中,Ingress Controller 的名称为 sharded

1.1.3. 配置路由超时

如果您的服务需要低超时(满足服务级别可用性 (SLA) 目的)或高超时(具有慢速后端的情况),您可以为现有路由配置默认超时。

重要

如果您在 OpenShift Container Platform 集群前面配置了用户管理的外部负载均衡器,请确保用户管理的外部负载均衡器的超时值高于路由的超时值。此配置可防止集群使用的网络的网络出现网络拥塞问题。

先决条件

  • 您需要在运行的集群中部署了 Ingress Controller。

流程

  • 使用 oc annotate 命令,为路由添加超时:

    $ oc annotate route <route_name> \
        --overwrite haproxy.router.openshift.io/timeout=<timeout><time_unit> 
    1
    Copy to Clipboard Toggle word wrap
    1
    支持的时间单位是微秒 (us)、毫秒 (ms)、秒钟 (s)、分钟 (m)、小时 (h)、或天 (d)。

    以下示例在名为 myroute 的路由上设置两秒的超时:

    $ oc annotate route myroute --overwrite haproxy.router.openshift.io/timeout=2s
    Copy to Clipboard Toggle word wrap

1.1.4. HTTP 严格传输安全性

HTTP 严格传输安全性 (HSTS) 策略是一种安全增强,向浏览器客户端发送信号,表示路由主机上仅允许 HTTPS 流量。HSTS 也通过信号 HTTPS 传输来优化 Web 流量,无需使用 HTTP 重定向。HSTS 对于加快与网站的交互非常有用。

强制 HSTS 策略时,HSTS 会向站点的 HTTP 和 HTTPS 响应添加 Strict Transport Security 标头。您可以在路由中使用 insecureEdgeTerminationPolicy 值,以将 HTTP 重定向到 HTTPS。强制 HSTS 时,客户端会在发送请求前将所有请求从 HTTP URL 更改为 HTTPS,无需重定向。

集群管理员可将 HSTS 配置为执行以下操作:

  • 根据每个路由启用 HSTS
  • 根据每个路由禁用 HSTS
  • 对一组域强制每个域的 HSTS,或者结合使用命名空间标签与域
重要

HSTS 仅适用于安全路由,可以是 edge-terminated 或 re-encrypt。其配置在 HTTP 或传递路由上无效。

HTTP 严格传输安全 (HSTS) 实施在 HAProxy 模板中,并应用到具有 haproxy.router.openshift.io/hsts_header 注解的边缘和重新加密路由。

前提条件

  • 您可以使用具有项目的管理员特权的用户登陆到集群。
  • 已安装 OpenShift CLI(oc)。

流程

  • 要在路由上启用 HSTS,请将 haproxy.router.openshift.io/hsts_header 值添加到 edge-terminated 或 re-encrypt 路由中。您可以运行以下命令来使用 oc annotate 工具来实现此目的:要正确运行,请确保 haproxy.router.openshift.io/hsts_header 路由注解中的分号(;)也用双引号("")括起来。

    将最长期限设置为 31536000 ms 的 annotate 命令示例(大约 8.5 小时)

    $ oc annotate route <route_name> -n <namespace> --overwrite=true "haproxy.router.openshift.io/hsts_header=max-age=31536000;\
    includeSubDomains;preload"
    Copy to Clipboard Toggle word wrap

    配置了注解的路由示例

    apiVersion: route.openshift.io/v1
    kind: Route
    metadata:
      annotations:
        haproxy.router.openshift.io/hsts_header: max-age=31536000;includeSubDomains;preload 
    1
     
    2
     
    3
    
    # ...
    spec:
      host: def.abc.com
      tls:
        termination: "reencrypt"
        ...
      wildcardPolicy: "Subdomain"
    # ...
    Copy to Clipboard Toggle word wrap

    1
    必需。Max-age 测量 HSTS 策略生效的时间长度,以秒为单位。如果设置为 0,它将对策略进行求反。
    2
    可选。包含时,includeSubDomains 告知客户端主机的所有子域都必须与主机具有相同的 HSTS 策略。
    3
    可选。当 max-age 大于 0 时,您可以在 haproxy.router.openshift.io/hsts_header 中添加 preload,以允许外部服务将这个站点包括在 HSTS 预加载列表中。例如,Google 等站点可以构造设有 preload 的站点的列表。浏览器可以使用这些列表来确定哪些站点可以通过 HTTPS 通信,即使它们与站点交互之前也是如此。如果没有设置 preload,浏览器必须已经通过 HTTPS 与站点交互(至少一次)才能获取标头。

要禁用 HTTP 严格传输安全性 (HSTS),您可以将路由注解中的 max-age 值设置为 0

前提条件

  • 您可以使用具有项目的管理员特权的用户登陆到集群。
  • 已安装 OpenShift CLI(oc)。

流程

  • 要禁用 HSTS,请输入以下命令将路由注解中的 max-age 值设置为 0

    $ oc annotate route <route_name> -n <namespace> --overwrite=true "haproxy.router.openshift.io/hsts_header"="max-age=0"
    Copy to Clipboard Toggle word wrap
    提示

    您还可以应用以下 YAML 来创建配置映射:

    根据每个路由禁用 HSTS 的示例

    metadata:
      annotations:
        haproxy.router.openshift.io/hsts_header: max-age=0
    Copy to Clipboard Toggle word wrap

  • 要为命名空间中的所有路由禁用 HSTS,请输入以下命令:

    $ oc annotate route --all -n <namespace> --overwrite=true "haproxy.router.openshift.io/hsts_header"="max-age=0"
    Copy to Clipboard Toggle word wrap

验证

  • 要查询所有路由的注解,请输入以下命令:

    $ oc get route  --all-namespaces -o go-template='{{range .items}}{{if .metadata.annotations}}{{$a := index .metadata.annotations "haproxy.router.openshift.io/hsts_header"}}{{$n := .metadata.name}}{{with $a}}Name: {{$n}} HSTS: {{$a}}{{"\n"}}{{else}}{{""}}{{end}}{{end}}{{end}}'
    Copy to Clipboard Toggle word wrap

    输出示例

    Name: routename HSTS: max-age=0
    Copy to Clipboard Toggle word wrap

1.1.4.3. 强制每个域 HTTP 严格传输安全性

要为安全路由强制实施 HTTP Strict Transport Security (HSTS),在 Ingress spec 中添加 requiredHSTSPolicies 记录来捕获 HSTS 策略的配置。

如果您将 requiredHSTSPolicy 配置为强制 HSTS,则任何新创建的路由都必须配置有兼容的 HSTS 策略注解。

注意

要使用不合规的 HSTS 路由处理升级的集群,您可以在源更新清单并应用更新。

注意

您无法使用 oc expose routeoc create route 命令在强制 HSTS 的域中添加路由,因为这些命令的 API 不接受注解。

重要

HSTS 无法应用到不安全或非 TLS 路由,即使 HSTS 全局请求了 HSTS。

先决条件

  • 您可以使用具有项目的管理员特权的用户登陆到集群。
  • 已安装 OpenShift CLI(oc)。

流程

  1. 运行以下命令来编辑 Ingress 配置 YAML,并根据需要更新字段:

    $ oc edit ingresses.config.openshift.io/cluster
    Copy to Clipboard Toggle word wrap

    HSTS 策略示例

    apiVersion: config.openshift.io/v1
    kind: Ingress
    metadata:
      name: cluster
    spec:
      domain: 'hello-openshift-default.apps.username.devcluster.openshift.com'
      requiredHSTSPolicies: 
    1
    
      - domainPatterns: 
    2
    
        - '*hello-openshift-default.apps.username.devcluster.openshift.com'
        - '*hello-openshift-default2.apps.username.devcluster.openshift.com'
        namespaceSelector: 
    3
    
          matchLabels:
            myPolicy: strict
        maxAge: 
    4
    
          smallestMaxAge: 1
          largestMaxAge: 31536000
        preloadPolicy: RequirePreload 
    5
    
        includeSubDomainsPolicy: RequireIncludeSubDomains 
    6
    
      - domainPatterns:
        - 'abc.example.com'
        - '*xyz.example.com'
        namespaceSelector:
          matchLabels: {}
        maxAge: {}
        preloadPolicy: NoOpinion
        includeSubDomainsPolicy: RequireNoIncludeSubDomains
    Copy to Clipboard Toggle word wrap

    1
    必需。requiredHSTSPolicies 会被按顺序验证,并应用第一个匹配的 domainPatterns
    2
    必需。您必须至少指定一个 domainPatterns 主机名。可以列出任意数量的域。您可以为不同的 domainPatterns 包括多个强制选项部分。
    3
    可选。如果包含 namespaceSelector,它必须与路由所在项目的标签匹配,以便在路由上强制执行设定 HSTS 策略。仅与 namespaceSelector 而不是 domainPatterns 匹配的路由不会被验证。
    4
    必需。Max-age 测量 HSTS 策略生效的时间长度,以秒为单位。此策略设置允许强制实施最小和最大的 max-age
    • largestMaxAge 值必须在 02147483647 之间。它可以不指定,这意味着不强制实施上限。
    • smallestMaxAge 值必须在 02147483647 之间。输入 0 来禁用 HSTS 以进行故障排除,或者如果您不需要禁用 HSTS,输入 1。它可以不知道,这意味着不强制实施较低限制。
    5
    可选。在 haproxy.router.openshift.io/hsts_header 中包含 preload 会使外部服务将此站点包括在 HSTS 预加载列表中。浏览器可以使用这些列表来决定哪些站点可通过 HTTPS 进行通信,然后再与站点交互。如果没有设置 preload,浏览器需要至少与站点交互一次,才能获取该标头。可使用以下方法之一设置 preload
    • RequirePreloadRequiredHSTSPolicy 需要 preload
    • RequireNoPreload:preloadRequiredHSTSPolicy 禁止。
    • NoOpinionpreloadRequiredHSTSPolicy 没有关系。
    6
    可选。includeSubDomainsPolicy 可使用以下之一设置:
    • RequireIncludeSubDomains: RequiredHSTSPolicy 需要 includeSubDomains
    • RequireNoIncludeSubDomains: includeSubDomainsRequiredHSTSPolicy 禁止。
    • NoOpinion : includeSubDomainsRequiredHSTSPolicy 没有关系。
  2. 您可以通过输入 oc annotate command,将 HSTS 应用到集群或特定命名空间中的所有路由。

    • 要将 HSTS 应用到集群中的所有路由,请输入 oc annotate command。例如:

      $ oc annotate route --all --all-namespaces --overwrite=true "haproxy.router.openshift.io/hsts_header"="max-age=31536000"
      Copy to Clipboard Toggle word wrap
    • 要将 HSTS 应用到特定命名空间中的所有路由,请输入 oc annotate command。例如:

      $ oc annotate route --all -n my-namespace --overwrite=true "haproxy.router.openshift.io/hsts_header"="max-age=31536000"
      Copy to Clipboard Toggle word wrap

验证

您可以查看您配置的 HSTS 策略。例如:

  • 要查看所需的 HSTS 策略的 maxAge 设置,请输入以下命令:

    $ oc get clusteroperator/ingress -n openshift-ingress-operator -o jsonpath='{range .spec.requiredHSTSPolicies[*]}{.spec.requiredHSTSPolicies.maxAgePolicy.largestMaxAge}{"\n"}{end}'
    Copy to Clipboard Toggle word wrap
  • 要查看所有路由上的 HSTS 注解,请输入以下命令:

    $ oc get route  --all-namespaces -o go-template='{{range .items}}{{if .metadata.annotations}}{{$a := index .metadata.annotations "haproxy.router.openshift.io/hsts_header"}}{{$n := .metadata.name}}{{with $a}}Name: {{$n}} HSTS: {{$a}}{{"\n"}}{{else}}{{""}}{{end}}{{end}}{{end}}'
    Copy to Clipboard Toggle word wrap

    输出示例

    Name: <_routename_> HSTS: max-age=31536000;preload;includeSubDomains
    Copy to Clipboard Toggle word wrap

1.1.5. 吞吐量问题的故障排除方法

有时,通过 OpenShift Container Platform 部署的应用程序可能会导致网络吞吐量问题,如特定服务间的延迟异常高。

如果 pod 日志没有显示造成问题的原因,请使用以下方法之一分析性能问题:

  • 使用 pingtcpdump 等数据包分析器,分析 pod 与其节点之间的流量。

    例如,在每个 pod 上运行 tcpdump 工具,同时重现导致问题的行为。检查两端的捕获信息,以便比较发送和接收时间戳来分析与 pod 往来的流量的延迟。如果节点接口被其他 pod、存储设备或者数据平面的流量过载,则 OpenShift Container Platform 中可能会出现延迟。

    $ tcpdump -s 0 -i any -w /tmp/dump.pcap host <podip 1> && host <podip 2> 
    1
    Copy to Clipboard Toggle word wrap
    1
    podip 是 pod 的 IP 地址。运行 oc get pod <pod_name> -o wide 命令来获取 pod 的 IP 地址。

    tcpdump 命令会在 /tmp/dump.pcap 中生成一个包含这两个 pod 间所有流量的文件。您可以在运行分析器后立即重现问题,并在问题重现完成后马上停止分析器,从而尽量减小文件的大小。您还可以使用以下方法在节点间运行数据包分析器

    $ tcpdump -s 0 -i any -w /tmp/dump.pcap port 4789
    Copy to Clipboard Toggle word wrap
  • 使用 iperf 等带宽测量工具来测量流吞吐量和 UDP 吞吐量。首先从 pod 运行该工具,然后从节点运行它,从而找到瓶颈。

  • 在某些情况下,因为延迟问题,集群可能会将带有路由器 pod 的节点标记为不健康。在执行操作前,使用 worker 延迟配置集调整集群等待节点状态更新的频率。
  • 如果您的集群指定了较低延迟和较高延迟节点,请将 Ingress Controller 中的 spec.nodePlacement 字段配置为控制路由器 pod 的放置。

1.1.6. 使用 Cookie 来保持路由有状态性

OpenShift Container Platform 提供粘性会话,通过确保所有流量都到达同一端点来实现有状态应用程序流量。但是,如果端点 pod 以重启、扩展或更改配置的方式被终止,这种有状态性可能会消失。

OpenShift Container Platform 可以使用 Cookie 来配置会话持久性。ingress 控制器选择一个端点来处理任何用户请求,并为会话创建一个 Cookie。Cookie 在响应请求时返回,用户则通过会话中的下一请求发回 Cookie。Cookie 告知 Ingress Controller 哪个端点正在处理会话,确保客户端请求使用这个 Cookie 使请求路由到同一个 pod。

注意

无法在 passthrough 路由上设置 Cookie,因为无法看到 HTTP 流量。相反,根据源 IP 地址计算数字,该地址决定了后端。

如果后端更改,可以将流量定向到错误的服务器,使其更不计。如果您使用负载均衡器来隐藏源 IP,则会为所有连接和流量都发送到同一 pod 设置相同的数字。

1.1.7. 基于路径的路由

基于路径的路由指定了一个路径组件,可以与 URL 进行比较,该 URL 需要基于 HTTP 的路由流量。因此,可以使用同一主机名提供多个路由,每个主机名都有不同的路径。路由器应该匹配基于最具体路径的路由。

下表显示了路由及其可访问性示例:

Expand
表 1.1. 路由可用性
Route(路由)当比较到可访问

www.example.com/test

www.example.com/test

www.example.com

www.example.com/testwww.example.com

www.example.com/test

www.example.com

www.example.com

www.example.com/text

yes(由主机匹配,而不是路由)

www.example.com

带有路径的未安全路由

apiVersion: route.openshift.io/v1
kind: Route
metadata:
  name: route-unsecured
spec:
  host: www.example.com
  path: "/test" 
1

  to:
    kind: Service
    name: service-name
Copy to Clipboard Toggle word wrap

1
该路径是基于路径的路由的唯一添加属性。
注意

使用 passthrough TLS 时,基于路径的路由不可用,因为路由器不会在这种情况下终止 TLS,且无法读取请求的内容。

1.1.8. HTTP 标头配置

OpenShift Container Platform 提供了不同的使用 HTTP 标头的方法。在设置或删除标头时,您可以使用 Ingress Controller 中的特定字段或单独的路由来修改请求和响应标头。您还可以使用路由注解设置某些标头。配置标头的各种方法在协同工作时可能会带来挑战。

注意

您只能在 IngressControllerRoute CR 中设置或删除标头,您无法附加它们。如果使用值设置 HTTP 标头,则该值必须已完成,且在以后不需要附加。在附加标头(如 X-Forwarded-For 标头)时,请使用 spec.httpHeaders.forwardedHeaderPolicy 字段,而不是 spec.httpHeaders.actions

1.1.8.1. 优先级顺序

当在 Ingress Controller 和路由中修改相同的 HTTP 标头时,HAProxy 会根据它是请求还是响应标头来优先选择操作。

  • 对于 HTTP 响应标头,Ingress Controller 中指定的操作会在路由中指定的操作后执行。这意味着 Ingress Controller 中指定的操作具有优先权。
  • 对于 HTTP 请求标头,路由中指定的操作会在 Ingress Controller 中指定的操作后执行。这意味着路由中指定的操作具有优先权。

例如,集群管理员使用以下配置设置 X-Frame-Options 响应标头,其值为 DENY

IngressController spec 示例

apiVersion: operator.openshift.io/v1
kind: IngressController
# ...
spec:
  httpHeaders:
    actions:
      response:
      - name: X-Frame-Options
        action:
          type: Set
          set:
            value: DENY
Copy to Clipboard Toggle word wrap

路由所有者设置 Ingress Controller 中设置的相同响应标头,但使用以下配置值 SAMEORIGIN

Route 规格示例

apiVersion: route.openshift.io/v1
kind: Route
# ...
spec:
  httpHeaders:
    actions:
      response:
      - name: X-Frame-Options
        action:
          type: Set
          set:
            value: SAMEORIGIN
Copy to Clipboard Toggle word wrap

IngressController spec 和 Route spec 都配置 X-Frame-Options 标头时,Ingress Controller 中的全局级别为这个标头设置的值将具有优先权,即使一个特定的路由允许帧。对于请求标头,Route spec 值会覆盖 IngressController spec 值。

发生这个优先级,因为 haproxy.config 文件使用以下逻辑,其中 Ingress Controller 被视为前端,单独的路由被视为后端。应用到前端配置的标头值 DENY 使用后端中设置的值 SAMEORIGIN 覆盖相同的标头:

frontend public
  http-response set-header X-Frame-Options 'DENY'

frontend fe_sni
  http-response set-header X-Frame-Options 'DENY'

frontend fe_no_sni
  http-response set-header X-Frame-Options 'DENY'

backend be_secure:openshift-monitoring:alertmanager-main
  http-response set-header X-Frame-Options 'SAMEORIGIN'
Copy to Clipboard Toggle word wrap

另外,Ingress Controller 或路由中定义的任何操作都覆盖使用路由注解设置的值。

1.1.8.2. 特殊情况标头

以下标头可能会阻止完全被设置或删除,或者在特定情况下允许:

Expand
表 1.2. 特殊情况标头配置选项
标头名称使用 IngressController spec 进行配置使用 Route 规格进行配置禁止的原因使用其他方法进行配置

proxy

proxy HTTP 请求标头可以通过将标头值注入 HTTP_PROXY 环境变量来利用这个安全漏洞的 CGI 应用程序。proxy HTTP 请求标头也是非标准的,在配置期间容易出错。

主机

当使用 IngressController CR 设置 host HTTP 请求标头时,HAProxy 在查找正确的路由时可能会失败。

strict-transport-security

strict-transport-security HTTP 响应标头已使用路由注解处理,不需要单独的实现。

是: haproxy.router.openshift.io/hsts_header 路由注解

cookieset-cookie

HAProxy 集的 Cookie 用于会话跟踪,用于将客户端连接映射到特定的后端服务器。允许设置这些标头可能会影响 HAProxy 的会话关联,并限制 HAProxy 的 Cookie 的所有权。

是:

  • haproxy.router.openshift.io/disable_cookie 路由注解
  • haproxy.router.openshift.io/cookie_name 路由注解

出于合规的原因,您可以设置或删除某些 HTTP 请求和响应标头。您可以为 Ingress Controller 提供的所有路由或特定路由设置或删除这些标头。

例如,如果内容使用多种语言编写,您可能希望让 Web 应用程序在备用位置提供内容,即使 Ingress Controller 为路由指定的默认全局位置。

以下流程会创建一个设置 Content-Location HTTP 请求标头的路由,以便与应用程序关联的 URL https://app.example.com 定向到位置 https://app.example.com/lang/en-us。将应用程序流量定向到此位置意味着使用该特定路由的任何人都可以访问以美国英语编写的 Web 内容。

先决条件

  • 已安装 OpenShift CLI(oc)。
  • 以项目管理员身份登录到 OpenShift Container Platform 集群。
  • 您有一个 web 应用来公开端口,以及侦听端口流量的 HTTP 或 TLS 端点。

流程

  1. 创建一个路由定义,并将它保存到名为 app-example-route.yaml 的文件中:

    使用 HTTP 标头指令创建路由的 YAML 定义

    apiVersion: route.openshift.io/v1
    kind: Route
    # ...
    spec:
      host: app.example.com
      tls:
        termination: edge
      to:
        kind: Service
        name: app-example
      httpHeaders:
        actions: 
    1
    
          response: 
    2
    
          - name: Content-Location 
    3
    
            action:
              type: Set 
    4
    
              set:
                value: /lang/en-us 
    5
    Copy to Clipboard Toggle word wrap

    1
    要在 HTTP 标头上执行的操作列表。
    2
    您要更改的标头类型。在本例中,响应标头。
    3
    您要更改的标头的名称。有关您可以设置或删除的可用标头列表,请参阅 HTTP 标头配置
    4
    在标头中执行的操作类型。此字段可以具有 SetDelete 的值。
    5
    在设置 HTTP 标头时,您必须提供一个 value。该值可以是该标头的可用指令列表中的字符串,如 DENY,也可以是使用 HAProxy 的动态值语法来解释的动态值。在这种情况下,该值被设置为内容的相对位置。
  2. 使用新创建的路由定义,创建到现有 Web 应用程序的路由:

    $ oc -n app-example create -f app-example-route.yaml
    Copy to Clipboard Toggle word wrap

对于 HTTP 请求标头,路由定义中指定的操作会在 Ingress Controller 中对 HTTP 请求标头执行的任何操作后执行。这意味着,路由中这些请求标头设置的任何值都将优先于 Ingress Controller 中设置的值。有关 HTTP 标头处理顺序的更多信息,请参阅 HTTP 标头配置

1.1.10. 特定于路由的注解

Ingress Controller 可以为它公开的所有路由设置默认选项。单个路由可以通过在其注解中提供特定配置来覆盖这些默认设置。红帽不支持在 Operator 管理的路由中添加路由注解。

重要

要创建带有多个源 IP 或子网的白名单,请使用以空格分隔的列表。任何其他限定类型会导致忽略列表,而不发出警告或错误消息。

Expand
表 1.3. 路由注解
变量描述

haproxy.router.openshift.io/balance

设置负载平衡算法。可用选项为 random, source, roundrobin[1], 和 leastconn。对于 TLS 透传路由,默认值为 source。对于所有其他路由,默认值为 random

haproxy.router.openshift.io/disable_cookies

禁用使用 cookie 来跟踪相关连接。如果设置为 'true''TRUE',则使用均衡算法选择每个传入 HTTP 请求的后端服务连接。

router.openshift.io/cookie_name

指定一个可选的、用于此路由的 cookie。名称只能包含大写字母和小写字母、数字、"_" 和 "-"。默认为路由的内部密钥进行哈希处理。

haproxy.router.openshift.io/pod-concurrent-connections

设置路由器支持的 pod 允许的最大连接数。
注: 如果有多个 pod,每个 pod 都有这些数量的连接。如果有多个路由器,它们之间没有协调关系,每个路由器都可能会多次连接。如果没有设置,或者将其设定为 0,则没有限制。

haproxy.router.openshift.io/rate-limit-connections

设置 'true''TRUE' 可启用速率限制功能,该功能通过每个路由上的特定后端的贴子实施。
注: 使用此注解提供了对拒绝服务攻击的基本保护。

haproxy.router.openshift.io/rate-limit-connections.concurrent-tcp

限制通过同一源 IP 地址进行的并发 TCP 连接数。它接受一个数字值。
注: 使用此注解提供了对拒绝服务攻击的基本保护。

haproxy.router.openshift.io/rate-limit-connections.rate-http

限制具有相同源 IP 地址的客户端可以发出 HTTP 请求的速率。它接受一个数字值。
注: 使用此注解提供了对拒绝服务攻击的基本保护。

haproxy.router.openshift.io/rate-limit-connections.rate-tcp

限制具有相同源 IP 地址的客户端可以进行 TCP 连接的速率。它接受一个数字值。

router.openshift.io/haproxy.health.check.interval

为后端健康检查设定间隔。(TimeUnits)

haproxy.router.openshift.io/ip_allowlist

为路由设置允许列表。允许列表(allowlist)是以空格分开的 IP 地址和 CIDR 范围列表,用来代表批准的源地址。不是来自允许列表中的 IP 地址的请求会被丢弃。

haproxy.config 文件中直接可见的最大 IP 地址和 CIDR 范围数为 61. [2]

haproxy.router.openshift.io/hsts_header

为 edge terminated 或 re-encrypt 路由设置 Strict-Transport-Security 标头。

haproxy.router.openshift.io/rewrite-target

在后端中设置请求的重写路径。

router.openshift.io/cookie-same-site

设置一个值来限制 cookies。数值是:

Lax: 浏览器不会在跨站点请求上发送 Cookie,当用户从外部站点导航到原始站点时发送 Cookie。当未指定 SameSite 值时,这是默认的浏览器行为。

Strict :浏览器仅针对同一站点请求发送 Cookie。

None :浏览器为跨站点和相同站点请求发送 Cookie。

这个值仅适用于重新加密和边缘路由。如需更多信息,请参阅 SameSite cookies 文档

haproxy.router.openshift.io/set-forwarded-headers

设置用于处理每个路由的 ForwardedX-Forwarded-For HTTP 标头的策略。数值是:

Append附加标头,保留任何现有的标头。这是默认值。

replace:设置标头,删除任何现有的标头。

Never:不设置标头,而是保留任何现有的标头。

if-none:如果没有设置标头,则设置它。

  1. 默认情况下,路由器会每 5 秒重新加载一次,它会从头重置容器集之间的平衡连接。因此,roundrobin 状态不会在重新加载后保留。当 pod 具有几乎相同的计算能力和存储容量时,此算法效果最佳。如果您的应用程序或服务会持续更改端点,例如,由于使用了 CI/CD 管道,可能会出现不平衡的结果。如果是这种情况下,可以使用不同的算法。
  2. 如果允许列表中的 IP 地址和 CIDR 范围超过 61,它们将被写入到一个独立的文件中,haproxy.config 会引用这个文件。此文件存储在 /var/lib/haproxy/router/allowlists 文件夹中。

    注意

    为确保地址被写入允许列表,请检查 Ingress Controller 配置文件中是否列出了 CIDR 范围的完整列表。etcd 对象大小限制了路由注解的大小。因此,它实际上是为您可以在允许列表中包含的 IP 地址和 CIDR 范围的最大数量创建一个阈值。

只允许一个特定 IP 地址的路由

metadata:
  annotations:
    haproxy.router.openshift.io/ip_allowlist: 192.168.1.10
Copy to Clipboard Toggle word wrap

允许多个 IP 地址的路由

metadata:
  annotations:
    haproxy.router.openshift.io/ip_allowlist: 192.168.1.10 192.168.1.11 192.168.1.12
Copy to Clipboard Toggle word wrap

允许 IP 地址 CIDR 网络的路由

metadata:
  annotations:
    haproxy.router.openshift.io/ip_allowlist: 192.168.1.0/24
Copy to Clipboard Toggle word wrap

允许 IP 地址和 IP 地址 CIDR 网络的路由

metadata:
  annotations:
    haproxy.router.openshift.io/ip_allowlist: 180.5.61.153 192.168.1.0/24 10.0.0.0/8
Copy to Clipboard Toggle word wrap

指定重写对象的路由

apiVersion: route.openshift.io/v1
kind: Route
metadata:
  annotations:
    haproxy.router.openshift.io/rewrite-target: / 
1

...
Copy to Clipboard Toggle word wrap

1
/ 设为后端请求的重写路径。

在路由上设置 haproxy.router.openshift.io/rewrite-target 注解,指定 Ingress Controller 在将请求转发到后端应用程序之前,应该使用此路由在 HTTP 请求中重写路径。与 spec.path 中指定的路径匹配的请求路径部分将替换为注解中指定的重写对象。

下表提供了在 spec.path、请求路径和重写对象的各种组合中重写行为的路径示例。

Expand
表 1.4. rewrite-target 示例
Route.spec.path请求路径重写目标转发请求路径

/foo

/foo

/

/

/foo

/foo/

/

/

/foo

/foo/bar

/

/bar

/foo

/foo/bar/

/

/bar/

/foo

/foo

/bar

/bar

/foo

/foo/

/bar

/bar/

/foo

/foo/bar

/baz

/baz/bar

/foo

/foo/bar/

/baz

/baz/bar/

/foo/

/foo

/

不适用(请求路径不匹配路由路径)

/foo/

/foo/

/

/

/foo/

/foo/bar

/

/bar

haproxy.router.openshift.io/rewrite-target 中的某些特殊字符需要特殊处理,因为它们必须正确转义。请参阅下表以了解这些字符的处理方式。

Expand
表 1.5. 特殊字符处理
对于字符使用字符

#

\#

避免使用 #,因为它会终止重写表达式

%

% 或 %%

避免奇数序列,如 %%%

\’

避免 ',因为它被忽略

所有其他有效的 URL 字符可以在不转义的情况下使用。

1.1.11. 配置路由准入策略

管理员和应用程序开发人员可在多个命名空间中运行具有相同域名的应用程序。这是针对多个团队开发的、在同一个主机名上公开的微服务的机构。

警告

只有在命名空间间有信任的集群才会启用跨命名空间之间的声明,否则恶意用户可能会接管主机名。因此,默认的准入策略不允许在命名空间间声明主机名。

先决条件

  • 必须具有集群管理员权限。

流程

  • 使用以下命令编辑 ingresscontroller 资源变量的.spec. routeAdmission 字段:

    $ oc -n openshift-ingress-operator patch ingresscontroller/default --patch '{"spec":{"routeAdmission":{"namespaceOwnership":"InterNamespaceAllowed"}}}' --type=merge
    Copy to Clipboard Toggle word wrap

    Ingress 控制器配置参数

    spec:
      routeAdmission:
        namespaceOwnership: InterNamespaceAllowed
    ...
    Copy to Clipboard Toggle word wrap

    提示

    您还可以应用以下 YAML 来配置路由准入策略:

    apiVersion: operator.openshift.io/v1
    kind: IngressController
    metadata:
      name: default
      namespace: openshift-ingress-operator
    spec:
      routeAdmission:
        namespaceOwnership: InterNamespaceAllowed
    Copy to Clipboard Toggle word wrap

1.1.12. 通过 Ingress 对象创建路由

一些生态系统组件与 Ingress 资源集成,但与路由资源不集成。要涵盖此问题单,OpenShift Container Platform 会在创建 Ingress 对象时自动创建受管路由对象。当相应 Ingress 对象被删除时,这些路由对象会被删除。

流程

  1. 在 OpenShift Container Platform 控制台中或通过 oc create 命令来定义 Ingress 对象:

    Ingress 的 YAML 定义

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: frontend
      annotations:
        route.openshift.io/termination: "reencrypt" 
    1
    
        route.openshift.io/destination-ca-certificate-secret: secret-ca-cert 
    2
    
    spec:
      rules:
      - host: www.example.com 
    3
    
        http:
          paths:
          - backend:
              service:
                name: frontend
                port:
                  number: 443
            path: /
            pathType: Prefix
      tls:
      - hosts:
        - www.example.com
        secretName: example-com-tls-certificate
    Copy to Clipboard Toggle word wrap

    1
    route.openshift.io/termination 注解可用于配置 Routespec.tls.termination 字段,因为 Ingress 没有此字段。可接受的值为 edgepassthroughreencrypt。所有其他值都会被静默忽略。当注解值未设置时,edge 是默认路由。模板文件中必须定义 TLS 证书详细信息,才能实现默认的边缘路由。
    3
    在使用 Ingress 对象时,您必须指定一个显式主机名,这与使用路由时不同。您可以使用 <host_name>.<cluster_ingress_domain> 语法(如 apps.openshiftdemos.com)以利用 *.<cluster_ingress_domain> 通配符 DNS 记录,为集群提供证书。否则,您必须确保有一个用于所选主机名的 DNS 记录。
    1. 如果您在 route.openshift.io/termination 注解中指定 passthrough 值,在 spec 中将 path 设置为 '',将 pathType 设置为 ImplementationSpecific

        spec:
          rules:
          - host: www.example.com
            http:
              paths:
              - path: ''
                pathType: ImplementationSpecific
                backend:
                  service:
                    name: frontend
                    port:
                      number: 443
      Copy to Clipboard Toggle word wrap
      $ oc apply -f ingress.yaml
      Copy to Clipboard Toggle word wrap
    2
    route.openshift.io/destination-ca-certificate-secret 可用于 Ingress 对象来定义带有自定义目的地证书(CA)的路由。该注解引用一个 kubernetes secret,secret-ca-cert 将插入到生成的路由中。
    1. 要从 ingress 对象使用目标 CA 指定路由对象,您必须在 secret 的 data.tls.crt specifier 中创建一个带有 PEM 编码格式的证书的 kubernetes.io/tlsOpaque 类型 secret。
  2. 列出您的路由:

    $ oc get routes
    Copy to Clipboard Toggle word wrap

    结果包括一个自动生成的路由,其名称以 frontend- 开头:

    NAME             HOST/PORT         PATH    SERVICES    PORT    TERMINATION          WILDCARD
    frontend-gnztq   www.example.com           frontend    443     reencrypt/Redirect   None
    Copy to Clipboard Toggle word wrap

    如果您检查这个路由,它会类似于:

    自动生成的路由的 YAML 定义

    apiVersion: route.openshift.io/v1
    kind: Route
    metadata:
      name: frontend-gnztq
      ownerReferences:
      - apiVersion: networking.k8s.io/v1
        controller: true
        kind: Ingress
        name: frontend
        uid: 4e6c59cc-704d-4f44-b390-617d879033b6
    spec:
      host: www.example.com
      path: /
      port:
        targetPort: https
      tls:
        certificate: |
          -----BEGIN CERTIFICATE-----
          [...]
          -----END CERTIFICATE-----
        insecureEdgeTerminationPolicy: Redirect
        key: |
          -----BEGIN RSA PRIVATE KEY-----
          [...]
          -----END RSA PRIVATE KEY-----
        termination: reencrypt
        destinationCACertificate: |
          -----BEGIN CERTIFICATE-----
          [...]
          -----END CERTIFICATE-----
      to:
        kind: Service
        name: frontend
    Copy to Clipboard Toggle word wrap

1.1.13. 通过 Ingress 对象使用默认证书创建路由

如果您在没有指定 TLS 配置的情况下创建 Ingress 对象,OpenShift Container Platform 会生成一个不安全的路由。要创建使用默认入口证书生成安全边缘终止路由的 Ingress 对象,您可以指定一个空的 TLS 配置,如下所示:

前提条件

  • 您有一个要公开的服务。
  • 您可以访问 OpenShift CLI(oc)。

流程

  1. 为 Ingress 对象创建 YAML 文件。在本例中,该文件名为 example-ingress.yaml

    Ingress 对象的 YAML 定义

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: frontend
      ...
    spec:
      rules:
        ...
      tls:
      - {} 
    1
    Copy to Clipboard Toggle word wrap

    1
    使用此精确的语法指定 TLS,而不指定自定义证书。
  2. 运行以下命令来创建 Ingress 对象:

    $ oc create -f example-ingress.yaml
    Copy to Clipboard Toggle word wrap

验证

  • 运行以下命令,验证 OpenShift Container Platform 是否为 Ingress 对象创建了预期的路由:

    $ oc get routes -o yaml
    Copy to Clipboard Toggle word wrap

    输出示例

    apiVersion: v1
    items:
    - apiVersion: route.openshift.io/v1
      kind: Route
      metadata:
        name: frontend-j9sdd 
    1
    
        ...
      spec:
      ...
        tls: 
    2
    
          insecureEdgeTerminationPolicy: Redirect
          termination: edge 
    3
    
      ...
    Copy to Clipboard Toggle word wrap

    1
    路由的名称包括 Ingress 对象的名称,后跟一个随机的后缀。
    2
    要使用默认证书,路由不应指定 spec.certificate
    3
    路由应指定 edge 终止策略。

在 Ingress 对象上可以使用 route.openshift.io/destination-ca-certificate-secret 注解来定义带有自定义目标 CA 证书的路由。

前提条件

  • 您可以在 PEM 编码文件中有一个证书/密钥对,其中的证书对路由主机有效。
  • 您可以在 PEM 编码文件中有一个单独的 CA 证书来补全证书链。
  • 您必须在 PEM 编码文件中有单独的目标 CA 证书。
  • 您必须具有要公开的服务。

流程

  1. 输入以下命令为目标 CA 证书创建 secret:

    $ oc create secret generic dest-ca-cert --from-file=tls.crt=<file_path>
    Copy to Clipboard Toggle word wrap

    例如:

    $ oc -n test-ns create secret generic dest-ca-cert --from-file=tls.crt=tls.crt
    Copy to Clipboard Toggle word wrap

    输出示例

    secret/dest-ca-cert created
    Copy to Clipboard Toggle word wrap

  2. route.openshift.io/destination-ca-certificate-secret 添加到 Ingress 注解中:

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: frontend
      annotations:
        route.openshift.io/termination: "reencrypt"
        route.openshift.io/destination-ca-certificate-secret: secret-ca-cert 
    1
    
    ...
    Copy to Clipboard Toggle word wrap
    1
    该注解引用 kubernetes secret。
  3. 此注解中引用的机密将插入到生成的路由中。

    输出示例

    apiVersion: route.openshift.io/v1
    kind: Route
    metadata:
      name: frontend
      annotations:
        route.openshift.io/termination: reencrypt
        route.openshift.io/destination-ca-certificate-secret: secret-ca-cert
    spec:
    ...
      tls:
        insecureEdgeTerminationPolicy: Redirect
        termination: reencrypt
        destinationCACertificate: |
          -----BEGIN CERTIFICATE-----
          [...]
          -----END CERTIFICATE-----
    ...
    Copy to Clipboard Toggle word wrap

如果您的 OpenShift Container Platform 集群是为 IPv4 和 IPv6 双栈网络配置的,则 OpenShift Container Platform 路由可从外部访问集群。

Ingress Controller 会自动提供具有 IPv4 和 IPv6 端点的服务,但您可以为单堆栈或双栈服务配置 Ingress Controller。

先决条件

  • 您在裸机上部署了 OpenShift Container Platform 集群。
  • 已安装 OpenShift CLI(oc)。

流程

  1. 要使 Ingress Controller 为工作负载提供通过 IPv4/IPv6 的流量,您可以通过设置 ipFamilies 和 ipFamilyPolicy 字段来创建服务 YAML 文件,或通过设置 ipFamiliesipFamilyPolicy 字段来修改现有服务 YAML 文件。例如:

    服务 YAML 文件示例

    apiVersion: v1
    kind: Service
    metadata:
      creationTimestamp: yyyy-mm-ddT00:00:00Z
      labels:
        name: <service_name>
        manager: kubectl-create
        operation: Update
        time: yyyy-mm-ddT00:00:00Z
      name: <service_name>
      namespace: <namespace_name>
      resourceVersion: "<resource_version_number>"
      selfLink: "/api/v1/namespaces/<namespace_name>/services/<service_name>"
      uid: <uid_number>
    spec:
      clusterIP: 172.30.0.0/16
      clusterIPs: 
    1
    
      - 172.30.0.0/16
      - <second_IP_address>
      ipFamilies: 
    2
    
      - IPv4
      - IPv6
      ipFamilyPolicy: RequireDualStack 
    3
    
      ports:
      - port: 8080
        protocol: TCP
        targetport: 8080
      selector:
        name: <namespace_name>
      sessionAffinity: None
      type: ClusterIP
    status:
      loadbalancer: {}
    Copy to Clipboard Toggle word wrap

    1
    在双栈实例中,提供了两个不同的 clusterIP
    2
    对于单堆栈实例,输入 IPv4IPv6。对于双栈实例,请输入 IPv4IPv6
    3
    对于单堆栈实例,请输入 SingleStack。对于双栈实例,请输入 RequireDualStack

    这些资源生成对应的端点。Ingress Controller 现在监视 endpointslices

  2. 要查看端点,请输入以下命令:

    $ oc get endpoints
    Copy to Clipboard Toggle word wrap
  3. 要查看endpointslices,输入以下命令:

    $ oc get endpointslices
    Copy to Clipboard Toggle word wrap

1.2. 安全路由

安全路由提供以下几种 TLS 终止功能来为客户端提供证书。以下小节介绍了如何使用自定义证书创建重新加密、边缘和透传路由。

重要

如果您在 Microsoft Azure 中创建通过公共端点的路由,则资源名称会受到限制。您不能创建使用某些词语的资源。如需 Azure 限制词语的列表,请参阅 Azure 文档中的解决预留资源名称错误

1.2.1. 使用自定义证书创建重新加密路由

您可以使用 oc create route 命令,使用重新加密 TLS 终止和自定义证书配置安全路由。

此流程使用自定义证书和重新加密 TLS 终止创建 Route 资源。以下步骤假定证书/密钥对位于当前工作目录下的 tls.crttls.key 文件中。您还必须指定一个目标 CA 证书,使 Ingress Controller 信任服务的证书。您也可以根据需要指定 CA 证书来补全证书链。替换 tls.crttls.keycacert.crt 和(可选)ca.crt 的实际路径名称。替换您要为 frontend 公开的 Service 资源的名称。使用适当的主机名替换 www.example.com

前提条件

  • 您必须在 PEM 编码文件中有一个证书/密钥对,其中的证书对路由主机有效。
  • 您可以在 PEM 编码文件中有一个单独的 CA 证书来补全证书链。
  • 您必须在 PEM 编码文件中有单独的目标 CA 证书。
  • 您必须具有要公开的服务。
注意

不支持密码保护的密钥文件。要从密钥文件中删除密码,使用以下命令:

$ openssl rsa -in password_protected_tls.key -out tls.key
Copy to Clipboard Toggle word wrap

流程

  • 使用重新加密 TLS 终止和自定义证书,创建安全 Route 资源:

    $ oc create route reencrypt --service=frontend --cert=tls.crt --key=tls.key --dest-ca-cert=destca.crt --ca-cert=ca.crt --hostname=www.example.com
    Copy to Clipboard Toggle word wrap

    如果您检查生成的 Route 资源,它应该类似于如下:

    安全路由 YAML 定义

    apiVersion: route.openshift.io/v1
    kind: Route
    metadata:
      name: frontend
    spec:
      host: www.example.com
      to:
        kind: Service
        name: frontend
      tls:
        termination: reencrypt
        key: |-
          -----BEGIN PRIVATE KEY-----
          [...]
          -----END PRIVATE KEY-----
        certificate: |-
          -----BEGIN CERTIFICATE-----
          [...]
          -----END CERTIFICATE-----
        caCertificate: |-
          -----BEGIN CERTIFICATE-----
          [...]
          -----END CERTIFICATE-----
        destinationCACertificate: |-
          -----BEGIN CERTIFICATE-----
          [...]
          -----END CERTIFICATE-----
    Copy to Clipboard Toggle word wrap

    如需了解更多选项,请参阅 oc create route reencrypt --help

1.2.2. 使用自定义证书创建边缘路由

您可以通过 oc create route 命令,使用边缘 TLS 终止和自定义证书配置安全路由。使用边缘路由时,Ingress Controller 在将流量转发到目标 pod 之前终止 TLS 加密。该路由指定了 Ingress Controller 用于路由的 TLS 证书和密钥。

此流程使用自定义证书和边缘 TLS 终止创建 Route 资源。以下步骤假定证书/密钥对位于当前工作目录下的 tls.crttls.key 文件中。您也可以根据需要指定 CA 证书来补全证书链。替换 tls.crttls.key 和(可选)ca.crt 的实际路径名称。替换您要为 frontend 公开的服务名称。使用适当的主机名替换 www.example.com

前提条件

  • 您必须在 PEM 编码文件中有一个证书/密钥对,其中的证书对路由主机有效。
  • 您可以在 PEM 编码文件中有一个单独的 CA 证书来补全证书链。
  • 您必须具有要公开的服务。
注意

不支持密码保护的密钥文件。要从密钥文件中删除密码,使用以下命令:

$ openssl rsa -in password_protected_tls.key -out tls.key
Copy to Clipboard Toggle word wrap

流程

  • 使用边缘 TLS 终止和自定义证书,创建安全 Route 资源。

    $ oc create route edge --service=frontend --cert=tls.crt --key=tls.key --ca-cert=ca.crt --hostname=www.example.com
    Copy to Clipboard Toggle word wrap

    如果您检查生成的 Route 资源,它应该类似于如下:

    安全路由 YAML 定义

    apiVersion: route.openshift.io/v1
    kind: Route
    metadata:
      name: frontend
    spec:
      host: www.example.com
      to:
        kind: Service
        name: frontend
      tls:
        termination: edge
        key: |-
          -----BEGIN PRIVATE KEY-----
          [...]
          -----END PRIVATE KEY-----
        certificate: |-
          -----BEGIN CERTIFICATE-----
          [...]
          -----END CERTIFICATE-----
        caCertificate: |-
          -----BEGIN CERTIFICATE-----
          [...]
          -----END CERTIFICATE-----
    Copy to Clipboard Toggle word wrap

    如需了解更多选项,请参阅 oc create route edge --help

1.2.3. 创建 passthrough 路由

您可以使用 oc create route 命令使用 passthrough 终止配置安全路由。如果 passthrough 终止,加密的流量会直接发送到目的地,而路由器不会提供 TLS 终止。因此,路由不需要密钥或证书。

前提条件

  • 您必须具有要公开的服务。

流程

  • 创建 Route 资源:

    $ oc create route passthrough route-passthrough-secured --service=frontend --port=8080
    Copy to Clipboard Toggle word wrap

    如果您检查生成的 Route 资源,它应该类似于如下:

    使用 Passthrough 终止的安全路由

    apiVersion: route.openshift.io/v1
    kind: Route
    metadata:
      name: route-passthrough-secured 
    1
    
    spec:
      host: www.example.com
      port:
        targetPort: 8080
      tls:
        termination: passthrough 
    2
    
        insecureEdgeTerminationPolicy: None 
    3
    
      to:
        kind: Service
        name: frontend
    Copy to Clipboard Toggle word wrap

    1
    对象的名称,长度限于 63 个字符。
    2
    termination 字段设置为 passthrough。这是唯一需要 tls 的字段。
    3
    可选的 insecureEdgeTerminationPolicy。禁用后唯一有效的值是 NoneRedirect 或为空。

    目标 pod 负责为端点上的流量提供证书。目前,这是唯一支持需要客户端证书的方法,也称双向验证。

1.2.4. 使用外部管理的证书创建路由

您可以使用路由 API 的 .spec.tls.externalCertificate 字段来使用第三方证书管理解决方案配置 OpenShift Container Platform 路由。您可以通过 secret 引用外部管理的 TLS 证书,无需手动证书管理。使用外部受管证书可减少确保证书更新平稳推出的错误,使 OpenShift 路由器能够及时提供更新的证书。

您可以将外部管理的证书与边缘路由和重新加密路由一起使用。

先决条件

  • 您必须启用 RouteExternalCertificate 功能门。
  • routes/custom-host 子资源具有 create 权限,该资源用于创建和更新路由。
  • 您必须有一个包含 PEM 编码格式的有效证书/密钥对的 secret,类型为 kubernetes.io/tls,其中包括 tls.keytls.crt 键。
  • 您必须将引用的 secret 放在与您要保护的路由相同的命名空间中。

流程

  1. 运行以下命令,在与 secret 相同的命名空间中创建一个 角色,以允许路由器服务帐户读取访问权限:

    $ oc create role secret-reader --verb=get,list,watch --resource=secrets --resource-name=<secret-name> \ 
    1
    
    --namespace=<current-namespace> 
    2
    Copy to Clipboard Toggle word wrap
    1
    指定 secret 的实际名称。
    2
    指定 secret 和路由所在的命名空间。
  2. 运行以下命令,在与 secret 相同的命名空间中创建 rolebinding,并将 router 服务帐户绑定到新创建的角色:

    $ oc create rolebinding secret-reader-binding --role=secret-reader --serviceaccount=openshift-ingress:router --namespace=<current-namespace> 
    1
    Copy to Clipboard Toggle word wrap
    1
    指定 secret 和路由所在的命名空间。
  3. 创建一个定义 路由的 YAML 文件,并使用以下示例指定包含证书的 secret。

    安全路由的 YAML 定义

    apiVersion: route.openshift.io/v1
    kind: Route
    metadata:
      name: myedge
      namespace: test
    spec:
      host: myedge-test.apps.example.com
      tls:
        externalCertificate:
          name: <secret-name> 
    1
    
        termination: edge
        [...]
    [...]
    Copy to Clipboard Toggle word wrap

    1
    指定 secret 的实际名称。
  4. 运行以下命令来创建一个路由资源:

    $ oc apply -f <route.yaml> 
    1
    Copy to Clipboard Toggle word wrap
    1
    指定生成的 YAML 文件名。

    如果 secret 存在并具有证书/密钥对,如果满足所有先决条件,路由器将提供生成的证书。

    注意

    如果没有提供 .spec.tls.externalCertificate,路由器将使用默认生成的证书。

    使用 .spec.tls.externalCertificate 字段时,您无法提供 .spec.tls.certificate 字段或 .spec.tls.key 字段。

第 2 章 配置集群入口流量

2.1. 集群入口流量配置概述

OpenShift Container Platform 提供了以下从集群外部与集群中运行的服务进行通信的方法。

建议采用以下方法,它们按顺序或首选程度排列:

  • 如果您有 HTTP/HTTPS,请使用 Ingress Controller。
  • 如果您有 HTTPS 之外的 TLS 加密协议。比如对于使用 SNI 标头的 TLS,请使用 Ingress Controller。
  • 否则,请使用负载均衡器、外部 IP 或 NodePort
Expand
方法用途

使用 Ingress Controller

允许访问 HTTP/HTTPS 流量和 HTTPS 以外的 TLS 加密协议(例如,使用 SNI 标头的 TLS)。

使用负载均衡器服务自动分配外部 IP

允许流量通过从池分配的 IP 地址传到非标准端口。大多数云平台都提供了一种使用负载平衡器 IP 地址启动服务的方法。

关于 MetalLB 和 MetalLB Operator

允许从机器网络中的一个池到特定 IP 地址的流量。对于裸机安装或类似于裸机的平台,MetalLB 提供了使用负载平衡器 IP 地址启动服务的途径。

手动将外部 IP 分配给服务

允许流量通过特定的 IP 地址传到非标准端口。

配置 NodePort

在集群中的所有节点上公开某一服务。

2.1.1. 比较:对外部 IP 地址的容错访问

对于提供对外部 IP 地址访问权限的通信方法,另一个考虑因素是对 IP 地址的容错访问。以下功能提供对外部 IP 地址的容错访问。

IP 故障切换
IP 故障切换管理一组节点的虚拟 IP 地址池。它通过 Keepalived 和虚拟路由器冗余协议 (VRRP) 实施。IP 故障转移仅仅是第 2 层机制,它依赖于多播。对于某些网络,多播可能有缺点。
MetalLB
MetalLB 具有 2 层模式,但它不使用多播。第 2 层模式有一个缺点,它会通过一个节点传输外部 IP 地址的所有流量。
手动分配外部 IP 地址
您可以使用 IP 地址块配置集群,用于为服务分配外部 IP 地址。默认情况下禁用此功能。此功能非常灵活,但给集群或网络管理员带来了最大的负担。集群已准备好接收目标为外部 IP 的流量,但每个客户必须决定如何将流量路由到节点。

2.2. 为服务配置 ExternalIP

作为集群管理员,您可以指定可向集群中服务发送流量的集群外部 IP 地址块。

这个功能通常最适用于在裸机硬件上安装的集群。

2.2.1. 先决条件

  • 您的网络基础架构必须将外部 IP 地址的流量路由到集群。

2.2.2. 关于 ExternalIP

对于非云环境,OpenShift Container Platform 支持使用 ExternalIP 工具在 Service 对象的 spec.externalIPs[] 参数中指定外部 IP 地址。使用 ExternalIP 功能配置的服务与具有 type=NodePort 的服务相似,通过流量定向到本地节点以进行负载均衡。

重要

对于云环境,使用负载均衡器服务自动部署云负载均衡器,以服务端点为目标。

为参数指定值后,OpenShift Container Platform 会为该服务分配额外的虚拟 IP 地址。IP 地址可以存在于您为集群定义的服务网络之外。

警告

因为默认情况下会禁用 ExternalIP,所以启用 ExternalIP 功能可能会给该服务带来安全风险,因为集群内到外部 IP 地址的流量会定向到该服务。此配置意味着集群用户可以截获用于外部资源的敏感流量。

您可以使用 MetalLB 实现或 IP 故障转移部署,将 ExternalIP 资源附加到服务:

自动分配一个外部 IP
当创建了一个带有 spec.type=LoadBalancer 设置的 Service 对象时,OpenShift Container Platform 会从autoAssignCIDRs CIDR 块中自动为 spec.externalIPs[] 分配一个 IP 地址。对于此配置,OpenShift Container Platform 实施负载均衡器服务类型的云版本,并为服务分配 IP 地址。默认情况下,自动分配被禁用,必须由集群管理员配置,如 "Configuration for ExternalIP" 部分所述。
手动分配外部 IP
OpenShift Container Platform 在创建 Service 对象时使用分配给 spec.externalIPs[] 数组的 IP 地址。您不能指定已经被其他服务使用的 IP 地址。

在使用 MetalLB 实现或 IP 故障转移部署来托管外部 IP 地址块后,您必须配置网络基础架构,以确保外部 IP 地址块路由到集群。此配置意味着,IP 地址没有在来自节点的网络接口中配置。要处理流量,您必须使用方法配置路由和访问外部 IP,如静态地址解析协议(ARP)条目。

OpenShift Container Platform 通过添加以下功能来扩展 Kubernetes 中的 ExternalIP 功能:

  • 通过可配置策略对用户使用外部 IP 地址的限制
  • 根据请求自动将外部 IP 地址分配给服务

2.2.3. 配置 ExternalIP

Network.config.openshift.io 自定义资源(CR)中的以下参数管理在 OpenShift Container Platform 中使用外部 IP 地址:

  • spec.externalIP.autoAssignCIDRs 定义了一个负载均衡器在为服务选择外部 IP 地址时使用的 IP 地址块。OpenShift Container Platform 只支持单个 IP 地址块进行自动分配。这个配置需要较少的步骤,而不是手动为服务分配 ExternalIP,这需要管理有限共享 IP 地址的端口空间。如果启用自动分配,Cloud Controller Manager Operator 会将外部 IP 地址分配给在其配置中带有 spec.type=LoadBalancer defind 的 Service 对象。
  • 在手动指定 IP 地址时,spec.externalIP.policy 定义了允许的 IP 地址块。OpenShift Container Platform 不将策略规则应用到您在 spec.externalIP.autoAssignCIDRs 参数中定义的 IP 地址块。

如果路由正确,来自配置的外部 IP 地址块的外部流量可以通过服务公开的任何 TCP 或 UDP 端口访问服务端点。

重要

作为集群管理员,您必须配置到 externalIPs 的路由。您还必须确保分配的 IP 地址块在集群中的一个或多个节点上终止。如需更多信息,请参阅 Kubernetes 外部 IP

OpenShift Container Platform 支持自动和手动 IP 地址分配。这一支持保证,每个地址被分配到最多一个服务,并且每个服务都可以公开其所选端口,而不考虑由其他服务公开的端口。

注意

要使用 OpenShift Container Platform 中由 autoAssignCIDRs 定义 的 IP 地址块,您必须为主机网络配置必要的 IP 地址分配和路由。

以下 YAML 描述了配置了外部 IP 地址的服务:

带有 spec.externalIPs[] 设置的示例 Service 对象

apiVersion: v1
kind: Service
metadata:
  name: http-service
spec:
  clusterIP: 172.30.163.110
  externalIPs:
  - 192.168.132.253
  externalTrafficPolicy: Cluster
  ports:
  - name: highport
    nodePort: 31903
    port: 30102
    protocol: TCP
    targetPort: 30102
  selector:
    app: web
  sessionAffinity: None
  type: LoadBalancer
status:
  loadBalancer:
    ingress:
    - ip: 192.168.132.253
# ...
Copy to Clipboard Toggle word wrap

如果在 cloud-provider 平台上运行私有集群,您可以通过运行以下 patch 命令将 Ingress Controller 负载均衡器的发布范围改为 internal

$ oc -n openshift-ingress-operator patch ingresscontrollers/ingress-controller-with-nlb --type=merge --patch='{"spec":{"endpointPublishingStrategy":{"loadBalancer":{"scope":"Internal"}}}}'
Copy to Clipboard Toggle word wrap

运行此命令后,Ingress Controller 只会将 OpenShift Container Platform 应用程序的路由限制为内部网络。

2.2.4. 对外部 IP 地址分配的限制

作为集群管理员,您可以指定 IP 地址块来允许和拒绝服务的 IP 地址。限制只针对没有 cluster-admin 权限的用户。集群管理员始终可以将服务 spec.externalIPs[] 字段设置为任何 IP 地址。

您可以通过在策略对象中为 spec.ExternalIP.policy 参数指定无类别域间路由(CIDR)地址块来配置 IP 地址 policy

policy 对象及其 CIDR 参数的 JSON 格式示例

{
  "policy": {
    "allowedCIDRs": [],
    "rejectedCIDRs": []
  }
}
Copy to Clipboard Toggle word wrap

在配置策略限制时,会应用以下规则:

  • 如果 policy 设置为 {},创建带有 spec.ExternalIPs[]Service 对象会导致服务失败。此设置是 OpenShift Container Platform 的默认设置。相同的行为存在于 policy: null
  • 如果设置了policy,并且设置了 policy.allowedCIDRs[]policy.rejectedCIDRs[],则应用以下规则:

    • 如果同时设置了 allowedCIDRs[]rejectedCIDRs[],则 rejectedCIDRs[] 优先于 allowedCIDRs[]
    • 如果设置了 allowedCIDRs[],只有在允许指定的 IP 地址时,创建带有 spec.ExternalIPs[]Service 对象才能成功。
    • 如果设置了 rejectedCIDRs[],只有在指定的 IP 地址未被拒绝时,创建带有 spec.ExternalIPs[]Service 对象才能成功。

2.2.5. 策略对象示例

本节中的示例显示不同的 spec.externalIP.policy 配置。

  • 在以下示例中,策略会阻止 OpenShift Container Platform 使用指定的外部 IP 地址创建任何服务。

    拒绝为 Service 对象 spec.externalIPs[] 指定的任何值的策略示例

    apiVersion: config.openshift.io/v1
    kind: Network
    metadata:
      name: cluster
    spec:
      externalIP:
        policy: {}
    # ...
    Copy to Clipboard Toggle word wrap

  • 在以下示例中,设置了 allowedCIDRsrejectedCIDRs 字段。

    包括允许和拒绝 CIDR 块的策略示例

    apiVersion: config.openshift.io/v1
    kind: Network
    metadata:
      name: cluster
    spec:
      externalIP:
        policy:
          allowedCIDRs:
          - 172.16.66.10/23
          rejectedCIDRs:
          - 172.16.66.10/24
    # ...
    Copy to Clipboard Toggle word wrap

  • 在以下示例中,policy 设置为 {}。使用这个配置,使用 oc get network.config.openshift.io -o yaml 命令查看配置意味着 policy 参数不会显示在命令输出上。相同的行为存在于 policy: null

    允许为 Service 对象 spec.externalIPs[]指定的任何值的示例策略

    apiVersion: config.openshift.io/v1
    kind: Network
    metadata:
      name: cluster
    spec:
      clusterNetwork:
      - cidr: 10.128.0.0/14
        hostPrefix: 23
      externalIP:
        policy: {}
    # ...
    Copy to Clipboard Toggle word wrap

2.2.6. ExternalIP 地址块配置

ExternalIP 地址块的配置由名为 cluster 的网络自定义资源(CR)定义。Network CR 是 config.openshift.io API 组的一部分。

重要

在集群安装过程中,Cluster Version Operator(CVO)会自动创建一个名为 cluster 的网络 CR。不支持创建此类型的任何其他 CR 对象。

以下 YAML 描述了 ExternalIP 配置:

network.config.openshift.io CR 名为 cluster

apiVersion: config.openshift.io/v1
kind: Network
metadata:
  name: cluster
spec:
  externalIP:
    autoAssignCIDRs: [] 
1

    policy: 
2

      ...
Copy to Clipboard Toggle word wrap

1
定义 CIDR 格式的 IP 地址块,可用于自动将外部 IP 地址分配给服务。只允许一个 IP 地址范围。
2
定义手动为服务分配 IP 地址的限制。如果没有定义限制,则不允许在 Service 对象中指定 spec.externalIP 字段。默认情况下,不会定义任何限制。

以下 YAML 描述了 policy 小节的字段:

network.config.openshift.io policy 小节

policy:
  allowedCIDRs: [] 
1

  rejectedCIDRs: [] 
2
Copy to Clipboard Toggle word wrap

1
CIDR 格式允许的 IP 地址范围列表。
2
CIDR 格式拒绝的 IP 地址范围列表。
2.2.6.1. 外部 IP 配置示例

以下示例中显示了外部 IP 地址池的一些可能配置:

  • 以下 YAML 描述了启用自动分配外部 IP 地址的配置:

    带有 spec.externalIP.autoAssignCIDRs 的配置示例

    apiVersion: config.openshift.io/v1
    kind: Network
    metadata:
      name: cluster
    spec:
      ...
      externalIP:
        autoAssignCIDRs:
        - 192.168.132.254/29
    Copy to Clipboard Toggle word wrap

  • 以下 YAML 为允许的和被拒绝的 CIDR 范围配置策略规则:

    带有 spec.externalIP.policy 的示例配置

    apiVersion: config.openshift.io/v1
    kind: Network
    metadata:
      name: cluster
    spec:
      ...
      externalIP:
        policy:
          allowedCIDRs:
          - 192.168.132.0/29
          - 192.168.132.8/29
          rejectedCIDRs:
          - 192.168.132.7/32
    Copy to Clipboard Toggle word wrap

2.2.7. 为集群配置外部 IP 地址块

作为集群管理员,可以配置以下 ExternalIP 设置:

  • OpenShift Container Platform 用来自动填充 Service 对象的 spec.clusterIP 字段的 ExternalIP 地址块。
  • 用于限制可手动分配给 Service 对象的 spec.clusterIP 数组的 IP 地址的策略对象。

先决条件

  • 安装 OpenShift CLI(oc)。
  • 使用具有 cluster-admin 角色的用户访问集群。

流程

  1. 可选: 要显示当前的外部 IP 配置,请输入以下命令:

    $ oc describe networks.config cluster
    Copy to Clipboard Toggle word wrap
  2. 要编辑配置,请输入以下命令:

    $ oc edit networks.config cluster
    Copy to Clipboard Toggle word wrap
  3. 修改 ExternalIP 配置,如下例所示:

    apiVersion: config.openshift.io/v1
    kind: Network
    metadata:
      name: cluster
    spec:
      ...
      externalIP: 
    1
    
      ...
    Copy to Clipboard Toggle word wrap
    1
    指定 externalIP 小节的配置。
  4. 要确认更新的 ExternalIP 配置,请输入以下命令:

    $ oc get networks.config cluster -o go-template='{{.spec.externalIP}}{{"\n"}}'
    Copy to Clipboard Toggle word wrap

2.2.9. 后续步骤

2.3. 使用 Ingress Controller 配置集群入口流量

OpenShift Container Platform 提供了从集群外部与集群中运行的服务进行通信的方法。此方法使用了 Ingress Controller。

2.3.1. 使用 Ingress Controller 和路由

Ingress Operator 管理 Ingress Controller 和通配符 DNS。

使用 Ingress Controller 是允许从外部访问 OpenShift Container Platform 集群的最常用方法。

Ingress Controller 配置为接受外部请求并根据配置的路由进行代理。这仅限于 HTTP、使用 SNI 的 HTTPS 以及使用 SNI 的 TLS,对于通过使用 SNI 的 TLS 工作的 Web 应用程序和服务而言已经足够。

与管理员合作将 Ingress Controller 配置为接受外部请求并根据配置的路由进行代理。

管理员可以创建通配符 DNS 条目,再设置 Ingress Controller。然后,您可以处理边缘 Ingress Controller,无需与管理员联系。

默认情况下,集群中的每个 Ingress Controller 都可以接受集群中任何项目中创建的所有路由。

Ingress Controller:

  • 默认有两个副本;即,它应该在两个 worker 节点上运行。
  • 可以纵向扩张,以在更多节点上具有更多副本。
注意

这部分中的流程需要由集群管理员执行先决条件。

2.3.2. 先决条件

在开始以下流程前,管理员必须:

  • 设置集群联网环境的外部端口,使请求能够到达集群。
  • 确定至少有一个用户具有集群管理员角色。要将此角色添加到用户,请运行以下命令:

    $ oc adm policy add-cluster-role-to-user cluster-admin username
    Copy to Clipboard Toggle word wrap
  • 有一个 OpenShift Container Platform 集群,其至少有一个 master 和至少一个节点,并且集群外有一个对集群具有网络访问权限的系统。此流程假设外部系统与集群位于同一个子网。不同子网上外部系统所需要的额外联网不在本主题的讨论范围内。

2.3.3. 创建项目和服务

如果要公开的项目和服务不存在,请创建项目,然后创建该服务。

如果项目和服务都已存在,跳到公开服务以创建路由这一步。

先决条件

  • 安装 OpenShift CLI (oc),并以集群管理员身份登录。

流程

  1. 运行 oc new-project 命令为您的服务创建一个新项目:

    $ oc new-project <project_name>
    Copy to Clipboard Toggle word wrap
  2. 使用 oc new-app 命令来创建服务:

    $ oc new-app nodejs:12~https://github.com/sclorg/nodejs-ex.git
    Copy to Clipboard Toggle word wrap
  3. 要验证该服务是否已创建,请运行以下命令:

    $ oc get svc -n <project_name>
    Copy to Clipboard Toggle word wrap

    输出示例

    NAME        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
    nodejs-ex   ClusterIP   172.30.197.157   <none>        8080/TCP   70s
    Copy to Clipboard Toggle word wrap

    注意

    默认情况下,新服务没有外部 IP 地址。

2.3.4. 通过创建路由公开服务

您可以使用 oc expose 命令,将服务公开为路由。

先决条件

  • 已登陆到 OpenShift Container Platform。

流程

  1. 登录您想公开的服务所在的项目:

    $ oc project <project_name>
    Copy to Clipboard Toggle word wrap
  2. 运行 oc expose service 命令以公开路由:

    $ oc expose service nodejs-ex
    Copy to Clipboard Toggle word wrap

    输出示例

    route.route.openshift.io/nodejs-ex exposed
    Copy to Clipboard Toggle word wrap

  3. 要验证该服务是否已公开,您可以使用 curl 等工具来检查该服务是否可从集群外部访问。

    1. 要查找路由的主机名,请输入以下命令:

      $ oc get route
      Copy to Clipboard Toggle word wrap

      输出示例

      NAME        HOST/PORT                        PATH   SERVICES    PORT       TERMINATION   WILDCARD
      nodejs-ex   nodejs-ex-myproject.example.com         nodejs-ex   8080-tcp                 None
      Copy to Clipboard Toggle word wrap

    2. 要检查主机是否响应 GET 请求,请输入以下命令:

      curl 命令示例

      $ curl --head nodejs-ex-myproject.example.com
      Copy to Clipboard Toggle word wrap

      输出示例

      HTTP/1.1 200 OK
      ...
      Copy to Clipboard Toggle word wrap

2.3.5. OpenShift Container Platform 中的 Ingress 分片

在 OpenShift Container Platform 中,Ingress Controller 可以服务所有路由,也可以提供路由的子集。默认情况下,Ingress Controller 提供集群中任何命名空间中创建的任何路由。您可以在集群中添加额外的 Ingress Controller,以通过创建 分片来优化路由,这些分片是基于所选特征的路由子集。要将路由标记为分片的成员,请使用 route 或 namespace metadata 字段中的标签。Ingress Controller 使用选择器 (也称为 选择表达式 )从要提供服务的整个路由池中选择路由子集。

当您希望在多个 Ingress Controller 之间负载平衡传入的流量时,当您要隔离到特定 Ingress Controller 的流量或下一部分中描述的各种其他原因时,Ingress 分片很有用。

默认情况下,每个路由都使用集群的默认域。但是,可以将路由配置为使用路由器的域。

2.3.6. Ingress Controller 分片

您可以通过向路由、命名空间或两者添加标签,使用 Ingress 分片(也称为路由器分片)在多个路由器之间分发一组路由。Ingress Controller 使用一组对应的选择器来只接受具有指定标签的路由。每个 Ingress 分片都由使用给定选择表达式过滤的路由组成。

Ingress Controller 是网络流量进入集群的主要机制,因此对它们的需求可能非常大。作为集群管理员,您可以对路由进行分片,以达到以下目的:

  • 在 Ingress Controller 或路由器与一些路由之间实现平衡,由此加快对变更的响应。
  • 分配特定的路由,使其具有不同于其它路由的可靠性保证。
  • 允许特定的 Ingress Controller 定义不同的策略。
  • 只允许特定的路由使用其他功能。
  • 在不同的地址上公开不同的路由,例如使内部和外部用户能够看到不同的路由。
  • 在蓝绿部署期间,将流量从应用的一个版本转移到另一个版本。

当 Ingress Controller 被分片时,一个给定路由被接受到组中的零个或多个 Ingress Controller。路由的状态描述了 Ingress Controller 是否已接受它。只有一个路由对一个分片是唯一的时,Ingress Controller 才会接受路由。

使用分片,您可以在多个 Ingress Controller 上分发路由子集。这些子集可以是非重叠的,也称为 传统 分片,或是重叠的,也称为 overlapped 分片。

下表概述了三分片方法:

Expand
分片方法描述

命名空间选择器

将命名空间选择器添加到 Ingress Controller 后,在与命名空间选择器匹配的命名空间中的所有路由都包含在 Ingress shard 中。当 Ingress Controller 提供在命名空间中创建的所有路由时,请考虑此方法。

路由选择器

将路由选择器添加到 Ingress Controller 后,所有与路由选择器匹配的标签的路由都包含在 Ingress shard 中。当您希望 Ingress Controller 仅服务命名空间中的路由子集或特定路由时,请考虑此方法。

命名空间和路由选择器

为命名空间选择器和路由选择器方法提供 Ingress Controller 范围。当您想获得命名空间选择器和路由选择器方法的灵活性时,请考虑此方法。

2.3.6.1. 传统分片示例

配置了 Ingress Controller finops-router 的示例,其标签选择器 spec.namespaceSelector.matchExpressions,其键值为 financeops

finops-router 的 YAML 定义示例

apiVersion: operator.openshift.io/v1
kind: IngressController
metadata:
  name: finops-router
  namespace: openshift-ingress-operator
spec:
  namespaceSelector:
    matchExpressions:
    - key: name
      operator: In
      values:
      - finance
      - ops
Copy to Clipboard Toggle word wrap

配置了 Ingress Controller dev-router 的示例,其标签选择器 spec.namespaceSelector.matchLabels.name,其键值为 dev

dev-router 的 YAML 定义示例

apiVersion: operator.openshift.io/v1
kind: IngressController
metadata:
  name: dev-router
  namespace: openshift-ingress-operator
spec:
  namespaceSelector:
    matchLabels:
      name: dev
Copy to Clipboard Toggle word wrap

如果所有应用程序路由都位于单独的命名空间中,每个命名空间都分别使用 name:financename:opsname:dev 标记,此配置会在两个 Ingress Controller 之间有效分发您的路由。不应处理用于控制台、身份验证和其他目的的 OpenShift Container Platform 路由。

在前面的场景中,分片成为分区的一种特殊情况,没有重叠的子集。路由在路由器分片之间划分。

警告

默认 Ingress Controller 继续提供所有路由,除非 namespaceSelectorrouteSelector 字段包含用于排除的路由。有关如何从默认 Ingress Controller 中排除路由的更多信息,请参阅这个 红帽知识库解决方案 和"分片默认 Ingress Controller"。

2.3.6.2. 重叠的分片示例

配置了 Ingress Controller devops-router 的示例,其标签选择器 spec.namespaceSelector.matchExpressions,其键值为 financeops

devops-router 的 YAML 定义示例

apiVersion: operator.openshift.io/v1
kind: IngressController
metadata:
  name: devops-router
  namespace: openshift-ingress-operator
spec:
  namespaceSelector:
    matchExpressions:
    - key: name
      operator: In
      values:
      - dev
      - ops
Copy to Clipboard Toggle word wrap

标签为 name:devname:ops 的命名空间中的路由现在由两个不同的 Ingress Controller 服务。使用这个配置,您有重叠的路由子集。

通过重叠的路由子集,您可以创建更复杂的路由规则。例如,您可以在向 devops-router 发送较低优先级的流量时,将优先级更高的流量放入专用的 finops-router

2.3.6.3. 分片默认 Ingress Controller

创建新的 Ingress shard 后,可能会接受到默认 Ingress Controller 接受的新 Ingress 分片的路由。这是因为默认 Ingress Controller 没有选择器,并默认接受所有路由。

您可以使用命名空间选择器或路由选择器来限制 Ingress Controller 使用特定标签提供路由。以下流程限制默认 Ingress Controller,使用命名空间选择器为新分片的 financeopsdev 提供。这为 Ingress 分片增加了额外的隔离。

重要

您必须在同一 Ingress Controller 上保留所有 OpenShift Container Platform 管理路由。因此,避免在排除这些基本路由的默认 Ingress Controller 中添加额外的选择器。

先决条件

  • 已安装 OpenShift CLI(oc)。
  • 您以项目管理员身份登录。

流程

  1. 运行以下命令来修改默认 Ingress Controller:

    $ oc edit ingresscontroller -n openshift-ingress-operator default
    Copy to Clipboard Toggle word wrap
  2. 编辑 Ingress Controller 以包含一个 namespaceSelector,它排除了任何 financeopsdev 标签的路由:

    apiVersion: operator.openshift.io/v1
    kind: IngressController
    metadata:
      name: default
      namespace: openshift-ingress-operator
    spec:
      namespaceSelector:
        matchExpressions:
          - key: name
            operator: NotIn
            values:
              - finance
              - ops
              - dev
    Copy to Clipboard Toggle word wrap

默认 Ingress Controller 不再提供标记为 name:financename:opsname:dev 的命名空间。

2.3.6.4. Ingress 分片和 DNS

集群管理员负责为项目中的每个路由器生成单独的 DNS 条目。路由器不会将未知路由转发到另一个路由器。

考虑以下示例:

  • 路由器 A 驻留在主机 192.168.0.5 上,并且具有 *.foo.com 的路由。
  • 路由器 B 驻留在主机 192.168.1.9 上,并且具有 *.example.com 的路由。

单独的 DNS 条目必须将 *.foo.com 解析为托管 Router A 和 *.example.com 的节点到托管路由器 B 的节点:

  • *.foo.com A IN 192.168.0.5
  • *.example.com A IN 192.168.1.9

使用路由标签进行 Ingress Controller 分片,意味着 Ingress Controller 提供由路由选择器选择的任意命名空间中的所有路由。

图 2.1. 使用路由标签进行 Ingress 分片

在一组 Ingress Controller 之间平衡传入的流量负载时,以及在将流量隔离到特定 Ingress Controller 时,Ingress Controller 分片会很有用处。例如,A 公司的流量使用一个 Ingress Controller,B 公司的流量则使用另外一个 Ingress Controller。

流程

  1. 编辑 router-internal.yaml 文件:

    apiVersion: operator.openshift.io/v1
    kind: IngressController
    metadata:
      name: sharded
      namespace: openshift-ingress-operator
    spec:
      domain: <apps-sharded.basedomain.example.net> 
    1
    
      nodePlacement:
        nodeSelector:
          matchLabels:
            node-role.kubernetes.io/worker: ""
      routeSelector:
        matchLabels:
          type: sharded
    Copy to Clipboard Toggle word wrap
    1
    指定 Ingress Controller 使用的域。此域必须与默认 Ingress Controller 域不同。
  2. 应用 Ingress Controller router-internal.yaml 文件:

    # oc apply -f router-internal.yaml
    Copy to Clipboard Toggle word wrap

    Ingress Controller 选择具有 type: sharded 标签的任意命名空间中的路由。

  3. 使用 router-internal.yaml 中配置的域创建新路由:

    $ oc expose svc <service-name> --hostname <route-name>.apps-sharded.basedomain.example.net
    Copy to Clipboard Toggle word wrap

使用命名空间标签进行 Ingress Controller 分片,意味着 Ingress Controller 提供由命名空间选择器选择的任意命名空间中的所有路由。

图 2.2. 使用命名空间标签进行 Ingress 分片

在一组 Ingress Controller 之间平衡传入的流量负载时,以及在将流量隔离到特定 Ingress Controller 时,Ingress Controller 分片会很有用处。例如,A 公司的流量使用一个 Ingress Controller,B 公司的流量则使用另外一个 Ingress Controller。

流程

  1. 编辑 router-internal.yaml 文件:

    $ cat router-internal.yaml
    Copy to Clipboard Toggle word wrap

    输出示例

    apiVersion: operator.openshift.io/v1
    kind: IngressController
    metadata:
      name: sharded
      namespace: openshift-ingress-operator
    spec:
      domain: <apps-sharded.basedomain.example.net> 
    1
    
      nodePlacement:
        nodeSelector:
          matchLabels:
            node-role.kubernetes.io/worker: ""
      namespaceSelector:
        matchLabels:
          type: sharded
    Copy to Clipboard Toggle word wrap

    1
    指定 Ingress Controller 使用的域。此域必须与默认 Ingress Controller 域不同。
  2. 应用 Ingress Controller router-internal.yaml 文件:

    $ oc apply -f router-internal.yaml
    Copy to Clipboard Toggle word wrap

    Ingress Controller 选择由命名空间选择器选择的具有 type: sharded 标签的任意命名空间中的路由。

  3. 使用 router-internal.yaml 中配置的域创建新路由:

    $ oc expose svc <service-name> --hostname <route-name>.apps-sharded.basedomain.example.net
    Copy to Clipboard Toggle word wrap
2.3.6.7. 为 Ingress Controller 分片创建路由

通过使用路由,您可以通过 URL 托管应用程序。Ingress Controller 分片有助于在一组 Ingress Controller 之间平衡传入的流量负载。它还可以将流量隔离到特定的 Ingress Controller。例如,A 公司的流量使用一个 Ingress Controller,B 公司的流量则使用另外一个 Ingress Controller。

以下流程描述了如何为 Ingress Controller 分片创建路由,使用 hello-openshift 应用程序作为示例。

先决条件

  • 已安装 OpenShift CLI(oc)。
  • 您以项目管理员身份登录。
  • 您有一个 web 应用来公开端口,以及侦听端口流量的 HTTP 或 TLS 端点。
  • 您已为分片配置了 Ingress Controller。

流程

  1. 运行以下命令,创建一个名为 hello-openshift 的项目:

    $ oc new-project hello-openshift
    Copy to Clipboard Toggle word wrap
  2. 运行以下命令,在项目中创建 pod:

    $ oc create -f https://raw.githubusercontent.com/openshift/origin/master/examples/hello-openshift/hello-pod.json
    Copy to Clipboard Toggle word wrap
  3. 运行以下命令,创建名为 hello-openshift 的服务:

    $ oc expose pod/hello-openshift
    Copy to Clipboard Toggle word wrap
  4. 创建名为 hello-openshift-route.yaml 的路由定义:

    为分片创建的路由的 YAML 定义

    apiVersion: route.openshift.io/v1
    kind: Route
    metadata:
      labels:
        type: sharded 
    1
    
      name: hello-openshift-edge
      namespace: hello-openshift
    spec:
      subdomain: hello-openshift 
    2
    
      tls:
        termination: edge
      to:
        kind: Service
        name: hello-openshift
    Copy to Clipboard Toggle word wrap

    1
    标签键及其对应标签值必须与 Ingress Controller 中指定的标签值匹配。在本例中,Ingress Controller 具有标签键和值 type: sharded
    2
    路由将使用 subdomain 字段的值公开。指定 subdomain 字段时,您必须保留主机名未设置。如果您同时指定了 hostsubdomain 字段,则路由将使用 host 字段的值,并忽略 subdomain 字段。
  5. 通过运行以下命令,使用 hello-openshift-route.yaml 创建到 hello-openshift 应用程序的路由:

    $ oc -n hello-openshift create -f hello-openshift-route.yaml
    Copy to Clipboard Toggle word wrap

验证

  • 使用以下命令获取路由的状态:

    $ oc -n hello-openshift get routes/hello-openshift-edge -o yaml
    Copy to Clipboard Toggle word wrap

    生成的 Route 资源应类似以下示例:

    输出示例

    apiVersion: route.openshift.io/v1
    kind: Route
    metadata:
      labels:
        type: sharded
      name: hello-openshift-edge
      namespace: hello-openshift
    spec:
      subdomain: hello-openshift
      tls:
        termination: edge
      to:
        kind: Service
        name: hello-openshift
    status:
      ingress:
      - host: hello-openshift.<apps-sharded.basedomain.example.net> 
    1
    
        routerCanonicalHostname: router-sharded.<apps-sharded.basedomain.example.net> 
    2
    
        routerName: sharded 
    3
    Copy to Clipboard Toggle word wrap

    1
    Ingress Controller 或路由器的主机名用于公开路由。host 字段的值由 Ingress Controller 自动决定,并使用它的域。在本例中,Ingress Controller 的域为 <apps-sharded.basedomain.example.net>
    2
    Ingress Controller 的主机名。如果没有设置主机名,则路由可以使用子域。当您指定子域时,会自动使用公开路由的 Ingress Controller 域。当路由由多个 Ingress Controller 公开时,路由由多个 URL 托管。
    3
    Ingress Controller 的名称。在本例中,Ingress Controller 的名称为 sharded
2.3.6.8. 其他资源

2.4. 配置 Ingress Controller 端点发布策略

endpointPublishingStrategy 用于向其他网络发布 Ingress Controller 端点,以启用负载均衡器集成,并提供对其他系统的访问。

重要

在 Red Hat OpenStack Platform (RHOSP)上,只有云供应商配置为创建健康监控器时,才支持 LoadBalancerService 端点发布策略。对于 RHOSP 16.2,只有在您使用 Amphora Octavia 供应商时,才能使用此策略。

如需更多信息,请参阅 RHOSP 安装文档中的"设置 RHOSP Cloud Controller Manager 选项"部分。

2.4.1. Ingress Controller 端点发布策略

NodePortService 端点发布策略

NodePortService 端点发布策略使用 Kubernetes NodePort 服务发布 Ingress Controller。

在这个配置中,Ingress Controller 部署使用容器网络。创建了一个 NodePortService 来发布部署。特定的节点端口由 OpenShift Container Platform 动态分配; 但是,为了支持静态端口分配,您会保留对受管 NodePortService 的节点端口字段的更改

图 2.3. NodePortService 图表

上图显示了与 OpenShift Container Platform Ingress NodePort 端点发布策略相关的以下概念:

  • 集群中的所有可用节点均有自己的外部可访问 IP 地址。集群中运行的服务绑定到所有节点的唯一 NodePort。
  • 当客户端连接到停机的节点时,例如,通过连接图形中的 10.0.128.4 IP 地址,节点端口将客户端直接连接到运行该服务的可用节点。在这种情况下,不需要负载平衡。如图形中所显,10.0.128.4 地址已不可用,必须使用另一个 IP 地址。
注意

Ingress Operator 忽略对服务的 .spec.ports[].nodePort 字段的任何更新。

默认情况下,端口会自动分配,您可以访问集成的端口分配。但是,有时需要静态分配端口来与现有基础架构集成,这些基础架构可能无法根据动态端口进行重新配置。要实现与静态节点端口的集成,您可以直接更新受管服务资源。

如需有关 daemonset 的更多信息,请参阅关于 NodePort 的 Kubernetes 服务文档

HostNetwork 端点发布策略

HostNetwork 端点发布策略会在部署 Ingress Controller 的节点端口上发布 Ingress Controller。

带有 HostNetwork 端点发布策略的 Ingress Controller 每个节点只能有一个 pod 副本。如果您想要 n 个副本,则必须至少使用可调度这些副本的 n 个节点。因为每个 Pod 副本都会通过调度的节点主机上的端口 80443 进行请求,所以如果同一节点上的其他 pod 使用这些端口,则无法将副本调度到该节点。

HostNetwork 对象有一个 hostNetwork 字段,它有以下用于可选绑定端口的默认值:httpPort: 80, httpsPort: 443, 和 statsPort: 1936。通过为您的网络指定不同的绑定端口,您可以为 HostNetwork 策略在同一节点上部署多个 Ingress Controller。

Example

apiVersion: operator.openshift.io/v1
kind: IngressController
metadata:
  name: internal
  namespace: openshift-ingress-operator
spec:
  domain: example.com
  endpointPublishingStrategy:
    type: HostNetwork
    hostNetwork:
      httpPort: 80
      httpsPort: 443
      statsPort: 1936
Copy to Clipboard Toggle word wrap

当集群管理员在没有指定集群为私有的情况下安装新集群时,将默认 Ingress Controller 创建,并将 scope 设置为 External。集群管理员可以将 External 范围的 Ingress Controller 更改为 Internal

先决条件

  • 已安装 oc CLI。

流程

  • 要将 External 范围的 Ingress Controller 更改为 Internal,请输入以下命令:

    $ oc -n openshift-ingress-operator patch ingresscontrollers/default --type=merge --patch='{"spec":{"endpointPublishingStrategy":{"type":"LoadBalancerService","loadBalancer":{"scope":"Internal"}}}}'
    Copy to Clipboard Toggle word wrap
  • 要检查 Ingress Controller 的状态,请输入以下命令:

    $ oc -n openshift-ingress-operator get ingresscontrollers/default -o yaml
    Copy to Clipboard Toggle word wrap
    • Progressing 状态条件指示您必须执行进一步的操作。例如,状态条件可以通过输入以下命令来指示需要删除该服务:

      $ oc -n openshift-ingress delete services/router-default
      Copy to Clipboard Toggle word wrap

      如果删除了该服务,Ingress Operator 会重新创建为 Internal

当集群管理员在没有指定集群为私有的情况下安装新集群时,将默认 Ingress Controller 创建,并将 scope 设置为 External

Ingress Controller 的范围可以在安装过程中或之后配置为 Internal,集群管理员可以将 内部 Ingress Controller 更改为 External

重要

在某些平台上,需要删除并重新创建服务。

更改范围可能会导致 Ingress 流量中断,这可能会持续几分钟。这适用于需要删除和重新创建服务的平台,因为流程可能会导致 OpenShift Container Platform 取消置备现有服务负载均衡器、置备一个新服务负载均衡器并更新 DNS。

先决条件

  • 已安装 oc CLI。

流程

  • 要将 内部范围的 Ingress Controller 更改为外部,请输入以下命令:

    $ oc -n openshift-ingress-operator patch ingresscontrollers/private --type=merge --patch='{"spec":{"endpointPublishingStrategy":{"type":"LoadBalancerService","loadBalancer":{"scope":"External"}}}}'
    Copy to Clipboard Toggle word wrap
  • 要检查 Ingress Controller 的状态,请输入以下命令:

    $ oc -n openshift-ingress-operator get ingresscontrollers/default -o yaml
    Copy to Clipboard Toggle word wrap
    • Progressing 状态条件指示您必须执行进一步的操作。例如,状态条件可以通过输入以下命令来指示需要删除该服务:

      $ oc -n openshift-ingress delete services/router-default
      Copy to Clipboard Toggle word wrap

      如果删除了该服务,Ingress Operator 会重新创建为 External

您可以创建自定义 Ingress Controller 以使用 NodePortService 端点发布策略,而不是为各个项目创建 NodePort 类型 Service。要防止端口冲突,在您要通过 Ingress 分片将一组路由应用到可能具有 HostNetwork Ingress Controller 的节点时,请考虑 Ingress Controller 的此配置。

在为每个项目设置 NodePort 类型 Service 前,请阅读以下注意事项:

  • 您必须为 Nodeport Ingress Controller 域创建一个通配符 DNS 记录。Nodeport Ingress Controller 路由可以从 worker 节点的地址访问。有关路由所需的 DNS 记录的更多信息,请参阅"用户置备 DNS 要求"。
  • 您必须为您的服务公开路由,并为自定义 Ingress Controller 域指定 --hostname 参数。
  • 您必须在路由中附加分配给 NodePort 类型 Service 的端口,以便您可以访问应用容器集。

先决条件

  • 已安装 OpenShift CLI(oc)。
  • 以具有 cluster-admin 权限的用户身份登录。
  • 您创建了通配符 DNS 记录。

流程

  1. 为 Ingress Controller 创建自定义资源 (CR) 文件:

    定义 IngressController 对象的信息的 CR 文件示例

    apiVersion: v1
    items:
    - apiVersion: operator.openshift.io/v1
      kind: IngressController
      metadata:
        name: <custom_ic_name> 
    1
    
        namespace: openshift-ingress-operator
      spec:
        replicas: 1
        domain: <custom_ic_domain_name> 
    2
    
        nodePlacement:
          nodeSelector:
            matchLabels:
              <key>: <value> 
    3
    
        namespaceSelector:
         matchLabels:
           <key>: <value> 
    4
    
        endpointPublishingStrategy:
          type: NodePortService
    # ...
    Copy to Clipboard Toggle word wrap

    1
    IngressController CR 指定一个自定义名称
    2
    Ingress Controller 服务的 DNS 名称。例如,默认的 ingresscontroller 域是 apps.ipi-cluster.example.com,因此您要将 <custom_ic_domain_name> 指定为 nodeportsvc.ipi-cluster.example.com
    3
    指定包含自定义 Ingress Controller 的节点的标签。
    4
    指定一组命名空间的标签。使用键值对替换 <key>:<value>,其中 <key> 是新标签的唯一名称,<value> 是它的值。例如:ingresscontroller: custom-ic
  2. 使用 oc label node 命令给节点添加标签:

    $ oc label node <node_name> <key>=<value> 
    1
    Copy to Clipboard Toggle word wrap
    1
    其中 <value> 必须与 IngressController CR 的 nodePlacement 部分中指定的键值对匹配。
  3. 创建 IngressController 对象:

    $ oc create -f <ingress_controller_cr>.yaml
    Copy to Clipboard Toggle word wrap
  4. 查找为 IngressController CR 创建的服务的端口:

    $ oc get svc -n openshift-ingress
    Copy to Clipboard Toggle word wrap

    显示 router-nodeport-custom-ic3 服务的端口 80:32432/TCP 的示例

    NAME                        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                                     AGE
    router-internal-default      ClusterIP   172.30.195.74    <none>        80/TCP,443/TCP,1936/TCP                     223d
    router-nodeport-custom-ic3   NodePort    172.30.109.219   <none>        80:32432/TCP,443:31366/TCP,1936:30499/TCP   155m
    Copy to Clipboard Toggle word wrap

  5. 要创建新项目,请输入以下命令:

    $ oc new-project <project_name>
    Copy to Clipboard Toggle word wrap
  6. 要标记新命名空间,请输入以下命令:

    $ oc label namespace <project_name> <key>=<value> 
    1
    Copy to Clipboard Toggle word wrap
    1
    其中 <key>=<value> 需要与 Ingress Controller CR 的 namespaceSelector 部分中的值匹配。
  7. 在集群中创建新应用程序:

    $ oc new-app --image=<image_name> 
    1
    Copy to Clipboard Toggle word wrap
    1
    一个 <image_name> 的示例是 quay.io/openshifttest/hello-openshift:multiarch
  8. 为服务创建 Route 对象,以便 pod 可以使用该服务向集群外部公开应用程序。

    $ oc expose svc/<service_name> --hostname=<svc_name>-<project_name>.<custom_ic_domain_name> 
    1
    Copy to Clipboard Toggle word wrap
    注意

    您必须在 --hostname 参数中指定自定义 Ingress Controller 的域名。如果没有这样做,Ingress Operator 会使用默认的 Ingress Controller 来提供集群的所有路由。

  9. 检查路由是否具有 Admitted 状态,并且包含自定义 Ingress Controller 的元数据:

    $ oc get route/hello-openshift -o json | jq '.status.ingress'
    Copy to Clipboard Toggle word wrap

    输出示例

    # ...
    {
      "conditions": [
        {
          "lastTransitionTime": "2024-05-17T18:25:41Z",
          "status": "True",
          "type": "Admitted"
        }
      ],
      [
        {
          "host": "hello-openshift.nodeportsvc.ipi-cluster.example.com",
          "routerCanonicalHostname": "router-nodeportsvc.nodeportsvc.ipi-cluster.example.com",
          "routerName": "nodeportsvc", "wildcardPolicy": "None"
        }
      ],
    }
    Copy to Clipboard Toggle word wrap

  10. 更新默认的 IngressController CR,以防止默认 Ingress Controller 管理 NodePort 类型 Service。默认 Ingress Controller 将继续监控所有其他集群流量。

    $ oc patch --type=merge -n openshift-ingress-operator ingresscontroller/default --patch '{"spec":{"namespaceSelector":{"matchExpressions":[{"key":"<key>","operator":"NotIn","values":["<value>]}]}}}'
    Copy to Clipboard Toggle word wrap

验证

  1. 输入以下命令验证 DNS 条目是否可以在集群内部和外部路由。命令输出之前从运行 oc label node 命令接收标签的节点的 IP 地址。

    $ dig +short <svc_name>-<project_name>.<custom_ic_domain_name>
    Copy to Clipboard Toggle word wrap
  2. 要验证集群是否使用来自外部 DNS 服务器的 IP 地址进行 DNS 解析,请输入以下命令检查集群的连接:

    $ curl <svc_name>-<project_name>.<custom_ic_domain_name>:<port> 
    1
    Copy to Clipboard Toggle word wrap
    1 1
    其中 <port> 是来自 NodePort 类型的 Service 的节点端口。根据 oc get svc -n openshift-ingress 命令的输出示例,80:32432/TCP HTTP 路由意味着 32432 是节点端口。

    输出示例

    Hello OpenShift!
    Copy to Clipboard Toggle word wrap

2.5. 使用负载均衡器配置集群入口流量

OpenShift Container Platform 提供了从集群外部与集群中运行的服务进行通信的方法。此方法使用了负载均衡器。

2.5.1. 使用负载均衡器使流量进入集群

如果不需要具体的外部 IP 地址,您可以配置负载均衡器服务,以便从外部访问 OpenShift Container Platform 集群。

负载均衡器服务分配唯一 IP。负载均衡器有单一边缘路由器 IP,它可以是虚拟 IP (VIP),但仍然是一台用于初始负载均衡的计算机。

注意

如果配置了池,则会在基础架构一级进行,而不是由集群管理员完成。

注意

这部分中的流程需要由集群管理员执行先决条件。

2.5.2. 先决条件

在开始以下流程前,管理员必须:

  • 设置集群联网环境的外部端口,使请求能够到达集群。
  • 确定至少有一个用户具有集群管理员角色。要将此角色添加到用户,请运行以下命令:

    $ oc adm policy add-cluster-role-to-user cluster-admin username
    Copy to Clipboard Toggle word wrap
  • 有一个 OpenShift Container Platform 集群,其至少有一个 master 和至少一个节点,并且集群外有一个对集群具有网络访问权限的系统。此流程假设外部系统与集群位于同一个子网。不同子网上外部系统所需要的额外联网不在本主题的讨论范围内。

2.5.3. 创建项目和服务

如果要公开的项目和服务不存在,请创建项目,然后创建该服务。

如果项目和服务都已存在,跳到公开服务以创建路由这一步。

先决条件

  • 安装 OpenShift CLI (oc),并以集群管理员身份登录。

流程

  1. 运行 oc new-project 命令为您的服务创建一个新项目:

    $ oc new-project <project_name>
    Copy to Clipboard Toggle word wrap
  2. 使用 oc new-app 命令来创建服务:

    $ oc new-app nodejs:12~https://github.com/sclorg/nodejs-ex.git
    Copy to Clipboard Toggle word wrap
  3. 要验证该服务是否已创建,请运行以下命令:

    $ oc get svc -n <project_name>
    Copy to Clipboard Toggle word wrap

    输出示例

    NAME        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
    nodejs-ex   ClusterIP   172.30.197.157   <none>        8080/TCP   70s
    Copy to Clipboard Toggle word wrap

    注意

    默认情况下,新服务没有外部 IP 地址。

2.5.4. 通过创建路由公开服务

您可以使用 oc expose 命令,将服务公开为路由。

先决条件

  • 已登陆到 OpenShift Container Platform。

流程

  1. 登录您想公开的服务所在的项目:

    $ oc project <project_name>
    Copy to Clipboard Toggle word wrap
  2. 运行 oc expose service 命令以公开路由:

    $ oc expose service nodejs-ex
    Copy to Clipboard Toggle word wrap

    输出示例

    route.route.openshift.io/nodejs-ex exposed
    Copy to Clipboard Toggle word wrap

  3. 要验证该服务是否已公开,您可以使用 curl 等工具来检查该服务是否可从集群外部访问。

    1. 要查找路由的主机名,请输入以下命令:

      $ oc get route
      Copy to Clipboard Toggle word wrap

      输出示例

      NAME        HOST/PORT                        PATH   SERVICES    PORT       TERMINATION   WILDCARD
      nodejs-ex   nodejs-ex-myproject.example.com         nodejs-ex   8080-tcp                 None
      Copy to Clipboard Toggle word wrap

    2. 要检查主机是否响应 GET 请求,请输入以下命令:

      curl 命令示例

      $ curl --head nodejs-ex-myproject.example.com
      Copy to Clipboard Toggle word wrap

      输出示例

      HTTP/1.1 200 OK
      ...
      Copy to Clipboard Toggle word wrap

2.5.5. 创建负载均衡器服务

使用以下流程来创建负载均衡器服务。

先决条件

  • 确保您要公开的项目和服务已经存在。
  • 您的云供应商支持负载均衡器。

流程

创建负载均衡器服务:

  1. 登录 OpenShift Container Platform。
  2. 加载您要公开的服务所在的项目。

    $ oc project project1
    Copy to Clipboard Toggle word wrap
  3. 在 control plane 节点上打开文本文件并粘贴以下文本,根据需要编辑该文件:

    负载均衡器配置文件示例

    apiVersion: v1
    kind: Service
    metadata:
      name: egress-2 
    1
    
    spec:
      ports:
      - name: db
        port: 3306 
    2
    
      loadBalancerIP:
      loadBalancerSourceRanges: 
    3
    
      - 10.0.0.0/8
      - 192.168.0.0/16
      type: LoadBalancer 
    4
    
      selector:
        name: mysql 
    5
    Copy to Clipboard Toggle word wrap

    1
    为负载均衡器服务输入一个描述性名称。
    2
    输入您要公开的服务所侦听的同一个端口。
    3
    输入特定 IP 地址列表来限制通过负载均衡器的流量。如果 cloud-provider 不支持这个功能,则此字段将被忽略。
    4
    输入 Loadbalancer 作为类型。
    5
    输入服务的名称。
    注意

    要将通过负载均衡器的流量限制到特定的 IP 地址,建议使用 Ingress Controller 字段 spec.endpointPublishingStrategy.loadBalancer.allowedSourceRanges。不要设置 loadBalancerSourceRanges 字段。

  4. 保存并退出 文件。
  5. 运行以下命令来创建服务:

    $ oc create -f <file-name>
    Copy to Clipboard Toggle word wrap

    例如:

    $ oc create -f mysql-lb.yaml
    Copy to Clipboard Toggle word wrap
  6. 执行以下命令以查看新服务:

    $ oc get svc
    Copy to Clipboard Toggle word wrap

    输出示例

    NAME       TYPE           CLUSTER-IP      EXTERNAL-IP                             PORT(S)          AGE
    egress-2   LoadBalancer   172.30.22.226   ad42f5d8b303045-487804948.example.com   3306:30357/TCP   15m
    Copy to Clipboard Toggle word wrap

    如果启用了云供应商,该服务会自动分配到一个外部 IP 地址。

  7. 在 master 上,使用 cURL 等工具来确保您可以通过公共 IP 地址访问该服务:

    $ curl <public-ip>:<port>
    Copy to Clipboard Toggle word wrap

    例如:

    $ curl 172.29.121.74:3306
    Copy to Clipboard Toggle word wrap

    此部分中的示例使用 MySQL 服务,这需要客户端应用程序。如果您得到一串字符并看到 Got packets out of order 消息,则您已连接到该服务:

    如果您有 MySQL 客户端,请使用标准 CLI 命令登录:

    $ mysql -h 172.30.131.89 -u admin -p
    Copy to Clipboard Toggle word wrap

    输出示例

    Enter password:
    Welcome to the MariaDB monitor.  Commands end with ; or \g.
    
    MySQL [(none)]>
    Copy to Clipboard Toggle word wrap

2.6. 在 AWS 上配置集群入口流量

OpenShift Container Platform 提供了从集群外部与集群中运行的服务进行通信的方法。此方法使用 AWS 上的负载均衡器,特别是 Network Load Balancer(NLB)或 Classic Load Balancer(CLB)。两种负载均衡器都可以将客户端的 IP 地址转发到节点,但 CLB 需要支持代理协议(OpenShift Container Platform 会自动启用)。

将 Ingress Controller 配置为使用 NLB 的方法有两种:

  1. 通过强制替换当前使用 CLB 的 Ingress Controller。这会删除 IngressController 对象,并在新的 DNS 记录传播并置备 NLB 时发生停机。
  2. 通过编辑使用 CLB 的现有 Ingress Controller 以使用 NLB。这会更改负载均衡器而无需删除并重新创建 IngressController 对象。

两种方法都可用于从 NLB 切换到 CLB。

您可以在新的或现有 AWS 集群上配置这些负载均衡器。

2.6.1. 在 AWS 中配置 Classic Load Balancer 超时

OpenShift Container Platform 提供了为特定路由或 Ingress Controller 设置自定义超时时间的方法。另外,AWS Classic Load Balancer(CLB)都有自己的超时时间,默认的超时时间为 60 秒。

如果 CLB 的超时时间小于路由超时或 Ingress Controller 超时,负载均衡器可以预先终止连接。您可以通过增加路由和 CLB 的超时周期来防止此问题。

2.6.1.1. 配置路由超时

如果您的服务需要低超时(满足服务级别可用性 (SLA) 目的)或高超时(具有慢速后端的情况),您可以为现有路由配置默认超时。

重要

如果您在 OpenShift Container Platform 集群前面配置了用户管理的外部负载均衡器,请确保用户管理的外部负载均衡器的超时值高于路由的超时值。此配置可防止集群使用的网络的网络出现网络拥塞问题。

先决条件

  • 您需要在运行的集群中部署了 Ingress Controller。

流程

  • 使用 oc annotate 命令,为路由添加超时:

    $ oc annotate route <route_name> \
        --overwrite haproxy.router.openshift.io/timeout=<timeout><time_unit> 
    1
    Copy to Clipboard Toggle word wrap
    1
    支持的时间单位是微秒 (us)、毫秒 (ms)、秒钟 (s)、分钟 (m)、小时 (h)、或天 (d)。

    以下示例在名为 myroute 的路由上设置两秒的超时:

    $ oc annotate route myroute --overwrite haproxy.router.openshift.io/timeout=2s
    Copy to Clipboard Toggle word wrap
2.6.1.2. 配置 Classic Load Balancer 超时

您可以为 Classic Load Balancer(CLB)配置默认超时来扩展闲置连接。

先决条件

  • 您必须在正在运行的集群中部署了 Ingress Controller。

流程

  1. 运行以下命令,为默认的 ingresscontroller 设置 AWS 连接闲置超时:

    $ oc -n openshift-ingress-operator patch ingresscontroller/default \
        --type=merge --patch='{"spec":{"endpointPublishingStrategy": \
        {"type":"LoadBalancerService", "loadBalancer": \
        {"scope":"External", "providerParameters":{"type":"AWS", "aws": \
        {"type":"Classic", "classicLoadBalancer": \
        {"connectionIdleTimeout":"5m"}}}}}}}'
    Copy to Clipboard Toggle word wrap
  2. 可选:运行以下命令来恢复超时的默认值:

    $ oc -n openshift-ingress-operator patch ingresscontroller/default \
        --type=merge --patch='{"spec":{"endpointPublishingStrategy": \
        {"loadBalancer":{"providerParameters":{"aws":{"classicLoadBalancer": \
        {"connectionIdleTimeout":null}}}}}}}'
    Copy to Clipboard Toggle word wrap
注意

在更改连接超时值时,您必须指定 scope 字段,除非已经设置了当前范围。设置 scope 字段时,如果恢复默认的超时值,则不需要再次这样做。

OpenShift Container Platform 提供了从集群外部与集群中运行的服务进行通信的方法。一个这样的方法是使用 Network Load Balancer(NLB)。您可以在新的或现有 AWS 集群上配置 NLB。

您可以将使用 Classic Load Balancer (CLB) 的 Ingress Controller 切换到使用 AWS 上的网络负载平衡器 (NLB) 的 Ingress Controller。

在这些负载均衡器间切换不会删除 IngressController 对象。

警告

此过程可能会导致以下问题:

  • 由于新的 DNS 记录传播、新的负载均衡器置备和其他因素而可能需要几分钟的中断。应用此步骤后,Ingress Controller 负载均衡器的 IP 地址和规范名称可能会改变。
  • 由于服务注解的变化,会泄漏负载均衡器资源。

流程

  1. 修改您要使用 NLB 切换到的现有 Ingress Controller。这个示例假定您的默认 Ingress Controller 具有外部范围,且没有其他自定义:

    ingresscontroller.yaml 文件示例

    apiVersion: operator.openshift.io/v1
    kind: IngressController
    metadata:
      creationTimestamp: null
      name: default
      namespace: openshift-ingress-operator
    spec:
      endpointPublishingStrategy:
        loadBalancer:
          scope: External
          providerParameters:
            type: AWS
            aws:
              type: NLB
        type: LoadBalancerService
    Copy to Clipboard Toggle word wrap

    注意

    如果您没有为 spec.endpointPublishingStrategy.loadBalancer.providerParameters.aws.type 字段指定值,Ingress Controller 会使用在安装过程中设置的集群 Ingress 配置中的 spec.loadBalancer.platform.aws.type 值。

    提示

    如果您的 Ingress Controller 有其他要更新的自定义(如更改域),请考虑强制替换 Ingress Controller 定义文件。

  2. 运行以下命令,将更改应用到 Ingress Controller YAML 文件:

    $ oc apply -f ingresscontroller.yaml
    Copy to Clipboard Toggle word wrap

    当 Ingress Controller 更新时,可能会有几分钟的停机。

在 AWS 中,您可以将使用 Network Load Balancer (NLB) 的 Ingress Controller 切换到使用 Classic Load Balancer (CLB) 的 Ingress Controller。

在这些负载均衡器间切换不会删除 IngressController 对象。

警告

此流程会导致预期的中断会因为新的 DNS 记录传播、新的负载均衡器置备和其他因素而可能需要几分钟。应用此步骤后,Ingress Controller 负载均衡器的 IP 地址和规范名称可能会改变。

流程

  1. 修改您要切换为使用 CLB 的现有 Ingress Controller。这个示例假定您的默认 Ingress Controller 具有外部范围,且没有其他自定义:

    ingresscontroller.yaml 文件示例

    apiVersion: operator.openshift.io/v1
    kind: IngressController
    metadata:
      creationTimestamp: null
      name: default
      namespace: openshift-ingress-operator
    spec:
      endpointPublishingStrategy:
        loadBalancer:
          scope: External
          providerParameters:
            type: AWS
            aws:
              type: Classic
        type: LoadBalancerService
    Copy to Clipboard Toggle word wrap

    注意

    如果您没有为 spec.endpointPublishingStrategy.loadBalancer.providerParameters.aws.type 字段指定值,Ingress Controller 会使用在安装过程中设置的集群 Ingress 配置中的 spec.loadBalancer.platform.aws.type 值。

    提示

    如果您的 Ingress Controller 有其他要更新的自定义(如更改域),请考虑强制替换 Ingress Controller 定义文件。

  2. 运行以下命令,将更改应用到 Ingress Controller YAML 文件:

    $ oc apply -f ingresscontroller.yaml
    Copy to Clipboard Toggle word wrap

    当 Ingress Controller 更新时,可能会有几分钟的停机。

您可以将使用 Classic 负载平衡器(CLB)的 Ingress Controller 替换为 AWS 上使用网络负载平衡器(NLB)的 Ingress Controller。

警告

此过程可能会导致以下问题:

  • 由于新的 DNS 记录传播、新的负载均衡器置备和其他因素而可能需要几分钟的中断。应用此步骤后,Ingress Controller 负载均衡器的 IP 地址和规范名称可能会改变。
  • 由于服务注解的变化,会泄漏负载均衡器资源。

流程

  1. 创建一个新的默认 Ingress Controller 文件。以下示例假定您的默认 Ingress Controller 具有外部范围,且没有其他自定义:

    ingresscontroller.yml 文件示例

    apiVersion: operator.openshift.io/v1
    kind: IngressController
    metadata:
      creationTimestamp: null
      name: default
      namespace: openshift-ingress-operator
    spec:
      endpointPublishingStrategy:
        loadBalancer:
          scope: External
          providerParameters:
            type: AWS
            aws:
              type: NLB
        type: LoadBalancerService
    Copy to Clipboard Toggle word wrap

    如果您的默认 Ingress Controller 有其他自定义,请确定您相应地修改该文件。

    提示

    如果您的 Ingress Controller 没有其他自定义,且您只更新负载均衡器类型,请考虑 "Switch the Ingress Controller from using an Classic Load Balancer to a Network Load Balancer" 中详述的步骤。

  2. 强制替换 Ingress Controller YAML 文件:

    $ oc replace --force --wait -f ingresscontroller.yml
    Copy to Clipboard Toggle word wrap

    等待 Ingress Controller 已被替换。预计会有几分钟的停机时间。

您可以在当前集群中创建一个由 AWS Network Load Balancer(NLB)支持的 Ingress Controller。

先决条件

  • 您必须已安装 AWS 集群。
  • 基础架构资源的 PlatformStatus 需要是 AWS。

    • 要验证 PlatformStatus 是否为 AWS,请运行:

      $ oc get infrastructure/cluster -o jsonpath='{.status.platformStatus.type}'
      AWS
      Copy to Clipboard Toggle word wrap

流程

在现有集群中,创建一个由 AWS NLB 支持的 Ingress Controller。

  1. 创建 Ingress Controller 清单:

     $ cat ingresscontroller-aws-nlb.yaml
    Copy to Clipboard Toggle word wrap

    输出示例

    apiVersion: operator.openshift.io/v1
    kind: IngressController
    metadata:
      name: $my_ingress_controller
    1
    
      namespace: openshift-ingress-operator
    spec:
      domain: $my_unique_ingress_domain
    2
    
      endpointPublishingStrategy:
        type: LoadBalancerService
        loadBalancer:
          scope: External
    3
    
          providerParameters:
            type: AWS
            aws:
              type: NLB
    Copy to Clipboard Toggle word wrap

    1
    $my_ingress_controller 替换为 Ingress Controller 的唯一名称。
    2
    $my_unique_ingress_domain 替换为集群中所有 Ingress Controller 的唯一域名。此变量需要是 DNS 名的子域 <clustername>.<domain>
    3
    您可以将 External 替换为 Internal,以使用内部 NLB。
  2. 在集群中创建资源:

    $ oc create -f ingresscontroller-aws-nlb.yaml
    Copy to Clipboard Toggle word wrap
重要

在新 AWS 集群上配置 Ingress Controller NLB 之前,您必须完成 创建安装配置文件 的步骤。

您可在新集群中创建一个由 AWS Network Load Balancer(NLB)支持的 Ingress Controller。

先决条件

  • 创建 install-config.yaml 文件并完成对其所做的任何修改。

流程

在新集群中,创建一个由 AWS NLB 支持的 Ingress Controller。

  1. 进入包含安装程序的目录并创建清单:

    $ ./openshift-install create manifests --dir <installation_directory> 
    1
    Copy to Clipboard Toggle word wrap
    1
    对于 <installation_directory>,请指定含有集群的 install-config.yaml 文件的目录的名称。
  2. <installation_directory>/manifests/ 目录中创建一个名为 cluster-ingress-default-ingresscontroller.yaml 的文件:

    $ touch <installation_directory>/manifests/cluster-ingress-default-ingresscontroller.yaml 
    1
    Copy to Clipboard Toggle word wrap
    1
    对于 <installation_directory>,请指定包含集群的 manifests/ 目录的目录名称。

    创建该文件后,几个网络配置文件位于 manifests/ 目录中,如下所示:

    $ ls <installation_directory>/manifests/cluster-ingress-default-ingresscontroller.yaml
    Copy to Clipboard Toggle word wrap

    输出示例

    cluster-ingress-default-ingresscontroller.yaml
    Copy to Clipboard Toggle word wrap

  3. 在编辑器中打开 cluster-ingress-default-ingresscontroller.yaml 文件,并输入描述您想要的 Operator 配置的自定义资源(CR):

    apiVersion: operator.openshift.io/v1
    kind: IngressController
    metadata:
      creationTimestamp: null
      name: default
      namespace: openshift-ingress-operator
    spec:
      endpointPublishingStrategy:
        loadBalancer:
          scope: External
          providerParameters:
            type: AWS
            aws:
              type: NLB
        type: LoadBalancerService
    Copy to Clipboard Toggle word wrap
  4. 保存 cluster-ingress-default-ingresscontroller.yaml 文件并退出文本编辑器。
  5. 可选:备份 manifests/cluster-ingress-default-ingresscontroller.yaml 文件。创建集群时,安装程序会删除 manifests/ 目录。

您可以为现有集群中的 Ingress Controller 手动指定负载均衡器子网。默认情况下,AWS 会自动发现负载均衡器子网,但在 Ingress Controller 中指定会覆盖它们,从而允许手动进行控制。

先决条件

  • 您必须已安装 AWS 集群。
  • 您必须知道要映射 IngressController 的子网的名称或 ID。

流程

  1. 创建自定义资源(CR)文件。

    使用以下内容创建 YAML 文件(如 sample-ingress.yaml):

    apiVersion: operator.openshift.io/v1
    kind: IngressController
    metadata:
      namespace: openshift-ingress-operator
      name: <name>
    spec:
      domain: <domain>
      endpointPublishingStrategy:
        type: LoadBalancerService
        loadBalancer:
          scope: External
      dnsManagementPolicy: Managed
    Copy to Clipboard Toggle word wrap
  2. 创建自定义资源(CR)文件。

    在 YAML 文件中添加子网:

    apiVersion: operator.openshift.io/v1
    kind: IngressController
    metadata:
      name:  <name> 
    1
    
      namespace: openshift-ingress-operator
    spec:
      domain: <domain> 
    2
    
      endpointPublishingStrategy:
        type: LoadBalancerService
        loadBalancer:
          scope: External
          providerParameters:
            type: AWS
            aws:
              type: Classic
              classicLoadBalancer: 
    3
    
                subnets:
                  ids: 
    4
    
                  - <subnet> 
    5
    
                  - <subnet>
                  - <subnet>
    dnsManagementPolicy: Managed
    Copy to Clipboard Toggle word wrap
    1
    <name> 替换为 IngressController 的名
    2
    <domain> 替换为由 IngressController 管理的服务的 DNS 名称。
    3
    如果使用 NLB,您还可以使用 networkLoadBalancer 字段。
    4
    您可以使用 name 字段通过名称指定子网,而不是使用 ID 来指定子网。
    5
    指定子网 ID (或名称,如果使用了 names)。
    重要

    您可以为每个可用区最多指定一个子网。仅为内部 Ingress Controller 提供外部 Ingress Controller 和专用子网。

  3. 应用 CR 文件。

    1. 保存文件并使用 OpenShift CLI (oc) 应用。

      $  oc apply -f sample-ingress.yaml
      Copy to Clipboard Toggle word wrap
    2. 通过检查 IngressController 条件确认负载均衡器已被成功置备。

      $ oc get ingresscontroller -n openshift-ingress-operator <name> -o jsonpath="{.status.conditions}" | yq -PC
      Copy to Clipboard Toggle word wrap
2.6.2.7. 更新现有 Ingress Controller 上的子网

您可以使用 OpenShift Container Platform 中手动指定的负载均衡器子网更新 IngressController,以避免中断,以保持服务的稳定性,并确保网络配置与您的特定要求保持一致。以下流程演示了如何选择和应用新子网,验证配置更改,并确认负载均衡器置备成功。

警告

此流程会导致预期的中断会因为新的 DNS 记录传播、新的负载均衡器置备和其他因素而可能需要几分钟。应用此步骤后,Ingress Controller 负载均衡器的 IP 地址和规范名称可能会改变。

流程

要使用手动指定的负载均衡器子网更新 IngressController,您可以按照以下步骤执行:

  1. 修改现有 IngressController 以更新到新子网。

    apiVersion: operator.openshift.io/v1
    kind: IngressController
    metadata:
      name:  <name> 
    1
    
      namespace: openshift-ingress-operator
    spec:
      domain: <domain> 
    2
    
      endpointPublishingStrategy:
        type: LoadBalancerService
        loadBalancer:
          scope: External
          providerParameters:
            type: AWS
            aws:
              type: Classic 
    3
    
              classicLoadBalancer: 
    4
    
                subnets:
                  ids: 
    5
    
                  - <updated_subnet> 
    6
    
                  - <updated_subnet>
                  - <updated_subnet>
    Copy to Clipboard Toggle word wrap
    1
    <name> 替换为 IngressController 的名
    2
    <domain> 替换为由 IngressController 管理的服务的 DNS 名称。
    3
    指定更新的子网 ID (或名称,如果使用了 names)。
    4
    如果使用 NLB,您还可以使用 networkLoadBalancer 字段。
    5
    您可以使用 name 字段通过名称指定子网,而不是使用 ID 来指定子网。
    6
    更新子网 ID (或名称,如果使用了 names)。
    重要

    您可以为每个可用区最多指定一个子网。仅为内部 Ingress Controller 提供外部 Ingress Controller 和专用子网。

  2. 运行以下命令,检查 IngressController 上的 Progressing 条件以获取如何应用子网更新的说明:

    $ oc get ingresscontroller -n openshift-ingress-operator subnets -o jsonpath="{.status.conditions[?(@.type==\"Progressing\")]}" | yq -PC
    Copy to Clipboard Toggle word wrap

    输出示例

    lastTransitionTime: "2024-11-25T20:19:31Z"
    message: 'One or more status conditions indicate progressing: LoadBalancerProgressing=True (OperandsProgressing: One or more managed resources are progressing: The IngressController subnets were changed from [...] to [...].  To effectuate this change, you must delete the service: `oc -n openshift-ingress delete svc/router-<name>`; the service load-balancer will then be deprovisioned and a new one created. This will most likely cause the new load-balancer to have a different host name and IP address and cause disruption. To return to the previous state, you can revert the change to the IngressController: [...]'
    reason: IngressControllerProgressing
    status: "True"
    type: Progressing
    Copy to Clipboard Toggle word wrap

  3. 要应用更新,请运行以下命令删除与 Ingress 控制器关联的服务:
$ oc -n openshift-ingress delete svc/router-<name>
Copy to Clipboard Toggle word wrap

验证

  • 要确认负载均衡器已被成功置备,请运行以下命令来检查 IngressController 条件:

    $ oc get ingresscontroller -n openshift-ingress-operator <name> -o jsonpath="{.status.conditions}" | yq -PC
    Copy to Clipboard Toggle word wrap

您可以在 Ingress Controller 中为网络负载均衡器(NLB)指定静态 IP (也称为弹性 IP)。这在您要为集群网络配置适当的防火墙规则时很有用。

先决条件

  • 您必须已安装 AWS 集群。
  • 您必须知道要映射 IngressController 的子网的名称或 ID。

流程

  1. 创建一个包含以下内容的 YAML 文件:

    sample-ingress.yaml

    apiVersion: operator.openshift.io/v1
    kind: IngressController
    metadata:
      namespace: openshift-ingress-operator
      name: <name> 
    1
    
    spec:
      domain: <domain> 
    2
    
      endpointPublishingStrategy:
        loadBalancer:
          scope: External 
    3
    
          type: LoadBalancerService
          providerParameters:
            type: AWS
            aws:
              type: NLB
              networkLoadBalancer:
                subnets: 
    4
    
                  ids:
                  - <subnet_ID>
                  names:
                  - <subnet_A>
                  - <subnet_B>
                eipAllocations: 
    5
    
                - <eipalloc_A>
                - <eipalloc_B>
                - <eipalloc_C>
    Copy to Clipboard Toggle word wrap

    1
    使用 Ingress Controller 的名称替换 <name> 占位符。
    2
    <domain> 占位符替换为 Ingress Controller 服务的 DNS 名称。
    3
    范围必须设置为 External 的值,并面向互联网,才能分配 EIP。
    4
    指定子网的 ID 和名称。ID 和名称的总数必须等于您分配的 EIP。
    5
    指定 EIP 地址。
    重要

    您可以为每个可用区最多指定一个子网。仅为外部 Ingress Controller 提供公共子网。您可以为每个子网关联一个 EIP 地址。

  2. 输入以下命令保存并应用 CR 文件:

    $  oc apply -f sample-ingress.yaml
    Copy to Clipboard Toggle word wrap

验证

  1. 运行以下命令,检查 IngressController 条件来确认负载均衡器是否已成功置备:

    $ oc get ingresscontroller -n openshift-ingress-operator <name> -o jsonpath="{.status.conditions}" | yq -PC
    Copy to Clipboard Toggle word wrap

2.7. 为服务外部 IP 配置 ingress 集群流量

您可以使用 MetalLB 实现或 IP 故障转移部署,将 ExternalIP 资源附加到服务,以便该服务可用于 OpenShift Container Platform 集群外的流量。以这种方式托管外部 IP 地址仅适用于在裸机硬件上安装的集群。

您必须确保正确配置外部网络基础架构,将流量路由到该服务。

2.7.1. 先决条件

  • 您的集群被配置为启用了 ExternalIP。如需更多信息,请参阅为服务配置 ExternalIPs

    注意

    对于 egress IP,不要使用相同的 ExternalIP。

2.7.2. 将 ExternalIP 附加到服务

您可以将 ExternalIP 资源附加到服务。如果您将集群配置为自动将资源附加到服务,您可能不需要手动将 ExternalIP 附加到该服务。

此流程中的示例使用 IP 故障转移配置手动将 ExternalIP 资源附加到集群中的服务。

流程

  1. 在 CLI 中输入以下命令来确认 ExternalIP 资源的兼容 IP 地址范围:

    $ oc get networks.config cluster -o jsonpath='{.spec.externalIP}{"\n"}'
    Copy to Clipboard Toggle word wrap
    注意

    如果设置了 autoAssignCIDRs,且您没有在 ExternalIP 资源中为 spec.externalIPs 指定值,OpenShift Container Platform 会自动将 ExternalIP 分配给新的 Service 对象。

  2. 选择以下选项之一将 ExternalIP 资源附加到服务:

    1. 如果要创建新服务,请在 spec.externalIPs 字段中指定一个值,在 allowedCIDRs 参数中指定一个包括一个或多个有效 IP 地址的数组。

      支持 ExternalIP 资源的服务 YAML 配置文件示例

      apiVersion: v1
      kind: Service
      metadata:
        name: svc-with-externalip
      spec:
        externalIPs:
          policy:
            allowedCIDRs:
            - 192.168.123.0/28
      Copy to Clipboard Toggle word wrap

    2. 如果您要将 ExternalIP 附加到现有服务中,请输入以下命令。将 <name> 替换为服务名称。将 <ip_address> 替换为有效的 ExternalIP 地址。您可以提供多个以逗号分开的 IP 地址。

      $ oc patch svc <name> -p \
        '{
          "spec": {
            "externalIPs": [ "<ip_address>" ]
          }
        }'
      Copy to Clipboard Toggle word wrap

      例如:

      $ oc patch svc mysql-55-rhel7 -p '{"spec":{"externalIPs":["192.174.120.10"]}}'
      Copy to Clipboard Toggle word wrap

      输出示例

      "mysql-55-rhel7" patched
      Copy to Clipboard Toggle word wrap

  3. 要确认一个 ExternalIP 地址已附加到该服务,请输入以下命令。如果为新服务指定 ExternalIP,您必须首先创建该服务。

    $ oc get svc
    Copy to Clipboard Toggle word wrap

    输出示例

    NAME               CLUSTER-IP      EXTERNAL-IP     PORT(S)    AGE
    mysql-55-rhel7     172.30.131.89   192.174.120.10  3306/TCP   13m
    Copy to Clipboard Toggle word wrap

2.8. 使用 NodePort 配置集群入口流量

OpenShift Container Platform 提供了从集群外部与集群中运行的服务进行通信的方法。此方法使用了 NodePort

2.8.1. 使用 NodePort 使流量进入集群

使用 NodePort 类型的 Service 资源,在集群中所有节点的特定端口上公开服务。端口在 Service 资源的 .spec.ports[*].nodePort 字段中指定。

重要

使用节点端口需要额外的端口资源。

NodePort 在节点 IP 地址的静态端口上公开服务。默认情况下,NodePort3000032767 的范围内,这意味着,NodePort 不可能与服务的预期端口匹配。例如:端口 8080 可能会在节点的端口 31020 中公开。

管理员必须确保外部 IP 地址路由到节点。

NodePort 和外部 IP 地址互相独立,可以同时使用它们。

注意

这部分中的流程需要由集群管理员执行先决条件。

2.8.2. 先决条件

在开始以下流程前,管理员必须:

  • 设置集群联网环境的外部端口,使请求能够到达集群。
  • 确定至少有一个用户具有集群管理员角色。要将此角色添加到用户,请运行以下命令:

    $ oc adm policy add-cluster-role-to-user cluster-admin <user_name>
    Copy to Clipboard Toggle word wrap
  • 有一个 OpenShift Container Platform 集群,其至少有一个 master 和至少一个节点,并且集群外有一个对集群具有网络访问权限的系统。此流程假设外部系统与集群位于同一个子网。不同子网上外部系统所需要的额外联网不在本主题的讨论范围内。

2.8.3. 创建项目和服务

如果要公开的项目和服务不存在,请创建项目,然后创建该服务。

如果项目和服务都已存在,跳到公开服务以创建路由这一步。

先决条件

  • 安装 OpenShift CLI (oc),并以集群管理员身份登录。

流程

  1. 运行 oc new-project 命令为您的服务创建一个新项目:

    $ oc new-project <project_name>
    Copy to Clipboard Toggle word wrap
  2. 使用 oc new-app 命令来创建服务:

    $ oc new-app nodejs:12~https://github.com/sclorg/nodejs-ex.git
    Copy to Clipboard Toggle word wrap
  3. 要验证该服务是否已创建,请运行以下命令:

    $ oc get svc -n <project_name>
    Copy to Clipboard Toggle word wrap

    输出示例

    NAME        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
    nodejs-ex   ClusterIP   172.30.197.157   <none>        8080/TCP   70s
    Copy to Clipboard Toggle word wrap

    注意

    默认情况下,新服务没有外部 IP 地址。

2.8.4. 通过创建路由公开服务

您可以使用 oc expose 命令,将服务公开为路由。

先决条件

  • 已登陆到 OpenShift Container Platform。

流程

  1. 登录您想公开的服务所在的项目:

    $ oc project <project_name>
    Copy to Clipboard Toggle word wrap
  2. 要为应用程序公开节点端口,请输入以下命令修改服务的自定义资源定义 (CRD):

    $ oc edit svc <service_name>
    Copy to Clipboard Toggle word wrap

    输出示例

    spec:
      ports:
      - name: 8443-tcp
        nodePort: 30327 
    1
    
        port: 8443
        protocol: TCP
        targetPort: 8443
      sessionAffinity: None
      type: NodePort 
    2
    Copy to Clipboard Toggle word wrap

    1
    可选:指定应用程序的节点端口范围。默认情况下,OpenShift Container Platform 在 30000-32767 范围内选择一个可用端口。
    2
    定义服务类型。
  3. 可选: 要使用公开的节点端口确认该服务可用,请输入以下命令:

    $ oc get svc -n myproject
    Copy to Clipboard Toggle word wrap

    输出示例

    NAME                TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
    nodejs-ex           ClusterIP   172.30.217.127   <none>        3306/TCP         9m44s
    nodejs-ex-ingress   NodePort    172.30.107.72    <none>        3306:31345/TCP   39s
    Copy to Clipboard Toggle word wrap

  4. 可选: 要删除由 oc new-app 命令自动创建的服务,请输入以下命令:

    $ oc delete svc nodejs-ex
    Copy to Clipboard Toggle word wrap

验证

  • 要检查服务节点端口是否已使用 30000-32767 范围内的端口更新,请输入以下命令:

    $ oc get svc
    Copy to Clipboard Toggle word wrap

    在以下示例输出中,更新的端口为 30327

    输出示例

    NAME    TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
    httpd   NodePort   172.xx.xx.xx    <none>        8443:30327/TCP   109s
    Copy to Clipboard Toggle word wrap

您可以为 IngressController 指定 IP 地址范围列表。这在 endpointPublishingStrategyLoadBalancerService 时,限制访问负载均衡器服务。

2.9.1. 配置负载均衡器允许的源范围

您可以启用并配置 spec.endpointPublishingStrategy.loadBalancer.allowedSourceRanges 字段。通过配置负载均衡器允许的源范围,您可以将 Ingress Controller 的负载均衡器的访问限制为指定的 IP 地址范围列表。Ingress Operator 协调负载均衡器服务,并根据 AllowedSourceRanges 设置 spec.loadBalancerSourceRanges 字段。

注意

如果您已经在 OpenShift Container Platform 的早期版本中设置了 spec.loadBalancerSourceRanges 字段或负载均衡器服务 anotation service.beta.kubernetes.io/load-balancer-source-ranges,Ingress Controller 会在升级后开始报告 Progressing=True。要解决这个问题,设置覆盖 spec.loadBalancerSourceRanges 字段的 AllowedSourceRanges,并清除 service.beta.kubernetes.io/load-balancer-source-ranges 注解。Ingress Controller 开始报告 Progressing=False

先决条件

  • 您需要在正在运行的集群中部署了 Ingress Controller。

流程

  • 运行以下命令,为 Ingress Controller 设置允许的源范围 API:

    $ oc -n openshift-ingress-operator patch ingresscontroller/default \
        --type=merge --patch='{"spec":{"endpointPublishingStrategy": \
        {"type":"LoadBalancerService", "loadbalancer": \
        {"scope":"External", "allowedSourceRanges":["0.0.0.0/0"]}}}}' 
    1
    Copy to Clipboard Toggle word wrap
    1
    示例值 0.0.0.0/0 指定允许的源范围。

2.9.2. 迁移到允许的源范围

如果您已经设置了注解 service.beta.kubernetes.io/load-balancer-source-ranges,您可以迁移到允许负载均衡器的源范围。当您设置 AllowedSourceRanges 时,Ingress Controller 根据 AllowedSourceRanges 值设置 spec.loadBalancerSourceRanges 字段,并取消设置 service.beta.kubernetes.io/load-balancer-source-ranges 注解。

注意

如果您已经在 OpenShift Container Platform 的早期版本中设置了 spec.loadBalancerSourceRanges 字段或负载均衡器服务 anotation service.beta.kubernetes.io/load-balancer-source-ranges,Ingress Controller 会在升级后开始报告 Progressing=True。要解决这个问题,设置覆盖 spec.loadBalancerSourceRanges 字段的 AllowedSourceRanges,并清除 service.beta.kubernetes.io/load-balancer-source-ranges 注解。Ingress Controller 再次开始报告 Progressing=False

先决条件

  • 您已设置了 service.beta.kubernetes.io/load-balancer-source-ranges 注解。

流程

  1. 确保设置了 service.beta.kubernetes.io/load-balancer-source-ranges

    $ oc get svc router-default -n openshift-ingress -o yaml
    Copy to Clipboard Toggle word wrap

    输出示例

    apiVersion: v1
    kind: Service
    metadata:
      annotations:
        service.beta.kubernetes.io/load-balancer-source-ranges: 192.168.0.1/32
    Copy to Clipboard Toggle word wrap

  2. 确保 spec.loadBalancerSourceRanges 字段已取消设置:

    $ oc get svc router-default -n openshift-ingress -o yaml
    Copy to Clipboard Toggle word wrap

    输出示例

    ...
    spec:
      loadBalancerSourceRanges:
      - 0.0.0.0/0
    ...
    Copy to Clipboard Toggle word wrap

  3. 将集群更新至 OpenShift Container Platform 4.20。
  4. 运行以下命令,为 ingresscontroller 设置允许的源范围 API:

    $ oc -n openshift-ingress-operator patch ingresscontroller/default \
        --type=merge --patch='{"spec":{"endpointPublishingStrategy": \
        {"loadBalancer":{"allowedSourceRanges":["0.0.0.0/0"]}}}}' 
    1
    Copy to Clipboard Toggle word wrap
    1
    示例值 0.0.0.0/0 指定允许的源范围。

2.10. 修补现有入口对象

您可以在不重新创建对象或中断服务的情况下更新或修改现有 Ingress 对象的以下字段:

  • Specifications
  • Host
  • 路径
  • 后端服务
  • SSL/TLS 设置
  • 注解

ingressClassName 字段指定 IngressClass 对象的名称。您必须为每个 Ingress 对象定义 ingressClassName 字段。

如果您还没有为 Ingress 对象定义 ingressClassName 字段,您可能会遇到路由问题。24 小时后,您将收到 ingressWithoutClassName 警报,以提醒您设置 ingressClassName 字段。

流程

使用完成的 ingressClassName 字段对 Ingress 对象进行补丁,以确保正确路由和功能。

  1. 列出所有 IngressClass 对象:

    $ oc get ingressclass
    Copy to Clipboard Toggle word wrap
  2. 列出所有命名空间中的所有 Ingress 对象:

    $ oc get ingress -A
    Copy to Clipboard Toggle word wrap
  3. Ingress 对象进行补丁:

    $ oc patch ingress/<ingress_name> --type=merge --patch '{"spec":{"ingressClassName":"openshift-default"}}'
    Copy to Clipboard Toggle word wrap

    <ingress_name> 替换为 Ingress 对象的名称。此命令对 Ingress 对象进行补丁,使其包含所需的入口类名称。

2.11. 将 Load Balancers 分配给特定的子网

您可以通过分配负载均衡器来有效地管理应用程序流量。网络管理员可以分配负载均衡器来自定义部署,这些部署可以确保最佳流量分布、应用程序高可用性、不间断的服务和网络分段。

您可以通过显式定义虚拟私有云(VPC)子网,并在 install-config.yaml 文件的 platform.aws.vpc.subnets 部分中直接为其分配特定的角色,从而控制 OpenShift Load Balancers (包括 Ingress Controller 的网络放置)。此方法提供对将哪些子网用于资源(如 Ingress Controller 和其他集群组件)的粒度控制。

执行以下步骤将 API 和入口负载均衡器分配给特定的子网。

先决条件

在开始前,请确定您有:

  • 现有的 AWS 虚拟私有云(VPC)。
  • 预先配置的 AWS 子网供 OpenShift 集群使用,请考虑以下事项:

    • 您有一个其子网 ID 列表(例如 subnet-0123456789abcdef0)。这些 ID 将在 install-config.yaml 文件中使用。
    • 使用至少跨越两个可用区(AZ)的子网来实现负载均衡器和其他关键组件(如 control plane)的高可用性。
    • 您在这些子网中有足够的可用 IP 地址用于所有分配的角色。
    • 这些子网的 AWS 配置(包括网络 ACL 和安全组)必须允许分配给它们的所有角色所需的流量。对于托管入口控制器的子网,这通常包括来自所需源的 TCP 端口 80 和 443。
  • 有目标 OpenShift 版本的 OpenShift 安装程序二进制文件。
  • 您有一个 install-config.yaml 文件。

流程

  1. 准备 install-config.yaml 文件:

    如果您还没有这样做,请使用 OpenShift 安装程序生成安装配置文件:

    $ openshift-install create install-config --dir=<your_installation_directory>
    Copy to Clipboard Toggle word wrap

    此命令在指定目录中创建 install-config.yaml 文件。

  2. 定义子网并分配角色:

    使用文本编辑器打开位于 < your_installation_directory > 中的 install-config.yaml 文件。您将在 platform.aws.vpc.subnets 字段中定义您的 VPC 子网及其指定角色。

    对于您要使用集群的每个 AWS 子网,您将创建一个条目,指定其 id角色列表。每个角色都是带有 type 键的对象。要为默认 Ingress Controller 指定子网,请为它分配一个 类型为 IngressControllerLB 的角色。

    apiVersion: v1
    baseDomain: example.com 
    1
    
    metadata:
      name: my-cluster # Example cluster name
    platform:
      aws:
        region: us-east-1 
    2
    
        vpc: 
    3
    
          subnets: 
    4
    
          - id: subnet-0fcf8e0392f0910d5 # Public Subnet in AZ us-east-1a 
    5
    
            roles:
            - type: IngressControllerLB 
    6
    
            - type: BootstrapNode
          - id: subnet-0xxxxxxxxxxxxxxza # Public Subnet in another AZ for HA
            roles:
            - type: IngressControllerLB
          - id: subnet-0fcf8e0392f0910d4 # Private Subnet in AZ us-east-1a
            roles:
            - type: ClusterNode 
    7
    
          - id: subnet-0yyyyyyyyyyyyyyzb # Private Subnet in another AZ for HA
            roles:
            - type: ClusterNode
          # Add other subnet IDs and their roles as needed for your cluster architecture
    pullSecret: '...' 
    8
    
    sshKey: '...' 
    9
    Copy to Clipboard Toggle word wrap
    1
    您的基域。
    2
    您的 AWS 区域。
    3
    platform.aws 下的 vpc 对象包含 subnets 列表。
    4
    OpenShift 将要使用的所有子网对象的列表。每个对象定义一个子网 id 及其角色。
    5
    使用您的 AWS 子网 ID 替换。
    6
    type: IngressControllerLB 角色专门用于为默认 Ingress Controller 的 LoadBalancer 指定这个子网。在私有/内部集群中,带有 IngressControllerLB 角色的子网必须是私有。
    7
    type: ClusterNode 角色为 control plane 和计算节点指定这个子网。这些通常是专用子网。
    8
    您的 pull secret。
    9
    您的 SSH 密钥。

    子网 列表中 control plane 负载均衡器的条目遵循类似的模式:

    # ... (within platform.aws.vpc.subnets list)
          - id: subnet-0fcf8e0392f0910d6 # Public Subnet for External API LB
            roles:
            - type: ControlPlaneExternalLB
          - id: subnet-0fcf8e0392f0910d7 # Private Subnet for Internal API LB
            roles:
            - type: ControlPlaneInternalLB
    # ...
    Copy to Clipboard Toggle word wrap

    对于默认公共 Ingress Controller,在 install-config.yaml 文件中分配了 IngressControllerLB 角色的任何子网都必须是公共子网。例如,必须在 AWS 中有一个路由表条目,用于将出站流量定向到互联网网关(IGW)。

    确保您在 AZ 中列出所有必要的子网、公共和私有子网,并根据集群架构分配适当的角色。

    子网 ID 在现有 VPC 中定义子网,并可选择性地指定它们的预期角色。如果在任何子网上没有指定角色,则会自动决定子网角色。在这种情况下,VPC 不得包含没有 kubernetes.io/cluster/<cluster-id> 标签的任何其他非集群子网。

    如果为子网指定角色,每个子网必须至少有一个分配的角色,并且 ClusterNodeBootstrapNodeIngressControllerLBControlPlaneExternalLBControlPlaneInternalLB 角色必须至少分配给一个子网。但是,如果集群范围是内部的,则不需要 ControlPlaneExternalLB

  3. 继续集群安装:

    将更改保存到 install-config.yaml 文件后,创建集群:

    $ openshift-install create cluster --dir=<your_installation_directory>
    Copy to Clipboard Toggle word wrap

    安装程序现在使用 install-config.yaml 文件的 platform.aws.vpc.subnets 部分中的子网定义和显式角色分配来置备集群资源,包括将 Ingress Controller 的 LoadBalancer 放置到您使用 IngressControllerLB 角色指定的子网中。

注意

platform.aws.vpc.subnets 中的角色分配机制,如 IngressControllerLB,ClusterNode,ControlPlaneExternalLB,ControlPlaneInternalLB,BootstrapNode 是 OpenShift 安装程序标识适合不同集群服务和组件的类型。

2.12. 了解 DNS 管理策略

作为集群管理员,在创建 Ingress Controller 时,Operator 会自动管理 DNS 记录。当所需的 DNS 区域与集群 DNS 区域不同或 DNS 区域被托管在云供应商时,这有一些限制。

2.12.1. Managed DNS 管理策略

Ingress Controller 的 Managed DNS 管理策略可确保云供应商上通配符 DNS 记录的生命周期由 Operator 自动管理。这是默认的行为。

当您将 Ingress Controller 从 Managed 改为 Unmanaged DNS 管理策略时,Operator 不会清理在云中置备的以前的通配符 DNS 记录。

当您将 Ingress Controller 从 Unmanaged 改为 Managed DNS 管理策略时,Operator 会尝试在云供应商上创建 DNS 记录(如果不存在),或更新 DNS 记录(如果已存在)。

2.12.2. Unmanaged DNS 管理策略

Ingress Controller 的 Unmanaged DNS 管理策略可确保云供应商上的通配符 DNS 记录的生命周期不会自动管理,而是由集群管理员负责。

2.12.3. 为手动 DNS 管理创建 Ingress Controller

作为集群管理员,您可以使用 Unmanaged DNS 管理策略创建新的自定义 Ingress Controller。

先决条件

  • 已安装 OpenShift CLI(oc)。
  • 您以具有 cluster-admin 权限的用户身份登录。

流程

  1. 使用以下内容创建 IngressController 自定义资源(CR)文件,名为 sample-ingress.yaml

    apiVersion: operator.openshift.io/v1
    kind: IngressController
    metadata:
      namespace: openshift-ingress-operator
      name: <name> 
    1
    
    spec:
      domain: <domain> 
    2
    
      endpointPublishingStrategy:
        type: LoadBalancerService
        loadBalancer:
          scope: External 
    3
    
          dnsManagementPolicy: Unmanaged 
    4
    Copy to Clipboard Toggle word wrap
    1
    使用 IngressController 对象的名称指定 <name>
    2
    根据作为前提条件创建的 DNS 记录指定 domain
    3
    scope 指定为 External,以在外部公开负载均衡器。
    4
    dnsManagementPolicy 表示 Ingress Controller 是否管理与负载均衡器关联的通配符 DNS 记录的生命周期。有效值为 ManagedUnmanaged。默认值为 Managed
  2. 应用清单以创建 IngressController 对象:

    $ oc apply -f sample-ingress.yaml
    Copy to Clipboard Toggle word wrap
  3. 运行以下命令,验证 Ingress Controller 是否已创建了正确的策略:

    $ oc get ingresscontroller <name> -n openshift-ingress-operator -o=jsonpath={.spec.endpointPublishingStrategy.loadBalancer}
    Copy to Clipboard Toggle word wrap

    检查输出,并确认 dnsManagementPolicy 已设置为 Unmanaged

2.12.4. 为手动 DNS 管理修改现有 Ingress Controller

作为集群管理员,您可以修改现有 Ingress Controller 以手动管理 DNS 记录生命周期。

先决条件

  • 已安装 OpenShift CLI(oc)。
  • 您以具有 cluster-admin 权限的用户身份登录。

流程

  1. 修改所选 Ingress Controller 来设置 dnsManagementPolicy 参数:

    $ SCOPE=$(oc -n openshift-ingress-operator get ingresscontroller <name> -o=jsonpath="{.status.endpointPublishingStrategy.loadBalancer.scope}")
    
    $ oc -n openshift-ingress-operator patch ingresscontrollers/default --type=merge --patch="{\"spec\":{\"endpointPublishingStrategy\":{\"type\":\"LoadBalancerService\",\"loadBalancer\":{\"dnsManagementPolicy\":\"Unmanaged\", \"scope\":\"${SCOPE}\"}}}}"
    ingresscontroller.operator.openshift.io/default patched
    Copy to Clipboard Toggle word wrap
  2. 运行以下命令验证 Ingress Controller 是否已正确修改:

    $ oc get ingresscontroller <name> -n openshift-ingress-operator -o=jsonpath={.spec.endpointPublishingStrategy.loadBalancer}
    Copy to Clipboard Toggle word wrap

    检查输出,并确认 dnsManagementPolicy 已设置为 Unmanaged

OpenShift Container Platform 提供了将网关 API 与 Ingress Operator 搭配使用配置网络流量的额外方法。

重要

网关 API 不支持用户定义的网络(UDN)。

2.13.1. Gateway API 概述

网关 API 是一种开源、社区管理的 Kubernetes 网络机制。它侧重于集群的传输层、L4 和应用程序层 L7 中的路由。各种供应商 提供许多网关 API 实施

该项目通过使用具有广泛社区支持的可移植 API 来提供标准化生态系统。通过将网关 API 功能集成到 Ingress Operator 中,它实现了与现有社区和上游开发工作一致的网络解决方案。

gateway API 扩展 Ingress Operator 的功能,以处理更精细的集群流量和路由配置。使用这些功能,您可以创建网关 API 自定义资源定义(CRD)的实例。对于 OpenShift Container Platform 集群,Ingress Operator 会创建以下资源:

网关
这个资源描述了如何将流量转换为集群中的服务。例如,一个特定的负载均衡器配置。
GatewayClass
此资源定义一组 共享通用 配置和行为的网关对象。例如,可以创建两个单独的 Gateway Class 对象来区分用于公共或私有应用程序的网关资源。
HTTPRoute
此资源指定从网关到服务的 HTTP 请求的路由行为,对于多路 HTTP 或已终止的 HTTPS 连接特别有用。
GRPCRoute
此资源指定 gRPC 请求的路由行为。
ReferenceGrant
此资源启用跨命名空间引用。例如,它允许路由将流量转发到位于不同命名空间中的后端。

在 OpenShift Container Platform 中,网关 API 的实现基于 gateway.networking.k8s.io/v1,且此版本中的所有字段都被支持。

2.13.1.1. 网关 API 的优点

网关 API 提供以下优点:

  • 可移植性:虽然 OpenShift Container Platform 使用 HAProxy 提高 Ingress 性能,但 Gateway API 不依赖于特定于供应商的注解来提供某些行为。要获得与 HAProxy 相同的性能,网关 对象需要水平扩展,或者需要垂直扩展其关联的节点。
  • 关注点:网关 API 对资源使用基于角色的方法,更必要地适合大型机构如何构建职责和团队。平台工程师可能专注于 Gateway Class 资源,集群管理员可能专注于配置网关资源,应用程序开发人员可能会专注于使用 HTTPRoute 资源路由其服务。
  • 可扩展性:额外的功能是作为标准化 CRD 开发的。
2.13.1.2. 网关 API 的限制

网关 API 有以下限制:

  • 版本不兼容:网关 API 生态系统快速变化,一些实现无法用于其他的实现,因为它们的功能集基于不同的网关 API 版本。
  • 资源开销:除了更灵活的,网关 API 使用多种资源类型来实现结果。对于较小的应用程序,传统 Ingress 的简洁性可能更好适合。

2.13.2. OpenShift Container Platform 的网关 API 实现

Ingress Operator 管理网关 API CRD 的生命周期,以便其他厂商实现使用 OpenShift Container Platform 集群中定义的 CRD。

在某些情况下,网关 API 提供一个或多个供应商实现不支持的字段,但该实现与其余字段在架构中兼容。这些"意外字段"可能会导致 Ingress 工作负载中断、不正确的置备应用程序和服务以及与安全相关的问题。由于 OpenShift Container Platform 使用特定版本的 Gateway API CRD,因此任何使用网关 API 的第三方实现都必须符合 OpenShift Container Platform 的实现,以确保所有字段都能正常工作。

在 OpenShift Container Platform 4.20 集群中创建的任何 CRD 都兼容,由 Ingress Operator 维护。如果 CRD 已存在但没有由 Ingress Operator 管理,Ingress Operator 会检查这些配置是否与 OpenShift Container Platform 支持的网关 API 版本兼容,并创建一个您需要确认 CRD 的 admin-gate。

重要

如果您要从包含 Gateway API CRD 的以前的 OpenShift Container Platform 版本更新集群,请更改这些资源,以便它们与 OpenShift Container Platform 支持的版本完全匹配。否则,您无法更新集群,因为这些 CRD 不是由 OpenShift Container Platform 管理,并可能包含红帽不支持的功能。

2.13.3. Ingress Operator 的 Gateway API 入门

当您在第一步中创建 GatewayClass 时,它会配置网关 API 以便在集群中使用。

流程

  1. 创建 GatewayClass 对象:

    1. 创建一个 YAML 文件 openshift-default.yaml,其中包含以下信息:

      GatewayClass CR 示例

      apiVersion: gateway.networking.k8s.io/v1
      kind: GatewayClass
      metadata:
        name: openshift-default
      spec:
        controllerName: openshift.io/gateway-controller/v1 
      1
      Copy to Clipboard Toggle word wrap

      1
      控制器名称。
      重要

      控制器名称必须与 Ingress Operator 显示完全相同,才能管理它。如果将此字段设置为任何其他对象,Ingress Operator 会忽略 Gateway Class 对象和所有关联的网关、GRPCRouteHTTPRoute 对象。控制器名称与 OpenShift Container Platform 中的网关 API 实施关联,openshift.io/gateway-controller/v1 是允许的唯一控制器名称。

    2. 运行以下命令来创建 GatewayClass 资源:

      $ oc create -f openshift-default.yaml
      Copy to Clipboard Toggle word wrap

      输出示例

      gatewayclass.gateway.networking.k8s.io/openshift-default created
      Copy to Clipboard Toggle word wrap

      在创建 GatewayClass 资源期间,Ingress Operator 会在 openshift-ingress 命名空间中安装一个轻量级版本的 Red Hat OpenShift Service Mesh、Istio 自定义资源和新部署。

    3. 可选:验证新部署 istiod-openshift-gateway 是否已就绪并可用:

      $ oc get deployment -n openshift-ingress
      Copy to Clipboard Toggle word wrap

      输出示例

      NAME                       READY   UP-TO-DATE   AVAILABLE   AGE
      istiod-openshift-gateway   1/1     1            1           55s
      router-default             2/2     2            2           6h4m
      Copy to Clipboard Toggle word wrap

  2. 运行以下命令来创建 secret:

    $ oc -n openshift-ingress create secret tls gwapi-wildcard --cert=wildcard.crt --key=wildcard.key
    Copy to Clipboard Toggle word wrap
  3. 运行以下命令,获取 Ingress Operator 的域:

    $ DOMAIN=$(oc get ingresses.config/cluster -o jsonpath={.spec.domain})
    Copy to Clipboard Toggle word wrap
  4. 创建网关 对象

    1. 创建一个 YAML 文件 example-gateway.yaml,其中包含以下信息:

      Gateway CR 示例

      apiVersion: gateway.networking.k8s.io/v1
      kind: Gateway
      metadata:
        name: example-gateway
        namespace: openshift-ingress 
      1
      
      spec:
        gatewayClassName: openshift-default 
      2
      
        listeners:
        - name: https 
      3
      
          hostname: "*.gwapi.${DOMAIN}" 
      4
      
          port: 443
          protocol: HTTPS
          tls:
            mode: Terminate
            certificateRefs:
            - name: gwapi-wildcard 
      5
      
          allowedRoutes:
            namespaces:
              from: All
      Copy to Clipboard Toggle word wrap

      1
      Gateway 对象必须在 openshift-ingress 命名空间中创建。
      2
      Gateway 对象必须引用之前创建的 GatewayClass 对象的名称。
      3
      HTTPS 侦听与集群域子域匹配的 HTTPS 请求。您可以使用此监听程序,通过网关 API HTTPRoute 资源为应用程序配置入口。
      4
      主机名必须是 Ingress Operator 域的子域。如果使用域,则监听器会尝试提供该域中的所有流量。
      5
      之前创建的 secret 的名称。
    2. 运行以下命令来应用资源:

      $ oc apply -f example-gateway.yaml
      Copy to Clipboard Toggle word wrap
    3. 可选:当您创建 网关 对象时,Red Hat OpenShift Service Mesh 会自动置备具有相同名称的部署和服务。运行以下命令验证:

      • 要验证部署,请运行以下命令:

        $ oc get deployment -n openshift-ingress example-gateway-openshift-default
        Copy to Clipboard Toggle word wrap

        输出示例

        NAME                                 READY   UP-TO-DATE   AVAILABLE   AGE
        example-gateway-openshift-default    1/1     1            1           25s
        Copy to Clipboard Toggle word wrap

      • 要验证该服务,请运行以下命令:

        $ oc get service -n openshift-ingress example-gateway-openshift-default
        Copy to Clipboard Toggle word wrap

        输出示例

        NAME                                TYPE           CLUSTER-IP   EXTERNAL-IP         PORT(S)      AGE
        example-gateway-openshift-default   LoadBalancer   10.1.2.3     <external_ipname>   <port_info>  47s
        Copy to Clipboard Toggle word wrap

    4. 可选:Ingress Operator 使用监听程序的主机名自动创建 DNSRecord CR,并添加标签 gateway.networking.k8s.io/gateway-name=example-gateway。运行以下命令,验证 DNS 记录的状态:

      $ oc -n openshift-ingress get dnsrecord -l gateway.networking.k8s.io/gateway-name=example-gateway -o yaml
      Copy to Clipboard Toggle word wrap

      输出示例

      kind: DNSRecord
        ...
      status:
        ...
        zones:
        - conditions:
          - message: The DNS provider succeeded in ensuring the record
            reason: ProviderSuccess
            status: "True"
            type: Published
          dnsZone:
            tags:
              ...
        - conditions:
          - message: The DNS provider succeeded in ensuring the record
            reason: ProviderSuccess
            status: "True"
            type: Published
          dnsZone:
            id: ...
      Copy to Clipboard Toggle word wrap

  5. 创建一个 HTTPRoute 资源,将请求定向到您已创建了 example-app/example-app 的应用程序:

    1. 创建一个 YAML 文件 example-route.yaml,其中包含以下信息:

      HTTPRoute CR 示例

      apiVersion: gateway.networking.k8s.io/v1
      kind: HTTPRoute
      metadata:
        name: example-route
        namespace: example-app-ns 
      1
      
      spec:
        parentRefs: 
      2
      
        - name: example-gateway
          namespace: openshift-ingress
        hostnames: ["example.gwapi.${DOMAIN}"] 
      3
      
        rules:
        - backendRefs: 
      4
      
          - name: example-app 
      5
      
            port: 8443
      Copy to Clipboard Toggle word wrap

      1
      部署应用程序的命名空间。
      2
      此字段必须指向您之前配置的 Gateway 对象。
      3
      主机名必须与 网关 对象中指定的主机名匹配。在这种情况下,监听程序使用通配符主机名。
      4
      此字段指定指向您的服务的后端引用。
      5
      应用程序的 Service 的名称。
    2. 运行以下命令来应用资源:

      $ oc apply -f example-route.yaml
      Copy to Clipboard Toggle word wrap

      输出示例

      httproute.gateway.networking.k8s.io/example-route created
      Copy to Clipboard Toggle word wrap

验证

  1. 运行以下命令验证 Gateway 对象是否已部署,并具有编程 程序

    $ oc wait -n openshift-ingress --for=condition=Programmed gateways.gateway.networking.k8s.io example-gateway
    Copy to Clipboard Toggle word wrap

    输出示例

    gateway.gateway.networking.k8s.io/example-gateway condition met
    Copy to Clipboard Toggle word wrap

  2. 向配置的 HTTPRoute 对象主机名发送请求:

    $ curl -I --cacert <local cert file> https://example.gwapi.${DOMAIN}:443
    Copy to Clipboard Toggle word wrap

2.13.4. 网关 API 部署拓扑

网关 API 设计为使用两个拓扑,即共享网关或专用网关。每个拓扑都有自己的优点和不同的安全影响。

专用网关
路由和任何负载均衡器或代理都从同一命名空间提供。Gateway 对象将路由限制到特定的应用程序命名空间。这是在 OpenShift Container Platform 中部署网关 API 资源时的默认拓扑。
共享网关
路由由多个命名空间提供,或使用多个主机名提供。Gateway 对象过滤器允许使用 spec.listeners.allowedRoutes.namespaces 字段从应用程序命名空间中路由。
2.13.4.1. 专用网关示例

以下示例显示了专用 网关资源 fin-gateway

专用 网关资源 示例

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: fin-gateway
  namespace: openshift-ingress
spec:
  listeners: 
1

  - name: http
    protocol: HTTP
    port: 8080
    hostname: "example.com"
Copy to Clipboard Toggle word wrap

1
在不使用 spec.listeners[].allowedRoutes 的情况下创建一个 Gateway 资源,则会隐式设置 namespaces.from 字段,使其具有值 Same

以下示例显示了关联的 HTTPRoute 资源 sales-db,它附加到专用 网关 对象:

HTTPRoute 资源示例

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: sales-db
  namespace: openshift-ingress
spec:
  parentRefs:
  - name: fin-gateway
  hostnames:
  - sales-db.example.com
  rules:
    - backendRefs:
        - name: sales-db
        ¦ port: 8080
Copy to Clipboard Toggle word wrap

HTTPRoute 资源必须具有 Gateway 对象的名称,作为其 parentRefs 字段的值,才能附加到网关。隐式来说,路由被假定为与 Gateway 对象位于同一个命名空间中。

2.13.4.2. 共享网关示例

以下示例显示了网关资源 devops-gateway,它有一个 spec.listeners.allowedRoutes.namespaces 标签选择器,以匹配包含 shared-gateway-access: "true" 的任何命名空间:

共享 网关资源 示例

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: devops-gateway
  namespace: openshift-ingress
listeners:
  - name: https
    protocol: HTTPS
    hostname: "example.com"
    allowedRoutes:
      namespaces:
        from: Selector
        selector:
        ¦ matchLabels:
        ¦   shared-gateway-access: "true"
Copy to Clipboard Toggle word wrap

以下示例显示了 devops-gateway 资源允许的命名空间:

Namespace 资源示例

apiVersion: v1
kind: Namespace
metadata:
  name: dev
  labels:
    shared-gateway-access: "true"
---
apiVersion: v1
kind: Namespace
metadata:
  name: ops
  labels:
    shared-gateway-access: "true"
Copy to Clipboard Toggle word wrap

在本例中,两个 HTTPRoute 资源 dev-portalops-home 都位于不同的命名空间中,但附加到共享网关:

apiVersion: v1
kind: HTTPRoute
metadata:
  name: dev-portal
  namespace: dev
spec:
  parentRefs:
  - name: devops-gateway
    namespace: openshift-ingress
  rules:
  - backendRefs:
    - name: dev-portal
      port: 8080
---
apiVersion: v1
kind: HTTPRoute
metadata:
  name: ops-home
  namespace: ops
spec:
  parentRefs:
  - name: devops-gateway
    namespace: openshift-ingress
  rules:
  - backendRefs:
    - name: ops-home
      port: 8080
Copy to Clipboard Toggle word wrap

使用共享网关拓扑时,路由必须指定它要附加到的 Gateway 对象的命名空间。可以在命名空间之间部署和共享多个 网关 对象。当有多个共享网关时,此拓扑概念类似于 Ingress Controller 分片。

其他资源

第 3 章 RHOSP 负载均衡

3.1. 负载均衡器服务的限制

Red Hat OpenStack Platform (RHOSP)上的 OpenShift Container Platform 集群使用 Octavia 来处理负载均衡器服务。因此,此类集群有很多功能限制。

RHOSP Octavia 有两个支持的供应商: Amphora 和 OVN。这些供应商在可用功能以及实施详情方面有所不同。这些差异会影响在集群中创建的负载均衡器服务。

3.1.1. 本地外部流量策略

您可以在负载均衡器服务上设置外部流量策略 (ETP) 参数 .spec.externalTrafficPolicy,以在到达服务端点 pod 时保留传入流量的源 IP 地址。但是,如果您的集群使用 Amphora Octavia 供应商,流量的源 IP 将替换为 Amphora 虚拟机的 IP 地址。如果您的集群使用 OVN Octavia 供应商,则不会发生此行为。

ETP 选项设置为 Local 需要为负载均衡器创建运行状况监控器。如果没有健康监控器,流量可以路由到没有功能端点的节点,这会导致连接丢弃。要强制 Cloud Provider OpenStack 创建运行状况监视器,您必须将云供应商配置中的 create-monitor 选项的值设置为 true

在 RHOSP 16.2 中,OVN Octavia 供应商不支持健康监控器。因此,不支持将 ETP 设置为 local。

在 RHOSP 16.2 中,Amphora Octavia 供应商不支持 UDP 池中的 HTTP 监视器。因此,UDP 负载均衡器服务会改为创建 UDP-CONNECT 监视器。由于实现详情,此配置只能使用 OVN-Kubernetes CNI 插件正常工作。

3.2. 使用 Octavia 为应用程序流量扩展集群

在 Red Hat OpenStack Platform (RHOSP)上运行的 OpenShift Container Platform 集群可以使用 Octavia 负载均衡服务在多个虚拟机(VM)或浮动 IP 地址间分发流量。这个功能减少了单一机器或地址生成的瓶颈。

您必须创建自己的 Octavia 负载均衡器,将其用于应用程序网络扩展。

3.2.1. 使用 Octavia 扩展集群

如果要使用多个 API 负载均衡器,请创建一个 Octavia 负载均衡器,然后将集群配置为使用它。

先决条件

  • Octavia 可用于您的 Red Hat OpenStack Platform (RHOSP)部署。

流程

  1. 在命令行中创建一个使用 Amphora 驱动程序的 Octavia 负载均衡器:

    $ openstack loadbalancer create --name API_OCP_CLUSTER --vip-subnet-id <id_of_worker_vms_subnet>
    Copy to Clipboard Toggle word wrap

    可以使用自己选择的名称而不是 API_OCP_CLUSTER

  2. 负载均衡器成为活跃后,创建监听程序:

    $ openstack loadbalancer listener create --name API_OCP_CLUSTER_6443 --protocol HTTPS--protocol-port 6443 API_OCP_CLUSTER
    Copy to Clipboard Toggle word wrap
    注意

    要查看负载均衡器的状态,请输入 openstack loadbalancer list

  3. 创建一个使用轮循算法的池,并启用了会话持久性:

    $ openstack loadbalancer pool create --name API_OCP_CLUSTER_pool_6443 --lb-algorithm ROUND_ROBIN --session-persistence type=<source_IP_address> --listener API_OCP_CLUSTER_6443 --protocol HTTPS
    Copy to Clipboard Toggle word wrap
  4. 为确保 control plane 机器可用,创建一个健康监控器:

    $ openstack loadbalancer healthmonitor create --delay 5 --max-retries 4 --timeout 10 --type TCP API_OCP_CLUSTER_pool_6443
    Copy to Clipboard Toggle word wrap
  5. 将 control plane 机器作为负载均衡器池的成员添加:

    $ for SERVER in $(MASTER-0-IP MASTER-1-IP MASTER-2-IP)
    do
      openstack loadbalancer member create --address $SERVER  --protocol-port 6443 API_OCP_CLUSTER_pool_6443
    done
    Copy to Clipboard Toggle word wrap
  6. 可选: 要重复使用集群 API 浮动 IP 地址,取消设置它:

    $ openstack floating ip unset $API_FIP
    Copy to Clipboard Toggle word wrap
  7. 为创建的负载均衡器 VIP 添加未设置的 API_FIP 或一个新地址:

    $ openstack floating ip set  --port $(openstack loadbalancer show -c <vip_port_id> -f value API_OCP_CLUSTER) $API_FIP
    Copy to Clipboard Toggle word wrap

您的集群现在使用 Octavia 进行负载平衡。

3.3. 用户管理的负载均衡器的服务

您可以在 Red Hat OpenStack Platform (RHOSP)上配置 OpenShift Container Platform 集群,以使用用户管理的负载均衡器来代替默认负载均衡器。

重要

配置用户管理的负载均衡器取决于您的厂商的负载均衡器。

本节中的信息和示例仅用于指导目的。有关供应商负载均衡器的更多信息,请参阅供应商文档。

红帽支持用户管理的负载均衡器的以下服务:

  • Ingress Controller
  • OpenShift API
  • OpenShift MachineConfig API

您可以选择是否要为用户管理的负载均衡器配置一个或多个所有服务。仅配置 Ingress Controller 服务是一个通用的配置选项。要更好地了解每个服务,请查看以下图表:

图 3.1. 显示 OpenShift Container Platform 环境中运行的 Ingress Controller 的网络工作流示例

图 3.2. 显示 OpenShift Container Platform 环境中运行的 OpenShift API 的网络工作流示例

图 3.3. 显示 OpenShift Container Platform 环境中运行的 OpenShift MachineConfig API 的网络工作流示例

用户管理的负载均衡器支持以下配置选项:

  • 使用节点选择器将 Ingress Controller 映射到一组特定的节点。您必须为这个集合中的每个节点分配一个静态 IP 地址,或者将每个节点配置为从动态主机配置协议(DHCP)接收相同的 IP 地址。基础架构节点通常接收这种类型的配置。
  • 以子网上的所有 IP 地址为目标。此配置可减少维护开销,因为您可以在这些网络中创建和销毁节点,而无需重新配置负载均衡器目标。如果您使用较小的网络上的机器集来部署入口 pod,如 /27/28,您可以简化负载均衡器目标。

    提示

    您可以通过检查机器配置池的资源来列出网络中存在的所有 IP 地址。

在为 OpenShift Container Platform 集群配置用户管理的负载均衡器前,请考虑以下信息:

  • 对于前端 IP 地址,您可以对前端 IP 地址、Ingress Controller 的负载均衡器和 API 负载均衡器使用相同的 IP 地址。查看厂商的文档以获取此功能的相关信息。
  • 对于后端 IP 地址,请确保 OpenShift Container Platform control plane 节点的 IP 地址在用户管理的负载均衡器生命周期内不会改变。您可以通过完成以下操作之一来实现此目的:

    • 为每个 control plane 节点分配一个静态 IP 地址。
    • 将每个节点配置为在每次节点请求 DHCP 租期时从 DHCP 接收相同的 IP 地址。根据供应商,DHCP 租期可能采用 IP 保留或静态 DHCP 分配的形式。
  • 在 Ingress Controller 后端服务的用户管理的负载均衡器中手动定义运行 Ingress Controller 的每个节点。例如,如果 Ingress Controller 移到未定义节点,则可能会出现连接中断。

3.3.1. 配置用户管理的负载均衡器

您可以在 Red Hat OpenStack Platform (RHOSP)上配置 OpenShift Container Platform 集群,以使用用户管理的负载均衡器来代替默认负载均衡器。

重要

在配置用户管理的负载均衡器前,请确保阅读用户管理的负载均衡器部分。

阅读适用于您要为用户管理的负载均衡器配置的服务的以下先决条件。

注意

MetalLB,在集群中运行,充当用户管理的负载均衡器。

OpenShift API 的先决条件

  • 您定义了前端 IP 地址。
  • TCP 端口 6443 和 22623 在负载均衡器的前端 IP 地址上公开。检查以下项:

    • 端口 6443 提供对 OpenShift API 服务的访问。
    • 端口 22623 可以为节点提供 ignition 启动配置。
  • 前端 IP 地址和端口 6443 可以被您的系统的所有用户访问,其位置为 OpenShift Container Platform 集群外部。
  • 前端 IP 地址和端口 22623 只能被 OpenShift Container Platform 节点访问。
  • 负载均衡器后端可以在端口 6443 和 22623 上与 OpenShift Container Platform control plane 节点通信。

Ingress Controller 的先决条件

  • 您定义了前端 IP 地址。
  • TCP 端口 443 和 80 在负载均衡器的前端 IP 地址上公开。
  • 前端 IP 地址、端口 80 和端口 443 可以被您的系统所有用户访问,以及 OpenShift Container Platform 集群外部的位置。
  • 前端 IP 地址、端口 80 和端口 443 可被 OpenShift Container Platform 集群中运行的所有节点访问。
  • 负载均衡器后端可以在端口 80、443 和 1936 上与运行 Ingress Controller 的 OpenShift Container Platform 节点通信。

健康检查 URL 规格的先决条件

您可以通过设置健康检查 URL 来配置大多数负载均衡器,以确定服务是否可用或不可用。OpenShift Container Platform 为 OpenShift API、Machine Configuration API 和 Ingress Controller 后端服务提供这些健康检查。

以下示例显示了之前列出的后端服务的健康检查规格:

Kubernetes API 健康检查规格示例

Path: HTTPS:6443/readyz
Healthy threshold: 2
Unhealthy threshold: 2
Timeout: 10
Interval: 10
Copy to Clipboard Toggle word wrap

Machine Config API 健康检查规格示例

Path: HTTPS:22623/healthz
Healthy threshold: 2
Unhealthy threshold: 2
Timeout: 10
Interval: 10
Copy to Clipboard Toggle word wrap

Ingress Controller 健康检查规格示例

Path: HTTP:1936/healthz/ready
Healthy threshold: 2
Unhealthy threshold: 2
Timeout: 5
Interval: 10
Copy to Clipboard Toggle word wrap

流程

  1. 配置 HAProxy Ingress Controller,以便您可以在端口 6443、22623、443 和 80 上从负载均衡器访问集群。根据您的需要,您可以在 HAProxy 配置中指定来自多个子网的单个子网或 IP 地址的 IP 地址。

    带有列出子网的 HAProxy 配置示例

    # ...
    listen my-cluster-api-6443
        bind 192.168.1.100:6443
        mode tcp
        balance roundrobin
      option httpchk
      http-check connect
      http-check send meth GET uri /readyz
      http-check expect status 200
        server my-cluster-master-2 192.168.1.101:6443 check inter 10s rise 2 fall 2
        server my-cluster-master-0 192.168.1.102:6443 check inter 10s rise 2 fall 2
        server my-cluster-master-1 192.168.1.103:6443 check inter 10s rise 2 fall 2
    
    listen my-cluster-machine-config-api-22623
        bind 192.168.1.100:22623
        mode tcp
        balance roundrobin
      option httpchk
      http-check connect
      http-check send meth GET uri /healthz
      http-check expect status 200
        server my-cluster-master-2 192.168.1.101:22623 check inter 10s rise 2 fall 2
        server my-cluster-master-0 192.168.1.102:22623 check inter 10s rise 2 fall 2
        server my-cluster-master-1 192.168.1.103:22623 check inter 10s rise 2 fall 2
    
    listen my-cluster-apps-443
        bind 192.168.1.100:443
        mode tcp
        balance roundrobin
      option httpchk
      http-check connect
      http-check send meth GET uri /healthz/ready
      http-check expect status 200
        server my-cluster-worker-0 192.168.1.111:443 check port 1936 inter 10s rise 2 fall 2
        server my-cluster-worker-1 192.168.1.112:443 check port 1936 inter 10s rise 2 fall 2
        server my-cluster-worker-2 192.168.1.113:443 check port 1936 inter 10s rise 2 fall 2
    
    listen my-cluster-apps-80
       bind 192.168.1.100:80
       mode tcp
       balance roundrobin
      option httpchk
      http-check connect
      http-check send meth GET uri /healthz/ready
      http-check expect status 200
        server my-cluster-worker-0 192.168.1.111:80 check port 1936 inter 10s rise 2 fall 2
        server my-cluster-worker-1 192.168.1.112:80 check port 1936 inter 10s rise 2 fall 2
        server my-cluster-worker-2 192.168.1.113:80 check port 1936 inter 10s rise 2 fall 2
    # ...
    Copy to Clipboard Toggle word wrap

    带有多个列出子网的 HAProxy 配置示例

    # ...
    listen api-server-6443
        bind *:6443
        mode tcp
          server master-00 192.168.83.89:6443 check inter 1s
          server master-01 192.168.84.90:6443 check inter 1s
          server master-02 192.168.85.99:6443 check inter 1s
          server bootstrap 192.168.80.89:6443 check inter 1s
    
    listen machine-config-server-22623
        bind *:22623
        mode tcp
          server master-00 192.168.83.89:22623 check inter 1s
          server master-01 192.168.84.90:22623 check inter 1s
          server master-02 192.168.85.99:22623 check inter 1s
          server bootstrap 192.168.80.89:22623 check inter 1s
    
    listen ingress-router-80
        bind *:80
        mode tcp
        balance source
          server worker-00 192.168.83.100:80 check inter 1s
          server worker-01 192.168.83.101:80 check inter 1s
    
    listen ingress-router-443
        bind *:443
        mode tcp
        balance source
          server worker-00 192.168.83.100:443 check inter 1s
          server worker-01 192.168.83.101:443 check inter 1s
    
    listen ironic-api-6385
        bind *:6385
        mode tcp
        balance source
          server master-00 192.168.83.89:6385 check inter 1s
          server master-01 192.168.84.90:6385 check inter 1s
          server master-02 192.168.85.99:6385 check inter 1s
          server bootstrap 192.168.80.89:6385 check inter 1s
    
    listen inspector-api-5050
        bind *:5050
        mode tcp
        balance source
          server master-00 192.168.83.89:5050 check inter 1s
          server master-01 192.168.84.90:5050 check inter 1s
          server master-02 192.168.85.99:5050 check inter 1s
          server bootstrap 192.168.80.89:5050 check inter 1s
    # ...
    Copy to Clipboard Toggle word wrap

  2. 使用 curl CLI 命令验证用户管理的负载均衡器及其资源是否正常运行:

    1. 运行以下命令并查看响应,验证集群机器配置 API 是否可以被 Kubernetes API 服务器资源访问:

      $ curl https://<loadbalancer_ip_address>:6443/version --insecure
      Copy to Clipboard Toggle word wrap

      如果配置正确,您会收到 JSON 对象的响应:

      {
        "major": "1",
        "minor": "11+",
        "gitVersion": "v1.11.0+ad103ed",
        "gitCommit": "ad103ed",
        "gitTreeState": "clean",
        "buildDate": "2019-01-09T06:44:10Z",
        "goVersion": "go1.10.3",
        "compiler": "gc",
        "platform": "linux/amd64"
      }
      Copy to Clipboard Toggle word wrap
    2. 运行以下命令并观察输出,验证集群机器配置 API 是否可以被 Machine 配置服务器资源访问:

      $ curl -v https://<loadbalancer_ip_address>:22623/healthz --insecure
      Copy to Clipboard Toggle word wrap

      如果配置正确,命令的输出会显示以下响应:

      HTTP/1.1 200 OK
      Content-Length: 0
      Copy to Clipboard Toggle word wrap
    3. 运行以下命令并观察输出,验证控制器是否可以被端口 80 上的 Ingress Controller 资源访问:

      $ curl -I -L -H "Host: console-openshift-console.apps.<cluster_name>.<base_domain>" http://<load_balancer_front_end_IP_address>
      Copy to Clipboard Toggle word wrap

      如果配置正确,命令的输出会显示以下响应:

      HTTP/1.1 302 Found
      content-length: 0
      location: https://console-openshift-console.apps.ocp4.private.opequon.net/
      cache-control: no-cache
      Copy to Clipboard Toggle word wrap
    4. 运行以下命令并观察输出,验证控制器是否可以被端口 443 上的 Ingress Controller 资源访问:

      $ curl -I -L --insecure --resolve console-openshift-console.apps.<cluster_name>.<base_domain>:443:<Load Balancer Front End IP Address> https://console-openshift-console.apps.<cluster_name>.<base_domain>
      Copy to Clipboard Toggle word wrap

      如果配置正确,命令的输出会显示以下响应:

      HTTP/1.1 200 OK
      referrer-policy: strict-origin-when-cross-origin
      set-cookie: csrf-token=UlYWOyQ62LWjw2h003xtYSKlh1a0Py2hhctw0WmV2YEdhJjFyQwWcGBsja261dGLgaYO0nxzVErhiXt6QepA7g==; Path=/; Secure; SameSite=Lax
      x-content-type-options: nosniff
      x-dns-prefetch-control: off
      x-frame-options: DENY
      x-xss-protection: 1; mode=block
      date: Wed, 04 Oct 2023 16:29:38 GMT
      content-type: text/html; charset=utf-8
      set-cookie: 1e2670d92730b515ce3a1bb65da45062=1bf5e9573c9a2760c964ed1659cc1673; path=/; HttpOnly; Secure; SameSite=None
      cache-control: private
      Copy to Clipboard Toggle word wrap
  3. 配置集群的 DNS 记录,使其以用户管理的负载均衡器的前端 IP 地址为目标。您必须在负载均衡器上将记录更新为集群 API 和应用程序的 DNS 服务器。

    修改 DNS 记录示例

    <load_balancer_ip_address>  A  api.<cluster_name>.<base_domain>
    A record pointing to Load Balancer Front End
    Copy to Clipboard Toggle word wrap

    <load_balancer_ip_address>   A apps.<cluster_name>.<base_domain>
    A record pointing to Load Balancer Front End
    Copy to Clipboard Toggle word wrap
    重要

    DNS 传播可能需要一些时间才能获得每个 DNS 记录。在验证每个记录前,请确保每个 DNS 记录传播。

  4. 要使 OpenShift Container Platform 集群使用用户管理的负载均衡器,您必须在集群的 install-config.yaml 文件中指定以下配置:

    # ...
    platform:
      openstack:
        loadBalancer:
          type: UserManaged 
    1
    
        apiVIPs:
        - <api_ip> 
    2
    
        ingressVIPs:
        - <ingress_ip> 
    3
    
    # ...
    Copy to Clipboard Toggle word wrap
    1
    type 参数设置 UserManaged,为集群指定用户管理的负载均衡器。参数默认为 OpenShiftManagedDefault,它表示默认的内部负载均衡器。对于 openshift-kni-infra 命名空间中定义的服务,用户管理的负载均衡器可将 coredns 服务部署到集群中的 pod,但忽略 keepalivedhaproxy 服务。
    2
    指定用户管理的负载均衡器时所需的参数。指定用户管理的负载均衡器的公共 IP 地址,以便 Kubernetes API 可以与用户管理的负载均衡器通信。
    3
    指定用户管理的负载均衡器时所需的参数。指定用户管理的负载均衡器的公共 IP 地址,以便用户管理的负载均衡器可以管理集群的入口流量。

验证

  1. 使用 curl CLI 命令验证用户管理的负载均衡器和 DNS 记录配置是否正常工作:

    1. 运行以下命令并查看输出,验证您可以访问集群 API:

      $ curl https://api.<cluster_name>.<base_domain>:6443/version --insecure
      Copy to Clipboard Toggle word wrap

      如果配置正确,您会收到 JSON 对象的响应:

      {
        "major": "1",
        "minor": "11+",
        "gitVersion": "v1.11.0+ad103ed",
        "gitCommit": "ad103ed",
        "gitTreeState": "clean",
        "buildDate": "2019-01-09T06:44:10Z",
        "goVersion": "go1.10.3",
        "compiler": "gc",
        "platform": "linux/amd64"
        }
      Copy to Clipboard Toggle word wrap
    2. 运行以下命令并查看输出,验证您可以访问集群机器配置:

      $ curl -v https://api.<cluster_name>.<base_domain>:22623/healthz --insecure
      Copy to Clipboard Toggle word wrap

      如果配置正确,命令的输出会显示以下响应:

      HTTP/1.1 200 OK
      Content-Length: 0
      Copy to Clipboard Toggle word wrap
    3. 运行以下命令并查看输出,验证您可以在端口上访问每个集群应用程序:

      $ curl http://console-openshift-console.apps.<cluster_name>.<base_domain> -I -L --insecure
      Copy to Clipboard Toggle word wrap

      如果配置正确,命令的输出会显示以下响应:

      HTTP/1.1 302 Found
      content-length: 0
      location: https://console-openshift-console.apps.<cluster-name>.<base domain>/
      cache-control: no-cacheHTTP/1.1 200 OK
      referrer-policy: strict-origin-when-cross-origin
      set-cookie: csrf-token=39HoZgztDnzjJkq/JuLJMeoKNXlfiVv2YgZc09c3TBOBU4NI6kDXaJH1LdicNhN1UsQWzon4Dor9GWGfopaTEQ==; Path=/; Secure
      x-content-type-options: nosniff
      x-dns-prefetch-control: off
      x-frame-options: DENY
      x-xss-protection: 1; mode=block
      date: Tue, 17 Nov 2020 08:42:10 GMT
      content-type: text/html; charset=utf-8
      set-cookie: 1e2670d92730b515ce3a1bb65da45062=9b714eb87e93cf34853e87a92d6894be; path=/; HttpOnly; Secure; SameSite=None
      cache-control: private
      Copy to Clipboard Toggle word wrap
    4. 运行以下命令并查看输出,验证您可以在端口 443 上访问每个集群应用程序:

      $ curl https://console-openshift-console.apps.<cluster_name>.<base_domain> -I -L --insecure
      Copy to Clipboard Toggle word wrap

      如果配置正确,命令的输出会显示以下响应:

      HTTP/1.1 200 OK
      referrer-policy: strict-origin-when-cross-origin
      set-cookie: csrf-token=UlYWOyQ62LWjw2h003xtYSKlh1a0Py2hhctw0WmV2YEdhJjFyQwWcGBsja261dGLgaYO0nxzVErhiXt6QepA7g==; Path=/; Secure; SameSite=Lax
      x-content-type-options: nosniff
      x-dns-prefetch-control: off
      x-frame-options: DENY
      x-xss-protection: 1; mode=block
      date: Wed, 04 Oct 2023 16:29:38 GMT
      content-type: text/html; charset=utf-8
      set-cookie: 1e2670d92730b515ce3a1bb65da45062=1bf5e9573c9a2760c964ed1659cc1673; path=/; HttpOnly; Secure; SameSite=None
      cache-control: private
      Copy to Clipboard Toggle word wrap

3.4. 在 Ingress Controller 中指定浮动 IP 地址

默认情况下,在部署时,浮动 IP 地址会随机分配给 Red Hat OpenStack Platform (RHOSP)上的 OpenShift Container Platform 集群。此浮动 IP 地址与您的 Ingress 端口关联。

您可能需要在更新 DNS 记录和集群部署前预先创建浮动 IP 地址。在这种情况下,您可以为 Ingress Controller 定义浮动 IP 地址。无论您是使用 Octavia 还是用户管理的集群,都可以执行此操作。

流程

  1. 使用浮动 IP 创建 Ingress Controller 自定义资源(CR)文件:

    Ingress config sample-ingress.yaml 示例

    apiVersion: operator.openshift.io/v1
    kind: IngressController
    metadata:
      namespace: openshift-ingress-operator
      name: <name> 
    1
    
    spec:
      domain: <domain> 
    2
    
      endpointPublishingStrategy:
        type: LoadBalancerService
        loadBalancer:
          scope: External 
    3
    
          providerParameters:
            type: OpenStack
            openstack:
              floatingIP: <ingress_port_IP> 
    4
    Copy to Clipboard Toggle word wrap

    1
    Ingress Controller 的名称。如果您使用默认的 Ingress Controller,则此字段的值为 default
    2
    Ingress Controller 提供服务的 DNS 名称。
    3
    您必须将 scope 设置为 External,才能使用浮动 IP 地址。
    4
    与 Ingress Controller 正在侦听的端口关联的浮动 IP 地址。
  2. 运行以下命令来应用 CR 文件:

    $ oc apply -f sample-ingress.yaml
    Copy to Clipboard Toggle word wrap
  3. 使用 Ingress Controller 端点更新 DNS 记录:

    *.apps.<name>.<domain>. IN A <ingress_port_IP>
    Copy to Clipboard Toggle word wrap
  4. 继续创建 OpenShift Container Platform 集群。

验证

  • 使用以下命令检查 IngressController 条件来确认负载均衡器是否已成功置备:

    $ oc get ingresscontroller -n openshift-ingress-operator <name> -o jsonpath="{.status.conditions}" | yq -PC
    Copy to Clipboard Toggle word wrap

第 4 章 使用 MetalLB 进行负载平衡

4.1. 配置 MetalLB 地址池

作为集群管理员,您可以添加、修改和删除地址池。MetalLB Operator 使用地址池自定义资源来设置 MetalLB 可分配给服务的 IP 地址。示例中使用的命名空间假定命名空间是 metallb-system

有关如何安装 MetalLB Operator 的更多信息,请参阅关于 MetalLB 和 MetalLB Operator

4.1.1. 关于 IPAddressPool 自定义资源

下表中描述了 IPAddressPool 自定义资源的字段。

Expand
表 4.1. MetalLB IPAddressPool 池自定义资源
字段类型描述

metadata.name

string

指定地址池的名称。添加服务时,您可以在 metallb.io/address-pool 注解中指定这个池名称,以从特定池中选择 IP 地址。整个文档中都使用名称 doc-examplesilvergold

metadata.namespace

string

指定地址池的命名空间。指定 MetalLB Operator 使用的同一命名空间。

metadata.label

string

可选:指定分配给 IPAddressPool 的键值对。这可通过 BGPAdvertisement and L2Advertisement CRD 中的 ipAddressPoolSelectors 进行引用,以将 IPAddressPool 与广告关联

spec.addresses

string

指定分配给服务的 MetalLB Operator 的 IP 地址列表。您可以在一个池中指定多个范围 ; 它们将共享相同的设置。以 CIDR 表示法指定每个范围,或者指定为以连字符隔开的起始和结束 IP 地址。

spec.autoAssign

布尔值

可选:指定 MetalLB 是否从这个池自动分配 IP 地址。如果要使用 metallb.io/address-pool 注解从这个池中显式请求 IP 地址,请指定 false。默认值为 true

注意

对于 IP 地址池配置,请确保 address 字段只指定可用的 IP,而不被其他网络设备(特别是网关地址)使用,以防止启用 autoAssign 时发生冲突。

spec.avoidBuggyIPs

布尔值

可选:这样可确保在启用 IP 地址以 .0.255 结尾时,不会从池中分配。默认值为 false。某些较旧的消费者网络设备错误地阻止以 .0.255 结尾的 IP 地址。

您可以通过配置 spec.serviceAllocation 规格,将 IP 地址从 IPAddressPool 分配给服务和命名空间。

Expand
表 4.2. MetalLB IPAddressPool 自定义资源 spec.serviceAllocation 子字段
字段类型描述

priority

int

可选:当多个 IP 地址池与服务或命名空间匹配时,定义 IP 地址池之间的优先级。较低数字表示优先级更高。

命名空间

数组(字符串)

可选:指定您可以分配给 IP 地址池 IP 地址的命名空间列表。

namespaceSelectors

数组 (LabelSelector)

可选:指定您可以使用列表格式的标签选择器从 IP 地址池分配给 IP 地址的命名空间标签。

serviceSelectors

数组 (LabelSelector)

可选:指定您可以使用列表格式的标签选择器从地址池中分配给 IP 地址的服务标签。

4.1.2. 配置地址池

作为集群管理员,您可以在集群中添加地址池来控制 MetalLB 可分配给负载均衡器服务的 IP 地址。

先决条件

  • 安装 OpenShift CLI(oc)。
  • 以具有 cluster-admin 特权的用户身份登录。

流程

  1. 创建一个文件,如 ipaddresspool.yaml,其内容类似以下示例:

    apiVersion: metallb.io/v1beta1
    kind: IPAddressPool
    metadata:
      namespace: metallb-system
      name: doc-example
      labels: 
    1
    
        zone: east
    spec:
      addresses:
      - 203.0.113.1-203.0.113.10
      - 203.0.113.65-203.0.113.75
    # ...
    Copy to Clipboard Toggle word wrap
    1
    分配给 IPAddressPool 的该标签可通过 BGPAdvertisement CRD 中的 ipAddressPoolSelectors 来引用,以将 IPAddressPool 与广告关联。
  2. 应用 IP 地址池的配置:

    $ oc apply -f ipaddresspool.yaml
    Copy to Clipboard Toggle word wrap

验证

  1. 输入以下命令来查看地址池:

    $ oc describe -n metallb-system IPAddressPool doc-example
    Copy to Clipboard Toggle word wrap

    输出示例

    Name:         doc-example
    Namespace:    metallb-system
    Labels:       zone=east
    Annotations:  <none>
    API Version:  metallb.io/v1beta1
    Kind:         IPAddressPool
    Metadata:
      ...
    Spec:
      Addresses:
        203.0.113.1-203.0.113.10
        203.0.113.65-203.0.113.75
      Auto Assign:  true
    Events:         <none>
    Copy to Clipboard Toggle word wrap

  2. 确认输出中已存在地址池名称,如 doc-example,以及 IP 地址范围。

4.1.3. 为 VLAN 配置 MetalLB 地址池

作为集群管理员,您可以在集群中添加地址池来控制 MetalLB 可分配给负载均衡器服务的创建的 VLAN 上的 IP 地址

先决条件

  • 安装 OpenShift CLI (oc) 。
  • 配置单独的 VLAN。
  • 以具有 cluster-admin 特权的用户身份登录。

流程

  1. 创建一个文件,如 ipaddresspool-vlan.yaml,该文件类似以下示例:

    apiVersion: metallb.io/v1beta1
    kind: IPAddressPool
    metadata:
      namespace: metallb-system
      name: doc-example-vlan
      labels:
        zone: east 
    1
    
    spec:
      addresses:
      - 192.168.100.1-192.168.100.254 
    2
    Copy to Clipboard Toggle word wrap
    1
    分配给 IPAddressPool 的该标签可通过 BGPAdvertisement CRD 中的 ipAddressPoolSelectors 来引用,以将 IPAddressPool 与广告关联。
    2
    此 IP 范围必须与分配给您网络上的 VLAN 的子网匹配。要支持第 2 层 (L2) 模式,IP 地址范围必须与集群节点位于同一个子网中。
  2. 应用 IP 地址池的配置:

    $ oc apply -f ipaddresspool-vlan.yaml
    Copy to Clipboard Toggle word wrap
  3. 为确保此配置适用于您需要将 spec gatewayConfig.ipForwarding 设置为 Global 的 VLAN。

    1. 运行以下命令来编辑网络配置自定义资源 (CR):

      $ oc edit network.operator.openshift/cluster
      Copy to Clipboard Toggle word wrap
    2. 更新 spec.defaultNetwork.ovnKubernetesConfig 部分,将 gatewayConfig.ipForwarding 设置为 Global。它应该类似如下:

      Example

      ...
      spec:
        clusterNetwork:
          - cidr: 10.128.0.0/14
            hostPrefix: 23
        defaultNetwork:
          type: OVNKubernetes
          ovnKubernetesConfig:
            gatewayConfig:
              ipForwarding: Global
      ...
      Copy to Clipboard Toggle word wrap

4.1.4. 地址池配置示例

以下示例演示了特定场景的地址池配置。

4.1.4.1. 示例:IPv4 和 CIDR 范围

您可以使用无类别域间路由(CIDR)标记指定 IP 地址范围。您可以将 CIDR 表示法与使用连字符分隔下限和上限的表示法合并。

apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: doc-example-cidr
  namespace: metallb-system
spec:
  addresses:
  - 192.168.100.0/24
  - 192.168.200.0/24
  - 192.168.255.1-192.168.255.5
# ...
Copy to Clipboard Toggle word wrap
4.1.4.2. 示例:分配 IP 地址

您可以将 autoAssign 字段设置为 false,以防止 MetalLB 自动从地址池中分配 IP 地址。然后,您可以从 IP 地址池分配单个 IP 地址或多个 IP 地址。要分配 IP 地址,请将 /32 CIDR 表示法附加到 spec.addresses 参数中的目标 IP 地址。此设置可确保只有特定 IP 地址可以分配,保留非保留 IP 地址供应用程序使用。

分配多个 IP 地址的 IPAddressPool CR 示例

apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: doc-example-reserved
  namespace: metallb-system
spec:
  addresses:
  - 192.168.100.1/32
  - 192.168.200.1/32
  autoAssign: false
# ...
Copy to Clipboard Toggle word wrap

注意

添加服务时,您可以从地址池中请求特定的 IP 地址,或者在注解中指定池名称,从池中请求任何 IP 地址。

4.1.4.3. 示例:IPv4 和 IPv6 地址

您可以添加使用 IPv4 和 IPv6 的地址池。您可以像几个 IPv4 示例一样在 地址 列表中指定多个范围。

无论服务被分配一个 IPv4 地址、一个 IPv6 地址,还是由您添加该服务来确定。spec.ipFamiliesspec.ipFamilyPolicy 字段控制 IP 地址如何分配给该服务。

apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: doc-example-combined
  namespace: metallb-system
spec:
  addresses:
  - 10.0.100.0/28 
1

  - 2002:2:2::1-2002:2:2::100
# ...
Copy to Clipboard Toggle word wrap
1
其中 10.0.100.0/28 是本地网络 IP 地址,后跟 /28 网络前缀。

您可以将 IP 地址从 IPAddressPool 分配给您指定的服务和命名空间。

如果您将服务或命名空间分配给多个 IP 地址池,MetalLB 将使用较高优先级 IP 地址池中的可用 IP 地址。如果分配的 IP 地址池没有 IP 地址可用,MetalLB 将使用较低优先级或没有优先级的 IP 地址池的可用 IP 地址。

注意

对于 namespaceSelectorsserviceSelectors 规格,您可以使用 matchLabels 标签选择器、matchExpressions 标签选择器或两者。本例展示了每个规格的一个标签选择器。

apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: doc-example-service-allocation
  namespace: metallb-system
spec:
  addresses:
    - 192.168.20.0/24
  serviceAllocation:
    priority: 50 
1

    namespaces: 
2

      - namespace-a
      - namespace-b
    namespaceSelectors: 
3

      - matchLabels:
          zone: east
    serviceSelectors: 
4

      - matchExpressions:
        - key: security
          operator: In
          values:
          - S1
# ...
Copy to Clipboard Toggle word wrap
1
为地址池分配优先级。较低数字表示优先级更高。
2
以列表格式为 IP 地址池分配一个或多个命名空间。
3
使用列表格式的标签选择器为 IP 地址池分配一个或多个命名空间标签。
4
使用列表格式的标签选择器,为 IP 地址池分配一个或多个服务标签。

4.1.5. 后续步骤

4.2. 关于 IP 地址池的广告

您可以配置 MetalLB,以便使用第 2 层协议、BGP 协议或两者来广告 IP 地址。通过第 2 层,MetalLB 提供了容错的外部 IP 地址。使用 BGP,MetalLB 为外部 IP 地址和负载均衡提供容错功能。

MetalLB 支持将 L2 和 BGP 用于同一组 IP 地址。

MetalLB 提供了将地址池分配给特定 BGP 对等对象到网络上节点子集的灵活性。这可以实现更复杂的配置,例如促进节点隔离或网络分段。

4.2.1. 关于 BGPAdvertisement 自定义资源

BGPAdvertise 对象的字段在下表中定义:

Expand
表 4.3. BGPAdvertise 配置
字段类型描述

metadata.name

string

指定 BGP 广告的名称。

metadata.namespace

string

指定 BGP 广告的命名空间。指定 MetalLB Operator 使用的同一命名空间。

spec.aggregationLength

整数

可选:指定 32 位 CIDR 掩码中包含的位数。为了聚合发言人向 BGP 对等者公告的路由,掩码将应用于多个服务 IP 地址的路由,speaker 会公告聚合的路由。例如,聚合长度为 24,speaker 可以聚合多个 10.0.1.x/32 服务 IP 地址并公告一个 10.0.1.0/24 路由。

spec.aggregationLengthV6

整数

可选:指定 128 位 CIDR 掩码中包含的位数。例如,在聚合长度为 124 时,speaker 可以聚合几个 fc00:f853:0ccd:e799::x/128 服务 IP 地址,并公告一个 fc00:f853:0ccd:e799::0/124 路由。

spec.communities

string

可选:指定一个或多个 BGP 社区。每个社区都被指定为两个 16 位值,用冒号字符分隔。知名的社区必须指定为 16 位值:

  • NO_EXPORT: 65535:65281
  • NO_ADVERTISE: 65535:65282
  • NO_EXPORT_SUBCONFED: 65535:65283

    注意

    您还可以使用与字符串一起创建的社区对象。

spec.localPref

整数

可选:指定这个广播的本地首选项。此 BGP 属性适用于 Autonomous System 中的 BGP 会话。

spec.ipAddressPools

string

可选:用于使用这个广告进行广告的 IPAddressPools 列表,按名称选择。

spec.ipAddressPoolSelectors

string

可选:使用这个广告进行广告的 IPAddressPools 的选择器。这可用于根据分配给 IPAddressPool 而非名称本身的标签将 IPAddressPool 与公告关联。如果这个或列表没有选择 IPAddressPool,则公告会应用到所有 IPAddressPools

spec.nodeSelectors

string

可选:NodeSelectors 允许限制节点作为负载均衡器 IP 的下一个跃点。如果为空,所有节点都会作为下一个跃点进行宣布。

spec.peers

string

可选:使用列表为每个 BGPPeer 资源指定 metadata.name 值,该资源接收 MetalLB 服务 IP 地址公告。MetalLB 服务 IP 地址从 IP 地址池分配。默认情况下,MetalLB 服务 IP 地址公告给所有配置的 BGPPeer 资源。使用此字段将公告限制到特定的 BGPpeer 资源。

4.2.2. 使用 BGP 公告和基本用例配置 MetalLB

按如下所示配置 MetalLB,使对等 BGP 路由器为每个 MetalLB 分配为服务的负载均衡器 IP 地址接收一个 203.0.113.200/32 路由和一个 fc00:f853:ccd:e799::1/128 路由。因为没有指定 localPrefcommunity 字段,所以路由会公告,并将 localPref 设置为 0,且没有 BGP 社区。

4.2.2.1. 示例:使用 BGP 传输基本地址池配置

按如下所示配置 MetalLB,以便使用 BGP 协议公告 IPAddressPool

先决条件

  • 安装 OpenShift CLI(oc)。
  • 以具有 cluster-admin 特权的用户身份登录。

流程

  1. 创建 IP 地址池。

    1. 创建一个文件,如 ipaddresspool.yaml,其内容类似以下示例:

      apiVersion: metallb.io/v1beta1
      kind: IPAddressPool
      metadata:
        namespace: metallb-system
        name: doc-example-bgp-basic
      spec:
        addresses:
          - 203.0.113.200/30
          - fc00:f853:ccd:e799::/124
      Copy to Clipboard Toggle word wrap
    2. 应用 IP 地址池的配置:

      $ oc apply -f ipaddresspool.yaml
      Copy to Clipboard Toggle word wrap
  2. 创建 BGP 公告。

    1. 创建一个文件,如 bgpadvertisement.yaml,内容类似以下示例:

      apiVersion: metallb.io/v1beta1
      kind: BGPAdvertisement
      metadata:
        name: bgpadvertisement-basic
        namespace: metallb-system
      spec:
        ipAddressPools:
        - doc-example-bgp-basic
      Copy to Clipboard Toggle word wrap
    2. 应用配置:

      $ oc apply -f bgpadvertisement.yaml
      Copy to Clipboard Toggle word wrap

4.2.3. 使用 BGP 广告和高级用例配置 MetalLB

按如下所示配置 MetalLB,使得 MetalLB 分配给负载均衡器的 IP 地址范围是 203.0.113.200203.0.113.203,以及 fc00:f853:ccd:e799::0fc00:f853:ccd:e799::f

为了说明两个 BGP 公告,在 MetalLB 分配 IP 地址 203.0.113.200 时,请考虑实例。以该 IP 地址为例,发言人向 BGP 对等点公告两个路由:

  • 203.0.113.200/32localPref 设置为 100,社区设置为 NO_ADVERTISE 社区的数字值。此规范指示它们可以使用此路由的对等路由器,但它们不应将有关此路由的信息传播到 BGP 对等点。
  • 203.0.113.200/30 将 MetalLB 分配的负载均衡器 IP 地址聚合到一个路由中。MetalLB 公告到 BGP 对等点的聚合路由,并将 community 属性设置为 8000:800。BGP 同行将 203.0.113.200/30 个路由传播到其他 BGP 同级服务器。当流量通过发言人路由到节点时,使用 203.0.113.200/32 路由将流量转发到集群以及与该服务关联的 pod。

当添加更多服务和 MetalLB 从池中分配更多负载均衡器 IP 地址时,对等路由器收到一个本地路由,203.0.113.20x/32,以及 203.0.113.200/30 聚合路由。您添加的每个服务都会生成 /30 路由,但 MetalLB 会将路由重复数据删除到一个 BGP 公告,然后再与对等路由器通信。

4.2.3.1. 示例:使用 BGP 传输高级地址池配置

按如下所示配置 MetalLB,以便使用 BGP 协议公告 IPAddressPool

先决条件

  • 安装 OpenShift CLI(oc)。
  • 以具有 cluster-admin 特权的用户身份登录。

流程

  1. 创建 IP 地址池。

    1. 创建一个文件,如 ipaddresspool.yaml,其内容类似以下示例:

      apiVersion: metallb.io/v1beta1
      kind: IPAddressPool
      metadata:
        namespace: metallb-system
        name: doc-example-bgp-adv
        labels:
          zone: east
      spec:
        addresses:
          - 203.0.113.200/30
          - fc00:f853:ccd:e799::/124
        autoAssign: false
      Copy to Clipboard Toggle word wrap
    2. 应用 IP 地址池的配置:

      $ oc apply -f ipaddresspool.yaml
      Copy to Clipboard Toggle word wrap
  2. 创建 BGP 公告。

    1. 创建一个文件,如 bgpadvertisement1.yaml,内容类似以下示例:

      apiVersion: metallb.io/v1beta1
      kind: BGPAdvertisement
      metadata:
        name: bgpadvertisement-adv-1
        namespace: metallb-system
      spec:
        ipAddressPools:
          - doc-example-bgp-adv
        communities:
          - 65535:65282
        aggregationLength: 32
        localPref: 100
      Copy to Clipboard Toggle word wrap
    2. 应用配置:

      $ oc apply -f bgpadvertisement1.yaml
      Copy to Clipboard Toggle word wrap
    3. 创建一个文件,如 bgpadvertisement2.yaml,内容类似以下示例:

      apiVersion: metallb.io/v1beta1
      kind: BGPAdvertisement
      metadata:
        name: bgpadvertisement-adv-2
        namespace: metallb-system
      spec:
        ipAddressPools:
          - doc-example-bgp-adv
        communities:
          - 8000:800
        aggregationLength: 30
        aggregationLengthV6: 124
      Copy to Clipboard Toggle word wrap
    4. 应用配置:

      $ oc apply -f bgpadvertisement2.yaml
      Copy to Clipboard Toggle word wrap

4.2.4. 从节点的子集公告 IP 地址池

要从 IP 地址池公告 IP 地址,请只使用特定的节点集合,使用 BGPAdvertisement 自定义资源中的 .spec.nodeSelector 规格。此规格将 IP 地址池与集群中的一组节点关联。如果您在集群中的不同子网上有节点,而您想要从特定子网的地址池中公告 IP 地址,例如仅面向公共的子网。

先决条件

  • 安装 OpenShift CLI(oc)。
  • 以具有 cluster-admin 特权的用户身份登录。

流程

  1. 使用自定义资源创建 IP 地址池:

    apiVersion: metallb.io/v1beta1
    kind: IPAddressPool
    metadata:
      namespace: metallb-system
      name: pool1
    spec:
      addresses:
        - 4.4.4.100-4.4.4.200
        - 2001:100:4::200-2001:100:4::400
    Copy to Clipboard Toggle word wrap
  2. 通过在 BGPAdvertisement 自定义资源中定义 .spec.nodeSelector 值,控制 pool1 广告的 IP 地址来自集群中的哪些节点:

    apiVersion: metallb.io/v1beta1
    kind: BGPAdvertisement
    metadata:
      name: example
    spec:
      ipAddressPools:
      - pool1
      nodeSelector:
      - matchLabels:
          kubernetes.io/hostname: NodeA
      - matchLabels:
          kubernetes.io/hostname: NodeB
    Copy to Clipboard Toggle word wrap

在本例中,pool1 广告的 IP 地址仅来自 NodeANodeB

4.2.5. 关于 L2Advertisement 自定义资源

l2Advertise 对象的字段在下表中定义:

Expand
表 4.4. L2 广告配置
字段类型描述

metadata.name

string

指定 L2 广告的名称。

metadata.namespace

string

指定 L2 广告的命名空间。指定 MetalLB Operator 使用的同一命名空间。

spec.ipAddressPools

string

可选:用于使用这个广告进行广告的 IPAddressPools 列表,按名称选择。

spec.ipAddressPoolSelectors

string

可选:使用这个广告进行广告的 IPAddressPools 的选择器。这可用于根据分配给 IPAddressPool 而非名称本身的标签将 IPAddressPool 与公告关联。如果这个或列表没有选择 IPAddressPool,则公告会应用到所有 IPAddressPools

spec.nodeSelectors

string

可选:NodeSelectors 将节点限制在负载均衡器 IP 的下一跃点中。如果为空,所有节点都会作为下一个跃点进行宣布。

重要

限制节点,因为下一跃点只是一个技术预览功能。技术预览功能不受红帽产品服务等级协议(SLA)支持,且功能可能并不完整。红帽不推荐在生产环境中使用它们。这些技术预览功能可以使用户提早试用新的功能,并有机会在开发阶段提供反馈意见。

有关红帽技术预览功能支持范围的更多信息,请参阅技术预览功能支持范围

spec.interfaces

string

可选:用于声明负载均衡器 IP 的接口列表。

4.2.6. 使用 L2 广告配置 MetalLB

按如下所示配置 MetalLB,以便使用 L2 协议广告 IPAddressPool

先决条件

  • 安装 OpenShift CLI(oc)。
  • 以具有 cluster-admin 特权的用户身份登录。

流程

  1. 创建 IP 地址池。

    1. 创建一个文件,如 ipaddresspool.yaml,其内容类似以下示例:

      apiVersion: metallb.io/v1beta1
      kind: IPAddressPool
      metadata:
        namespace: metallb-system
        name: doc-example-l2
      spec:
        addresses:
          - 4.4.4.0/24
        autoAssign: false
      Copy to Clipboard Toggle word wrap
    2. 应用 IP 地址池的配置:

      $ oc apply -f ipaddresspool.yaml
      Copy to Clipboard Toggle word wrap
  2. 创建 L2 广告。

    1. 创建一个文件,如 l2advertisement.yaml,内容类似以下示例:

      apiVersion: metallb.io/v1beta1
      kind: L2Advertisement
      metadata:
        name: l2advertisement
        namespace: metallb-system
      spec:
        ipAddressPools:
         - doc-example-l2
      Copy to Clipboard Toggle word wrap
    2. 应用配置:

      $ oc apply -f l2advertisement.yaml
      Copy to Clipboard Toggle word wrap

4.2.7. 使用 L2 广告和标签配置 MetalLB

BGPAdvertisementL2Advertisement 中的 ipAddress Pools 字段用于根据分配给 IPAddressPool 的标签将 IPAddressPool 与广告相关联。

本例演示了如何配置 MetalLB,以便通过配置 ipAddressPoolSelectors 字段来广告使用 L2 协议的 IPAddressPools

先决条件

  • 安装 OpenShift CLI(oc)。
  • 以具有 cluster-admin 特权的用户身份登录。

流程

  1. 创建 IP 地址池。

    1. 创建一个文件,如 ipaddresspool.yaml,其内容类似以下示例:

      apiVersion: metallb.io/v1beta1
      kind: IPAddressPool
      metadata:
        namespace: metallb-system
        name: doc-example-l2-label
        labels:
          zone: east
      spec:
        addresses:
          - 172.31.249.87/32
      Copy to Clipboard Toggle word wrap
    2. 应用 IP 地址池的配置:

      $ oc apply -f ipaddresspool.yaml
      Copy to Clipboard Toggle word wrap
  2. 使用 ipAddressPoolSelectors 创建 L2 广告广告 IP。

    1. 创建一个文件,如 l2advertisement.yaml,内容类似以下示例:

      apiVersion: metallb.io/v1beta1
      kind: L2Advertisement
      metadata:
        name: l2advertisement-label
        namespace: metallb-system
      spec:
        ipAddressPoolSelectors:
          - matchExpressions:
              - key: zone
                operator: In
                values:
                  - east
      Copy to Clipboard Toggle word wrap
    2. 应用配置:

      $ oc apply -f l2advertisement.yaml
      Copy to Clipboard Toggle word wrap

4.2.8. 为所选接口配置带有 L2 广告的 MetalLB

默认情况下,分配给该服务的 IP 地址池的 IP 地址将从所有网络接口公告。L2Advertisement 自定义资源定义中的 interfaces 字段用于限制公告 IP 地址池的网络接口。

本例演示了如何配置 MetalLB,以便仅从所有节点的 interfaces 字段中列出的网络接口公告 IP 地址池。

先决条件

  • 已安装 OpenShift CLI(oc)。
  • 您以具有 cluster-admin 权限的用户身份登录。

流程

  1. 创建 IP 地址池。

    1. 创建一个文件,如 ipaddresspool.yaml,并输入类似以下示例的配置详情:

      apiVersion: metallb.io/v1beta1
      kind: IPAddressPool
      metadata:
        namespace: metallb-system
        name: doc-example-l2
      spec:
        addresses:
          - 4.4.4.0/24
        autoAssign: false
      Copy to Clipboard Toggle word wrap
    2. 为 IP 地址池应用配置,如下例所示:

      $ oc apply -f ipaddresspool.yaml
      Copy to Clipboard Toggle word wrap
  2. 使用 接口 选择器创建 L2 广告广告 IP。

    1. 创建一个 YAML 文件,如 l2advertisement.yaml,并输入类似以下示例的配置详情:

      apiVersion: metallb.io/v1beta1
      kind: L2Advertisement
      metadata:
        name: l2advertisement
        namespace: metallb-system
      spec:
        ipAddressPools:
         - doc-example-l2
         interfaces:
         - interfaceA
         - interfaceB
      Copy to Clipboard Toggle word wrap
    2. 为公告应用配置,如下例所示:

      $ oc apply -f l2advertisement.yaml
      Copy to Clipboard Toggle word wrap
重要

接口选择器不会影响 MetalLB 如何使用 L2 选择给定 IP 的节点。如果节点没有所选接口,则所选节点不会宣布该服务。

4.2.9. 使用二级网络配置 MetalLB

在 OpenShift Container Platform 4.14 中,默认的网络行为是不允许在网络接口之间转发 IP 数据包。因此,当在二级接口上配置 MetalLB 时,您需要添加机器配置来只为所需的接口启用 IP 转发。

注意

从 4.13 升级的 OpenShift Container Platform 集群不受影响,因为在升级过程中设置了全局参数来启用全局 IP 转发。

要为二级接口启用 IP 转发,有两个选项:

  • 为特定接口启用 IP 转发。
  • 为所有接口启用 IP 转发。

    注意

    为特定接口启用 IP 转发提供了更精细的控制,同时为所有接口启用它应用全局设置。

4.2.9.1. 为特定接口启用 IP 转发

流程

  1. 运行以下命令修补 Cluster Network Operator,将参数 routingViaHost 设置为 true

    $ oc patch network.operator cluster -p '{"spec":{"defaultNetwork":{"ovnKubernetesConfig":{"gatewayConfig": {"routingViaHost": true} }}}}' --type=merge
    Copy to Clipboard Toggle word wrap
  2. 通过创建并应用 MachineConfig CR,为特定二级接口启用转发,如 bridge-net

    1. 在本地机器中运行以下命令来配置网络内核参数的字符串(基于 Base64 编码):

      $ echo -e "net.ipv4.conf.bridge-net.forwarding = 1\nnet.ipv6.conf.bridge-net.forwarding = 1\nnet.ipv4.conf.bridge-net.rp_filter = 0\nnet.ipv6.conf.bridge-net.rp_filter = 0" | base64 -w0
      Copy to Clipboard Toggle word wrap

      输出示例

      bmV0LmlwdjQuY29uZi5icmlkZ2UtbmV0LmZvcndhcmRpbmcgPSAxCm5ldC5pcHY2LmNvbmYuYnJpZGdlLW5ldC5mb3J3YXJkaW5nID0gMQpuZXQuaXB2NC5jb25mLmJyaWRnZS1uZXQucnBfZmlsdGVyID0gMApuZXQuaXB2Ni5jb25mLmJyaWRnZS1uZXQucnBfZmlsdGVyID0gMAo=
      Copy to Clipboard Toggle word wrap

    2. 创建 MachineConfig CR,为名为 bridge-net 的指定的二级接口启用 IP 转发。
    3. 将以下 YAML 保存到 enable-ip-forward.yaml 文件中:

      apiVersion: machineconfiguration.openshift.io/v1
      kind: MachineConfig
      metadata:
        labels:
          machineconfiguration.openshift.io/role: <node_role> 
      1
      
        name: 81-enable-global-forwarding
      spec:
        config:
          ignition:
            version: 3.2.0
          storage:
            files:
            - contents:
                source: data:text/plain;charset=utf-8;base64,bmV0LmlwdjQuY29uZi5icmlkZ2UtbmV0LmZvcndhcmRpbmcgPSAxCm5ldC5pcHY2LmNvbmYuYnJpZGdlLW5ldC5mb3J3YXJkaW5nID0gMQpuZXQuaXB2NC5jb25mLmJyaWRnZS1uZXQucnBfZmlsdGVyID0gMApuZXQuaXB2Ni5jb25mLmJyaWRnZS1uZXQucnBfZmlsdGVyID0gMAo= 
      2
      
                verification: {}
              filesystem: root
              mode: 420
              path: /etc/sysctl.d/enable-global-forwarding.conf
        osImageURL: ""
      Copy to Clipboard Toggle word wrap
      1
      要启用 IP 转发的节点角色,如 worker
      2
      使用生成的 base64 字符串填充
    4. 运行以下命令来应用配置:

      $ oc apply -f enable-ip-forward.yaml
      Copy to Clipboard Toggle word wrap

验证

  1. 应用机器配置后,按照以下步骤验证更改:

    1. 运行以下命令,在目标节点上进入 debug 会话:

      $ oc debug node/<node-name>
      Copy to Clipboard Toggle word wrap

      此步骤实例化一个名为 <node-name>-debug 的 debug pod。

    2. 运行以下命令,将 /host 设置为 debug shell 中的根目录:

      $ chroot /host
      Copy to Clipboard Toggle word wrap

      debug pod 在 pod 中的 /host 中挂载主机的 root 文件系统。通过将根目录改为 /host,您可以运行主机可执行路径中包含的二进制文件。

    3. 运行以下命令验证 IP 转发是否已启用:

      $ cat /etc/sysctl.d/enable-global-forwarding.conf
      Copy to Clipboard Toggle word wrap

      预期输出

      net.ipv4.conf.bridge-net.forwarding = 1
      net.ipv6.conf.bridge-net.forwarding = 1
      net.ipv4.conf.bridge-net.rp_filter = 0
      net.ipv6.conf.bridge-net.rp_filter = 0
      Copy to Clipboard Toggle word wrap

      输出显示 bridge-net 接口上启用了 IPv4 和 IPv6 数据包转发。

4.2.9.2. 全局启用 IP 转发
  • 运行以下命令来全局启用 IP 转发:
$ oc patch network.operator cluster -p '{"spec":{"defaultNetwork":{"ovnKubernetesConfig":{"gatewayConfig":{"ipForwarding": "Global"}}}}}' --type=merge
Copy to Clipboard Toggle word wrap

4.3. 配置 MetalLB BGP peer

作为集群管理员,您可以添加、修改和删除边框网关协议(BGP)对等点。MetalLB Operator 使用 BGP peer 自定义资源来标识 MetalLB speaker pod 联系的对等者启动 BGP 会话。对等点接收 MetalLB 分配给服务的负载均衡器 IP 地址的路由公告。

4.3.1. 关于 BGP peer 自定义资源

下表中描述了 BGP peer 自定义资源的字段。

Expand
表 4.5. MetalLB BGP peer 自定义资源
字段类型描述

metadata.name

string

指定 BGP peer 自定义资源的名称。

metadata.namespace

string

指定 BGP peer 自定义资源的命名空间。

spec.myASN

整数

为 BGP 会话的本地末尾指定 Autonomous System Number (ASN)。在您添加的所有 BGP peer 自定义资源中,指定相同的值。范围是从 04294967295

spec.peerASN

整数

指定 BGP 会话的远程端的 ASN。范围是从 04294967295。如果使用此字段,则无法在 spec.dynamicASN 字段中指定值。

spec.dynamicASN

string

检测用于会话远程端的 ASN,而不明确设置它。为具有相同 ASN 的对等点指定 internal,或为具有不同 ASN 的对等点指定 external。如果使用此字段,则无法在 spec.peerASN 字段中指定一个值。

spec.peerAddress

string

指定建立 BGP 会话的对等点的 IP 地址。如果使用此字段,则无法在 spec.interface 字段中指定值。

spec.interface

string

指定建立会话时使用的接口名称。使用此字段配置未编号的 BGP 对等。您必须在两个 BGP 对等点之间建立点对点、第 2 层连接。您可以将未编号的 BGP 对等用于 IPv4、IPv6 或双栈,但您必须启用 IPv6 RAs (Router Advertisements)。每个接口都限制为一个 BGP 连接。如果使用此字段,则无法在 spec.peerAddress 字段中指定一个值。

spec.sourceAddress

string

可选:指定建立 BGP 会话时要使用的 IP 地址。该值必须是 IPv4 地址。

spec.peerPort

整数

可选:指定用来建立 BGP 会话的对等端口。范围为 016384

spec.holdTime

string

可选:指定到 BGP 对等点的保留时间。最小值为 3 秒(3s)。常见的单位是秒和分钟,如 3s1m5m30s。要更快地检测路径失败,还要配置 BFD。

spec.keepaliveTime

string

可选:指定向 BGP 对等发送保留消息之间的最大间隔。如果指定此字段,还必须为 holdTime 字段指定一个值。指定的值必须小于 holdTime 字段的值。

spec.routerID

string

可选:指定要公告到 BGP peer 的路由器 ID。如果指定了此字段,则必须在添加的每个 BGP peer 自定义资源中指定相同的值。

spec.password

string

可选:指定 MD5 密码,以发送到执行 TCP MD5 经过身份验证的 BGP 会话的路由器的对等点。

spec.passwordSecret

string

可选:指定 BGP Peer 的身份验证 secret 的名称。secret 必须存在于 metallb 命名空间中,且类型为 basic-auth。

spec.bfdProfile

string

可选:指定 BFD 配置集的名称。

spec.nodeSelectors

object[]

可选:使用匹配表达式和匹配标签指定选择器,以控制哪些节点可以连接到 BGP 对等点。

spec.ebgpMultiHop

布尔值

可选:指定 BGP peer 是否有多个网络跃点。如果 BGP peer 没有直接连接到同一网络,则 speaker 无法建立 BGP 会话,除非此字段设置为 true。此字段适用于 外部 BGP。外部 BGP 是用来描述当 BGP 对等点属于不同的自治系统的术语。

connectTime

duration

指定 BGP 在连接尝试到邻居之间等待的时间。

注意

passwordSecret 字段与 password 字段相互排斥,包含对包含密码的 secret 的引用。设置这两个字段会导致解析失败。

4.3.2. 配置 BGP peer

作为集群管理员,您可以添加 BGP peer 自定义资源来与网络路由器交换路由信息,并为服务公告 IP 地址。

先决条件

  • 安装 OpenShift CLI(oc)。
  • 以具有 cluster-admin 特权的用户身份登录。
  • 使用 BGP 公告配置 MetalLB。

流程

  1. 创建一个文件,如 bgppeer.yaml,其内容类似以下示例:

    apiVersion: metallb.io/v1beta2
    kind: BGPPeer
    metadata:
      namespace: metallb-system
      name: doc-example-peer
    spec:
      peerAddress: 10.0.0.1
      peerASN: 64501
      myASN: 64500
      routerID: 10.10.10.10
    Copy to Clipboard Toggle word wrap
  2. 应用 BGP peer 的配置:

    $ oc apply -f bgppeer.yaml
    Copy to Clipboard Toggle word wrap

此流程演示了如何:

  • 配置一组地址池(pool1pool2)。
  • 配置一组 BGP 对等点(pe1peer2)。
  • 配置 BGP 广告,将 pool1 分配给 peer1,将 pool2 分配给 peer2

先决条件

  • 安装 OpenShift CLI(oc)。
  • 以具有 cluster-admin 特权的用户身份登录。

流程

  1. 创建地址池 pool1

    1. 创建一个文件,如 ipaddresspool1.yaml,其内容类似以下示例:

      apiVersion: metallb.io/v1beta1
      kind: IPAddressPool
      metadata:
        namespace: metallb-system
        name: pool1
      spec:
        addresses:
          - 4.4.4.100-4.4.4.200
          - 2001:100:4::200-2001:100:4::400
      Copy to Clipboard Toggle word wrap
    2. 为 IP 地址池 pool1 应用配置:

      $ oc apply -f ipaddresspool1.yaml
      Copy to Clipboard Toggle word wrap
  2. 创建地址池 pool2

    1. 创建一个文件,如 ipaddresspool2.yaml,其内容类似以下示例:

      apiVersion: metallb.io/v1beta1
      kind: IPAddressPool
      metadata:
        namespace: metallb-system
        name: pool2
      spec:
        addresses:
          - 5.5.5.100-5.5.5.200
          - 2001:100:5::200-2001:100:5::400
      Copy to Clipboard Toggle word wrap
    2. 为 IP 地址池 pool2 应用配置:

      $ oc apply -f ipaddresspool2.yaml
      Copy to Clipboard Toggle word wrap
  3. 创建 BGP peer1

    1. 创建一个文件,如 bgppeer1.yaml,内容类似以下示例:

      apiVersion: metallb.io/v1beta2
      kind: BGPPeer
      metadata:
        namespace: metallb-system
        name: peer1
      spec:
        peerAddress: 10.0.0.1
        peerASN: 64501
        myASN: 64500
        routerID: 10.10.10.10
      Copy to Clipboard Toggle word wrap
    2. 应用 BGP peer 的配置:

      $ oc apply -f bgppeer1.yaml
      Copy to Clipboard Toggle word wrap
  4. 创建 BGP peer2

    1. 创建一个文件,如 bgppeer2.yaml,其内容类似以下示例:

      apiVersion: metallb.io/v1beta2
      kind: BGPPeer
      metadata:
        namespace: metallb-system
        name: peer2
      spec:
        peerAddress: 10.0.0.2
        peerASN: 64501
        myASN: 64500
        routerID: 10.10.10.10
      Copy to Clipboard Toggle word wrap
    2. 应用 BGP peer2 的配置:

      $ oc apply -f bgppeer2.yaml
      Copy to Clipboard Toggle word wrap
  5. 创建 BGP 广告 1。

    1. 创建一个文件,如 bgpadvertisement1.yaml,内容类似以下示例:

      apiVersion: metallb.io/v1beta1
      kind: BGPAdvertisement
      metadata:
        name: bgpadvertisement-1
        namespace: metallb-system
      spec:
        ipAddressPools:
          - pool1
        peers:
          - peer1
        communities:
          - 65535:65282
        aggregationLength: 32
        aggregationLengthV6: 128
        localPref: 100
      Copy to Clipboard Toggle word wrap
    2. 应用配置:

      $ oc apply -f bgpadvertisement1.yaml
      Copy to Clipboard Toggle word wrap
  6. 创建 BGP 广告 2。

    1. 创建一个文件,如 bgpadvertisement2.yaml,内容类似以下示例:

      apiVersion: metallb.io/v1beta1
      kind: BGPAdvertisement
      metadata:
        name: bgpadvertisement-2
        namespace: metallb-system
      spec:
        ipAddressPools:
          - pool2
        peers:
          - peer2
        communities:
          - 65535:65282
        aggregationLength: 32
        aggregationLengthV6: 128
        localPref: 100
      Copy to Clipboard Toggle word wrap
    2. 应用配置:

      $ oc apply -f bgpadvertisement2.yaml
      Copy to Clipboard Toggle word wrap

4.3.4. 通过网络 VRF 公开服务

您可以通过在网络接口上将 VRF 与 BGP 对等点关联,通过虚拟路由和转发(VRF)实例公开服务。

重要

通过 BGP 对等点上的 VRF 公开服务只是一个技术预览功能。技术预览功能不受红帽产品服务等级协议(SLA)支持,且功能可能并不完整。红帽不推荐在生产环境中使用它们。这些技术预览功能可以使用户提早试用新的功能,并有机会在开发阶段提供反馈意见。

有关红帽技术预览功能支持范围的更多信息,请参阅技术预览功能支持范围

通过使用网络接口上的 VRF 通过 BGP 对等点公开服务,您可以将流量隔离到服务,配置独立路由决策,并在网络接口上启用多租户支持。

注意

通过一个属于网络 VRF 的接口建立 BGP 会话,MetalLB 可以通过该接口公告服务,并让外部流量通过这个接口访问该服务。但是,network VRF 路由表与 OVN-Kubernetes 使用的默认 VRF 路由表不同。因此,流量无法访问 OVN-Kubernetes 网络基础架构。

要启用定向到服务的流量访问 OVN-Kubernetes 网络基础架构,您必须配置路由规则来为网络流量定义下一跃点。如需更多信息,请参阅附加资源部分中的"使用 MetalLB 管理对称路由"中的 NodeNetworkConfigurationPolicy 资源。

这些是通过带有 BGP peer 的网络 VRF 公开服务的高级步骤:

  1. 定义 BGP peer 并添加网络 VRF 实例。
  2. 为 MetalLB 指定 IP 地址池。
  3. 为 MetalLB 配置 BGP 路由广告,以使用指定的 IP 地址池以及与 VRF 实例关联的 BGP 对等点公告路由。
  4. 部署服务来测试配置。

先决条件

  • 已安装 OpenShift CLI(oc)。
  • 以具有 cluster-admin 权限的用户身份登录。
  • 您定义了一个 NodeNetworkConfigurationPolicy,将虚拟路由和转发(VRF)实例与网络接口关联。有关完成此先决条件的更多信息,请参阅附加资源部分。
  • 在集群中安装了 MetalLB。

流程

  1. 创建 BGPPeer 自定义资源 (CR):

    1. 创建一个文件,如 frrviavrf.yaml,其内容类似以下示例:

      apiVersion: metallb.io/v1beta2
      kind: BGPPeer
      metadata:
        name: frrviavrf
        namespace: metallb-system
      spec:
        myASN: 100
        peerASN: 200
        peerAddress: 192.168.130.1
        vrf: ens4vrf 
      1
      Copy to Clipboard Toggle word wrap
      1
      指定要与 BGP peer 关联的网络 VRF 实例。MetalLB 可以公告服务并根据 VRF 中的路由信息做出路由决策。
      注意

      您必须在 NodeNetworkConfigurationPolicy CR 中配置此网络 VRF 实例。如需更多信息,请参阅附加资源

    2. 运行以下命令,应用 BGP peer 的配置:

      $ oc apply -f frrviavrf.yaml
      Copy to Clipboard Toggle word wrap
  2. 创建一个 IPAddressPool CR:

    1. 创建一个文件,如 first-pool.yaml,其内容类似以下示例:

      apiVersion: metallb.io/v1beta1
      kind: IPAddressPool
      metadata:
        name: first-pool
        namespace: metallb-system
      spec:
        addresses:
        - 192.169.10.0/32
      Copy to Clipboard Toggle word wrap
    2. 运行以下命令,为 IP 地址池应用配置:

      $ oc apply -f first-pool.yaml
      Copy to Clipboard Toggle word wrap
  3. 创建 BGPAdvertisement CR:

    1. 创建一个文件,如 first-adv.yaml,其内容类似以下示例:

      apiVersion: metallb.io/v1beta1
      kind: BGPAdvertisement
      metadata:
        name: first-adv
        namespace: metallb-system
      spec:
        ipAddressPools:
          - first-pool
        peers:
          - frrviavrf 
      1
      Copy to Clipboard Toggle word wrap
      1
      在本例中,MetalLB 将来自 first-pool IP 地址池的 IP 地址范围公告给 frrviavrf BGP peer。
    2. 运行以下命令,应用 BGP 公告的配置:

      $ oc apply -f first-adv.yaml
      Copy to Clipboard Toggle word wrap
  4. 创建一个 Namespace, Deployment, 和 Service CR:

    1. 创建一个文件,如 deploy-service.yaml,其内容类似以下示例:

      apiVersion: v1
      kind: Namespace
      metadata:
        name: test
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: server
        namespace: test
      spec:
        selector:
          matchLabels:
            app: server
        template:
          metadata:
            labels:
              app: server
          spec:
            containers:
            - name: server
              image: registry.redhat.io/ubi9/ubi
              ports:
              - name: http
                containerPort: 30100
              command: ["/bin/sh", "-c"]
              args: ["sleep INF"]
      ---
      apiVersion: v1
      kind: Service
      metadata:
        name: server1
        namespace: test
      spec:
        ports:
        - name: http
          port: 30100
          protocol: TCP
          targetPort: 30100
        selector:
          app: server
        type: LoadBalancer
      Copy to Clipboard Toggle word wrap
    2. 运行以下命令,为命名空间、部署和服务应用配置:

      $ oc apply -f deploy-service.yaml
      Copy to Clipboard Toggle word wrap

验证

  1. 运行以下命令来识别 MetalLB speaker pod:

    $ oc get -n metallb-system pods -l component=speaker
    Copy to Clipboard Toggle word wrap

    输出示例

    NAME            READY   STATUS    RESTARTS   AGE
    speaker-c6c5f   6/6     Running   0          69m
    Copy to Clipboard Toggle word wrap

  2. 运行以下命令,在 speaker pod 中验证 BGP 会话的状态是否为 Established,替换变量以匹配您的配置:

    $ oc exec -n metallb-system <speaker_pod> -c frr -- vtysh -c "show bgp vrf <vrf_name> neigh"
    Copy to Clipboard Toggle word wrap

    输出示例

    BGP neighbor is 192.168.30.1, remote AS 200, local AS 100, external link
      BGP version 4, remote router ID 192.168.30.1, local router ID 192.168.30.71
      BGP state = Established, up for 04:20:09
    
    ...
    Copy to Clipboard Toggle word wrap

  3. 运行以下命令验证该服务是否已正确公告:

    $ oc exec -n metallb-system <speaker_pod> -c frr -- vtysh -c "show bgp vrf <vrf_name> ipv4"
    Copy to Clipboard Toggle word wrap

4.3.5. BGP 对等配置示例

4.3.5.1. 示例:限制节点连接到 BGP peer

您可以指定节点选择器字段来控制哪些节点可以连接到 BGP 对等点。

apiVersion: metallb.io/v1beta2
kind: BGPPeer
metadata:
  name: doc-example-nodesel
  namespace: metallb-system
spec:
  peerAddress: 10.0.20.1
  peerASN: 64501
  myASN: 64500
  nodeSelectors:
  - matchExpressions:
    - key: kubernetes.io/hostname
      operator: In
      values: [compute-1.example.com, compute-2.example.com]
Copy to Clipboard Toggle word wrap
4.3.5.2. 示例:为 BGP peer 指定 BFD 配置集

您可以指定一个 BFD 配置集,以与 BGP 对等点关联。BFD 复杂的 BGP 通过单独提供与 BGP 间通信故障的更快速检测。

apiVersion: metallb.io/v1beta2
kind: BGPPeer
metadata:
  name: doc-example-peer-bfd
  namespace: metallb-system
spec:
  peerAddress: 10.0.20.1
  peerASN: 64501
  myASN: 64500
  holdTime: "10s"
  bfdProfile: doc-example-bfd-profile-full
Copy to Clipboard Toggle word wrap
注意

删除双向转发检测 (BFD) 配置集并删除添加到边框网关协议 (BGP) 对等资源中的 bfdProfile 不会禁用 BFD。相反,BGP 对等点开始使用默认的 BFD 配置集。要从 BGP peer 资源禁用 BFD,请删除 BGP 对等配置,并在没有 BFD 配置集的情况下重新创建它。如需更多信息,请参阅 BZ#2050824

4.3.5.3. 示例:为双栈网络指定 BGP 对等点

要支持双栈网络,请为 IPv4 添加一个 BGP peer 自定义资源,并为 IPv6 添加一个 BGP peer 自定义资源。

apiVersion: metallb.io/v1beta2
kind: BGPPeer
metadata:
  name: doc-example-dual-stack-ipv4
  namespace: metallb-system
spec:
  peerAddress: 10.0.20.1
  peerASN: 64500
  myASN: 64500
---
apiVersion: metallb.io/v1beta2
kind: BGPPeer
metadata:
  name: doc-example-dual-stack-ipv6
  namespace: metallb-system
spec:
  peerAddress: 2620:52:0:88::104
  peerASN: 64500
  myASN: 64500
Copy to Clipboard Toggle word wrap

要配置未编号的 BGP peering,请使用以下示例配置在 spec.interface 字段中指定接口:

apiVersion: metallb.io/v1beta2
kind: BGPPeer
metadata:
  name: peer-unnumber
  namespace: metallb-system
spec:
  myASN: 64512
  ASN: 645000
  interface: net0
Copy to Clipboard Toggle word wrap
注意

要使用 interface 字段,您必须在两个 BGP 对等点之间建立点对点、第 2 层连接。您可以将未编号的 BGP 对等用于 IPv4、IPv6 或双栈,但您必须启用 IPv6 RAs (Router Advertisements)。每个接口都限制为一个 BGP 连接。

如果使用此字段,则无法在 spec.bgp.routers.neighbors.address 字段中指定一个值。

4.3.6. 后续步骤

4.4. 配置社区别名

作为集群管理员,您可以配置一个社区别名并在不同的广告中使用它。

4.4.1. 关于社区自定义资源

community 自定义资源是社区的一个别名集合。用户可使用 BGPAdvertis 定义广告 ipAddressPools 时使用的命名别名。下表中描述了 community 自定义资源的字段。

注意

community CRD 仅适用于 BGPAdvertisement。

Expand
表 4.6. MetalLB 社区自定义资源
字段类型描述

metadata.name

string

指定 community 的名称。

metadata.namespace

string

指定 community 的命名空间。指定 MetalLB Operator 使用的同一命名空间。

spec.communities

string

指定可在 BGPAdvertisements 中使用的 BGP 社区别名列表。社区别名由名称(别名)和值(数字:number)组成。通过引用 spec.communities 字段中的别名名称,将 BGPAdvertisement 链接到社区别名。

Expand
表 4.7. CommunityAlias
字段类型描述

name

string

community 的别名名称。

value

string

与给定名称对应的 BGP community 值。

4.4.2. 使用 BGP 广告和社区别名配置 MetalLB

按如下所示配置 MetalLB,以便 BGP 协议广告 IPAddressPool,并将社区别名设置为 NO_ADVERTISE 社区的数字值。

在以下示例中,对等 BGP 路由器 doc-example-peer-community 接收一个 203.0.113.200/32 路由,以及一个 fc00:f853:ccd:e799::1/128 路由,每个 load-balancer IP 地址都分配给服务。使用 NO_ADVERTISE 社区配置了一个社区别名。

先决条件

  • 安装 OpenShift CLI(oc)。
  • 以具有 cluster-admin 特权的用户身份登录。

流程

  1. 创建 IP 地址池。

    1. 创建一个文件,如 ipaddresspool.yaml,其内容类似以下示例:

      apiVersion: metallb.io/v1beta1
      kind: IPAddressPool
      metadata:
        namespace: metallb-system
        name: doc-example-bgp-community
      spec:
        addresses:
          - 203.0.113.200/30
          - fc00:f853:ccd:e799::/124
      Copy to Clipboard Toggle word wrap
    2. 应用 IP 地址池的配置:

      $ oc apply -f ipaddresspool.yaml
      Copy to Clipboard Toggle word wrap
  2. 创建名为 community1 的社区别名。

    apiVersion: metallb.io/v1beta1
    kind: Community
    metadata:
      name: community1
      namespace: metallb-system
    spec:
      communities:
        - name: NO_ADVERTISE
          value: '65535:65282'
    Copy to Clipboard Toggle word wrap
  3. 创建一个名为 doc-example-bgp-peer 的 BGP peer。

    1. 创建一个文件,如 bgppeer.yaml,其内容类似以下示例:

      apiVersion: metallb.io/v1beta2
      kind: BGPPeer
      metadata:
        namespace: metallb-system
        name: doc-example-bgp-peer
      spec:
        peerAddress: 10.0.0.1
        peerASN: 64501
        myASN: 64500
        routerID: 10.10.10.10
      Copy to Clipboard Toggle word wrap
    2. 应用 BGP peer 的配置:

      $ oc apply -f bgppeer.yaml
      Copy to Clipboard Toggle word wrap
  4. 创建一个带有社区别名的 BGP 广告。

    1. 创建一个文件,如 bgpadvertisement.yaml,内容类似以下示例:

      apiVersion: metallb.io/v1beta1
      kind: BGPAdvertisement
      metadata:
        name: bgp-community-sample
        namespace: metallb-system
      spec:
        aggregationLength: 32
        aggregationLengthV6: 128
        communities:
          - NO_ADVERTISE 
      1
      
        ipAddressPools:
          - doc-example-bgp-community
        peers:
          - doc-example-peer
      Copy to Clipboard Toggle word wrap
      1
      在这里指定 CommunityAlias.name,而不是社区自定义资源 (CR) 名称。
    2. 应用配置:

      $ oc apply -f bgpadvertisement.yaml
      Copy to Clipboard Toggle word wrap

4.5. 配置 MetalLB BFD 配置集

作为集群管理员,您可以添加、修改和删除双向检测(BFD)配置集。MetalLB Operator 使用 BFD 配置集自定义资源来识别哪个 BGP 会话使用 BFD 来单独提供比 BGP 更快地提供的路径故障检测。

4.5.1. 关于 BFD 配置集自定义资源

下表中描述了 BFD 配置集自定义资源的字段。

Expand
表 4.8. BFD 配置集自定义资源
字段类型描述

metadata.name

string

指定 BFD 配置集自定义资源的名称。

metadata.namespace

string

指定 BFD 配置集自定义资源的命名空间。

spec.detectMultiplier

整数

指定确定数据包丢失的检测倍数。远程传输间隔乘以这个值来确定连接丢失检测计时器。

例如,当本地系统的检测倍数设置为 3,而远程系统会将传输间隔设置为 300 时,本地系统仅在没有接收数据包的 900 ms 后才会检测故障。

范围为 2255。默认值为 3

spec.echoMode

布尔值

指定回显传输模式。如果您不使用分布式 BFD,则回显传输模式仅在 peer 也是 FRR 时才可以正常工作。默认值为 false,而回显传输模式被禁用。

启用回显传输模式时,请考虑增加控制数据包的传输间隔,以减少带宽使用量。例如,考虑将传输间隔增加到 2000 毫秒。

spec.echoInterval

整数

指定此系统用来发送和接收回显数据包的最小传输间隔(较少的)。范围为 1060000。默认值为 50 ms。

spec.minimumTtl

整数

指定传入控制数据包的最低预期 TTL。此字段只适用于多跃点会话。

设置最小 TTL 的目的是使数据包验证要求更加严格,并避免从其他会话接收控制数据包。

默认值为 254,表示系统在该系统和对等点之间仅需要一个跃点。

spec.passiveMode

布尔值

指定会话是否标记为主动或者被动。被动会话不会尝试启动连接。相反,被动会话会等待来自 peer 的控制数据包,然后再开始回复。

当您有一个作为星星网络的中央节点,并且您希望发送不需要系统发送的控制数据包时,如果您有一个路由器将会话标记为被动。

默认值为 false,并将会话标记为 active。

spec.receiveInterval

整数

指定此系统可以接收控制数据包的最低间隔。范围为 1060000。默认值为 300 ms。

spec.transmitInterval

整数

指定此系统用来发送控制数据包的最小传输间隔(较少的)。范围为 1060000。默认值为 300 ms。

4.5.2. 配置 BFD 配置集

作为集群管理员,您可以添加 BFD 配置集,并配置 BGP 对等点来使用配置集。BFD 仅提供比 BGP 快于 BGP 的路径故障检测速度。

先决条件

  • 安装 OpenShift CLI(oc)。
  • 以具有 cluster-admin 特权的用户身份登录。

流程

  1. 创建一个文件,如 bfdprofile.yaml,其内容如下:

    apiVersion: metallb.io/v1beta1
    kind: BFDProfile
    metadata:
      name: doc-example-bfd-profile-full
      namespace: metallb-system
    spec:
      receiveInterval: 300
      transmitInterval: 300
      detectMultiplier: 3
      echoMode: false
      passiveMode: true
      minimumTtl: 254
    Copy to Clipboard Toggle word wrap
  2. 为 BFD 配置集应用配置:

    $ oc apply -f bfdprofile.yaml
    Copy to Clipboard Toggle word wrap

4.5.3. 后续步骤

4.6. 将服务配置为使用 MetalLB

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

4.6.1. 请求特定 IP 地址

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

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

特定 IP 地址的服务 YAML 示例

apiVersion: v1
kind: Service
metadata:
  name: <service_name>
  annotations:
    metallb.io/address-pool: <address_pool_name>
spec:
  selector:
    <label_key>: <label_value>
  ports:
    - port: 8080
      targetPort: 8080
      protocol: TCP
  type: LoadBalancer
  loadBalancerIP: <ip_address>
Copy to Clipboard Toggle word wrap

如果 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
Copy to Clipboard Toggle word wrap

4.6.2. 从特定池中请求 IP 地址

要从特定范围分配 IP 地址,但您不关注特定的 IP 地址,您可以使用 metallb.io/address-pool 注解从指定地址池中请求 IP 地址。

来自特定池的 IP 地址的服务 YAML 示例

apiVersion: v1
kind: Service
metadata:
  name: <service_name>
  annotations:
    metallb.io/address-pool: <address_pool_name>
spec:
  selector:
    <label_key>: <label_value>
  ports:
    - port: 8080
      targetPort: 8080
      protocol: TCP
  type: LoadBalancer
Copy to Clipboard Toggle word wrap

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

4.6.3. 接受任何 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
Copy to Clipboard Toggle word wrap

4.6.4. 共享特定 IP 地址

默认情况下,服务不共享 IP 地址。但是,如果您需要在单个 IP 地址上并置服务,可以通过向服务添加 metallb.io/allow-shared-ip 注解来启用选择性 IP 共享。

apiVersion: v1
kind: Service
metadata:
  name: service-http
  annotations:
    metallb.io/address-pool: doc-example
    metallb.io/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.io/address-pool: doc-example
    metallb.io/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
Copy to Clipboard Toggle word wrap
1
metallb.io/allow-shared-ip 注解指定相同的值。此值被称为 共享键(sharing key)
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 地址上并置。

4.6.5. 使用 MetalLB 配置服务

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

先决条件

  • 安装 OpenShift CLI (oc) 。
  • 安装 MetalLB Operator 并启动 MetalLB。
  • 至少配置一个地址池。
  • 配置网络,将流量从客户端路由到集群的主机网络。

流程

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

    有关如何请求 MetalLB 分配给服务的外部 IP 地址的信息,请参考示例。

  2. 创建服务:

    $ oc apply -f <service_name>.yaml
    Copy to Clipboard Toggle word wrap

    输出示例

    service/<service_name> created
    Copy to Clipboard Toggle word wrap

验证

  • 描述该服务:

    $ oc describe service <service_name>
    Copy to Clipboard Toggle word wrap

    输出示例

    Name:                     <service_name>
    Namespace:                default
    Labels:                   <none>
    Annotations:              metallb.io/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>"
    Copy to Clipboard Toggle word wrap

    1
    如果您从特定池请求 IP 地址,则会显示该注释。
    2
    服务类型必须表示 LoadBalancer
    3
    如果服务被正确分配,load-balancer ingress 字段会指示外部 IP 地址。
    4
    events 字段显示分配给声明外部 IP 地址的节点名称。如果出现错误,Event 字段会指示错误的原因。

4.7. 使用 MetalLB 管理对称路由

作为集群管理员,您可以通过从 MetalLB、NMState 和 OVN-Kubernetes 实现功能来有效地管理带有多个主机接口的 MetalLB 负载均衡器服务后面的 pod 的流量。通过结合此上下文中的这些功能,您可以提供对称路由、流量隔离,并支持具有不同网络上的客户端及重叠 CIDR 地址。

要实现此功能,了解如何使用 MetalLB 实施虚拟路由和转发(VRF)实例,并配置出口服务。

重要

使用带有 MetalLB 和出口服务的 VRF 实例配置对称流量只是一个技术预览功能。技术预览功能不受红帽产品服务等级协议(SLA)支持,且功能可能并不完整。红帽不推荐在生产环境中使用它们。这些技术预览功能可以使用户提早试用新的功能,并有机会在开发阶段提供反馈意见。

有关红帽技术预览功能支持范围的更多信息,请参阅技术预览功能支持范围

4.7.1. 使用 MetalLB 管理对称路由的挑战

当您将 MetalLB 与多个主机接口搭配使用时,MetalLB 通过主机上的所有可用接口公开并宣布服务。这可能会造成与网络隔离、非对称返回流量和重叠 CIDR 地址相关的挑战。

确保返回流量达到正确的客户端的一个选项是使用静态路由。但是,使用这个解决方案,MetalLB 无法隔离服务,然后通过不同的接口声明每个服务。另外,静态路由需要手动配置,并在添加远程站点时需要维护。

在实现 MetalLB 服务时,对称路由的进一步挑战是外部系统预期应用程序的源和目标 IP 地址相同的情况。OpenShift Container Platform 的默认行为是将主机网络接口的 IP 地址分配为来自 pod 的流量的源 IP 地址。这在多个主机接口中存在问题。

您可以通过实施组合来自 MetalLB、NMState 和 OVN-Kubernetes 的功能的配置来解决这些挑战。

您可以使用 NMState 在主机上配置 VRF 实例、将 VRF 实例与 MetalLB BGPPeer 资源关联,以及为出口流量配置出口服务来克服实施对称路由的挑战。

图 4.1. 使用带有 MetalLB 的 VRF 管理对称路由的网络概述

配置过程涉及三个阶段:

1.定义 VRF 和路由规则

  • 配置 NodeNetworkConfigurationPolicy 自定义资源 (CR),将 VRF 实例与网络接口关联。
  • 使用 VRF 路由表直接入口和出口流量。

2.将 VRF 链接到 MetalLB BGPPeer

  • 配置 MetalLB BGPPeer 资源,以使用网络接口上的 VRF 实例。
  • 通过将 BGPPeer 资源与 VRF 实例关联,指定的网络接口成为 BGP 会话的主接口,MetalLB 通过这个接口公告服务。

3.配置出口服务

  • 配置出口服务,为出口流量选择与 VRF 实例关联的网络。
  • 可选:将出口服务配置为使用 MetalLB 负载均衡器服务的 IP 地址作为出口流量的源 IP。

4.7.3. 使用带有 MetalLB 的 VRF 配置对称路由

您可以为需要同一入口和出口网络路径的 MetalLB 服务后面的应用程序配置对称网络路由。

这个示例将 VRF 路由表与 MetalLB 和出口服务相关联,以便为 LoadBalancer 服务后面的 pod 启用对称路由。

重要
  • 如果您在 EgressService CR 中使用 sourceIPBy: "LoadBalancerIP" 设置,您必须在 BGPAdvertisement 自定义资源 (CR) 中指定负载均衡器节点。
  • 在使用带有 gatewayConfig.routingViaHost 规格设置为 true 的 OVN-Kubernetes 的集群中,您可以使用 sourceIPBy: "Network" 设置。另外,如果您使用 sourceIPBy: "Network" 设置,您必须在使用网络 VRF 实例配置的节点上调度应用程序工作负载。

先决条件

  • 安装 OpenShift CLI(oc)。
  • 以具有 cluster-admin 特权的用户身份登录。
  • 安装 Kubernetes NMState Operator。
  • 安装 MetalLB Operator。

流程

  1. 创建一个 NodeNetworkConfigurationPolicy CR 来定义 VRF 实例:

    1. 创建一个文件,如 node-network-vrf.yaml,其内容类似以下示例:

      apiVersion: nmstate.io/v1
      kind: NodeNetworkConfigurationPolicy
      metadata:
        name: vrfpolicy 
      1
      
      spec:
        nodeSelector:
          vrf: "true" 
      2
      
        maxUnavailable: 3
        desiredState:
          interfaces:
          - name: ens4vrf 
      3
      
            type: vrf 
      4
      
            state: up
            vrf:
              port:
              - ens4 
      5
      
              route-table-id: 2 
      6
      
          - name: ens4 
      7
      
            type: ethernet
            state: up
            ipv4:
              address:
              - ip: 192.168.130.130
                prefix-length: 24
              dhcp: false
              enabled: true
          routes: 
      8
      
            config:
            - destination: 0.0.0.0/0
              metric: 150
              next-hop-address: 192.168.130.1
              next-hop-interface: ens4
              table-id: 2
          route-rules: 
      9
      
            config:
            - ip-to: 172.30.0.0/16
              priority: 998
              route-table: 254 
      10
      
            - ip-to: 10.132.0.0/14
              priority: 998
              route-table: 254
            - ip-to: 169.254.0.0/17
              priority: 998
              route-table: 254
      Copy to Clipboard Toggle word wrap
      1
      策略的名称。
      2
      这个示例将策略应用到带有 vrf:true 标签的所有节点。
      3
      接口的名称。
      4
      接口的类型。这个示例创建了一个 VRF 实例。
      5
      VRF 附加到的节点接口。
      6
      VRF 的路由表 ID 的名称。
      7
      与 VRF 关联的接口的 IPv4 地址。
      8
      定义网络路由的配置。next-hop-address 字段定义路由的下一跃点的 IP 地址。next-hop-interface 字段定义路由的传出接口。在本例中,VRF 路由表是 2,它引用您在 EgressService CR 中定义的 ID。
      9
      定义额外的路由规则。ip-to 字段必须与 Cluster Network CIDR、Service Network CIDR 和 Internal Masquerade 子网 CIDR 匹配。您可以运行以下命令来查看这些 CIDR 地址规格的值: oc describe network.operator/cluster
      10
      计算路由时使用的 Linux 内核的主路由表的 ID 为 254
    2. 运行以下命令来应用策略:

      $ oc apply -f node-network-vrf.yaml
      Copy to Clipboard Toggle word wrap
  2. 创建 BGPPeer 自定义资源 (CR):

    1. 创建一个文件,如 frr-via-vrf.yaml,其内容类似以下示例:

      apiVersion: metallb.io/v1beta2
      kind: BGPPeer
      metadata:
        name: frrviavrf
        namespace: metallb-system
      spec:
        myASN: 100
        peerASN: 200
        peerAddress: 192.168.130.1
        vrf: ens4vrf 
      1
      Copy to Clipboard Toggle word wrap
      1
      指定要与 BGP peer 关联的 VRF 实例。MetalLB 可以公告服务并根据 VRF 中的路由信息做出路由决策。
    2. 运行以下命令,应用 BGP peer 的配置:

      $ oc apply -f frr-via-vrf.yaml
      Copy to Clipboard Toggle word wrap
  3. 创建一个 IPAddressPool CR:

    1. 创建一个文件,如 first-pool.yaml,其内容类似以下示例:

      apiVersion: metallb.io/v1beta1
      kind: IPAddressPool
      metadata:
        name: first-pool
        namespace: metallb-system
      spec:
        addresses:
        - 192.169.10.0/32
      Copy to Clipboard Toggle word wrap
    2. 运行以下命令,为 IP 地址池应用配置:

      $ oc apply -f first-pool.yaml
      Copy to Clipboard Toggle word wrap
  4. 创建 BGPAdvertisement CR:

    1. 创建一个文件,如 first-adv.yaml,其内容类似以下示例:

      apiVersion: metallb.io/v1beta1
      kind: BGPAdvertisement
      metadata:
        name: first-adv
        namespace: metallb-system
      spec:
        ipAddressPools:
          - first-pool
        peers:
          - frrviavrf 
      1
      
        nodeSelectors:
          - matchLabels:
              egress-service.k8s.ovn.org/test-server1: "" 
      2
      Copy to Clipboard Toggle word wrap
      1
      在本例中,MetalLB 将来自 first-pool IP 地址池的 IP 地址范围公告给 frrviavrf BGP peer。
      2
      在本例中,EgressService CR 将出口流量的源 IP 地址配置为使用负载均衡器服务 IP 地址。因此,您必须指定负载均衡器节点返回流量,以便为来自 pod 的流量使用相同的返回路径。
    2. 运行以下命令,应用 BGP 公告的配置:

      $ oc apply -f first-adv.yaml
      Copy to Clipboard Toggle word wrap
  5. 创建一个 EgressService CR:

    1. 创建一个文件,如 egress-service.yaml,其内容类似以下示例:

      apiVersion: k8s.ovn.org/v1
      kind: EgressService
      metadata:
        name: server1 
      1
      
        namespace: test 
      2
      
      spec:
        sourceIPBy: "LoadBalancerIP" 
      3
      
        nodeSelector:
          matchLabels:
            vrf: "true" 
      4
      
        network: "2" 
      5
      Copy to Clipboard Toggle word wrap
      1
      指定出口服务的名称。EgressService 资源的名称必须与您要修改的负载均衡器服务的名称匹配。
      2
      指定出口服务的命名空间。EgressService 的命名空间必须与您要修改的负载均衡器服务的命名空间匹配。egress 服务是命名空间范围的。
      3
      这个示例将 LoadBalancer 服务入口 IP 地址分配为出口流量的源 IP 地址。
      4
      如果为 sourceIPBy 规格指定 LoadBalancer,则单一节点处理 LoadBalancer 服务流量。在本例中,只有标签 vrf: "true" 的节点才能处理服务流量。如果没有指定节点,OVN-Kubernetes 会选择一个 worker 节点来处理服务流量。当选择节点时,OVN-Kubernetes 以以下格式标记节点: egress-service.k8s.ovn.org/<svc_namespace>-<svc_name>: ""
      5
      指定出口流量的路由表 ID。确保值与 NodeNetworkConfigurationPolicy 资源中定义的 route-table-id ID 匹配,例如 route-table-id: 2
    2. 运行以下命令,为出口服务应用配置:

      $ oc apply -f egress-service.yaml
      Copy to Clipboard Toggle word wrap

验证

  1. 运行以下命令,验证您可以访问 MetalLB 服务后运行的 pod 的应用程序端点:

    $ curl <external_ip_address>:<port_number> 
    1
    Copy to Clipboard Toggle word wrap
    1
    更新外部 IP 地址和端口号,以适合您的应用程序端点。
  2. 可选:如果您将 LoadBalancer 服务入口 IP 地址指定为出口流量的源 IP 地址,请使用 tcpdump 等工具分析外部客户端接收的数据包,以此验证此配置。

4.8. 配置 MetalLB 和 FRR-K8s 的集成

FRRouting (FRR) 是一个免费的开源互联网路由协议套件,用于 Linux 和 UNIX 平台。FRR-K8s 是基于 Kubernetes 的 DaemonSet,它以 Kubernetes 兼容的方式公开 FRR API 的子集。作为集群管理员,您可以使用 FRRConfiguration 自定义资源 (CR) 访问 MetalLB 未提供的一些 FRR 服务,例如接收路由。MetalLB 生成 FRR-K8s 配置,对应于应用的 MetalLB 配置。

警告

在配置虚拟路由转发(VRF)用户时,必须将其 VRF 改为小于 1000 的表 ID,因为 OpenShift Container Platform 保留大于 1000。

4.8.1. FRR 配置

您可以创建多个 FRRConfiguration CR,以便在 MetalLB 中使用 FRR 服务。MetalLB 生成一个 FRRConfiguration 对象,它 FRR-K8s 与所有用户创建的所有配置合并。

例如,您可以配置 FRR-K8s,以接收给定邻居公告的所有前缀。以下示例将 FRR-K8s 配置为接收带有主机 172.18.0.5BGPPeer 公告的所有前缀:

FRRConfiguration CR 示例

apiVersion: frrk8s.metallb.io/v1beta1
kind: FRRConfiguration
metadata:
 name: test
 namespace: metallb-system
spec:
 bgp:
   routers:
   - asn: 64512
     neighbors:
     - address: 172.18.0.5
       asn: 64512
       toReceive:
        allowed:
            mode: all
Copy to Clipboard Toggle word wrap

您还可以将 FRR-K8s 配置为始终阻止一组前缀,而不考虑应用的配置。这可用于避免到可能造成集群故障的 pod 或 ClusterIP CIDR 的路由。以下示例阻止了一组前缀 192.168.1.0/24

MetalLB CR 示例

apiVersion: metallb.io/v1beta1
kind: MetalLB
metadata:
  name: metallb
  namespace: metallb-system
spec:
  bgpBackend: frr-k8s
  frrk8sConfig:
    alwaysBlock:
    - 192.168.1.0/24
Copy to Clipboard Toggle word wrap

您可以将 FRR-K8s 设置为阻止 Cluster Network CIDR 和 Service Network CIDR。您可以运行以下命令来查看这些 CIDR 地址规格的值:

$ oc describe network.config/cluster
Copy to Clipboard Toggle word wrap

4.8.2. 配置 FRRConfiguration CRD

以下部分提供了使用 FRRConfiguration 自定义资源 (CR) 的参考示例。

4.8.2.1. router 字段

您可以使用 router 字段配置多个路由器,每个虚拟路由和转发 (VRF) 资源对应一个。对于每个路由器,您必须定义自主系统号 (ASN)。

您还可以定义要连接的边框网关协议 (BGP) 邻居列表,如下例所示:

FRRConfiguration CR 示例

apiVersion: frrk8s.metallb.io/v1beta1
kind: FRRConfiguration
metadata:
  name: test
  namespace: frr-k8s-system
spec:
  bgp:
    routers:
    - asn: 64512
      neighbors:
      - address: 172.30.0.3
        asn: 4200000000
        ebgpMultiHop: true
        port: 180
      - address: 172.18.0.6
        asn: 4200000000
        port: 179
Copy to Clipboard Toggle word wrap

4.8.2.2. toAdvertise 字段

默认情况下,FRR-K8s 不会公告配置为路由器配置的前缀。要公告它们,您可以使用 toAdvertise 字段。

您可以公告前缀的子集,如下例所示:

FRRConfiguration CR 示例

apiVersion: frrk8s.metallb.io/v1beta1
kind: FRRConfiguration
metadata:
  name: test
  namespace: frr-k8s-system
spec:
  bgp:
    routers:
    - asn: 64512
      neighbors:
      - address: 172.30.0.3
        asn: 4200000000
        ebgpMultiHop: true
        port: 180
        toAdvertise:
          allowed:
            prefixes: 
1

            - 192.168.2.0/24
      prefixes:
        - 192.168.2.0/24
        - 192.169.2.0/24
Copy to Clipboard Toggle word wrap

1
广告一个前缀子集。

以下示例演示了如何公告所有前缀:

FRRConfiguration CR 示例

apiVersion: frrk8s.metallb.io/v1beta1
kind: FRRConfiguration
metadata:
  name: test
  namespace: frr-k8s-system
spec:
  bgp:
    routers:
    - asn: 64512
      neighbors:
      - address: 172.30.0.3
        asn: 4200000000
        ebgpMultiHop: true
        port: 180
        toAdvertise:
          allowed:
            mode: all 
1

      prefixes:
        - 192.168.2.0/24
        - 192.169.2.0/24
Copy to Clipboard Toggle word wrap

1
公告所有前缀。
4.8.2.3. toReceive 字段

默认情况下,FRR-K8s 不处理邻居公告的任何前缀。您可以使用 toReceive 字段来处理此类地址。

您可以为前缀的子集配置,如下例所示:

FRRConfiguration CR 示例

apiVersion: frrk8s.metallb.io/v1beta1
kind: FRRConfiguration
metadata:
  name: test
  namespace: frr-k8s-system
spec:
  bgp:
    routers:
    - asn: 64512
      neighbors:
      - address: 172.18.0.5
          asn: 64512
          port: 179
          toReceive:
            allowed:
              prefixes:
              - prefix: 192.168.1.0/24
              - prefix: 192.169.2.0/24
                ge: 25 
1

                le: 28 
2
Copy to Clipboard Toggle word wrap

1 2
如果前缀长度小于或等于 le 的前缀长度,且大于或等于 ge 的前缀长度,则应用前缀。

以下示例将 FRR 配置为处理声明的所有前缀:

FRRConfiguration CR 示例

apiVersion: frrk8s.metallb.io/v1beta1
kind: FRRConfiguration
metadata:
  name: test
  namespace: frr-k8s-system
spec:
  bgp:
    routers:
    - asn: 64512
      neighbors:
      - address: 172.18.0.5
          asn: 64512
          port: 179
          toReceive:
            allowed:
              mode: all
Copy to Clipboard Toggle word wrap

4.8.2.4. bgp 字段

您可以使用 bgp 字段定义各种 BFD 配置集,并将它们与邻居关联。在以下示例中,BFD 备份 BGP 会话,FRR 可以检测链接失败:

FRRConfiguration CR 示例

apiVersion: frrk8s.metallb.io/v1beta1
kind: FRRConfiguration
metadata:
  name: test
  namespace: frr-k8s-system
spec:
  bgp:
    routers:
    - asn: 64512
      neighbors:
      - address: 172.30.0.3
        asn: 64512
        port: 180
        bfdProfile: defaultprofile
    bfdProfiles:
      - name: defaultprofile
Copy to Clipboard Toggle word wrap

4.8.2.5. nodeSelector 字段

默认情况下,FRR-K8s 将配置应用到守护进程运行的所有节点。您可以使用 nodeSelector 字段指定要应用配置的节点。例如:

FRRConfiguration CR 示例

apiVersion: frrk8s.metallb.io/v1beta1
kind: FRRConfiguration
metadata:
  name: test
  namespace: frr-k8s-system
spec:
  bgp:
    routers:
    - asn: 64512
  nodeSelector:
    labelSelector:
    foo: "bar"
Copy to Clipboard Toggle word wrap

4.8.2.6. interface 字段

您可以使用 interface 字段配置 unnumbered BGP peering,使用以下示例配置:

FRRConfiguration CR 示例

apiVersion: frrk8s.metallb.io/v1beta1
kind: FRRConfiguration
metadata:
  name: test
  namespace: frr-k8s-system
spec:
  bgp:
    bfdProfiles:
    - echoMode: false
      name: simple
      passiveMode: false
    routers:
    - asn: 64512
      neighbors:
      - asn: 64512
        bfdProfile: simple
        disableMP: false
        interface: net10 
1

        port: 179
        toAdvertise:
          allowed:
            mode: filtered
            prefixes:
            - 5.5.5.5/32
        toReceive:
          allowed:
            mode: filtered
      prefixes:
      - 5.5.5.5/32
Copy to Clipboard Toggle word wrap

1
激活未编号的 BGP 对等。
注意

要使用 interface 字段,您必须在两个 BGP 对等点之间建立点对点、第 2 层连接。您可以将未编号的 BGP 对等用于 IPv4、IPv6 或双栈,但您必须启用 IPv6 RAs (Router Advertisements)。每个接口都限制为一个 BGP 连接。

如果使用此字段,则无法在 spec.bgp.routers.neighbors.address 字段中指定一个值。

FRRConfiguration 自定义资源的字段在下表中描述:

Expand
表 4.9. MetalLB FRRConfiguration 自定义资源
字段类型描述

spec.bgp.routers

数组

指定 FRR 来配置的路由器(每个 VRF 一个)。

spec.bgp.routers.asn

整数

用于会话的本地后端的自主系统编号(ASN)。

spec.bgp.routers.id

string

指定 bgp 路由器的 ID。

spec.bgp.routers.vrf

string

指定用于建立来自此路由器会话的主机 vrf。

spec.bgp.routers.neighbors

数组

指定要建立 BGP 会话的邻居。

spec.bgp.routers.neighbors.asn

整数

指定用于会话远程结尾的 ASN。如果使用此字段,则无法在 spec.bgp.routers.neighbors.dynamicASN 字段中指定一个值。

spec.bgp.routers.neighbors.dynamicASN

string

检测用于会话远程端的 ASN,而不明确设置它。为具有相同 ASN 的邻居指定 internal,或为具有不同 ASN 的邻居指定 external。如果使用此字段,则无法在 spec.bgp.routers.neighbors.asn 字段中指定一个值。

spec.bgp.routers.neighbors.address

string

指定要建立会话的 IP 地址。如果使用此字段,则无法在 spec.bgp.routers.neighbors.interface 字段中指定一个值。

spec.bgp.routers.neighbors.interface

string

指定建立会话时使用的接口名称。使用此字段配置未编号的 BGP 对等。必须有两个 BGP 对等点之间的点对点、第 2 层连接。您可以将未编号的 BGP 对等用于 IPv4、IPv6 或双栈,但您必须启用 IPv6 RAs (Router Advertisements)。每个接口都限制为一个 BGP 连接。

spec.bgp.routers.neighbors.port

整数

指定建立会话时要结束的端口。默认值为 179。

spec.bgp.routers.neighbors.password

string

指定用来建立 BGP 会话的密码。passwordPasswordSecret 是互斥的。

spec.bgp.routers.neighbors.passwordSecret

string

指定邻居的身份验证 secret 的名称。secret 必须是 "kubernetes.io/basic-auth" 类型,并且与 FRR-K8s 守护进程位于同一个命名空间中。密钥 "password" 将密码存储在 secret 中。passwordPasswordSecret 是互斥的。

spec.bgp.routers.neighbors.holdTime

duration

根据 RFC4271 指定请求的 BGP 保留时间。默认为 180s。

spec.bgp.routers.neighbors.keepaliveTime

duration

根据 RFC4271 指定请求的 BGP keepalive 时间。默认值为 60s

spec.bgp.routers.neighbors.connectTime

duration

指定 BGP 在连接尝试到邻居之间等待的时间。

spec.bgp.routers.neighbors.ebgpMultiHop

布尔值

指明 BGPPeer 是否离开了多跃点。

spec.bgp.routers.neighbors.bfdProfile

string

指定用于与 BGP 会话关联的 BFD 会话的 BFD Profile 名称。如果没有设置,则不会设置 BFD 会话。

spec.bgp.routers.neighbors.toAdvertise.allowed

数组

表示要公告给邻居的前缀列表,以及相关的属性。

spec.bgp.routers.neighbors.toAdvertise.allowed.prefixes

字符串数组

指定要公告到邻居的前缀列表。此列表必须与您在路由器中定义的前缀匹配。

spec.bgp.routers.neighbors.toAdvertise.allowed.mode

string

指定处理前缀时要使用的模式。您可以将 filtered 设置为只允许前缀列表中的前缀。您可以设置为 all,以允许路由器上配置的所有前缀。

spec.bgp.routers.neighbors.toAdvertise.withLocalPref

数组

指定与公告的本地首选项关联的前缀。您必须在允许公告的前缀中指定与本地首选项关联的前缀。

spec.bgp.routers.neighbors.toAdvertise.withLocalPref.prefixes

字符串数组

指定与本地首选项关联的前缀。

spec.bgp.routers.neighbors.toAdvertise.withLocalPref.localPref

整数

指定与前缀关联的本地首选项。

spec.bgp.routers.neighbors.toAdvertise.withCommunity

数组

指定与公告的 BGP 社区关联的前缀。您必须在您要公告的前缀列表中包含与本地首选项关联的前缀。

spec.bgp.routers.neighbors.toAdvertise.withCommunity.prefixes

字符串数组

指定与社区关联的前缀。

spec.bgp.routers.neighbors.toAdvertise.withCommunity.community

string

指定与前缀关联的社区。

spec.bgp.routers.neighbors.toReceive

数组

指定要从邻居接收的前缀。

spec.bgp.routers.neighbors.toReceive.allowed

数组

指定要从邻居接收的信息。

spec.bgp.routers.neighbors.toReceive.allowed.prefixes

数组

指定来自邻居的前缀。

spec.bgp.routers.neighbors.toReceive.allowed.mode

string

指定处理前缀时要使用的模式。当设置为 filtered 时,只允许 prefixes 列表中的前缀。当设置为 all 时,允许路由器上配置的所有前缀。

spec.bgp.routers.neighbors.disableMP

布尔值

禁用 MP BGP 以防止它将 IPv4 和 IPv6 路由划分为不同的 BGP 会话。

spec.bgp.routers.prefixes

字符串数组

指定从此路由器实例公告的所有前缀。

spec.bgp.bfdProfiles

数组

指定配置邻居时要使用的 bfd 配置集列表。

spec.bgp.bfdProfiles.name

string

要在配置的其他部分中引用的 BFD 配置集的名称。

spec.bgp.bfdProfiles.receiveInterval

整数

指定此系统可以接收控制数据包的最小间隔(以毫秒为单位)。默认值为 300ms

spec.bgp.bfdProfiles.transmitInterval

整数

指定排除 jitter 的最小传输间隔,此系统希望用来发送 BFD 控制数据包(以毫秒为单位)。默认值为 300ms

spec.bgp.bfdProfiles.detectMultiplier

整数

配置检测倍数以确定数据包丢失。要确定连接丢失检测计时器,请将远程传输间隔乘以这个值。

spec.bgp.bfdProfiles.echoInterval

整数

配置此系统可以处理的最小 echo receive transfer-interval (以毫秒为单位)。默认值为 50ms

spec.bgp.bfdProfiles.echoMode

布尔值

启用或禁用回显传输模式。这个模式默认为禁用,在多跃点设置中不支持。

spec.bgp.bfdProfiles.passiveMode

布尔值

将会话标记为被动。被动会话不会尝试启动连接,并在开始回复前等待来自对等的控制数据包。

spec.bgp.bfdProfiles.MinimumTtl

整数

仅限多跃点会话。为传入的 BFD 控制数据包配置最低预期 TTL。

spec.nodeSelector

string

限制尝试应用此配置的节点。如果指定,则只有标签与指定选择器匹配的节点才会应用配置。如果没有指定,则所有节点都会尝试应用此配置。

status

string

定义 FRRConfiguration 的观察状态。

4.8.3. FRR-K8s 如何合并多个配置

如果多个用户添加选择同一节点的配置,FRR-K8s 会合并配置。每个配置都只能扩展其他配置。这意味着,可以添加新的邻居到路由器,或向邻居公告额外的前缀,但不能删除由其他配置添加的组件。

4.8.3.1. 配置冲突

某些配置可能会导致冲突,从而导致错误,例如:

  • 同一路由器的不同 ASN (在同一 VRF 中)
  • 同一邻居的不同 ASN (具有相同 IP / 端口)
  • 多个带有相同名称的 BFD 配置集,但不同的值

当守护进程为节点找到无效的配置时,它会将配置报告为无效,并恢复到之前有效的 FRR 配置。

4.8.3.2. 合并

在合并时,可以执行以下操作:

  • 将您要公告的 IP 集合扩展到邻居。
  • 使用 IP 集合添加额外的邻居。
  • 扩展您要关联社区的 IP 集合。
  • 允许邻居的传入路由。

每个配置都必须自包含。例如,通过利用来自其他配置的前缀,不允许在路由器部分中定义的前缀。

如果要应用的配置兼容,则合并可以正常工作,如下所示:

  • frr-K8s 结合了所有路由器。
  • frr-K8s 合并每个路由器的所有前缀和邻居。
  • frr-K8s 合并每个邻居的所有过滤器。
注意

不太严格的过滤会优先于更严格的过滤。例如,接受某些前缀的过滤会优先于不接受任何前缀的过滤,接受所有前缀的过滤优先于接受部分前缀的过滤。

4.9. MetalLB 日志记录、故障排除和支持

如果您需要对 MetalLB 配置进行故障排除,请查看以下部分来了解常用命令。

4.9.1. 设置 MetalLB 日志记录级别

MetalLB 在带有默认设置 info 的容器中使用 FRRouting(FRR)会生成大量日志。您可以通过设置 logLevel 来控制生成的日志的详细程度,如下例所示。

通过将 logLevel 设置为 debug 来深入了解 MetalLB,如下所示:

先决条件

  • 您可以使用具有 cluster-admin 角色的用户访问集群。
  • 已安装 OpenShift CLI(oc)。

流程

  1. 创建一个文件,如 setdebugloglevel.yaml,其内容类似以下示例:

    apiVersion: metallb.io/v1beta1
    kind: MetalLB
    metadata:
      name: metallb
      namespace: metallb-system
    spec:
      logLevel: debug
      nodeSelector:
        node-role.kubernetes.io/worker: ""
    Copy to Clipboard Toggle word wrap
  2. 应用配置:

    $ oc replace -f setdebugloglevel.yaml
    Copy to Clipboard Toggle word wrap
    注意

    使用 oc replace 可以被理解为,metallb CR 已被创建,您在此处更改了日志级别。

  3. 显示 speaker pod 的名称:

    $ oc get -n metallb-system pods -l component=speaker
    Copy to Clipboard Toggle word wrap

    输出示例

    NAME                    READY   STATUS    RESTARTS   AGE
    speaker-2m9pm           4/4     Running   0          9m19s
    speaker-7m4qw           3/4     Running   0          19s
    speaker-szlmx           4/4     Running   0          9m19s
    Copy to Clipboard Toggle word wrap

    注意

    重新创建发言人和控制器 Pod,以确保应用更新的日志记录级别。对于 MetalLB 的所有组件,会修改日志记录级别。

  4. 查看 speaker 日志:

    $ oc logs -n metallb-system speaker-7m4qw -c speaker
    Copy to Clipboard Toggle word wrap

    输出示例

    {"branch":"main","caller":"main.go:92","commit":"3d052535","goversion":"gc / go1.17.1 / amd64","level":"info","msg":"MetalLB speaker starting (commit 3d052535, branch main)","ts":"2022-05-17T09:55:05Z","version":""}
    {"caller":"announcer.go:110","event":"createARPResponder","interface":"ens4","level":"info","msg":"created ARP responder for interface","ts":"2022-05-17T09:55:05Z"}
    {"caller":"announcer.go:119","event":"createNDPResponder","interface":"ens4","level":"info","msg":"created NDP responder for interface","ts":"2022-05-17T09:55:05Z"}
    {"caller":"announcer.go:110","event":"createARPResponder","interface":"tun0","level":"info","msg":"created ARP responder for interface","ts":"2022-05-17T09:55:05Z"}
    {"caller":"announcer.go:119","event":"createNDPResponder","interface":"tun0","level":"info","msg":"created NDP responder for interface","ts":"2022-05-17T09:55:05Z"}
    I0517 09:55:06.515686      95 request.go:665] Waited for 1.026500832s due to client-side throttling, not priority and fairness, request: GET:https://172.30.0.1:443/apis/operators.coreos.com/v1alpha1?timeout=32s
    {"Starting Manager":"(MISSING)","caller":"k8s.go:389","level":"info","ts":"2022-05-17T09:55:08Z"}
    {"caller":"speakerlist.go:310","level":"info","msg":"node event - forcing sync","node addr":"10.0.128.4","node event":"NodeJoin","node name":"ci-ln-qb8t3mb-72292-7s7rh-worker-a-vvznj","ts":"2022-05-17T09:55:08Z"}
    {"caller":"service_controller.go:113","controller":"ServiceReconciler","enqueueing":"openshift-kube-controller-manager-operator/metrics","epslice":"{\"metadata\":{\"name\":\"metrics-xtsxr\",\"generateName\":\"metrics-\",\"namespace\":\"openshift-kube-controller-manager-operator\",\"uid\":\"ac6766d7-8504-492c-9d1e-4ae8897990ad\",\"resourceVersion\":\"9041\",\"generation\":4,\"creationTimestamp\":\"2022-05-17T07:16:53Z\",\"labels\":{\"app\":\"kube-controller-manager-operator\",\"endpointslice.kubernetes.io/managed-by\":\"endpointslice-controller.k8s.io\",\"kubernetes.io/service-name\":\"metrics\"},\"annotations\":{\"endpoints.kubernetes.io/last-change-trigger-time\":\"2022-05-17T07:21:34Z\"},\"ownerReferences\":[{\"apiVersion\":\"v1\",\"kind\":\"Service\",\"name\":\"metrics\",\"uid\":\"0518eed3-6152-42be-b566-0bd00a60faf8\",\"controller\":true,\"blockOwnerDeletion\":true}],\"managedFields\":[{\"manager\":\"kube-controller-manager\",\"operation\":\"Update\",\"apiVersion\":\"discovery.k8s.io/v1\",\"time\":\"2022-05-17T07:20:02Z\",\"fieldsType\":\"FieldsV1\",\"fieldsV1\":{\"f:addressType\":{},\"f:endpoints\":{},\"f:metadata\":{\"f:annotations\":{\".\":{},\"f:endpoints.kubernetes.io/last-change-trigger-time\":{}},\"f:generateName\":{},\"f:labels\":{\".\":{},\"f:app\":{},\"f:endpointslice.kubernetes.io/managed-by\":{},\"f:kubernetes.io/service-name\":{}},\"f:ownerReferences\":{\".\":{},\"k:{\\\"uid\\\":\\\"0518eed3-6152-42be-b566-0bd00a60faf8\\\"}\":{}}},\"f:ports\":{}}}]},\"addressType\":\"IPv4\",\"endpoints\":[{\"addresses\":[\"10.129.0.7\"],\"conditions\":{\"ready\":true,\"serving\":true,\"terminating\":false},\"targetRef\":{\"kind\":\"Pod\",\"namespace\":\"openshift-kube-controller-manager-operator\",\"name\":\"kube-controller-manager-operator-6b98b89ddd-8d4nf\",\"uid\":\"dd5139b8-e41c-4946-a31b-1a629314e844\",\"resourceVersion\":\"9038\"},\"nodeName\":\"ci-ln-qb8t3mb-72292-7s7rh-master-0\",\"zone\":\"us-central1-a\"}],\"ports\":[{\"name\":\"https\",\"protocol\":\"TCP\",\"port\":8443}]}","level":"debug","ts":"2022-05-17T09:55:08Z"}
    Copy to Clipboard Toggle word wrap

  5. 查看 FRR 日志:

    $ oc logs -n metallb-system speaker-7m4qw -c frr
    Copy to Clipboard Toggle word wrap

    输出示例

    Started watchfrr
    2022/05/17 09:55:05 ZEBRA: client 16 says hello and bids fair to announce only bgp routes vrf=0
    2022/05/17 09:55:05 ZEBRA: client 31 says hello and bids fair to announce only vnc routes vrf=0
    2022/05/17 09:55:05 ZEBRA: client 38 says hello and bids fair to announce only static routes vrf=0
    2022/05/17 09:55:05 ZEBRA: client 43 says hello and bids fair to announce only bfd routes vrf=0
    2022/05/17 09:57:25.089 BGP: Creating Default VRF, AS 64500
    2022/05/17 09:57:25.090 BGP: dup addr detect enable max_moves 5 time 180 freeze disable freeze_time 0
    2022/05/17 09:57:25.090 BGP: bgp_get: Registering BGP instance (null) to zebra
    2022/05/17 09:57:25.090 BGP: Registering VRF 0
    2022/05/17 09:57:25.091 BGP: Rx Router Id update VRF 0 Id 10.131.0.1/32
    2022/05/17 09:57:25.091 BGP: RID change : vrf VRF default(0), RTR ID 10.131.0.1
    2022/05/17 09:57:25.091 BGP: Rx Intf add VRF 0 IF br0
    2022/05/17 09:57:25.091 BGP: Rx Intf add VRF 0 IF ens4
    2022/05/17 09:57:25.091 BGP: Rx Intf address add VRF 0 IF ens4 addr 10.0.128.4/32
    2022/05/17 09:57:25.091 BGP: Rx Intf address add VRF 0 IF ens4 addr fe80::c9d:84da:4d86:5618/64
    2022/05/17 09:57:25.091 BGP: Rx Intf add VRF 0 IF lo
    2022/05/17 09:57:25.091 BGP: Rx Intf add VRF 0 IF ovs-system
    2022/05/17 09:57:25.091 BGP: Rx Intf add VRF 0 IF tun0
    2022/05/17 09:57:25.091 BGP: Rx Intf address add VRF 0 IF tun0 addr 10.131.0.1/23
    2022/05/17 09:57:25.091 BGP: Rx Intf address add VRF 0 IF tun0 addr fe80::40f1:d1ff:feb6:5322/64
    2022/05/17 09:57:25.091 BGP: Rx Intf add VRF 0 IF veth2da49fed
    2022/05/17 09:57:25.091 BGP: Rx Intf address add VRF 0 IF veth2da49fed addr fe80::24bd:d1ff:fec1:d88/64
    2022/05/17 09:57:25.091 BGP: Rx Intf add VRF 0 IF veth2fa08c8c
    2022/05/17 09:57:25.091 BGP: Rx Intf address add VRF 0 IF veth2fa08c8c addr fe80::6870:ff:fe96:efc8/64
    2022/05/17 09:57:25.091 BGP: Rx Intf add VRF 0 IF veth41e356b7
    2022/05/17 09:57:25.091 BGP: Rx Intf address add VRF 0 IF veth41e356b7 addr fe80::48ff:37ff:fede:eb4b/64
    2022/05/17 09:57:25.092 BGP: Rx Intf add VRF 0 IF veth1295c6e2
    2022/05/17 09:57:25.092 BGP: Rx Intf address add VRF 0 IF veth1295c6e2 addr fe80::b827:a2ff:feed:637/64
    2022/05/17 09:57:25.092 BGP: Rx Intf add VRF 0 IF veth9733c6dc
    2022/05/17 09:57:25.092 BGP: Rx Intf address add VRF 0 IF veth9733c6dc addr fe80::3cf4:15ff:fe11:e541/64
    2022/05/17 09:57:25.092 BGP: Rx Intf add VRF 0 IF veth336680ea
    2022/05/17 09:57:25.092 BGP: Rx Intf address add VRF 0 IF veth336680ea addr fe80::94b1:8bff:fe7e:488c/64
    2022/05/17 09:57:25.092 BGP: Rx Intf add VRF 0 IF vetha0a907b7
    2022/05/17 09:57:25.092 BGP: Rx Intf address add VRF 0 IF vetha0a907b7 addr fe80::3855:a6ff:fe73:46c3/64
    2022/05/17 09:57:25.092 BGP: Rx Intf add VRF 0 IF vethf35a4398
    2022/05/17 09:57:25.092 BGP: Rx Intf address add VRF 0 IF vethf35a4398 addr fe80::40ef:2fff:fe57:4c4d/64
    2022/05/17 09:57:25.092 BGP: Rx Intf add VRF 0 IF vethf831b7f4
    2022/05/17 09:57:25.092 BGP: Rx Intf address add VRF 0 IF vethf831b7f4 addr fe80::f0d9:89ff:fe7c:1d32/64
    2022/05/17 09:57:25.092 BGP: Rx Intf add VRF 0 IF vxlan_sys_4789
    2022/05/17 09:57:25.092 BGP: Rx Intf address add VRF 0 IF vxlan_sys_4789 addr fe80::80c1:82ff:fe4b:f078/64
    2022/05/17 09:57:26.094 BGP: 10.0.0.1 [FSM] Timer (start timer expire).
    2022/05/17 09:57:26.094 BGP: 10.0.0.1 [FSM] BGP_Start (Idle->Connect), fd -1
    2022/05/17 09:57:26.094 BGP: Allocated bnc 10.0.0.1/32(0)(VRF default) peer 0x7f807f7631a0
    2022/05/17 09:57:26.094 BGP: sendmsg_zebra_rnh: sending cmd ZEBRA_NEXTHOP_REGISTER for 10.0.0.1/32 (vrf VRF default)
    2022/05/17 09:57:26.094 BGP: 10.0.0.1 [FSM] Waiting for NHT
    2022/05/17 09:57:26.094 BGP: bgp_fsm_change_status : vrf default(0), Status: Connect established_peers 0
    2022/05/17 09:57:26.094 BGP: 10.0.0.1 went from Idle to Connect
    2022/05/17 09:57:26.094 BGP: 10.0.0.1 [FSM] TCP_connection_open_failed (Connect->Active), fd -1
    2022/05/17 09:57:26.094 BGP: bgp_fsm_change_status : vrf default(0), Status: Active established_peers 0
    2022/05/17 09:57:26.094 BGP: 10.0.0.1 went from Connect to Active
    2022/05/17 09:57:26.094 ZEBRA: rnh_register msg from client bgp: hdr->length=8, type=nexthop vrf=0
    2022/05/17 09:57:26.094 ZEBRA: 0: Add RNH 10.0.0.1/32 type Nexthop
    2022/05/17 09:57:26.094 ZEBRA: 0:10.0.0.1/32: Evaluate RNH, type Nexthop (force)
    2022/05/17 09:57:26.094 ZEBRA: 0:10.0.0.1/32: NH has become unresolved
    2022/05/17 09:57:26.094 ZEBRA: 0: Client bgp registers for RNH 10.0.0.1/32 type Nexthop
    2022/05/17 09:57:26.094 BGP: VRF default(0): Rcvd NH update 10.0.0.1/32(0) - metric 0/0 #nhops 0/0 flags 0x6
    2022/05/17 09:57:26.094 BGP: NH update for 10.0.0.1/32(0)(VRF default) - flags 0x6 chgflags 0x0 - evaluate paths
    2022/05/17 09:57:26.094 BGP: evaluate_paths: Updating peer (10.0.0.1(VRF default)) status with NHT
    2022/05/17 09:57:30.081 ZEBRA: Event driven route-map update triggered
    2022/05/17 09:57:30.081 ZEBRA: Event handler for route-map: 10.0.0.1-out
    2022/05/17 09:57:30.081 ZEBRA: Event handler for route-map: 10.0.0.1-in
    2022/05/17 09:57:31.104 ZEBRA: netlink_parse_info: netlink-listen (NS 0) type RTM_NEWNEIGH(28), len=76, seq=0, pid=0
    2022/05/17 09:57:31.104 ZEBRA: 	Neighbor Entry received is not on a VLAN or a BRIDGE, ignoring
    2022/05/17 09:57:31.105 ZEBRA: netlink_parse_info: netlink-listen (NS 0) type RTM_NEWNEIGH(28), len=76, seq=0, pid=0
    2022/05/17 09:57:31.105 ZEBRA: 	Neighbor Entry received is not on a VLAN or a BRIDGE, ignoring
    Copy to Clipboard Toggle word wrap

4.9.1.1. FRRouting(FRR)日志级别

下表描述了 FRR 日志记录级别。

Expand
表 4.10. 日志级别
日志级别描述

all

为所有日志记录级别提供所有日志信息。

debug

这些信息有助于相关人员进行问题诊断。设置为 debug,以提供详细的故障排除信息。

info

提供始终应记录的信息,但在正常情况下,不需要用户干预。这是默认的日志记录级别。

warn

任何可能导致 MetalLB 行为不一致的情况。通常 MicalLB 会自动从这类错误中恢复。

错误

MetalLB 功能有验证影响的重大错误。这些错误通常需要管理员干预才能修复。

none

关闭所有日志。

4.9.2. BGP 故障排除问题

作为集群管理员,如果您需要对 BGP 配置问题进行故障排除,您需要在 FRR 容器中运行命令。

先决条件

  • 您可以使用具有 cluster-admin 角色的用户访问集群。
  • 已安装 OpenShift CLI(oc)。

流程

  1. 运行以下命令,显示 frr-k8s pod 的名称:

    $ oc -n metallb-system get pods -l component=frr-k8s
    Copy to Clipboard Toggle word wrap

    输出示例

    NAME            READY   STATUS    RESTARTS   AGE
    frr-k8s-thsmw   6/6     Running   0          109m
    Copy to Clipboard Toggle word wrap

  2. 运行以下命令显示 FRR 的运行配置:

    $ oc exec -n metallb-system frr-k8s-thsmw -c frr -- vtysh -c "show running-config"
    Copy to Clipboard Toggle word wrap

    输出示例

    Building configuration...
    
    Current configuration:
    !
    frr version 8.5.3
    frr defaults traditional
    hostname some-hostname
    log file /etc/frr/frr.log informational
    log timestamp precision 3
    no ip forwarding
    no ipv6 forwarding
    service integrated-vtysh-config
    !
    router bgp 64500  
    1
    
     bgp router-id 10.0.1.2
     no bgp ebgp-requires-policy
     no bgp default ipv4-unicast
     no bgp network import-check
     neighbor 10.0.2.3 remote-as 64500  
    2
    
     neighbor 10.0.2.3 bfd profile doc-example-bfd-profile-full  
    3
    
     neighbor 10.0.2.3 timers 5 15
     neighbor 10.0.2.4 remote-as 64500
     neighbor 10.0.2.4 bfd profile doc-example-bfd-profile-full
     neighbor 10.0.2.4 timers 5 15
     !
     address-family ipv4 unicast
      network 203.0.113.200/30   
    4
    
      neighbor 10.0.2.3 activate
      neighbor 10.0.2.3 route-map 10.0.2.3-in in
      neighbor 10.0.2.4 activate
      neighbor 10.0.2.4 route-map 10.0.2.4-in in
     exit-address-family
     !
     address-family ipv6 unicast
      network fc00:f853:ccd:e799::/124
      neighbor 10.0.2.3 activate
      neighbor 10.0.2.3 route-map 10.0.2.3-in in
      neighbor 10.0.2.4 activate
      neighbor 10.0.2.4 route-map 10.0.2.4-in in
     exit-address-family
    !
    route-map 10.0.2.3-in deny 20
    !
    route-map 10.0.2.4-in deny 20
    !
    ip nht resolve-via-default
    !
    ipv6 nht resolve-via-default
    !
    line vty
    !
    bfd
     profile doc-example-bfd-profile-full
      transmit-interval 35
      receive-interval 35
      passive-mode
      echo-mode
      echo-interval 35
      minimum-ttl 10
     !
    !
    end
    Copy to Clipboard Toggle word wrap

    1
    router bgp 部分指示 MetalLB 的 ASN。
    2
    确认添加的每个 BGP peer 自定义资源都有一个 neighbor <ip-address> remote-as <peer-ASN> 行。
    3
    如果您配置了 BFD,请确认 BFD 配置集已与正确的 BGP peer 关联,并且 BFD 配置集出现在命令输出中。
    4
    确认 network <ip-address-range> 行与您在地址池自定义资源中指定的 IP 地址范围匹配。
  3. 运行以下命令显示 BGP 概述:

    $ oc exec -n metallb-system frr-k8s-thsmw -c frr -- vtysh -c "show bgp summary"
    Copy to Clipboard Toggle word wrap

    输出示例

    IPv4 Unicast Summary:
    BGP router identifier 10.0.1.2, local AS number 64500 vrf-id 0
    BGP table version 1
    RIB entries 1, using 192 bytes of memory
    Peers 2, using 29 KiB of memory
    
    Neighbor        V         AS   MsgRcvd   MsgSent   TblVer  InQ OutQ  Up/Down State/PfxRcd   PfxSnt
    10.0.2.3        4      64500       387       389        0    0    0 00:32:02            0        1  
    1
    
    10.0.2.4        4      64500         0         0        0    0    0    never       Active        0  
    2
    
    
    Total number of neighbors 2
    
    IPv6 Unicast Summary:
    BGP router identifier 10.0.1.2, local AS number 64500 vrf-id 0
    BGP table version 1
    RIB entries 1, using 192 bytes of memory
    Peers 2, using 29 KiB of memory
    
    Neighbor        V         AS   MsgRcvd   MsgSent   TblVer  InQ OutQ  Up/Down State/PfxRcd   PfxSnt
    10.0.2.3        4      64500       387       389        0    0    0 00:32:02 NoNeg
    10.0.2.4        4      64500         0         0        0    0    0    never       Active        0
    
    Total number of neighbors 2
    Copy to Clipboard Toggle word wrap

    1
    确认输出包含您添加的每个 BGP peer 自定义资源的行。
    2
    显示收到的 0 个消息,并且发送的消息指示没有 BGP 会话的 BGP 对等点。检查 BGP 对等点的网络连接和 BGP 配置。
  4. 运行以下命令,显示接收地址池的 BGP 对等点:

    $ oc exec -n metallb-system frr-k8s-thsmw -c frr -- vtysh -c "show bgp ipv4 unicast 203.0.113.200/30"
    Copy to Clipboard Toggle word wrap

    ipv4 替换为 ipv6,以显示接收 IPv6 地址池的 BGP 对等点。将 203.0.113.200/30 替换为地址池的 IPv4 或 IPv6 IP 地址范围。

    输出示例

    BGP routing table entry for 203.0.113.200/30
    Paths: (1 available, best #1, table default)
      Advertised to non peer-group peers:
      10.0.2.3  
    1
    
      Local
        0.0.0.0 from 0.0.0.0 (10.0.1.2)
          Origin IGP, metric 0, weight 32768, valid, sourced, local, best (First path received)
          Last update: Mon Jan 10 19:49:07 2022
    Copy to Clipboard Toggle word wrap

    1
    确认输出中包含 BGP peer 的 IP 地址。

4.9.3. BFD 问题故障排除

红帽支持双向转发检测(BFD)实施,在 speaker Pod 中使用 FRRouting(FRR)。BFD 实施依赖于 BFD 对等点,也被配置为带有已建立的 BGP 会话的 BGP 对等点。作为集群管理员,如果您需要排除 BFD 配置问题,则需要在 FRR 容器中运行命令。

先决条件

  • 您可以使用具有 cluster-admin 角色的用户访问集群。
  • 已安装 OpenShift CLI(oc)。

流程

  1. 显示 speaker pod 的名称:

    $ oc get -n metallb-system pods -l component=speaker
    Copy to Clipboard Toggle word wrap

    输出示例

    NAME            READY   STATUS    RESTARTS   AGE
    speaker-66bth   4/4     Running   0          26m
    speaker-gvfnf   4/4     Running   0          26m
    ...
    Copy to Clipboard Toggle word wrap

  2. 显示 BFD 对等点:

    $ oc exec -n metallb-system speaker-66bth -c frr -- vtysh -c "show bfd peers brief"
    Copy to Clipboard Toggle word wrap

    输出示例

    Session count: 2
    SessionId  LocalAddress              PeerAddress              Status
    =========  ============              ===========              ======
    3909139637 10.0.1.2                  10.0.2.3                 up  <.>
    Copy to Clipboard Toggle word wrap

    确认 PeerAddress 列包含每个 BFD 对等点。如果输出没有列出输出要包含的 BFD peer IP 地址,并与 peer 对 BGP 连接性进行故障排除。如果状态字段显示 down,请检查在节点和对等点间的链接和设备连接。您可以使用 oc get pods -n metallb-system speaker-66bth -o jsonpath='{.spec.nodeName}' 命令确定 speaker pod 的节点名称。

4.9.4. BGP 和 BFD 的 MetalLB 指标

OpenShift Container Platform 捕获与 BGP peer 和 BFD 配置集相关的 MetalLB 的以下 Prometheus 指标。

Expand
表 4.11. MetalLB BFD 指标
Name描述

frrk8s_bfd_control_packet_input

统计从每个 BFD peer 接收的 BFD 控制数据包的数量。

frrk8s_bfd_control_packet_output

统计发送到每个 BFD 对等点的 BFD 控制数据包的数量。

frrk8s_bfd_echo_packet_input

统计从每个 BFD 对等点接收的 BFD 回显数据包的数量。

frrk8s_bfd_echo_packet_output

计算发送到每个 BFD 的 BFD 回显数据包的数量。

frrk8s_bfd_session_down_events

统计 BFD 会话进入 down 状态的次数。

frrk8s_bfd_session_up

指示与 BFD 对等点的连接状态。1 表示会话状态为 up0 表示会话为 down

frrk8s_bfd_session_up_events

统计 BFD 会话进入 up 状态的次数。

frrk8s_bfd_zebra_notifications

统计每个 BFD Zebra 通知的数量。

Expand
表 4.12. MetalLB BGP 指标
Name描述

frrk8s_bgp_announced_prefixes_total

计算公告给 BGP 对等的负载均衡器 IP 地址前缀的数量。术语 前缀(prefix)聚合路由(aggregated route) 具有相同的含义。

frrk8s_bgp_session_up

指示与 BGP 对等点的连接状态。1 表示会话状态为 up0 表示会话为 down

frrk8s_bgp_updates_total

计算发送到每个 BGP 对等点的 BGP 更新消息数量。

frrk8s_bgp_opens_sent

计算发送到每个 BGP 对等点的 BGP 打开消息数量。

frrk8s_bgp_opens_received

计算从每个 BGP 对等点接收的 BGP 打开消息的数量。

frrk8s_bgp_notifications_sent

计算发送到每个 BGP 对等点的 BGP 通知消息数量。

frrk8s_bgp_updates_total_received

计算从每个 BGP 对等点接收的 BGP 更新消息数量。

frrk8s_bgp_keepalives_sent

计算发送到每个 BGP 对等点的 BGP keepalive 消息数量。

frrk8s_bgp_keepalives_received

计算从每个 BGP 对等点接收的 BGP keepalive 消息数量。

frrk8s_bgp_route_refresh_sent

计算发送到每个 BGP 对等点的 BGP 路由刷新消息的数量。

frrk8s_bgp_total_sent

计算发送到每个 BGP 对等点的 BGP 消息总数。

frrk8s_bgp_total_received

计算从每个 BGP 对等点接收的 BGP 消息总数。

其他资源

4.9.5. 关于收集 MetalLB 数据

您可以使用 oc adm must-gather CLI 命令来收集有关集群、MetalLB 配置和 MetalLB Operator 的信息。以下功能和对象与 MetalLB 和 MetalLB Operator 关联:

  • 在其中部署 MetalLB Operator 的命名空间和子对象
  • 所有 MetalLB Operator 自定义资源定义(CRD)

oc adm must-gather CLI 命令会收集红帽用来实施 BGP 和 BFD 的 FRRouting(FRR)的以下信息:

  • /etc/frr/frr.conf
  • /etc/frr/frr.log
  • /etc/frr/daemons 配置文件
  • /etc/frr/vtysh.conf

上述列表中的日志和配置文件从每个 speaker pod 中的 frr 容器收集。

除了日志和配置文件外,oc adm must-gather CLI 命令还会从以下 vtysh 命令收集输出:

  • show running-config
  • show bgp ipv4
  • show bgp ipv6
  • show bgp neighbor
  • show bfd peer

运行 oc adm must-gather CLI 命令时不需要额外的配置。

其他资源

Legal Notice

Copyright © 2025 Red Hat

OpenShift documentation is licensed under the Apache License 2.0 (https://www.apache.org/licenses/LICENSE-2.0).

Modified versions must remove all Red Hat trademarks.

Portions adapted from https://github.com/kubernetes-incubator/service-catalog/ with modifications by Red Hat.

Red Hat, Red Hat Enterprise Linux, the Red Hat logo, the Shadowman logo, JBoss, OpenShift, Fedora, the Infinity logo, and RHCE are trademarks of Red Hat, Inc., registered in the United States and other countries.

Linux® is the registered trademark of Linus Torvalds in the United States and other countries.

Java® is a registered trademark of Oracle and/or its affiliates.

XFS® is a trademark of Silicon Graphics International Corp. or its subsidiaries in the United States and/or other countries.

MySQL® is a registered trademark of MySQL AB in the United States, the European Union and other countries.

Node.js® is an official trademark of Joyent. Red Hat Software Collections is not formally related to or endorsed by the official Joyent Node.js open source or commercial project.

The OpenStack® Word Mark and OpenStack logo are either registered trademarks/service marks or trademarks/service marks of the OpenStack Foundation, in the United States and other countries and are used with the OpenStack Foundation’s permission. We are not affiliated with, endorsed or sponsored by the OpenStack Foundation, or the OpenStack community.

All other trademarks are the property of their respective owners.

返回顶部
Red Hat logoGithubredditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。 了解我们当前的更新.

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

Theme

© 2025 Red Hat