一、Knative网络流量分析

创建项目:

oc new-project knativetutorial

git clone https://github.com/redhat-developer-demos/knative-tutorial &&\ export TUTORIAL_HOME="$(pwd)/knative-tutorial"


我们分析应用配置文件:cd $TUTORIAL_HOME/basics。该文件使用quay.io/rhdevelopers/knative-tutorial-greeter:quarkus镜像创建应knative service:

Kvative实现蓝绿部署和弹性伸缩:Knative在OpenShift上的实践2_java

应用配置:

oc apply -n knativetutorial -f service.yaml


接下来,我们查看knativetutorial项目中被创建了什么资源:

产生了一个K8S层面的deployments:

Kvative实现蓝绿部署和弹性伸缩:Knative在OpenShift上的实践2_java_02

产生了三个K8S的service:

Kvative实现蓝绿部署和弹性伸缩:Knative在OpenShift上的实践2_java_03

产生了一个knative的service,greeter。

Kvative实现蓝绿部署和弹性伸缩:Knative在OpenShift上的实践2_java_04

利用oc get rt  -n knativetutorial查看knative route:

利用oc get route   -n knativetutorial查看OCP route,未发现:

查看pod,未发现:

接下来,我们查看knative路由指向:100%指向了knative service:greeter:

# oc get rt greeter -o yaml -n knativetutorial


我们查看knative service greeter 的内容:其中包含了指向revision的流量信息。

# kn   service list greeter  -o yaml


接下来,我们从OCP的角度,查看svc:greeter。

从下面图内容我们可以得知:greeter的svc的外部地址是:kourier-internal.knative-serving-ingress.svc.cluster.local,也就是说与knative-serving-ingress项目中的service:kourier-internal关联起来了。

# oc get svc greeter -o yaml -n knativetutorial

我们查看knative-serving-ingress项目中service:kourier-internal的内容,它指向了knative-serving-ingress项目中的ingress pod:

# oc get svc kourier-internal -o yaml -n knative-serving-ingress


接下来,我们查看knative-serving-ingress项目中的资源:

项目中没有knative route: 

有OCP route:route-db15f484-546d-46b9-8e31-2fad2527ed5c-356631366663



查看这条OCP route的指向,指向service:kourier

# oc get route route-db15f484-546d-46b9-8e31-2fad2527ed5c-356631366663 -o yaml -n knative-serving-ingress

Kvative实现蓝绿部署和弹性伸缩:Knative在OpenShift上的实践2_java_05

继续分析,发现这条OCP路由与haproxy的关系:

Kvative实现蓝绿部署和弹性伸缩:Knative在OpenShift上的实践2_java_06

查看service:kourier的内容,指向了ingress pod:

Kvative实现蓝绿部署和弹性伸缩:Knative在OpenShift上的实践2_java_07

kourier和kourier-internal的区别是:前者是

External Load Balancer,Ingress point(s) of load balancer后者是Accessible within the cluster only。这两个service其实指向相同的pod。类型不同。第一种通常和lb结合使用,比如云厂商的lb,可以对内也可以对外。第二种是对内,完全是k8s管理的。


从上面一系列图我们可以得出OCP上Kvative网络流量图(这是大魏理解的图,仅供参考):

Kvative实现蓝绿部署和弹性伸缩:Knative在OpenShift上的实践2_java_08

二、测试应用

使用http调用我们部署的greeter应用:

[root@lb.weixinyucluster ~]# export SVC_URL=`oc get rt greeter -o yaml | yq read - 'sta.url'` && \

> http $SVC_URL

调用反馈结果是:Hi  greeter => '9861675f8845' : 1

此时查看pod:

在没有新的请求时,pod会自动删除:

我们查看configuration:

 oc --namespace knativetutorial get configurations.serving.knative.dev greeter

oc --namespace knativetutorial get rev \ --selector=serving.knative.dev/service=greeter \ --sort-by="{.metadata.creationTimestamp}"

接下来,我们部署version2的应用,我们查看配置文件,版本2的应用被注入了MESSAGE_PREFIX:Namaste

应用配置:

我们查看revision信息:

oc --namespace knativetutorial get rev \ --selector=serving.knative.dev/service=greeter \ --sort-by="{.metadata.creationTimestamp}"

此时OCP也创新了新的K8S SVC:

我们再用http访问应用:

export SVC_URL=`oc get rt greeter -o yaml | yq read - 'sta.url'` && \

> http $SVC_URL

我们看到此次访问结果增加了MESSAGE_PREFIX:Namaste

我们可以动态调整到两个revision的流量百分比。使用OCP的UI较为方便:

进行修改:


命令行双重确认,调整成功:


三、scale-to-zero

假设已经部署了Greeter服务,一旦看到没有更多流量进入该服务,我们希望将该服务缩减为零个副本。这就是所谓的scale-to-zero.。


scale-to-zero.是使Knative成为无服务器平台的主要特性之一。在定义的空闲时间(所谓的稳定窗口)之后,revisions被视为无效。现在,所有指向当前无效revisions的路由都将指向所谓的activator。网络的重新编程本质上是异步的,因此从零到零的宽限期应该提供足够的松弛时间来实现。一旦scale-to-zero宽限期结束,revisions将最终缩放到零副本。


如果另一个请求试图到达revision,则activator将获取它,指示autoscaler尽快为该revision建新的容器,并缓冲该请求,直到创建了这些新容器。


默认情况下,scale-to-zero宽限期为30秒,稳定窗口为60秒。向greeter 服务发出请求将调出pod(如果已终止,如上所述)(如果已被终止)以处理该请求。保留它而没有任何其他请求将自动导致它在大约60-70秒内缩放为零。pod开始终止后到完全终止之前,至少需要20秒。


四、弹性伸缩


默认情况下,Knative Serving允许将100个并发请求放入pod中。这是由knative-serving名称空间中configmap config-autoscaler中的container-concurrency-target-default设置定义的。让我们使我们的服务仅处理10个并发请求。一旦我们针对revision并行运行10个以上的请求,这将导致Knative自动缩放器扩展到更多的Pod。


创建一个新的项目:

# oc new-project knativetutorial

[root@lb.weixinyucluster ~/knative-tutorial/basics]# cat service-10.yaml

apiVersion: serving.knative.dev/v1

kind: Service

metadata:

  name: prime-generator

spec:

  template:

    metadata:

      annotations:

        # Target 10 in-flight-requests per pod.

        autoscaling.knative.dev/target: "10"

    spec:

      containers:

      - image: quay.io/rhdevelopers/prime-generator:v27-quarkus

        livenessProbe:

          httpGet:

            path: /healthz

        readinessProbe:

          httpGet:

            path: /healthz



[root@lb.weixinyucluster ~/knative-tutorial/basics]# oc apply -f service-10.yaml

service.serving.knative.dev/prime-generator created



export SVC_URL=`oc get rt prime-generator -o yaml | yq read - 'status.url'`


hey -c 50 -z 10s \  "${SVC_URL}/?sleep=3&upto=10000&memload=100"


Kvative实现蓝绿部署和弹性伸缩:Knative在OpenShift上的实践2_java_09


Kvative实现蓝绿部署和弹性伸缩:Knative在OpenShift上的实践2_java_10


在现实世界中,您的服务可能需要处理突然的请求高峰。Knative使用默认的1个副本启动每个服务。如上所述,最终将如上所述将其缩放为零。如果您的应用在任何情况下都需要保持特别的响应速度和/或启动时间较长,那么始终保持最少数量的Pod可能是有益的。这可以通过注释autoscaling.knative.dev/minScale完成。


以下示例显示了如何使Knative创建以2的副本数开始并且永远不会扩展到其以下的服务。

[root@lb.weixinyucluster ~/knative-tutorial/basics]# cat service-min-max-scale.yaml

apiVersion: serving.knative.dev/v1

kind: Service

metadata:

  name: prime-generator

spec:

  template:

    metadata:

      annotations:

        # the minimum number of pods to scale down to

        autoscaling.knative.dev/minScale: "2"

        # Target 10 in-flight-requests per pod.

        autoscaling.knative.dev/target: "10"

    spec:

      containers:

      - image: quay.io/rhdevelopers/prime-generator:v27-quarkus

        livenessProbe:

          httpGet:

            path: /healthz

        readinessProbe:

          httpGet:

            path: /healthz


[root@lb.weixinyucluster ~/knative-tutorial/basics]# oc apply -f  service-min-max-scale.yaml

service.serving.knative.dev/prime-generator created


在没有外部请求时,pod的数量也是两个:

Kvative实现蓝绿部署和弹性伸缩:Knative在OpenShift上的实践2_java_11

发起峰值压力后,pod的数量会增加:

Kvative实现蓝绿部署和弹性伸缩:Knative在OpenShift上的实践2_java_12