Knative Serving入门


多年来,人们已经创建了许多无服务器框架,这些框架都在Kubernetes之上运行,例如kubeless,OpenFaas和Fission,这些和Knative之间的区别在于,Knative由企业中的主要参与者支持,如RedHat,Pivotal,Google等。
Knative本身分为三个部分:

  • 构建:允许在Kubernetes中轻松构建容器镜像的源。它允许轻松定义源代码的CI管道,并且具有许多已定义的构建模板。
  • 服务:这是无服务器部分,用于执行,扩展和处理Docker容器的路由。它可以扩展到零,并具有自动缩放功能。
  • 事件:允许定义订阅和交付模型以管理,发送和接收事件。

Knative的所有组件都基于Istio,可以单独安装。因此,需要已经运行的Istio安装,您可以使用Knative提供的清单文件来部署Istio。
在本教程中,我们将介绍Serving入门的详细信息。

将Knative服务部署到Kubernetes集群
在我的环境中,使用了没有LoadBalancer支持服务的Kubernetes集群,也使用了更新版本的Istio,然后按照Knative Serving安装说明中进行了安装,产生了一个错误:即Knative发现安装的Istio prometheus桥接在Istio 1.0.3版中被移除了。以下命令将安装Knative Serving并删除prometheus网桥连接:

$ curl -L https://github.com/knative/serving/releases/download/v0.2.3/serving.yaml \
    | sed 's/LoadBalancer/ClusterIP/' \
    | sed '/nodePort:/d' \
    | sed '/--statsdUdpAddress/d' \
    | sed '/istio-statsd-prom-bridge/d' \
    | kubectl apply -f -

这将在Knative-serving命名空间中安装Knative Serving组件:

$ kubectl get pods -n knative-serving
NAME                          READY   STATUS    RESTARTS   AGE
activator-db5b7fd87-2vq7b     2/2     Running   0          24h
activator-db5b7fd87-9xcgc     2/2     Running   0          24h
activator-db5b7fd87-xlpxd     2/2     Running   0          24h
autoscaler-5547f9f84d-zr8m8   2/2     Running   0          2d21h
controller-59465dfb58-plzfg   1/1     Running   0          2d21h
webhook-7bf4f5dc4-vmr6m      1/1     Running   0          2d21h

正如您所看到的,它在knative-serving命名空间中安装了4个不同的部署,这些部署是knative-serving正确运行所必需的。它还在istio-system命名空间中安装入口网关。

示例应用
我开发了一个小示例应用程序,当一个新的jpg文件上传到一个名为images的存储桶时接收Minio Webhooks,然后它将生成一个具有可配置比例因子的较小版本,并将其再次存储到minio中名为thumbnail的另一个存储桶中。

部署示例应用程序
该应用程序是用Java编写的,它有一个名为/ webhook / image的端点,它接收带有由Minio生成的ImageEvents的POST消息。为了准备应用程序,我生成了一个Dockerfile,它有一个名为PORT的环境变量,默认值为8080.这个环境变量由Knative提供,它指定应用程序应该侦听流量的端口。
现在我们可以使用以下清单文件简单地部署应用程序:

apiVersion: v1
kind: Namespace
metadata:
  name: simple-serving
  labels:
    istio-injection: enabled
---
apiVersion: serving.knative.dev/v1alpha1
kind: Service
metadata:
  name: simple-serving-java
  namespace: simple-serving
spec:
  runLatest:
    configuration:
      revisionTemplate:
        metadata:
          annotations:
        spec:
          container:
            image: registry.gitlab.com/koudingspawn-public/knative/simple-serving-hello:latest
            env:
              - name: RESIZE_FACTOR
                value: "0.2"
            readinessProbe:
              exec:
                command:
                  - /bin/sh
                  - -c
                  - curl localhost:8081/actuator/health
              initialDelaySeconds: 10
              periodSeconds: 3


此清单文件生成名为simple-serving的命名空间,并为此命名空间启用Istio注入许可控制器。然后它应用Knative服务服务,指定Docker镜像和简单的Probe。为了使它更容易一点,我使用curl进行健康检查以绕过Istio mtls和策略的问题。
在此之后你应该看到,有一个新的Knative Service部署到集群:

$ kubectl get ksvc -n simple-serving
NAME                  DOMAIN                                           LATESTCREATED               LATESTREADY                 READY   REASON
simple-serving-java   simple-serving-java.simple-serving.example.com   simple-serving-java-00001   simple-serving-java-00001   True    

Knative Service就像部署高级资源一样,在后台Knative生成了一些额外的资源:

  • 配置:管理应用程序的所需状态。
  • 修订:对应用程序部署信息的每次更改(如环境变量或使用的映像)都将生成新的修订。在部署的情况下,它与ReplicaSet相当。
  • 路由:负责将网络流量路由到一个或多个修订版。
  • Knative Pod Autoscaler(kpa):负责根据容量进行缩放。

默认情况下,通过Istio中Ingress Gateway的传入流量的Knative域是example.com。该域由Knative Service名称和名称空间组成。通过对此域的简单curl 访问,可以将流量发送到我们的resizer-application。
因此,您必须配置一个dns条目,该条目指向istio-system命名空间中新生成的Knative Ingress Gateway。您可以通过以下命令找到服务的IP地址以指向dns条目:

$ kubectl describe service -n istio-system knative-ingressgateway

否则,您可以为Minio配置一个额外的/ etc / hosts条目,将dns条目指向knative-ingressgateway的ip。因此,您可以简单地使用Kubernetes文档中描述的hostAliases

部署Minio
Minio的部署非常简单且前进,只需要配置Webhook。因此,请参阅minio deployment.yaml文件的第12行。它指向新生成的Knative Service,以便将应用程序通知新文件及其元数据。为了允许我们使用Knative部署的应用程序与Minio通信,我们必须为此服务禁用Istio MTLS,因为我们在Istio之外部署了Minio。因此,请简单地应用以下DestionationRule:

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: "minio-ext"
  namespace: simple-serving
spec:
  host:
"minio-service.minio.svc.cluster.local"
  trafficPolicy:
    tls:
      mode: DISABLE

这允许我们的应用程序在不使用mTLS的情况下与minio通信。
作为最后一步,我们必须配置minio:

$ kubectl port-forward -n minio -l app=minio 9000:9000 &
$ mc config host add minio http://120.0.0.1:9000 minio minio123
$ mc mb minio/images
$ mc mb minio/thumbnail
$ mc event add minio/images arn:minio:sqs::1:webhook --event put --suffix .jpg

第三个和第四个命令生成两个称为images 和thumbnail的桶,最后一个命令为* .jpg文件创建webhook。
在此之后,您可以简单地将jpg文件复制到images 存储桶,并将消息发送到我们的应用程序以生成调整大小的版本:

$ mc cp demo.jpg minio/images/demo.jpg
$ mc ls minio/thumbnail/demo.jpg

路由到不同的版本
第一个可缩放版本生成缩略图,其大小为原始文件大小的20%。但是,如果我们计划仅调整大小的50%并希望慢慢迁移到新版本,该怎么办?

因此,我们可以简单地应用新的Knative Service版本,将50%的流量路由到新的,并将50%的minio事件路由到我们的旧版本:

apiVersion: serving.knative.dev/v1alpha1
kind: Service
metadata:
  name: simple-serving-java
  namespace: simple-serving
spec:
  release:
    revisions: ["simple-serving-java-00001", "simple-serving-java-00002"]
    rolloutPercent: 50
    configuration:
      revisionTemplate:
        metadata:
        spec:
          container:
            image: registry.gitlab.com/koudingspawn-public/knative/simple-serving-hello:latest
            env:
            - name: RESIZE_FACTOR
              value:
"0.5"
            readinessProbe:
              exec:
                command:
                - /bin/sh
                - -c
                - curl localhost:8081/actuator/health
              initialDelaySeconds: 10
              periodSeconds: 3


重要的部分是“修订版”和“rolloutPercent”参数。数组中的第一个版本是当前版本,第二个版本是接收50%minio事件的候选版本,仅将图像大小调整为50%。

$ kubectl get revision -n simple-serving
NAME                        SERVICE NAME                       READY   REASON
simple-serving-java-00001   simple-serving-java-00001-service   True
simple-serving-java-00002   simple-serving-java-00002-service   True

您只需运行以下命令即可看到此信息:

$ kubectl get route -n simple-serving

apiVersion: serving.knative.dev/v1alpha1
kind: Route
metadata:
  creationTimestamp: "2018-12-23T21:29:27Z"
  generation: 11
  labels:
    serving.knative.dev/service: simple-serving-java
  name: simple-serving-java
  namespace: simple-serving
  ownerReferences:
  - apiVersion: serving.knative.dev/v1alpha1
    blockOwnerDeletion: true
    controller: true
    kind: Service
    name: simple-serving-java
spec:
  generation: 2
  traffic:
  - name: current
    percent: 50
    revisionName: simple-serving-java-00001
  - name: candidate
    percent: 50
    revisionName: simple-serving-java-00002
  - configurationName: simple-serving-java
    name: latest
    percent: 0
status:
  address:
    hostname: simple-serving-java.simple-serving.svc.cluster.local
  conditions:
  - lastTransitionTime:
"2018-12-23T21:31:54Z"
    status:
"True"
    type: AllTrafficAssigned
  - lastTransitionTime:
"2018-12-23T21:29:57Z"
    status:
"True"
    type: IngressReady
  - lastTransitionTime:
"2018-12-23T21:31:54Z"
    status:
"True"
    type: Ready
  domain: simple-serving-java.simple-serving.example.com
  domainInternal: simple-serving-java.simple-serving.svc.cluster.local
  traffic:
  - name: current
    percent: 50
    revisionName: simple-serving-java-00001
  - name: candidate
    percent: 50
    revisionName: simple-serving-java-00002
  - name: latest
    percent: 0
    revisionName: simple-serving-java-00002

根据容量和比例范围进行缩放
默认情况下,Knative配置为在几分钟内没有流量时将应用程序缩放到零(此参数是可配置的)。这可能会产生冷启动问题,因为第一次调用服务需要很长时间,因为应用程序必须启动。要更改此项或允许的最大副本数,您只需添加以下两个注释即可:

apiVersion: serving.knative.dev/v1alpha1
kind: Service
metadata:
  name: simple-serving-java
  namespace: simple-serving
spec:
  runLatest:
    configuration:
      revisionTemplate:
        metadata:
          annotations:
            autoscaling.knative.dev/maxScale: "5"
            autoscaling.knative.dev/minScale:
"1"
        spec:
          containerConcurrency: 2
          container:
            image: registry.gitlab.com/koudingspawn-public/knative/simple-serving-hello:latest
            env:
            - name: RESIZE_FACTOR
              value:
"0.5"
            readinessProbe:
              exec:
                command:
                - /bin/sh
                - -c
                - curl localhost:8081/actuator/health
              initialDelaySeconds: 10
              periodSeconds: 3

现在,如果没有新流量,应用程序将不会关闭,并且将缩放到最大大小为5。

​​​​​​​此外,在此示例中,配置了容器Concurrency of two,这意味着此容器可以处理两个并行请求。如果有更多请求,autoscaler将调整应用程序的容量以并行处理请求。