【AICon】AI 基础设施、LLM运维、大模型训练与推理,一场会议,全方位涵盖! >>> 了解详情
写点什么

Knative 系列(三):Serving 篇

  • 2019-06-21
  • 本文字数:4816 字

    阅读完需:约 16 分钟

Knative 系列(三):Serving篇

前一篇文章已经介绍了 Build 的使用方式和原理,本文将紧接上文介绍 Serving。



简而言之,Serving 提供了Serverless应用或函数(Function)的部署能力,并通过 istio 实现服务管理,提供容器扩缩容能力。接管应用的部署和运维,节省开发者在应用部署和运维上消耗的精力。同时,在应用运维方面,Serving 提供了根据应用访问量自动扩缩容的能力,在没有访问的时候能把应用实例缩减到 0,本文通过将 Serving 部署到 K8s 平台之上试用,以讲解这一组件的原理。

Serving 部署

安装 istio

安装 Serving 之前,我们需要先安装 istio,这里使用Knative提供的简易方式安装。


kubectl apply --filename [](https://raw.githubusercontent.com/knative/serving/release-0.6/third_party/istio-1.1.3/istio-crds.yaml) \   --filename [](https://raw.githubusercontent.com/knative/serving/release-0.6/third_party/istio-1.1.3/istio.yaml)   
复制代码

安装 Serving

Serving 可以单独部署,但是也可以和 Build 一起部署,我们先来看 Serving 单独部署模式:


kubectl apply --selector   knative.dev/crd-install=true \   --filename [](https://github.com/knative/serving/releases/download/v0.6.0/serving.yaml)  --selector   networking.knative.dev/certificate-provider!=cert-manager  
复制代码


执行成功以后,可以通过以下命令查看:


[](null) 
复制代码


当 pod 全部正常执行后,我们就可以开始使用 Serving。

Serving 概念和试用

概念

Knative 把应用里的所有能力全都放到统一的 CRD 资源中管理—Service。这里的 Service 与 K8s 原生用户访问的 Service 不同,这是 Knative 的自定义资源,管理 Knative 应用的整个生命周期。


  • Service:service.serving.knative.dev 资源管理着工作负载的整个生命周期。它控制其他对象(Route、Configration、Revison)的创建,并确保每次对 Service 的更新都作用到其他对象。

  • Route: route.serving.knative.dev 资源将网络端点映射到一个或多个 Revision。可以通过配置 Route 实现多种流量管理方式,包括部分流量和命名路由。

  • Configuration:configuration.serving.knative.dev 资源保持部署所需的状态。它提供了代码和配置之间的清晰分离,并遵循十二要素应用程序方法。修改 Configuration 将创建新的 Revision。

  • Revision:revision.serving.knative.dev 资源是对工作负荷所做的每个修改的代码和配置的时间点快照。修订是不变的对象,只要有用就可以保留。Revision 可以根据进入的流量自动扩缩容。


样例

现在让我们来看一个最简单的 Knative Service 样例:


apiVersion:   serving.knative.dev/v1alpha1   kind: Service   metadata:     name: autoscale-go     namespace: default   spec:     template:       metadata:         annotations:           # Target 10 in-flight-requests per   pod.           autoscaling.knative.dev/target:   "10"       spec:         containers:         - image:   gcr.io/knative-samples/autoscale-go:0.1
复制代码


可以发现,一个 Service 相当简洁,在最简单的模式下只需要填写一个镜像即可,其他都会默认填充。现在把这个样例创建到集群中,并查看它自动创建的资源。


kubectl apply --filename [](https://raw.githubusercontent.com/knative/docs/release-0.6/docs/serving/samples/autoscale-go/service.yaml)   kubectl get serving.knative.dev 
复制代码


创建 Service 之后,自动创建 Configuration、Route、Revision、Deployment 等资源。


自动扩缩容


接下来测试 Service 的自动扩缩容功能,在上文例子中,annotations 里面设置了每个 Pod 的请求并发数为 10。


INGRESSGATEWAY=istio-ingressgateway   export IP_ADDRESS=`kubectl get svc   $INGRESSGATEWAY --namespace istio-system --output jsonpath="{.status.loadBalancer.ingress[*].ip}"`      hey -z 30s -c 50 \       -host "autoscale-go.default.example.com" \       "http://${IP_ADDRESS?}?sleep=100&prime=10000&bloat=5"   \       && kubectl get pods   Summary:       Total:        30.3379 secs       Slowest:      0.7433 secs       Fastest:      0.1672 secs       Average:      0.2778 secs       Requests/sec: 178.7861          Total data:   542038 bytes       Size/request: 99 bytes      Response time histogram:      0.167 [1]     \|       0.225 [1462]    \|■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■       0.282 [1303]  \|■■■■■■■■■■■■■■■■■■■■■■■■■■■■       0.340 [1894]    \|■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■       0.398 [471]   \|■■■■■■■■■■       0.455 [159]   \|■■■       0.513 [68]    \|■      0.570 [18]    \|       0.628 [14]    \|       0.686 [21]    \|       0.743 [13]    \|      Latency distribution:       10% in 0.1805 secs       25% in 0.2197 secs       50% in 0.2801 secs       75% in 0.3129 secs       90% in 0.3596 secs       95% in 0.4020 secs       99% in 0.5457 secs      Details (average, fastest, slowest):       DNS+dialup:   0.0007 secs,   0.1672 secs, 0.7433 secs       DNS-lookup:   0.0000 secs,   0.0000 secs, 0.0000 secs       req write:    0.0001 secs,   0.0000 secs, 0.0045 secs       resp wait:    0.2766 secs,   0.1669 secs, 0.6633 secs       resp read:    0.0002 secs,   0.0000 secs, 0.0065 secs      Status code distribution:       [200] 5424 responses   NAME                                             READY   STATUS      RESTARTS   AGE   autoscale-go-00001-deployment-78cdc67bf4-2w4sk   3/3       Running   0          26s   autoscale-go-00001-deployment-78cdc67bf4-dd2zb   3/3       Running   0          24s   autoscale-go-00001-deployment-78cdc67bf4-pg55p   3/3       Running   0          18s   autoscale-go-00001-deployment-78cdc67bf4-q8bf9   3/3       Running   0          1m   autoscale-go-00001-deployment-78cdc67bf4-thjbq   3/3       Running   0          26s 
复制代码


以 50qps 去访问 autoscale-go 时,autoscale-go 自动从 1 个实例扩展到 5 个实例, 刚好和我们设置的并发匹配。


当我们等待一段时间不访问 autoscale-go 后再去获取实例数量,可以看到实例数被缩减到 0。


kubectl get pods   NAME                                          READY   STATUS    RESTARTS     AGE 
复制代码


多版本管理


这次,换个应用,我们先创建一个 Service:


cat >   stock.yaml << EOF   apiVersion: serving.knative.dev/v1alpha1   kind: Service  metadata:     name: stock-service-example     namespace: default   spec:     template:       metadata:         name: stock-service-example-first       spec:         containers:         - image: ${REPO}/rest-api-go          env:             - name: RESOURCE               value: stock           readinessProbe:             httpGet:               path: /             initialDelaySeconds: 0             periodSeconds: 3     traffic:     - tag: current       revisionName: stock-service-example-first       percent: 100     - tag: latest       latestRevision: true     percent: 0   EOF   kubectl create -f   stock.yaml 
复制代码


这个 Service 配置了流量信息,但是第一次创建时,我们先把所有的流量都导到 Revision:stock-service-example-first 上。


之后修改 Service,另起创建新的 Revision,并将一半流量切换到新的 Revision。


cat >   stock.yaml << EOF   apiVersion:   serving.knative.dev/v1alpha1   kind: Service   metadata:     name: stock-service-example     namespace: default   spec:     template:       metadata:         name: stock-service-example-second       spec:         containers:         - image: ${REPO}/rest-api-go           env:             - name: RESOURCE               value: share           readinessProbe:             httpGet:               path: /             initialDelaySeconds: 0             periodSeconds: 3     traffic:     - tag: current       revisionName: stock-service-example-first       percent: 50     - tag: candidate       revisionName:   stock-service-example-second       percent: 50     - tag: latest       latestRevision: true       percent: 0   EOF   kubectl create -f   stock.yaml   
复制代码


接着,我们通过域名访问 Service,多次的结果分别为 Welcome to the share app! 或者 Welcome to the stock app!,比例大致为各一半。


 curl   --header "Host: stock-service-example.default.example.com"   [](http://$){INGRESS_IP}  
复制代码

Serving 原理

Serving 总共有 5 个组件,其中 4 个在 knative-serving 这个 namespace 下面,是 controller 、webhook 、autoscaler、activator 这四个组件;还有一个 queue, 运行在每个应用的 pod 里,作为 pod 的 sidecar 存在。


1.  Controller 负载 Service 整个生命周期的管理,涉及、Configuration、Route、Revision 等的 CURD。


2.  Webhook 主要负责创建和更新的参数校验。


3.  Autoscaler 根据应用的请求并发量对应用扩缩容。


4.  Activator 在应用缩容到 0 后,拦截用户的请求,通知 autoscaler 启动相应应用实例,等待启动后将请求转发。


5.  Queue 负载拦截转发给 Pod 的请求,用于统计 Pod 的请求并发量等,autoscaler 会访问 queue 获取相应数据对应用扩缩容。



自动扩缩容


1->n: 任何访问应用的请求在进入 Pod 后都会被 Queue 拦截,统计当前 Pod 的请求并发数,同时 Queue 会开放一个 metric 接口,autoscalor 通过访问该端口去获取 Pod 的请求并发量并计算是否需要扩缩容。当需要扩缩容时,autoscalor 会通过修改 Revision 下的 deployment 的实例个数达到扩缩容的效果。


0->1: 在应用长时间无请求访问时,实例会缩减到 0。这个时候,访问应用的请求会被转发到 activator,并在请求在转发到 activator 之前会被标记请求访问的 Revision 信息(由 controller 修改 VirtualService 实现)。activator 接收到请求后,会将改 Revision 的并发量加 1,并将 metric 推送给 autoscalor,启动 Pod。同时,activator 监控 Revision 的启动状态,Revision 正常启动后,将请求转发给相应的 Pod。


当然,在 Revision 正常启动后,应用的请求将不会再发送到 activator,而且直接发送至应用的 Pod(由 controller 修改 VirtualService 实现)。


Knative 网络模式


网络模式分两个部分,一个为 Service 之间的访问,一个为外部访问。


Service 之间的访问:


  • istio 会解析 Knative Service 的 VirtualService 下发给各个 Pod 的 Envoy,当应用通过域名相互访问时,Envoy 会拦截请求直接转发给相应的 Pod。


外部访问:


  • 如果是在集群外访问,素哟有的请求入口为 ingressgateway,ingressgateway 将请求根据访问域名转发到应用。

  • 如果是在集群节点上访问,每个 Knative Service 都对应一个 k8s Service, 这个 Service 的后端都为 ingressgateway,ingressgateway 会根据访问域名转发到应用。

总结

Knative 的 Serving 在 istio 基础上,实现应用的简易部署和多版本管理,把开发人员从应用的部署和运维中真正的解放出来;同时动态扩缩容能力避免了资源冗余造成的浪费,有效节省应用成本。


相关文章:


《Knative 系列(一):基本概念和原理解读》


《Knative 系列(二):兵马未动粮草先行之 Build 篇》


2019-06-21 08:406889

评论

发布
暂无评论
发现更多内容

Raft/Paxos类协议与分布式事务

TiDB 社区干货传送门

数据库架构设计

在CentOS7上进行TiDB/PD/TIKV编译分享

TiDB 社区干货传送门

实践案例 安装 & 部署

悲观锁模式下 TiDB 与其他数据库在 RC 及 RR 隔离级别的行为对比

TiDB 社区干货传送门

【白皮书】TiDelta,一款简单易用的 TiDB 性能对比 Web 工具。

TiDB 社区干货传送门

TiSpark 2.4.1(Spark 2.4.5)到TiSpark 2.5.0(Spark 3.0.X/3.1.X)迁移实践

TiDB 社区干货传送门

实践案例

【备考指南】新版 PingCAP PCTP 认证考试

TiDB 社区干货传送门

TiDB统计信息原理简介与实践

TiDB 社区干货传送门

管理与运维

混沌工程在建信金科的应用实践

TiDB 社区干货传送门

实践案例 故障排查/诊断 TUG 话题探讨

TiEM初体验

TiDB 社区干货传送门

集群管理 管理与运维 6.x 实践

dm-V1.0.5使用汇总

TiDB 社区干货传送门

管理与运维

DR Auto-Sync 搭建和计划内切换操作手册

TiDB 社区干货传送门

文盘Rust -- 生命周期问题引发的 static hashmap 锁

TiDB 社区干货传送门

开发语言

PointGet的一生

TiDB 社区干货传送门

开发语言 TiDB 底层架构 TiDB 源码解读 TiKV 源码解读 TiKV 底层架构

黄东旭: 关于基础软件产品价值的思考

TiDB 社区干货传送门

TiDB中快速恢复被Truncate 的表

TiDB 社区干货传送门

管理与运维

ticdc没报错,tso却不变的奇怪现象

TiDB 社区干货传送门

TiDB 5.4 发版丨新功能解读

TiDB 社区干货传送门

温故知新 | mydumper & dumpling 知识点汇总

TiDB 社区干货传送门

TiDB与众不同的优化器

TiDB 社区干货传送门

性能测评 应用适配

TiDB热点测试

TiDB 社区干货传送门

版本测评 性能测评

数据库调优之硬件

TiDB 社区干货传送门

性能调优

DM 同步 modify column 语句到 TiDB 5.3 踩坑一:数据乱码

TiDB 社区干货传送门

实践案例 故障排查/诊断

TiDB源码系列之沉浸式编译TiDB

TiDB 社区干货传送门

TiDB 源码解读

Tidb为什么能做到国产第一

TiDB 社区干货传送门

性能测评 数据库架构设计 应用适配

【专栏平台上线】来自社区的一份感谢信,致谢 137 位 TiDB 社区技术布道师

TiDB 社区干货传送门

用 Gravity 实现 MongoDB 到 TiDB 的数据复制

TiDB 社区干货传送门

DM 同步 modify column 语句到 TiDB 5.3 踩坑二:DDL 语句重放

TiDB 社区干货传送门

实践案例 故障排查/诊断

TiDB 5.4 单机快速安装初体验

TiDB 社区干货传送门

管理与运维 版本测评

从单点到分布式的哲学启蒙

TiDB 社区干货传送门

数据库前沿趋势

TPC-H 下 TiFlash 的扩展性测试报告 - v5.1.0

TiDB 社区干货传送门

版本测评 性能测评

TIKV、PD添加TLS总结

TiDB 社区干货传送门

实践案例

Knative 系列(三):Serving篇_语言 & 开发_华为云原生团队_InfoQ精选文章