第 6 章 配置路由

6.1. 路由配置

6.1.1. 创建基于 HTTP 的路由

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

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

先决条件

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

流程

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

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

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

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

    $ oc expose svc hello-openshift

验证

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

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

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

apiVersion: route.openshift.io/v1
kind: Route
metadata:
  name: hello-openshift
spec:
  host: hello-openshift-hello-openshift.<Ingress_Domain> 1
  port:
    targetPort: 8080 2
  to:
    kind: Service
    name: hello-openshift

1
<Ingress_Domain> 是默认的入口域名。ingresses.config/cluster 对象在安装过程中创建,且无法更改。如果要指定不同的域,您可以使用 appsDomain 选项指定备用集群域。
2
targetPort 是此路由所指向的服务选择的 pod 上的目标端口。
注意

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

$ oc get ingresses.config/cluster -o jsonpath={.spec.domain}

6.1.2. 配置路由超时

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

先决条件

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

流程

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

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

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

    $ oc annotate route myroute --overwrite haproxy.router.openshift.io/timeout=2s

6.1.3. 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 或传递路由上无效。

6.1.3.1. 根据每个路由启用 HTTP 严格传输安全性

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

先决条件

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

流程

  • 要在路由上启用 HSTS,请将 haproxy.router.openshift.io/hsts_header 值添加到 edge-terminated 或 re-encrypt 路由中。您可以运行以下命令来使用 oc annotate 工具来实现此目的:

    $ oc annotate route <route_name> -n <namespace> --overwrite=true "haproxy.router.openshift.io/hsts_header"="max-age=31536000;\ 1
    includeSubDomains;preload"
    1
    在本例中,最长期限设置为 31536000 ms,大约有 8 小时和半小时。
    注意

    在这个示例中,等号(=)是引号里。这是正确执行注解命令所必需的。

    配置了注解的路由示例

    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"

    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 与站点交互(至少一次)才能获取标头。

6.1.3.2. 根据每个路由禁用 HTTP 严格传输安全性

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

先决条件

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

流程

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

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

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

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

    metadata:
      annotations:
        haproxy.router.openshift.io/hsts_header: max-age=0

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

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

验证

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

    $ 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}}'

    输出示例

    Name: routename HSTS: max-age=0

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

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

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

注意

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

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

6.1.5. 基于路径的路由

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

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

表 6.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

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

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

6.1.6. 特定于路由的注解

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

重要

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

表 6.2. 路由注解

变量描述默认的环境变量

haproxy.router.openshift.io/balance

设置负载平衡算法。可用选项是 randomsourceroundrobinleastconn。默认值为 random

passthrough 路由 使用 ROUTER_TCP_BALANCE_SCHEME 。否则,使用 ROUTER_LOAD_BALANCE_algorithm

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' 可启用速率限制功能,该功能通过每个路由上的特定后端的贴子实施。
注:使用此注解可提供基本保护,防止分布式拒绝服务 (DDoS) 攻击。

 

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

限制通过同一源 IP 地址进行的并发 TCP 连接数。它接受一个数字值。
注:使用此注解可提供基本保护,防止分布式拒绝服务 (DDoS) 攻击。

 

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

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

 

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

限制具有相同源 IP 地址的客户端可以进行 TCP 连接的速率。它接受一个数字值。
注:使用此注解可提供基本保护,防止分布式拒绝服务 (DDoS) 攻击。

 

haproxy.router.openshift.io/timeout

为路由设定服务器端超时。(TimeUnits)

ROUTER_DEFAULT_SERVER_TIMEOUT

haproxy.router.openshift.io/timeout-tunnel

这个超时适用于隧道连接,如明文、边缘、重新加密或透传路由。使用明文、边缘或重新加密路由类型,此注解作为带有现有超时值的超时隧道应用。对于 passthrough 路由类型,注解优先于设置任何现有的超时值。

ROUTER_DEFAULT_TUNNEL_TIMEOUT

ingresses.config/cluster ingress.operator.openshift.io/hard-stop-after

您可以设置 IngressController 或 ingress 配置。此注解重新部署路由器,并将 HA 代理配置为在全局后发出 haproxy hard-stop- after 全局 选项,用于定义执行干净的软停止的最长时间。

ROUTER_HARD_STOP_AFTER

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

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

ROUTER_BACKEND_CHECK_INTERVAL

haproxy.router.openshift.io/ip_whitelist

为路由设置白名单。白名单是以空格分开的 IP 地址和 CIDR 范围列表,用来代表批准的源地址。来自白名单以外的 IP 地址的请求会被丢弃。

白名单中允许的最大 IP 地址和 CIDR 范围数为 61。

 

haproxy.router.openshift.io/hsts_header

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

 

haproxy.router.openshift.io/log-send-hostname

在 Syslog 标头中设置 hostname 字段。使用系统的主机名。如果路由器启用了任何 Ingress API 日志记录方法(如 sidecar 或 Syslog 工具),则默认启用 log-send-hostname

 

haproxy.router.openshift.io/rewrite-target

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

 

router.openshift.io/cookie-same-site

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

Lax:cookies 在访问的站点和第三方站点间进行传输。

Strict:cookies 仅限于访问的站点。

None:cookies 仅限于指定的站点。

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

 

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

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

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

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

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

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

ROUTER_SET_FORWARDED_HEADERS

注意

环境变量不能编辑。

路由器超时变量

TimeUnits 由一个数字及一个时间单位表示:us *(microseconds), ms(毫秒,默认)、s(秒)、m (分钟)、h *(小时) 、d (天)。

正则表达式是: [1-9][0-9]*(us\|ms\|s\|m\|h\|d)。

变量默认Description

ROUTER_BACKEND_CHECK_INTERVAL

5000ms

后端上后续存活度检查之间的时长。

ROUTER_CLIENT_FIN_TIMEOUT

1s

控制连接到路由的客户端的 TCP FIN 超时周期。如果发送到关闭连接的 FIN 在给定时间内没有回答,HAProxy 会关闭连接。如果设置为较低值,并且在路由器上使用较少的资源,则这不会产生任何损害。

ROUTER_DEFAULT_CLIENT_TIMEOUT

30s

客户端必须确认或发送数据的时长。

ROUTER_DEFAULT_CONNECT_TIMEOUT

5s

最长连接时间。

ROUTER_DEFAULT_SERVER_FIN_TIMEOUT

1s

控制路由器到支持路由的 pod 的 TCP FIN 超时。

ROUTER_DEFAULT_SERVER_TIMEOUT

30s

服务器必须确认或发送数据的时长。

ROUTER_DEFAULT_TUNNEL_TIMEOUT

1h

TCP 或 WebSocket 连接保持打开的时长。每当 HAProxy 重新加载时,这个超时期限都会重置。

ROUTER_SLOWLORIS_HTTP_KEEPALIVE

300s

设置等待出现新 HTTP 请求的最长时间。如果设置得太低,可能会导致浏览器和应用程序无法期望较小的 keepalive 值。

某些有效的超时值可以是某些变量的总和,而不是特定的预期超时。例如: ROUTER_SLOWLORIS_HTTP_KEEPALIVE 调整 timeout http-keep-alive。默认情况下,它设置为 300s,但 HAProxy 也会在 tcp-request inspect-delay 上等待,它被设置为 5s。在这种情况下,整个超时时间将是 300s5s

ROUTER_SLOWLORIS_TIMEOUT

10s

HTTP 请求传输可以花费的时间长度。

RELOAD_INTERVAL

5s

允许路由器至少执行重新加载和接受新更改的频率。

ROUTER_METRICS_HAPROXY_TIMEOUT

5s

收集 HAProxy 指标的超时时间。

设置自定义超时的路由

apiVersion: route.openshift.io/v1
kind: Route
metadata:
  annotations:
    haproxy.router.openshift.io/timeout: 5500ms 1
...

1
使用 HAProxy 支持的时间单位(us, ms, s, m, h, d)指定新的超时时间。如果没有提供时间单位,ms 会被默认使用。
注意

如果为 passthrough 路由设置的服务器端的超时值太低,则会导致 WebSocket 连接在那个路由上经常出现超时的情况。

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

metadata:
  annotations:
    haproxy.router.openshift.io/ip_whitelist: 192.168.1.10

允许多个 IP 地址的路由

metadata:
  annotations:
    haproxy.router.openshift.io/ip_whitelist: 192.168.1.10 192.168.1.11 192.168.1.12

允许 IP 地址 CIDR 网络的路由

metadata:
  annotations:
    haproxy.router.openshift.io/ip_whitelist: 192.168.1.0/24

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

metadata:
  annotations:
    haproxy.router.openshift.io/ip_whitelist: 180.5.61.153 192.168.1.0/24 10.0.0.0/8

指定重写对象的路由

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

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

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

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

表 6.3. 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

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

如果您在没有指定 TLS 配置的情况下创建 Ingress 对象,OpenShift Dedicated 会生成不安全的路由。要创建使用默认入口证书生成安全边缘终止路由的 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

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

    $ oc create -f example-ingress.yaml

验证

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

    $ oc get routes -o yaml

    输出示例

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

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

6.1.8. 在 Ingress 注解中使用目标 CA 证书创建路由

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

先决条件

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

流程

  1. 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
    ...
    1
    该注解引用 kubernetes secret。
  2. 此注解中引用的机密将插入到生成的路由中。

    输出示例

    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-----
    ...