4.5. External 和 Ingress 路由
4.5.1. 路由概述
Knative 利用 OpenShift Container Platform TLS 终止来为 Knative 服务提供路由。创建 Knative 服务时,会自动为该服务创建一个 OpenShift Container Platform 路由。此路由由 OpenShift Serverless Operator 管理。OpenShift Container Platform 路由通过与 OpenShift Container Platform 集群相同的域公开 Knative 服务。
您可以禁用 OpenShift Container Platform 路由的 Operator 控制,以便您可以配置 Knative 路由来直接使用 TLS 证书。
Knative 路由也可以与 OpenShift Container Platform 路由一起使用,以提供额外的精细路由功能,如流量分割。
4.5.1.1. 其他资源
4.5.2. 自定义标签和注解
OpenShift Container Platform 路由支持使用自定义标签和注解,您可以通过修改 Knative 服务的元数据规格来配置这些标签和注解
。自定义标签和注解从服务传播到 Knative 路由,然后传播到 Knative ingress,最后传播到 OpenShift Container Platform 路由。
4.5.2.1. 为 OpenShift Container Platform 路由自定义标签和注解
先决条件
- 您必须已在 OpenShift Container Platform 集群中安装了 OpenShift Serverless Operator 和 Knative Serving。
-
安装 OpenShift CLI (
oc
) 。
流程
创建包含您要传播到 OpenShift Container Platform 路由的标签或注解的 Knative 服务:
使用 YAML 创建服务:
使用 YAML 创建的服务示例
apiVersion: serving.knative.dev/v1 kind: Service metadata: name: <service_name> labels: <label_name>: <label_value> annotations: <annotation_name>: <annotation_value> ...
要使用 Knative (
kn
) CLI 创建服务,请输入:使用
kn
命令创建的服务示例$ kn service create <service_name> \ --image=<image> \ --annotation <annotation_name>=<annotation_value> \ --label <label_value>=<label_value>
通过检查以下命令的输出来验证 OpenShift Container Platform 路由是否已使用您添加的注解或标签创建:
验证命令示例
$ oc get routes.route.openshift.io \ -l serving.knative.openshift.io/ingressName=<service_name> \ 1 -l serving.knative.openshift.io/ingressNamespace=<service_namespace> \ 2 -n knative-serving-ingress -o yaml \ | grep -e "<label_name>: \"<label_value>\"" -e "<annotation_name>: <annotation_value>" 3
4.5.3. 为 Knative 服务配置路由
如果要将 Knative 服务配置为在 OpenShift Container Platform 上使用 TLS 证书,则必须禁用 OpenShift Serverless Operator 为服务自动创建路由,而是手动为服务创建路由。
完成以下步骤时,不会创建 knative-serving-ingress
命名空间中的默认 OpenShift Container Platform 路由。但是,应用程序的 Knative 路由仍然在此命名空间中创建。
4.5.3.1. 为 Knative 服务配置 OpenShift Container Platform 路由
先决条件
- OpenShift Serverless Operator 和 Knative Serving 组件必须安装在 OpenShift Container Platform 集群中。
-
安装 OpenShift CLI (
oc
) 。
流程
创建包含
service.knative.openshift.io/disableRoute=true
注解的 Knative 服务:重要service.knative.openshift.io/disableRoute=true
注解指示 OpenShift Serverless 不自动为您创建路由。但是,该服务仍然会显示 URL 并达到Ready
状态。除非使用与 URL 中主机名相同的主机名创建自己的路由,此 URL 才能在外部工作。创建 Knative
Service
资源:资源示例
apiVersion: serving.knative.dev/v1 kind: Service metadata: name: <service_name> annotations: serving.knative.openshift.io/disableRoute: "true" spec: template: spec: containers: - image: <image> ...
应用
Service
资源:$ oc apply -f <filename>
可选。使用
kn service create
命令创建 Knative 服务:kn
命令示例$ kn service create <service_name> \ --image=gcr.io/knative-samples/helloworld-go \ --annotation serving.knative.openshift.io/disableRoute=true
验证没有为服务创建 OpenShift Container Platform 路由:
示例命令
$ $ oc get routes.route.openshift.io \ -l serving.knative.openshift.io/ingressName=$KSERVICE_NAME \ -l serving.knative.openshift.io/ingressNamespace=$KSERVICE_NAMESPACE \ -n knative-serving-ingress
您将看到以下输出:
No resources found in knative-serving-ingress namespace.
在
knative-serving-ingress
命名空间中创建Route
资源:apiVersion: route.openshift.io/v1 kind: Route metadata: annotations: haproxy.router.openshift.io/timeout: 600s 1 name: <route_name> 2 namespace: knative-serving-ingress 3 spec: host: <service_host> 4 port: targetPort: http2 to: kind: Service name: kourier weight: 100 tls: insecureEdgeTerminationPolicy: Allow termination: edge 5 key: |- -----BEGIN PRIVATE KEY----- [...] -----END PRIVATE KEY----- certificate: |- -----BEGIN CERTIFICATE----- [...] -----END CERTIFICATE----- caCertificate: |- -----BEGIN CERTIFICATE----- [...] -----END CERTIFICATE---- wildcardPolicy: None
应用
Route
资源:$ oc apply -f <filename>
4.5.4. 全局 HTTPS 重定向
HTTPS 重定向为传入的 HTTP 请求提供重定向。这些重定向的 HTTP 请求会被加密。您可以通过为 KnativeServing
自定义资源 (CR) 配置 httpProtocol
spec,为集群中的所有服务启用 HTTPS 重定向。
4.5.4.1. HTTPS 重定向全局设置
启用 HTTPS 重定向的 KnativeServing
CR 示例
apiVersion: operator.knative.dev/v1beta1 kind: KnativeServing metadata: name: knative-serving spec: config: network: httpProtocol: "redirected" ...
4.5.5. 外部路由的 URL 方案
用于增强安全性,外部路由的 URL 方案默认为 HTTPS。这个方案由 KnativeServing
自定义资源 (CR) spec 中的 default-external-scheme
键决定。
4.5.5.1. 为外部路由设置 URL 方案
默认规格
... spec: config: network: default-external-scheme: "https" ...
您可以通过修改 default-external-scheme
键来覆盖默认的 spec 以使用 HTTP:
HTTP 覆盖规格
... spec: config: network: default-external-scheme: "http" ...
4.5.6. 每个服务的 HTTPS 重定向
您可以通过配置 networking.knative.dev/http-option
注解来为服务启用或禁用 HTTPS 重定向。
4.5.6.1. 为服务重定向 HTTPS
以下示例演示了如何在 Knative Service
YAML 对象中使用此注解:
apiVersion: serving.knative.dev/v1 kind: Service metadata: name: example namespace: default annotations: networking.knative.dev/http-option: "redirected" spec: ...
4.5.7. 集群本地可用性
默认情况下,Knative 服务会发布到一个公共 IP 地址。被发布到一个公共 IP 地址意味着 Knative 服务是公共应用程序,并有一个公开访问的 URL。
可以从集群以外访问公开的 URL。但是,开发人员可能需要构建后端服务,这些服务只能从集群内部访问(称为 私有服务 )。开发人员可以使用 networking.knative.dev/visibility=cluster-local
标签标记集群中的各个服务,使其私有。
对于 OpenShift Serverless 1.15.0 及更新的版本,service.knative.dev/visibility
标签不再可用。您必须更新现有服务来改用 networking.knative.dev/visibility
标签。
4.5.7.1. 将集群可用性设置为集群本地
先决条件
- 在集群中安装了 OpenShift Serverless Operator 和 Knative Serving。
- 您已创建了 Knative 服务。
流程
通过添加
networking.knative.dev/visibility=cluster-local
标签来设置服务的可见性:$ oc label ksvc <service_name> networking.knative.dev/visibility=cluster-local
验证
输入以下命令并查看输出结果,检查您的服务的 URL 是否现在格式为
http://<service_name>.<namespace>.svc.cluster.local
:$ oc get ksvc
输出示例
NAME URL LATESTCREATED LATESTREADY READY REASON hello http://hello.default.svc.cluster.local hello-tx2g7 hello-tx2g7 True
4.5.7.2. 为集群本地服务启用 TLS 身份验证
对于集群本地服务,使用 Kourier 本地网关 kourier-internal
。如果要针对 Kourier 本地网关使用 TLS 流量,则必须在本地网关中配置您自己的服务器证书。
先决条件
- 安装了 OpenShift Serverless Operator 和 Knative Serving。
- 有管理员权限。
-
已安装 OpenShift (
oc
) CLI。
流程
在
knative-serving-ingress
命名空间中部署服务器证书:$ export san="knative"
注意需要主题备用名称(SAN)验证,以便这些证书能够向
<app_name>.<namespace>.svc.cluster.local
提供请求。生成 root 密钥和证书:
$ openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 \ -subj '/O=Example/CN=Example' \ -keyout ca.key \ -out ca.crt
生成使用 SAN 验证的服务器密钥:
$ openssl req -out tls.csr -newkey rsa:2048 -nodes -keyout tls.key \ -subj "/CN=Example/O=Example" \ -addext "subjectAltName = DNS:$san"
创建服务器证书:
$ openssl x509 -req -extfile <(printf "subjectAltName=DNS:$san") \ -days 365 -in tls.csr \ -CA ca.crt -CAkey ca.key -CAcreateserial -out tls.crt
为 Kourier 本地网关配置 secret:
从前面的步骤创建的证书,在
knative-serving-ingress
命名空间中部署 secret:$ oc create -n knative-serving-ingress secret tls server-certs \ --key=tls.key \ --cert=tls.crt --dry-run=client -o yaml | oc apply -f -
更新
KnativeServing
自定义资源 (CR) spec,以使用 Kourier 网关创建的 secret:KnativeServing CR 示例
... spec: config: kourier: cluster-cert-secret: server-certs ...
Kourier 控制器在不重启该服务的情况下设置证书,因此您不需要重启 pod。
您可以通过端口 443
访问 Kourier 内部服务,方法是从客户端挂载并使用 ca.crt
。
4.5.8. Kourier 网关服务类型
Kourier 网关默认作为 ClusterIP
服务类型公开。此服务类型由 KnativeServing
自定义资源 (CR) 中的 service-type
ingress spec 决定。
默认规格
... spec: ingress: kourier: service-type: ClusterIP ...
4.5.8.1. 设置 Kourier 网关服务类型
您可以通过修改 service-type
spec 来覆盖默认服务类型来使用负载均衡器服务类型:
LoadBalancer 覆盖规格
... spec: ingress: kourier: service-type: LoadBalancer ...
4.5.9. 使用 HTTP2 和 gRPC
OpenShift Serverless 只支持不安全或边缘终端路由。不安全或边缘终端路由不支持 OpenShift Container Platform 中的 HTTP2。这些路由也不支持 gRPC,因为 gRPC 由 HTTP2 传输。如果您在应用程序中使用这些协议,则必须使用入口(ingress)网关直接调用应用程序。要做到这一点,您必须找到 ingress 网关的公共地址以及应用程序的特定主机。
4.5.9.1. 使用 HTTP2 和 gRPC 与无服务器应用程序交互
此方法需要使用 LoadBalancer
服务类型公开 Kourier 网关。您可以通过在 KnativeServing
自定义资源定义 (CRD) 中添加以下 YAML 来配置:
... spec: ingress: kourier: service-type: LoadBalancer ...
先决条件
- 在集群中安装了 OpenShift Serverless Operator 和 Knative Serving。
-
安装 OpenShift CLI (
oc
) 。 - 您已创建了 Knative 服务。
流程
- 找到应用程序主机。请参阅验证无服务器应用程序部署中的相关内容。
查找 ingress 网关的公共地址:
$ oc -n knative-serving-ingress get svc kourier
输出示例
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kourier LoadBalancer 172.30.51.103 a83e86291bcdd11e993af02b7a65e514-33544245.us-east-1.elb.amazonaws.com 80:31380/TCP,443:31390/TCP 67m
公共地址位于
EXTERNAL-IP
字段,在本例中是a83e86291bcdd11e993af02b7a65e514-33544245.us-east-1.elb.amazonaws.com
。手动在 HTTP 请求的主机标头中设置应用程序的主机,但将请求定向到 ingress 网关的公共地址。
$ curl -H "Host: hello-default.example.com" a83e86291bcdd11e993af02b7a65e514-33544245.us-east-1.elb.amazonaws.com
输出示例
Hello Serverless!
您还可以通过将授权设置为应用程序的主机来发出 gRPC 请求,同时将请求直接定向到 ingress 网关:
grpc.Dial( "a83e86291bcdd11e993af02b7a65e514-33544245.us-east-1.elb.amazonaws.com:80", grpc.WithAuthority("hello-default.example.com:80"), grpc.WithInsecure(), )
注意如上例所示,请确保将对应的端口(默认为 80)附加到两个主机中。