1
2
3
4
5
作者:李晓辉

微信联系:lxh_chat

联系邮箱: 939958092@qq.com

OpenShift里有好几种服务资源类型,能搞定外部访问的事儿。

  • NodePort:这玩意儿会在集群里所有节点上暴露一个网络端口,然后把进来的流量转发到服务对应的容器或者虚拟机。不过,用NodePort得允许直接连到集群节点的网络,这可有点安全隐患。
  • LoadBalancer:这资源类型能指示OpenShift在云环境里搞个负载均衡器。负载均衡器会让OpenShift和集群运行的云提供商打交道,搞定一个负载均衡器,然后给应用提供一个能从外部访问的IP地址。
    • 对于不在云提供商上跑的集群,MetalLB操作符就能提供负载均衡服务。后面也会讲怎么配置MetalLB负载均衡器服务。
    • 非云环境里,还能通过LoadBalancer服务类型配置一个外部IP,把流量发到服务上。不过,外部IP功能默认是关着的,也存在安全风险,因为那些原本在集群里、要发给外部资源的敏感流量,可能会被截胡。
  • Ingress Controller:这可是让外部能访问集群资源的常用方法。Ingress操作符管着Ingress控制器,它主要处理HTTP、HTTPS和TLS(用SNI实现)的流量,配置好之后,就能接收外部请求,然后根据设置的路由把请求转发过去。

OpenShift提供的路由资源,能让你的应用被集群外的网络访问到。路由能让HTTP、HTTPS流量,TCP应用,还有非TCP流量进来。有了路由,你可以用一个公开可访问的独特域名来访问应用。

Kubernetes也有类似路由资源的入口资源,不过路由功能更多,比如:

  • TLS重新加密
  • TLS直通
  • 蓝绿部署的流量分割

要是你把虚拟机从别的虚拟化技术迁移到OpenShift虚拟化,你可以配置外部访问,让客户还能像以前一样访问应用。你也可以让数据库服务器被集群外运行的服务访问到。要是有些老应用你打算以后转成容器,也可以先暴露出来。等应用转成容器之后,你再重新配置外部访问,让客户能用原来的DNS名字继续访问应用。

配置OpenShift Routes

配置OpenShift路由也很简单。OpenShift路由能让HTTP、HTTPS和TLS流量进入集群里的服务。路由把一个面向公网的DNS主机名和一个面向内部的服务IP连接起来。

OpenShift是通过部署一个集群范围的路由器服务来实现路由的,这个路由器服务在OpenShift集群里以容器化应用的形式运行一个HAProxy负载均衡器。OpenShift像处理其他应用一样,对路由器Pod进行扩展和复制。

route

当你在OpenShift里创建一个路由的时候,它能自动给你的应用分配一个DNS条目。具体来说,OpenShift会给路由分配一个名字,格式是routename-namespace.default_domain。这里的default_domain是在集群安装的时候,由OpenShift管理员设置好的基础域名。举个例子,假设你的默认域名是apps.mycompany.com,然后你在prod项目里创建了一个叫intranet的路由,那分配到的DNS名字就是intranet-prod.apps.mycompany.com

不过,OpenShift管理员还得搞定一件事,就是得配置公司的DNS系统,让default_domain对应的通配符DNS记录指向运行路由器的节点的公网IP地址。

注意一下哦,托管通配符域名的DNS服务器其实并不知道路由主机名是个啥。它只是简单地把任何名字解析到配置好的IP地址上。真正了解路由主机名的只有OpenShift路由器,它把每个主机名当做一个HTTP虚拟主机来处理。要是有无效的通配符域名主机名,和任何路由都不匹配的话,OpenShift路由器就会拦截这些请求,并且返回一个HTTP错误。

另外,路由只支持特定类型的流量,就是HTTP、支持服务器名称指示(SNI)的HTTPS,还有支持SNI的TLS。有了SNI,客户端在握手过程中就能以明文形式发送它要访问的主机名。OpenShift就是利用这个特性,在收到加密流量的时候,确定要转发到哪个服务。

要是你有其他类型的流量,比如UDP流量或者非Web的TCP流量,Red Hat建议你用LoadBalancer或者NodePort类型的服务来处理。

创建路由

首先,当你创建了一个ClusterIP类型的服务,让它指向你的容器或者虚拟机之后,就可以为你的应用创建路由了。虽然你可以用YAML或者JSON格式的资源文件来声明路由,但OpenShift提供了一个很方便的命令“oc expose service”,能简化这个创建过程。

比如,你可以这样创建一个路由:

1
2
[lixiaohui@host ~]$ oc expose service/web
route.route.openshift.io/web exposed

这条命令会创建一个和你的服务同名的路由资源。如果你想要给路由起个不一样的名字,可以用“–name”选项来定义。

OpenShift会自动给路由分配一个DNS名字。如果你想手动定义DNS名字,可以用“–hostname”选项,后面跟着你想要的DNS名字。比如,下面这条命令会创建一个定义了web-production.apps.mycompany.com主机名的web路由:

1
2
3
[lixiaohui@host ~]$ oc expose service/web --name web \
--hostname web-production.apps.mycompany.com
route.route.openshift.io/web exposed

要是你想查看分配给路由的DNS名字,可以用“oc get route”命令:

1
2
3
[lixiaohui@host ~]$ oc get route web
NAME HOST/PORT PATH SERVICES PORT TERMINATION WILDCARD
web web-production.apps.mycompany.com web 8080 None

从Web控制台里也可以创建路由哦。你只需要进入“Networking → Routes”,选择一个命名空间,点击“Create Route”,然后把路由的详细信息填到表单里。你得给路由起个名字,还得选择关联的服务及其端口。

routeui

创建基于路径的路由

OpenShift的路由资源定义接受path变量,用来指定URL的路径部分。有了这个配置,你就可以用同一个DNS名字为多个服务提供服务,并且根据路径部分来转发流量。比如,你可以用http://intranet-prod.apps.mycompany.com/static这个URL,把流量转发到提供静态网页内容的容器或者虚拟机上。对于REST API请求,你可以用http://intranet-prod.apps.mycompany.com/api这个URL,把流量转发到应用的后端。

在使用oc expose service命令的时候,加上--path选项就可以配置基于路径的路由了。比如:

1
2
3
4
5
6
7
[lixiaohui@host ~]$ oc expose service/static --path=/static \
--hostname=intranet-prod.apps.mycompany.com
route.route.openshift.io/static exposed

[lixiaohui@host ~]$ oc expose service/restapi --path=/api \
--hostname=intranet-prod.apps.mycompany.com
route.route.openshift.io/restapi exposed

你可以用oc get routes命令来查看路由的信息:

1
2
3
4
[lixiaohui@host ~]$ oc get routes
NAME HOST/PORT PATH SERVICES PORT ...
static intranet-prod.apps.mycompany.com /static static 8080 ...
restapi intranet-prod.apps.mycompany.com /api restapi 80 ...

加密路由

路由可以是加密的(TLS或HTTPS),也可以是未加密的(HTTP)。加密路由使用几种类型的TLS终止来向客户端提供证书。

加密路由会指定路由的TLS终止类型。下面这个列表描述了可用的终止类型:

  • Edge:TLS终止发生在路由器处,然后OpenShift才把流量路由到容器或者虚拟机。路由器向客户端提供TLS证书。你在创建路由的时候可以提供自己的证书,或者让OpenShift使用它的证书。因为TLS是在路由器处终止的,所以路由器到端点之间的内部网络连接是没有加密的。
  • Pass through:路由器直接把流量发送到目标容器或者虚拟机。在这种模式下,应用本身负责为流量提供证书。
  • Re-encryption:这是Edge终止的一个变种。路由器用一个证书终止TLS,然后重新加密它和端点之间的连接,端点可能有不同的证书。因此,整个连接路径都是加密的,即使是在内部网络上也是如此。

创建加密路由

当你使用Web控制台创建路由的时候,创建路由的表单里会有一个安全部分,用来配置加密路由。表单上显示的字段会根据你选择的TLS终止类型而改变。当你选择Edge终止的时候,就会显示下面这个表单:

createRouteFormPart3

在Web控制台的创建路由表单里,有“Browse…”按钮,可以用它来选择证书和私钥。如果没提供证书和私钥,OpenShift就会用内部证书颁发机构(CA)的证书和私钥。表单里的“不安全流量”字段用来设置OpenShift管理不安全流量(比如HTTP)的策略。下面这个表格列出了这个字段可以选择的值:

含义
None禁用未加密流量
Allow通过不安全的协议(比如HTTP)发送未加密流量
Redirect将不安全的协议(HTTP)重定向到安全的协议(HTTPS)

表单在处理TLS直通和TLS重新加密时,这些字段会有一些细微的变化。

从命令行来说,oc expose命令只能创建未加密的路由。要是想创建加密路由,就得用oc create route命令。下面这个例子用web服务创建了一个使用Edge加密、名字相同的路由:

1
2
3
[lixiaohui@host ~]$ oc create route edge \
--service web \
--hostname api.apps.acme.com

在这个例子中,OpenShift入口控制器会提供内部CA的证书。如果你想提供自定义的私钥和签名证书,那么可以用--key--cert选项来提供这些内容。

为虚拟机配置路由

要为虚拟机配置路由,你得先为虚拟机的virt-launcher Pod创建一个服务:

  • .spec.template.metadata.labels路径处给虚拟机资源添加一个标签。
  • 从YAML格式的定义文件创建服务资源。用标签来选择virt-launcher Pod。下面这个例子假设virt-launcher Pod有一个tier: front标签。
1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: v1
kind: Service
metadata:
name: web
namespace: prod2
spec:
type: ClusterIP
selector:
tier: front
ports:
- protocol: TCP
port: 80
targetPort: 8080

创建好服务之后,你就可以创建路由了。

从命令行来说,用oc expose service命令来创建路由:

1
2
[lixiaohui@host ~]$ oc expose service/web
route.route.openshift.io/web exposed

启用来自路由器Pod的流量

当你在项目里使用网络策略的时候,你得添加一条规则来启用来自路由器Pod的流量。不然的话,路由资源就不管用了,因为路由器Pod没法到达目标Pod和虚拟机。

路由器Pod运行在openshift-ingress命名空间里。这个命名空间已经有一个标签,你可以用它来配合你的网络策略。下面这条命令显示了标签是network.openshift.io/policy-group: ingress

1
2
3
4
5
6
7
8
9
10
11
12
13
[lixiaohui@host ~]$ oc get namespace openshift-ingress -o yaml
kind: Namespace
apiVersion: v1
metadata:
...output omitted...
labels:
kubernetes.io/metadata.name: openshift-ingress
name: openshift-ingress
network.openshift.io/policy-group: ingress
olm.operatorgroup.uid/44814614-edc3-4e46-9491-5f0f97af9c84: ""
openshift.io/cluster-monitoring: "true"
policy-group.network.openshift.io/ingress: ""
...output omitted...

给你的项目添加下面这个网络策略资源,来启用来自路由器Pod的流量:

1
2
3
4
5
6
7
8
9
10
11
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: allow-from-openshift-ingress
spec:
ingress:
- from:
- namespaceSelector:
matchLabels:
network.openshift.io/policy-group: ingress
podSelector: {}
  1. 网络策略启用了来自openshift-ingress命名空间的流量,因为这个命名空间有network.openshift.io/policy-group: ingress标签。
  2. podSelector参数为空时,网络策略针对当前命名空间里的所有Pod。

配置Kubernetes入口资源

路由资源是OpenShift特有的。Kubernetes提供了入口资源,有一些和路由相似的功能。不过,有些路由功能,比如TLS重新加密,在入口资源里是不可用的。

下面这个例子定义了一个名为web的入口资源:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web
spec:
rules:
- host: web-production.apps.mycompany.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web
port:
number: 8080
  1. host参数提供了要分配给应用的URL。
  2. path参数提供了URL的路径部分。
  3. pathType参数指定了如何匹配URL的路径部分。如果设置为Exact,那么路径必须和path参数完全一致。如果设置为Prefix,那么任何以路径部分开头的路径都匹配。
  4. service部分提供了要和入口资源关联的服务。

OpenShift用路由资源来实现入口资源。下面这个例子显示了OpenShift创建的路由资源:

1
2
3
4
5
6
7
[lixiaohui@host ~]$ oc get ingress
NAMESPACE NAME CLASS HOSTS ADDRESS ...
production web <none> web-production...com router-default...com

[lixiaohui@host ~]$ oc get routes
NAME HOST/PORT PATH SERVICES PORT ...
web-djh2b web-production.apps.mycompany.com / web 8080-tcp ...

从Web控制台创建入口资源的话,进入“Networking → Ingresses”,点击“Create Ingress”,然后用入口参数完成YAML清单。

ingressui