27.3. 使用 Ingress Controller 配置集群入口流量
OpenShift Container Platform 提供了从集群外部与集群中运行的服务进行通信的方法。此方法使用了 Ingress Controller。
27.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 节点上运行。
- 可以纵向扩张,以在更多节点上具有更多副本。
这部分中的流程需要由集群管理员执行先决条件。
27.3.2. 先决条件
在开始以下流程前,管理员必须:
- 设置集群联网环境的外部端口,使请求能够到达集群。
确定至少有一个用户具有集群管理员角色。要将此角色添加到用户,请运行以下命令:
$ oc adm policy add-cluster-role-to-user cluster-admin username
- 有一个 OpenShift Container Platform 集群,其至少有一个 master 和至少一个节点,并且集群外有一个对集群具有网络访问权限的系统。此流程假设外部系统与集群位于同一个子网。不同子网上外部系统所需要的额外联网不在本主题的讨论范围内。
27.3.3. 创建项目和服务
如果要公开的项目和服务不存在,请创建项目,然后创建该服务。
如果项目和服务都已存在,跳到公开服务以创建路由这一步。
先决条件
-
安装 OpenShift CLI (
oc
),并以集群管理员身份登录。
流程
运行
oc new-project
命令为您的服务创建一个新项目:$ oc new-project <project_name>
使用
oc new-app
命令来创建服务:$ oc new-app nodejs:12~https://github.com/sclorg/nodejs-ex.git
要验证该服务是否已创建,请运行以下命令:
$ oc get svc -n <project_name>
输出示例
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nodejs-ex ClusterIP 172.30.197.157 <none> 8080/TCP 70s
注意默认情况下,新服务没有外部 IP 地址。
27.3.4. 通过创建路由公开服务
您可以使用 oc expose
命令,将服务公开为路由。
先决条件
- 已登陆到 OpenShift Container Platform。
流程
登录您想公开的服务所在的项目:
$ oc project <project_name>
运行
oc expose service
命令以公开路由:$ oc expose service nodejs-ex
输出示例
route.route.openshift.io/nodejs-ex exposed
要验证该服务是否已公开,您可以使用
curl
等工具来检查该服务是否可从集群外部访问。要查找路由的主机名,请输入以下命令:
$ oc get route
输出示例
NAME HOST/PORT PATH SERVICES PORT TERMINATION WILDCARD nodejs-ex nodejs-ex-myproject.example.com nodejs-ex 8080-tcp None
要检查主机是否响应 GET 请求,请输入以下命令:
curl
命令示例$ curl --head nodejs-ex-myproject.example.com
输出示例
HTTP/1.1 200 OK ...
27.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 分片很有用。
默认情况下,每个路由都使用集群的默认域。但是,可以将路由配置为使用路由器的域。
27.3.6. Ingress Controller 分片
您可以通过向路由、命名空间或两者添加标签,使用 Ingress 分片(也称为路由器分片)在多个路由器之间分发一组路由。Ingress Controller 使用一组对应的选择器来只接受具有指定标签的路由。每个 Ingress 分片都由使用给定选择表达式过滤的路由组成。
Ingress Controller 是网络流量进入集群的主要机制,因此对它们的需求可能非常大。作为集群管理员,您可以对路由进行分片,以达到以下目的:
- 在 Ingress Controller 或路由器与一些路由之间实现平衡,由此加快对变更的响应。
- 分配特定的路由,使其具有不同于其它路由的可靠性保证。
- 允许特定的 Ingress Controller 定义不同的策略。
- 只允许特定的路由使用其他功能。
- 在不同的地址上公开不同的路由,例如使内部和外部用户能够看到不同的路由。
- 在蓝绿部署期间,将流量从应用的一个版本转移到另一个版本。
当 Ingress Controller 被分片时,一个给定路由被接受到组中的零个或多个 Ingress Controller。路由的状态描述了 Ingress Controller 是否已接受它。只有 Ingress Controller 对其分片是唯一的时,才会接受路由。
Ingress Controller 可以使用三个分片方法:
- 仅将命名空间选择器添加到 Ingress Controller,以便命名空间中带有与命名空间选择器匹配的标签的所有路由都位于 Ingress shard 中。
- 只向 Ingress Controller 添加路由选择器,因此所有与路由选择器匹配的标签的路由都位于 Ingress 分片中。
- 将命名空间选择器和路由选择器添加到 Ingress Controller 中,以便使用与命名空间选择器匹配的路由选择器匹配的标签的路由位于 Ingress shard 中。
使用分片,您可以在多个 Ingress Controller 上分发路由子集。这些子集可以是非重叠的,也称为 传统 分片,或是重叠的,也称为 overlapped 分片。
27.3.6.1. 传统分片示例
配置了 Ingress Controller finops-router
的示例,其标签选择器 spec.namespaceSelector.matchExpressions
,其键值为 finance
和 ops
:
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
配置了 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
如果所有应用程序路由都位于单独的命名空间中,每个命名空间都分别使用 name:finance
、name:ops
和 name:dev
标记,此配置会在两个 Ingress Controller 之间有效分发您的路由。不应处理用于控制台、身份验证和其他目的的 OpenShift Container Platform 路由。
在前面的场景中,分片成为分区的一种特殊情况,没有重叠的子集。路由在路由器分片之间划分。
默认
Ingress Controller 继续提供所有路由,除非 namespaceSelector
或 routeSelector
字段包含用于排除的路由。有关如何从默认 Ingress Controller 中排除路由的更多信息,请参阅这个 红帽知识库解决方案 和"分片默认 Ingress Controller"。
27.3.6.2. 重叠的分片示例
配置了 Ingress Controller devops-router
的示例,其标签选择器 spec.namespaceSelector.matchExpressions
,其键值为 finance
和 ops
:
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
标签为 name:dev
和 name:ops
的命名空间中的路由现在由两个不同的 Ingress Controller 服务。使用这个配置,您有重叠的路由子集。
通过重叠的路由子集,您可以创建更复杂的路由规则。例如,您可以在向 devops-router
发送较低优先级的流量时,将优先级更高的流量放入专用的 finops-router
。
27.3.6.3. 分片默认 Ingress Controller
创建新的 Ingress shard 后,可能会接受到默认 Ingress Controller 接受的新 Ingress 分片的路由。这是因为默认 Ingress Controller 没有选择器,并默认接受所有路由。
您可以使用命名空间选择器或路由选择器来限制 Ingress Controller 使用特定标签提供路由。以下流程限制默认 Ingress Controller,使用命名空间选择器为新分片的 finance
、ops
和 dev
提供。这为 Ingress 分片增加了额外的隔离。
您必须在同一 Ingress Controller 上保留所有 OpenShift Container Platform 管理路由。因此,避免在排除这些基本路由的默认 Ingress Controller 中添加额外的选择器。
先决条件
-
已安装 OpenShift CLI(
oc
)。 - 您以项目管理员身份登录。
流程
运行以下命令来修改默认 Ingress Controller:
$ oc edit ingresscontroller -n openshift-ingress-operator default
编辑 Ingress Controller 以包含一个
namespaceSelector
,它排除了任何finance
、ops
和dev
标签的路由:apiVersion: operator.openshift.io/v1 kind: IngressController metadata: name: default namespace: openshift-ingress-operator spec: namespaceSelector: matchExpressions: - key: type operator: NotIn values: - finance - ops - dev
默认 Ingress Controller 不再提供标记为 name:finance
、name:ops
和 name:dev
的命名空间。
27.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
27.3.6.5. 通过路由标签(label)配置 Ingress Controller 分片
使用路由标签进行 Ingress Controller 分片,意味着 Ingress Controller 提供由路由选择器选择的任意命名空间中的所有路由。
图 27.1. 使用路由标签进行 Ingress 分片
在一组 Ingress Controller 之间平衡传入的流量负载时,以及在将流量隔离到特定 Ingress Controller 时,Ingress Controller 分片会很有用处。例如,A 公司的流量使用一个 Ingress Controller,B 公司的流量则使用另外一个 Ingress Controller。
流程
编辑
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
- 1
- 指定 Ingress Controller 使用的域。此域必须与默认 Ingress Controller 域不同。
应用 Ingress Controller
router-internal.yaml
文件:# oc apply -f router-internal.yaml
Ingress Controller 选择具有
type: sharded
标签的任意命名空间中的路由。使用
router-internal.yaml
中配置的域创建新路由:$ oc expose svc <service-name> --hostname <route-name>.apps-sharded.basedomain.example.net
27.3.6.6. 使用命名空间标签配置 Ingress Controller 分片
使用命名空间标签进行 Ingress Controller 分片,意味着 Ingress Controller 提供由命名空间选择器选择的任意命名空间中的所有路由。
图 27.2. 使用命名空间标签进行 Ingress 分片
在一组 Ingress Controller 之间平衡传入的流量负载时,以及在将流量隔离到特定 Ingress Controller 时,Ingress Controller 分片会很有用处。例如,A 公司的流量使用一个 Ingress Controller,B 公司的流量则使用另外一个 Ingress Controller。
流程
编辑
router-internal.yaml
文件:$ cat 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: "" namespaceSelector: matchLabels: type: sharded
- 1
- 指定 Ingress Controller 使用的域。此域必须与默认 Ingress Controller 域不同。
应用 Ingress Controller
router-internal.yaml
文件:$ oc apply -f router-internal.yaml
Ingress Controller 选择由命名空间选择器选择的具有
type: sharded
标签的任意命名空间中的路由。使用
router-internal.yaml
中配置的域创建新路由:$ oc expose svc <service-name> --hostname <route-name>.apps-sharded.basedomain.example.net
27.3.6.7. 为 Ingress Controller 分片创建路由
通过使用路由,您可以通过 URL 托管应用程序。在这种情况下,主机名没有被设置,路由会使用子域。当您指定子域时,会自动使用公开路由的 Ingress Controller 域。对于由多个 Ingress Controller 公开路由的情况,路由由多个 URL 托管。
以下流程描述了如何为 Ingress Controller 分片创建路由,使用 hello-openshift
应用程序作为示例。
在一组 Ingress Controller 之间平衡传入的流量负载时,以及在将流量隔离到特定 Ingress Controller 时,Ingress Controller 分片会很有用处。例如,A 公司的流量使用一个 Ingress Controller,B 公司的流量则使用另外一个 Ingress Controller。
先决条件
-
已安装 OpenShift CLI(
oc
)。 - 您以项目管理员身份登录。
- 您有一个 web 应用来公开端口,以及侦听端口流量的 HTTP 或 TLS 端点。
- 您已为分片配置了 Ingress Controller。
流程
运行以下命令,创建一个名为
hello-openshift
的项目:$ oc new-project hello-openshift
运行以下命令,在项目中创建 pod:
$ oc create -f https://raw.githubusercontent.com/openshift/origin/master/examples/hello-openshift/hello-pod.json
运行以下命令,创建名为
hello-openshift
的服务:$ oc expose pod/hello-openshift
创建名为
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
通过运行以下命令,使用
hello-openshift-route.yaml
创建到hello-openshift
应用程序的路由:$ oc -n hello-openshift create -f hello-openshift-route.yaml
验证
使用以下命令获取路由的状态:
$ oc -n hello-openshift get routes/hello-openshift-edge -o yaml
生成的
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