3.2.19. 使用通配符路由(用于子域)
HAProxy 路由器支持通配符路由,这通过将 ROUTER_ALLOW_WILDCARD_ROUTES
环境变量设置为 true
来启用。具有 Subdomain
通配符策略且通过路由器准入检查的任何路由都将由 HAProxy 路由器提供服务。然后,HAProxy 路由器根据路由的通配符策略公开相关的服务(用于路由)。
要更改路由的通配符策略,您必须删除路由并使用更新的通配符策略重新创建路由。仅编辑路由的 .yaml 文件中的路由通配符策略无法正常工作。
$ oc adm router --replicas=0 ... $ oc set env dc/router ROUTER_ALLOW_WILDCARD_ROUTES=true $ oc scale dc/router --replicas=1
使用安全通配符边缘终止路由
这个示例反映了在流量代理到目的地之前在路由器上发生的 TLS 终止。发送到子域 example.org(
)中的任何主机的流量将代理到公开的服务。
*.
example.org
安全边缘终止路由指定 TLS 证书和密钥信息。TLS 证书由与子域(*.example.org
)匹配的所有主机的路由器前端提供。
启动路由器实例:
$ oc adm router --replicas=0 --service-account=router $ oc set env dc/router ROUTER_ALLOW_WILDCARD_ROUTES=true $ oc scale dc/router --replicas=1
为边缘安全路由创建私钥、证书签名请求(CSR)和证书。
有关如何执行此操作的说明特定于您的证书颁发机构和供应商。有关名为
*.example.test
的域的简单自签名证书,请查看以下示例:# sudo openssl genrsa -out example-test.key 2048 # # sudo openssl req -new -key example-test.key -out example-test.csr \ -subj "/C=US/ST=CA/L=Mountain View/O=OS3/OU=Eng/CN=*.example.test" # # sudo openssl x509 -req -days 366 -in example-test.csr \ -signkey example-test.key -out example-test.crt
使用上述证书和密钥生成通配符路由:
$ cat > route.yaml <<REOF apiVersion: v1 kind: Route metadata: name: my-service spec: host: www.example.test wildcardPolicy: Subdomain to: kind: Service name: my-service tls: termination: edge key: "$(perl -pe 's/\n/\\n/' example-test.key)" certificate: "$(perl -pe 's/\n/\\n/' example-test.cert)" REOF $ oc create -f route.yaml
确保
*.example.test
的 DNS 条目指向您的路由器实例,并且到域的路由可用。这个示例使用带有本地解析器的
curl
来模拟 DNS 查找:# routerip="4.1.1.1" # replace with IP address of one of your router instances. # curl -k --resolve www.example.test:443:$routerip https://www.example.test/ # curl -k --resolve abc.example.test:443:$routerip https://abc.example.test/ # curl -k --resolve anyname.example.test:443:$routerip https://anyname.example.test/
对于允许通配符路由的路由器(ROUTER_ALLOW_WILDCARD_ROUTES
设置为 true
),存在一些注意事项,即与通配符路由关联的子域的所有权。
在通配符路由之前,所有权基于针对任何其他声明赢得路由最旧的命名空间的主机名提出的声明。例如,如果路由 r1
比路由 r2
老,对于 主机名 one.example.test
,命名空间 ns1
中的路由 r1
(有一个 one.example.test
的声明)会优于命令空间 ns2
中具有相同声明的路由 r2
。
另外,其他命名空间中的路由也被允许声明非覆盖的主机名。例如,命名空间 ns1
中的路由 rone
可以声明 www.example.test
,命名空间 d2
中的另一个路由 rtwo
可以声明 c3po.example.test
。
如果没有任何通配符路由声明同一子域(上例中的example.test
),则仍会出现这种情况。
但是,通配符路由需要声明子域中的所有主机名(以 \*.example.test
格式的主机名)。通配符路由的声明会根据该子域的最旧路由(example.test
)是否与通配符路由在同一命名空间中被允许或拒绝。最旧的路由可以是常规路由,也可以是通配符路由。
例如,如果已有一个路由 eldest
存在于 s1
命名空间中,声明一个名为 owner.example.test
的主机,如果稍后某个时间点上添加了一个新的通配符用来通配
子域 (example.test
) 中的路由,则通配路由的声明仅在与拥有的路由处于相同命名空间 (ns1
)时才被允许。
以下示例演示了通配符路由的声明将成功或失败的各种情景。
在以下示例中,只要通配符路由未声明子域,允许通配符路由的路由器将允许对子域 example.test
中的主机进行非覆盖声明。
$ oc adm router ... $ oc set env dc/router ROUTER_ALLOW_WILDCARD_ROUTES=true $ oc project ns1 $ oc expose service myservice --hostname=owner.example.test $ oc expose service myservice --hostname=aname.example.test $ oc expose service myservice --hostname=bname.example.test $ oc project ns2 $ oc expose service anotherservice --hostname=second.example.test $ oc expose service anotherservice --hostname=cname.example.test $ oc project otherns $ oc expose service thirdservice --hostname=emmy.example.test $ oc expose service thirdservice --hostname=webby.example.test
在以下示例中,允许通配符路由的路由器不允许 owner.example.test
或 aname.example.test
的声明成功,因为拥有的命名空间是 ns1
。
$ oc adm router ... $ oc set env dc/router ROUTER_ALLOW_WILDCARD_ROUTES=true $ oc project ns1 $ oc expose service myservice --hostname=owner.example.test $ oc expose service myservice --hostname=aname.example.test $ oc project ns2 $ oc expose service secondservice --hostname=bname.example.test $ oc expose service secondservice --hostname=cname.example.test $ # Router will not allow this claim with a different path name `/p1` as $ # namespace `ns1` has an older route claiming host `aname.example.test`. $ oc expose service secondservice --hostname=aname.example.test --path="/p1" $ # Router will not allow this claim as namespace `ns1` has an older route $ # claiming host name `owner.example.test`. $ oc expose service secondservice --hostname=owner.example.test $ oc project otherns $ # Router will not allow this claim as namespace `ns1` has an older route $ # claiming host name `aname.example.test`. $ oc expose service thirdservice --hostname=aname.example.test
在以下示例中,允许通配符路由的路由器将允许 '\*.example.test
声明成功,因为拥有的命名空间是 ns1
,通配符路由属于同一命名空间。
$ oc adm router ... $ oc set env dc/router ROUTER_ALLOW_WILDCARD_ROUTES=true $ oc project ns1 $ oc expose service myservice --hostname=owner.example.test $ # Reusing the route.yaml from the previous example. $ # spec: $ # host: www.example.test $ # wildcardPolicy: Subdomain $ oc create -f route.yaml # router will allow this claim.
在以下示例中,允许通配符路由的路由器不允许 '\*.example.test
声明成功,因为拥有的命名空间是 ns1
,并且通配符路由属于另一个命名空间 cyclone
。
$ oc adm router ... $ oc set env dc/router ROUTER_ALLOW_WILDCARD_ROUTES=true $ oc project ns1 $ oc expose service myservice --hostname=owner.example.test $ # Switch to a different namespace/project. $ oc project cyclone $ # Reusing the route.yaml from a prior example. $ # spec: $ # host: www.example.test $ # wildcardPolicy: Subdomain $ oc create -f route.yaml # router will deny (_NOT_ allow) this claim.
同样,当具有通配符路由的命名空间声明子域后,只有该命名空间中的路由才能声明同一子域中的任何主机。
在以下示例中,当命名空间 ns1
中带有通配符路由声明子域 example.test
的路由之后,只有命名空间 ns1
中的路由可以声明同一子域中的任何主机。
$ oc adm router ... $ oc set env dc/router ROUTER_ALLOW_WILDCARD_ROUTES=true $ oc project ns1 $ oc expose service myservice --hostname=owner.example.test $ oc project otherns $ # namespace `otherns` is allowed to claim for other.example.test $ oc expose service otherservice --hostname=other.example.test $ oc project ns1 $ # Reusing the route.yaml from the previous example. $ # spec: $ # host: www.example.test $ # wildcardPolicy: Subdomain $ oc create -f route.yaml # Router will allow this claim. $ # In addition, route in namespace otherns will lose its claim to host $ # `other.example.test` due to the wildcard route claiming the subdomain. $ # namespace `ns1` is allowed to claim for deux.example.test $ oc expose service mysecondservice --hostname=deux.example.test $ # namespace `ns1` is allowed to claim for deux.example.test with path /p1 $ oc expose service mythirdservice --hostname=deux.example.test --path="/p1" $ oc project otherns $ # namespace `otherns` is not allowed to claim for deux.example.test $ # with a different path '/otherpath' $ oc expose service otherservice --hostname=deux.example.test --path="/otherpath" $ # namespace `otherns` is not allowed to claim for owner.example.test $ oc expose service yetanotherservice --hostname=owner.example.test $ # namespace `otherns` is not allowed to claim for unclaimed.example.test $ oc expose service yetanotherservice --hostname=unclaimed.example.test
在以下示例中,显示了不同的场景,其中删除所有者路由并在命名空间内和跨命名空间传递所有权。虽然命名空间 ns1
中存在声明主机 eldest.example.test
的路由,但该命名空间中的通配符路由可以声明子域 example.test
。当删除主机 eldest.example.test
的路由时,下一个最旧的路由 senior.example.test
将成为最旧的路由,不会影响任何其他路由。删除主机 senior.example.test
的路由后,下一个最旧的路由 junior.example.test
将成为最旧路由并阻止通配符路由。
$ oc adm router ... $ oc set env dc/router ROUTER_ALLOW_WILDCARD_ROUTES=true $ oc project ns1 $ oc expose service myservice --hostname=eldest.example.test $ oc expose service seniorservice --hostname=senior.example.test $ oc project otherns $ # namespace `otherns` is allowed to claim for other.example.test $ oc expose service juniorservice --hostname=junior.example.test $ oc project ns1 $ # Reusing the route.yaml from the previous example. $ # spec: $ # host: www.example.test $ # wildcardPolicy: Subdomain $ oc create -f route.yaml # Router will allow this claim. $ # In addition, route in namespace otherns will lose its claim to host $ # `junior.example.test` due to the wildcard route claiming the subdomain. $ # namespace `ns1` is allowed to claim for dos.example.test $ oc expose service mysecondservice --hostname=dos.example.test $ # Delete route for host `eldest.example.test`, the next oldest route is $ # the one claiming `senior.example.test`, so route claims are unaffacted. $ oc delete route myservice $ # Delete route for host `senior.example.test`, the next oldest route is $ # the one claiming `junior.example.test` in another namespace, so claims $ # for a wildcard route would be affected. The route for the host $ # `dos.example.test` would be unaffected as there are no other wildcard $ # claimants blocking it. $ oc delete route seniorservice