Knative路由管理

Knative通过控制入口网关的流量分配来实现服务的路由管理。Knative为每个服务生成唯一的域名,入口网关会根据域名转发请求到对应的服务。

1 定制Knative服务的主域名

Knative默认为每个Service生成一个域名,Istio Gateway会根据域名判断请求应该转发给哪个服务。Knative默认使用的主域名是example.com,由于该域名不能用作线上服务,需要修改默认主域名,添加自定义域名或根据路径关联到不同的服务。

以下示例中,首先部署一个Knative服务,将配置保存到service.yaml文件中,然后执行kubectl apply-f service.yaml,这样就可以把helloworld服务部署到default命名空间。

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: helloworld
spec:
  template:
    metadata:
      labels:
        app: helloworld
      annotations:
        autoscaling.knative.dev/target: "10"
    spec:
      containers:
       - image: registry.cnlab.dangdang.com/knative-sample/helloworld-go
          env:
           - name: TARGET
              value: "World"

通过以下命令查看Knative服务自动生成的域名配置:

# kubectl-n default get ksvc
NAME        URL           LATESTCREATED   LATESTREADY   READY   REASON
helloworld  http://helloworld.default.example.com  helloworld-xsabn   
  helloworld-xsabn   True

使用curl命令指定Host来访问Knative服务时,首先需要获取可以访问到入口网关Istio Gateway的IP地址和端口号。

如果istio-ingressgateway的Kubernetes服务类型为LoadBalancer,我们可以通过如下方式获得入口网关的IP地址和端口号。(通常,各大公有云厂商都会提供Kubernetes的托管服务与LoadBalancer服务之间的集成。)

# export GATEWAY_IP='kubectl get svc istio-ingressgateway--namespace istio-
  system--output jsonpath="{.status.loadBalancer.ingress[*]['ip']}"
## 获取istio-ingressgateway k8s服务的NodePort端口号
# export GATEWAY_PORT='kubectl get svc istio-ingressgateway--namespace istio-
  system--output jsonpath="{.spec.ports[1].nodePort}"'

如果istio-ingressgateway的Kubernetes服务类型为NodePort(通常在本地部署环境中使用),NodePort端口在集群节点范围内有效,则Kubernetes集群任一节点IP都可以。

# export GATEWAY_IP='kubectl get nodes --output jsonpath="{.items[0].status.
  addresses[0].address}"
## 获取istio-ingressgateway Kubernetes服务的NodePort端口号
# export GATEWAY_PORT='kubectl get svc istio-ingressgateway--namespace istio-
  system--output jsonpath="{.spec.ports[1].nodePort}"'

访问knative helloworld服务。

# curl http://${GATEWAY_IP}:${GATEWAY_PORT}--header "Host:helloworld.default.
  example.com"
Hello World!

如果需要对外提供服务,需要使用自己的公网域名对外暴露服务。假设想要使用的主域名是knative.dangdang.cn,就需要修改knative-serving命名空间的config-domain ConfigMap配置来实现。下面在config-domain中添加knative.dangdang.cn域名进行说明。

apiVersion: v1
data:
  _example: |
    ################################
    #                              #
    #    EXAMPLE CONFIGURATION     #
    #                              #
    ################################

    # This block is not actually functional configuration,
    # but serves to illustrate the available configuration
    # options and document them in a way that is accessible
    # to users that 'kubectl edit' this config map.
    #
    # These sample configuration options may be copied out of
    # this example block and unindented to be in the data block
    # to actually change the configuration.
    # Default value for domain.
    # Although it will match all routes, it is the least-specific rule so it
    # will only be used if no other domain matches.
    example.com: |
    # These are example settings of domain.
    # example.org will be used for routes having app=nonprofit.
    example.org: |
      selector:
        app: nonprofit
    # Routes having domain suffix of 'svc.cluster.local' will not be exposed
    # through Ingress. You can define your own label selector to assign that
    # domain suffix to your Route here, or you can set the label
    #    "serving.knative.dev/visibility=cluster-local"
    # to achieve the same effect.  This shows how to make routes having
    # the label app=secret only exposed to the local cluster.
    svc.cluster.local: |
      selector:
        app: secret
  knative.dangdang.cn: ""
kind: ConfigMap
metadata:
  creationTimestamp: "2020-06-03T08:51:40Z"
  labels:
    serving.knative.dev/release: v0.15.0
  name: config-domain
  namespace: knative-serving
  resourceVersion: "65723826"
  selfLink: /api/v1/namespaces/knative-serving/configmaps/config-domain
  uid: 02ec18af-75fc-4cb2-ba67-5386157c5560

可以通过命令kubectl edit cm config-domain--namespace knative-serving修改配置,修改完成后保存退出。再看一下Knative服务的域名,显示修改的域名已生效。

# kubectl-n default get ksvc
NAME        URL           LATESTCREATED   LATESTREADY   READY   REASON
helloworld  http://helloworld.default.knative.dangdang.cn  helloworld-xsabn   
  helloworld-xsabn   True

2 DNS泛域名解析配置

如果定制了服务的主域名,希望在集群外部直接使用该域名访问Knative服务,还需要对集群外部使用的DNS进行配置。

Knative服务默认生成的域名规则是{servicename}.{namespace}.{default-domain}。不同的命名空间会生成不用的子域名,每个Knative服务会生成集群范围内唯一的子域名。为了让所有服务都能够在集群外部被访问到,需要做一个泛域名解析,把*.knative.dangdang.cn解析到Istio Gateway服务对应的外部IP地址上,一般是通过在DNS中添加一个A记录*.knative.dangdang.cn,并将其对应的IP地址设置为可以访问到Istio Gateway服务的IP地址。在公有云中,该地址通常是LoadBalancer的地址。本地部署的Kubernetes集群通常会采用NodePort对外暴露Istio Gateway服务。NodePort端口范围默认为30 000~32 767,这会导致服务监听的端口并不是默认的80和443端口。为了解决这个问题,还需要在集群外部搭建一个L4的反向代理来完成端口的转发。DNS中添加的A记录*.knative.dangdang.cn对应的IP地址就是该反向代理的IP地址。通常,使用Nginx或HAProxy来实现。

下面以Nginx为例展示反向代理的配置。

server {
       listen 80;
       proxy_connect_timeout 10s;
       proxy_timeout 10s;
       proxy_pass k8s_80;
}
server {
       listen 443;
       proxy_connect_timeout 10s;
       proxy_timeout 10m;
       proxy_pass k8s_443;
}
# upstream中的server ip:port 对应Kubernetes集群中各节点的IP地址和NodePort端口号
upstream k8s_80 {
        hash $remote_addr consistent;
        server 10.6.10.1:30080  weight=1 max_fails=3 fail_timeout=30s;
        server 10.6.10.2:30080  weight=1 max_fails=3 fail_timeout=30s;
    }
    upstream k8s_443 {
        hash $remote_addr consistent;
        server 10.6.10.1:30443  weight=1 max_fails=3 fail_timeout=30s;
        server 10.6.10.2:30443  weight=1 max_fails=3 fail_timeout=30s;
    }

3 服务的可见范围控制

默认情况下,通过Knative部署的服务会发布到外部IP地址,从而使它们成为具有公共URL的服务。这对于需要从集群外部访问的服务很有用,但往往只需要构建一个集群内部可用的后端服务,且该服务并不需要在集群外可见。

Knative提供了两种方式来开启仅集群内部可用的专有服务。

1)如果想要使所有服务仅在集群内部可用,可通过修改config-domain的ConfigMap,将默认域更改为svc.cluster.local。该配置将实现Knative部署的全部服务在仅集群内部可用,在集群外部无法使用。

2)如果只是想要修改个别服务的集群可见性,可以在相应服务或路由对象上打上相应的标签,以避免服务被发布到外部网关。

下面介绍将服务标记为cluster-local的方法。

为了配置一个KService的可用范围为集群内部网络(cluster-local),可以将标签serving.knative.dev/visibility=cluster-local应用到KService、Route或Kubernetes Service对象。

标记KService的方法:

kubectl label ksvc ${KSVC_NAME} serving.knative.dev/visibility=cluster-local

标记Route的方法:

kubectl label route ${ROUTE_NAME} serving.knative.dev/visibility=cluster-local

标记Kubernetes Service的方法:

kubectl label svc ${SERVICE_NAME} serving.knative.dev/visibility=cluster-local

通过标记Kubernetes Service,可以在更细粒度来限制服务的可见性。

下面通过标记已部署的Hello World例子来转换集群可见性。

kubectl label ksvc helloworld-go serving.knative.dev/visibility=cluster-local

验证helloword-go服务的URL的改变:

kubectl get ksvc helloworld-go

NAME           URL                            LATESTCREATED   LATESTREADY     READY   REASON
helloworld-go  http://helloworld-go.default.  helloworld-go-  helloworld-go-  True
               svc.cluster.local              2bz5l           2bz5l

服务返回的URL以svc.cluster.local为主域名,表示服务仅在集群本地网络范围内可用。

 

posted @ 2023-01-25 16:33  muzinan110  阅读(104)  评论(0编辑  收藏  举报