Serverless和Service Mesh是两种流行的云原生技术,客户正在探索如何从中创造价值。 随着我们与客户深入研究这些解决方案,问题经常出现在这两种流行技术之间的交集以及它们如何相互补充上。我们能否利用 Service Mesh 来保护、观察和公开我们的 Knative 无服务器应用程序?本文试图解释如何在一个托管的服务网格技术平台上支持基于Knative的Serverless容器, 以及基于流量模式的自动扩缩能力, 从中可以替换如何通过托管式服务网格来简化用户维护底层基础设施的复杂度, 让用户可以轻松地构建自己的Serverless平台。
前提条件
- 创建Istio版本为1.12.4.50或更高版本的阿里云服务网格 (ASM) 实例。
- 创建容器服务Kubernetes (ACK) 集群。
- 将ACK集群添加到ASM实例。
- ASM开启数据面KubeAPI访问能力。
Knative Serving 安装文件
下表描述了 Knative Serving 中包含的安装文件:
文件名 |
描述 |
依赖项 |
serving-crds.yaml |
必需:Knative Serving 核心 CRD。 |
none |
serving-core.yaml |
必需:Knative Serving 核心组件。 |
serving-crds.yaml |
此外, Knative CLI ( kn) 为创建 Knative 资源(例如 Knative 服务和事件源)提供了一个快速简单的界面,无需直接创建或修改 YAML 文件。可以参考
https://knative.dev/docs/install/client/install-kn/ 进行安装。
安装 Knative Serving 组件
- 通过运行以下命令安装所需的自定义资源:
kubectl apply -f https://alibabacloudservicemesh.oss-cn-beijing.aliyuncs.com/knative/v0.26/serving-crds.yaml
- 通过运行以下命令安装 Knative Serving 的核心组件:
kubectl apply -f https://alibabacloudservicemesh.oss-cn-beijing.aliyuncs.com/knative/v0.26/serving-core.yaml
启用服务网格及集成Knative
在托管模式下,服务网格ASM和ArgoCD所管理的容器服务ACK并不处于同一个集群环境,需要启用阿里云服务网格ASM特有的“数据面KubeAPI访问能力”后,使得能像访问ACK集群的资源一样,访问ASM集群中的Istio资源。在阿里云服务网格 ASM 控制台中,可以参考文档 https://help.aliyun.com/document_detail/431215.html 启用该能力。
通过运行以下命令安装 Knative Istio 控制器:
kubectl apply -f https://alibabacloudservicemesh.oss-cn-beijing.aliyuncs.com/knative/v0.26/net-istio.yaml
通过运行以下命令获取外部 IP 地址:
kubectl --namespace istio-system getservice istio-ingressgateway
保存它以在以下配置 DNS部分中使用。
验证安装
监控 Knative 组件,直到所有组件都显示 a STATUSofRunning或Completed。您可以通过运行以下命令并检查输出来执行此操作:
kubectl get pods -n knative-serving
示例输出:
NAME READY STATUS RESTARTS AGE activator-558bf66d75-svbgz 1/1 Running 0 94m autoscaler-6fcd9d475-5kgmw 1/1 Running 0 94m controller-5f98898db-d5zh4 1/1 Running 0 94m domain-mapping-67d655f47d-wrzz7 1/1 Running 0 94m domainmapping-webhook-9f59bb774-z792g 1/1 Running 0 94m net-istio-controller-846c69dbb-qnchg 1/1 Running 0 94m net-istio-webhook-86cf98b497-vmdqn 1/1 Running 0 94m webhook-777c5d4548-6tzj6 1/1 Running 0 94m
部署第一个 Knative 服务
- 部署 Knative 服务。此服务接受环境变量 TARGET,并打印Hello ${TARGET}!。 将以下 YAML 复制到名为hello.yaml 的文件中:
apiVersion serving.knative.dev/v1 kind Service metadata name helloworld-go spec template spec containersimage registry.cn-hangzhou.aliyuncs.com/acs/helloworld-go 160e4dc8 portscontainerPort8080 envname TARGET value"World"
2. 通过运行以下命令部署 Knative 服务:
kubectl apply -f hello.yaml
- 通过运行以下命令查看 Knative 服务列表:
如果您curl用于访问示例应用程序或您自己的 Knative 应用程序,并且无法使用“Magic DNS (sslip.io)”或“Real DNS”方法,则有一个临时方法。
启动应用程序后,获取应用程序的 URL:
kubectl get ksvc
输出应类似于:
NAME URL LATESTCREATED LATESTREADY READY REASON helloworld-go http://helloworld-go.default.example.com helloworld-go-00001 helloworld-go-00001 True
指定curl连接到前面提到的入口网关的外部 IP地址,并使用-H "Host:"命令行选项指定 Knative 应用程序的主机名。例如,如果网络层定义了您的外部 IP 和端口为http://39.97.65.87:80, 并且您希望访问helloworld-go前面提到的应用程序,请使用:
curl-H"Host: helloworld-go.default.example.com" http://39.97.65.87:80
对于提供的helloworld-go示例应用程序,使用默认配置,输出为:
Hello World!
缩放到零
Knative Serving 的强大功能之一是内置自动缩放,也称为自动缩放。这意味着您的 Knative 服务仅在需要时启动您的应用程序以执行其工作(在这种情况下,说“Hello world!”)。否则,它将通过向下旋转并等待新请求进入来缩放为零。
重新运行上述curl命令访问示例应用, 现在观察 pod,看看它们在流量停止流向 URL 后如何缩放到零。输出应类似于:
kubectl get pod -l serving.knative.dev/service=helloworld-go -wNAME READY STATUS RESTARTS AGE helloworld-go-00001-deployment-6f8dfb548-nwfqc 3/3 Running 0 39s helloworld-go-00001-deployment-6f8dfb548-nwfqc 3/3 Terminating 0 65s helloworld-go-00001-deployment-6f8dfb548-nwfqc 0/3 Terminating 0 102s helloworld-go-00001-deployment-6f8dfb548-nwfqc 0/3 Terminating 0 102s helloworld-go-00001-deployment-6f8dfb548-nwfqc 0/3 Terminating 0 102s
流量拆分
每次更改 Knative 服务的配置时,都会创建一个新的修订版本。在拆分流量时,Knative 会在您的 Knative 服务的不同版本之间拆分流量。
创建新修订
编辑现有hello.yaml文件以包含以下内容:
apiVersion serving.knative.dev/v1 kind Service metadata name helloworld-go spec template spec containersimage registry.cn-hangzhou.aliyuncs.com/acs/helloworld-go 160e4dc8 portscontainerPort8080 envname TARGET value"Knative"
通过运行以下命令部署更新版本的 Knative 服务:
kubectl apply -f hello.yaml
请注意,由于我们正在更新现有的 Knative Service hello,因此 URL 不会更改,但我们的新 Revision 应该具有新名称hello-00002。
访问新版本
指定curl连接到前面提到的入口网关的外部 IP地址,并使用-H "Host:"命令行选项指定 Knative 应用程序的主机名。例如,如果网络层定义了您的外部 IP 和端口为http://39.97.65.87:80, 并且您希望访问helloworld-go前面提到的应用程序,请使用:
curl -H "Host helloworld-go.default.example.com" http://39.97.65.87:80
对于提供的helloworld-go示例应用程序,使用默认配置,输出为:
Hello World!
列出所有修订
通过运行以下命令查看修订列表:
kubectl get revisions
输出应类似于:
NAME CONFIG NAME K8S SERVICE NAME GENERATION READY REASON ACTUAL REPLICAS DESIRED REPLICAS helloworld-go-00001 helloworld-go 1 True 00helloworld-go-00002 helloworld-go 2 True 00
在修订之间拆分流量
让我们在两个修订版之间拆分流量, 将该部分添加到现有文件 traffic的底部:
apiVersion serving.knative.dev/v1 kind Service metadata name helloworld-go spec template spec containersimage registry.cn-hangzhou.aliyuncs.com/acs/helloworld-go 160e4dc8 portscontainerPort8080 envname TARGET value"Knative" trafficlatestRevisiontrue percent50latestRevisionfalse percent50 revisionName hello-00001
通过运行以下命令应用 YAML:
kubectl apply -f hello.yaml
验证流量拆分
要验证流量拆分是否已正确配置,请通过运行以下命令再次列出修订:
kn revisions list
输出应类似于:
NAME SERVICE TRAFFIC TAGS GENERATION AGE CONDITIONS READY REASON helloworld-go-00002 helloworld-go 50% 2 59s 4 OK / 4 True helloworld-go-00001 helloworld-go 50% 1 2m58s 4 OK / 4 True
在浏览器中多次访问该 Knative 服务,以查看每个修订版提供的不同输出。例如, 可以从终端多次访问服务 URL,以查看在修订之间拆分的流量。
输出应类似于:
Hello Knative! Hello World! Hello Knative! Hello World!
总结
作为业内首个全托管Istio兼容的阿里云服务网格产品ASM,一开始从架构上就保持了与社区、业界趋势的一致性,控制平面的组件托管在阿里云侧,与数据面侧的用户集群独立。ASM产品是基于社区Istio定制实现的,在托管的控制面侧提供了用于支撑精细化的流量管理和安全管理的组件能力。通过托管模式,解耦了Istio组件与所管理的K8s集群的生命周期管理,使得架构更加灵活,提升了系统的可伸缩性。从2022年4月1日起,阿里云服务网格ASM正式推出商业化版本, 提供了更丰富的能力、更大的规模支持及更完善的技术保障,更好地满足客户的不同需求场景, 详情可见产品介绍:https://www.aliyun.com/product/servicemesh 。
通过上述内容, 可以看到基于一个托管的服务网格技术平台上支持基于Knative的Serverless容器, 可以简化用户维护底层基础设施的复杂度, 让用户可以轻松地构建自己的Serverless平台。