阿里云K8s+Istio+Knative搭建Serverless平台

简介: 本文以一个Nodejs前端开发者角度出发,从零基于阿里云平台能力搭建一个弹性的Serverless平台的记录。希望对也想了解这个产品整体的小伙伴们有一定帮助 以上我们利用阿里云K8s+Istio+Knative 搭建Serverless平台 - 部署了k8s集群 - 部署了Istio - .

前言

本文以一个Nodejs前端开发者角度出发,从零基于阿里云平台能力搭建一个弹性的Serverless平台的记录。希望对也想了解这个产品整体的小伙伴们有一定帮助。

官方文档:https://help.aliyun.com/document_detail/121509.html
控制台:https://cs.console.aliyun.com/

为什么是Knative

项目主页:https://knative.dev/
项目仓库:https://github.com/knative

总结为下面两张之前我分享的PPT

  • knative 定位:

enter image description here

  • knative 三大组件:

enter image description here

前置依赖

  • 创建一个k8s集群,且集群中Worker节点的数量大于等于3个。
  • 部署 Istio。

下图可知它们之间的关系:
enter image description here

部署k8s集群

文档:https://help.aliyun.com/document_detail/86488.html
Kubernetes 是流行的开源容器编排技术,按照以下步骤快速创建一个k8s集群

  1. 选择标准托管k8s
  2. 创建专有网络和虚拟交换机, 否则无法选择购买实例规格
  3. 选择worker实例规格,因为是体验平台,故我选择了3台最小规格支持Pod的实例, 这是最低要求。因为是托管k8s集群,故不需要选择master

enter image description here

  1. 创建和选择 密钥对,后面在本机电脑操作远端服务的认证
  2. 公网访问:使用 EIP 暴露 API Server 记得选择上集群创建好不能修改, 不然无法在本机电脑上通过http url 访问服务
  3. 选择上日志服务
  4. 保障账户余额不低于100
  5. 其他默认配置

点击创建k8s集群,所有检查项通过后,约10 分钟创建成功所有资源
enter image description here

部署Istio

Istio为解决微服务的分布式应用架构在运维、调试、和安全管理等维度存在的问题,可通过部署Istio创建微服务网络,并提供负载均衡、服务间认证以及监控等能力,同时Istio不需要修改服务即可实现以上功能
通过下面步骤快速在上面的k8s中部署istio

  1. 选择对应集群部署istio

enter image description here

  1. 如果要实现 Tracing 分布式追踪服务,勾选开启
  2. 在链路追踪服务,打开Region对应信息查看token, 复制与集群region一直的内网接入http url 到istio配置中
  3. 其他默认配置,点击部署,很快相应服务部署成功再k8s集群上

enter image description here

部署Knative

文档:https://help.aliyun.com/document_detail/121509.html
在控制台左侧,找到Knative(公测),选择组件管理,点击右上方一键部署,部署我们前面讲到的Knative 三大组件

  • Tekton 组件 (原build 组件不在推荐) - v0.9.2
  • Serving 组件 - v0.11.0
  • Eventing 组件 - v0.11.0

enter image description here

检查未通过,需要开启 istio-ingressgateway,解决:
在控制台> 服务网格 > istio管理, 点右侧更新
将如下,光标高亮 gateways enabled 默认false 修改为 true, 点击更新后,
enter image description here

再次部署kantive组件,很快即可部署成功
enter image description here

部署服务

下载Knative 官方服务demo 工程

git clone https://github.com/knative/docs

# nodejs demo 服务
cd docs/serving/samples/hello-world/helloworld-nodejs

查看修复成,你想要的服务


const express = require('express');
const app = express();

app.get('/', (req, res) => {
  console.log('Hello world received a request.');

  const target = process.env.TARGET || 'World';

 // 我添加了输出,可以查看流量访问的不同服务版本
  const kRevision = process.env.K_REVISION || '';  
  res.send(`Hello ${target} (revision: ${kRevision}) \n`);
});

const port = process.env.PORT || 8080;
app.listen(port, () => {
  console.log('Hello world listening on port', port);
});

镜像构建与发布

# 目前 Docker 官方维护了一个公共仓库Docker Hub 我们将自己构建的镜像发布上去
# https://hub.docker.com/
# 进行镜像构建, 其中859652049替换成你的账号名
docker build -t 859652049/helloworld-nodejs .
# 推送镜像到公共仓库Docker Hub
docker push 859652049/helloworld-nodejs

控制台可视化部署

  1. 回到控制面板 > Knative > 服务管理 > 选择k8s集群命名空间default, 创建服务
  2. 支持根据模板快速创建 和 可视化编辑创建。
  3. 我们选择可视化创建
  4. 镜像名称输入:docker.io/859652049/helloworld-nodejs (也可以用你上面自己创建的镜像)
  5. 配置环境变量 TARGET: NodeX 1 (服务代码里用到这个环境变量)
  6. 其他默认配置,可以自由配置

    • 最大并发不控制
    • 弹性实例最小0, 最大100
    • CPU 0.25Core, 内存 125M
    • 不挂载额外存储数据卷

enter image description here

服务部署成功
enter image description here

访问服务,其中下面的ip 和 host 对应,上图中默认域名和访问网关ip

curl -H "HOST: nodejs.default.example.com" http://47.111.223.97 

或者通过绑定公网ip 到默认域名上

# 推荐工具SwitchHosts https://github.com/oldj/SwitchHosts/blob/master/README_cn.md
47.111.223.97 nodejs.default.example.com

两种方式,接口数据返回成功
enter image description here
enter image description here

Kubectl命令行部署

文档:https://help.aliyun.com/document_detail/86494.html

  1. 安装 kubectl 客户端,根据文档, 我这边mac 通过docker 客户端 Preferences 设置中 enable kubernetes 后安装了。
  2. 配置登录凭据
  3. 集群列表,点击集群名,选择KubeConfig(公网访问)页签,并单击复制,将内容复制到本地计算机的 $HOME/.kube/config

enter image description here

  1. 执行 kubectl get revisions 查看部署服务的版本,如下可以看到我们上面通过控制台可视化部署的服务nodejs, 一个版本nodejs-dn5vh
    enter image description here

5.通过kubectl 部署新的一个版本

还是我们之前使用的 helloworld-nodejs 工程, 将配置文件service.yaml

apiVersion: serving.knative.dev/v1alpha1
kind: Service
metadata:
  name: nodejs # 服务名
  namespace: default  # 服务部署的命名空间
spec:
  template:
    metadata:
      name: nodejs-dn5vh-v2
    spec:
      containers:
      - image: docker.io/859652049/helloworld-nodejs
        env:
        - name: TARGET
          value: "NodeX 2" # 环境变量更新为2
  traffic:  # 设置流量分配到不同服务版本, 也可通过如下图可视化修改配置
    - tag: current
      revisionName: nodejs-dn5vh # 修改为自动可视化自动生成的版本号
      percent: 50 # 50% 流量版本1
    - tag: candidate
      revisionName: nodejs-dn5vh-v2  # 与当前版本号一致
      percent: 50  # 50% 流量版本2
    - tag: latest
      latestRevision: true
      percent: 0
  1. 部署服务
kubectl --namespace default apply -f ./service.yaml 
  1. 多次访问服务,流量按比例导入到2个版本

enter image description here
enter image description here
enter image description here

自定义域名

在Knative Serving route 路由中默认使用 example.com 作为默认域名,route 完全定义的域名格式默认为:
{service}.{namespace}.{default-domain} ,如:nodejs.default.example.com

域名A记录到网关

  1. 首先你要有个阿里云备案过的域名,否则最后访问会显示需要接入备案
  2. 将域名 A记录 指向自己的公网网关地址,如上:47.111.223.97

这个有个注意点,因为服务部署的命名空间和服务名 都会不断变化,或者有多个。故A记录时候使用泛域名绑定
比如 dev.lianxuify.com 这个子域名是我用来开发测试的
dev.lianxuify.com
nodejs.default.dev.lianxuify.com
nodejs-1.default.dev.lianxuify.com

  1. 修改默认域名example.com 为 dev.lianxuify.com

通过控制台配置

菜单 Knative > 组件管理 > 点击核心组件Serving 详情 > 自定义域名模板 > 点击查看yaml

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

    # This block is not actually functional configuration
    # ....
    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
    # ...
    svc.cluster.local: |
      selector:
        app: secret
  # 以上都是注释
  dev.lianxuify.com: '' # 自定义域名,仅需要添加该行,前面添加两个空格,与顶部_example对齐
kind: ConfigMap
metadata:
  creationTimestamp: '2020-02-05T15:21:13Z'
  labels:
    serving.knative.dev/release: v0.11.0
  name: config-domain
  namespace: knative-serving
  resourceVersion: '83466654'
  selfLink: /api/v1/namespaces/knative-serving/configmaps/config-domain
  uid: 257133b2-482b-11ea-9d30-8e59b18ed506

yaml语法 基本语法 http://www.ruanyifeng.com/blog/2016/07/yaml.html

  • 大小写敏感
  • 使用缩进表示层级关系,几个空格不重要
  • 缩进时不允许使用Tab键,只允许使用空格 已验证
  • 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
  • \#表示注释
  • | 保留换行符 字符串

通过 kubectl 配置

kubectl edit cm config-domain --namespace knative-serving
# 同上添加一行,保存即生效

# 验证生效
kubectl get route
# NAME     URL                                       READY   REASON
# nodejs   http://nodejs.default.dev.lianxuify.com   True

enter image description here

路由转发

当我们有多个服务使用相同的域名,通过请求的Path不同,将流量转发到不同服务中

坑:knative 官方demo 工程,不支持路径访问,只处理根路径访问。 因为这个一直接口返回失败,以为配置搭建问题。

const express = require('express');
const app = express();
// 修改/ 为 *
// app.get('/', (req, res) => {
app.get('*', (req, res) => {
  // ...
});

// 
  1. 修改代码路由为*,重新构建镜像,发布镜像 (docker.io/859652049/helloworld-nodejs:latest 已经修改过)
  2. 重新部署服务, 按照上面可视化、或者 kubectl 方式重新部署两个服务 nodejs、nodejs2

enter image description here

  1. 选择 Knative > 服务管理 > 点击服务名 > 选择路由转发 > 点击配置

enter image description here

  1. 配置保存后立即生效,访问符合预期

    • dev.lianxuify.com/nodejs 到服务1 nodejs
    • dev.lianxuify.com/nodejs 到服务2 nodejs2

enter image description here
enter image description here

弹性验证与配置

 kubectl get pods -w  // 查看运行的容器组,sidecar+业务服务

如下所示,当没有流量后 pod 自动会删除,流量进来会弹性扩展
enter image description here

流量根据如下配置进行扩缩容,可根据业务场景要求配置
Knative > 组件管理 > 点击Serving组件详情> 点击扩缩容配置
enter image description here
这些参数是服务弹性算法的关键配置,需要结合业务配置出最佳实践,鼠标hover小绿点有详细说明。

日志监控

在Knative 上对分布式的日志,监控接入这里没有进行深度探索。文档整体看下来,流程与常规服务接入没区别,开通对应产品进行接入即可。
以下是创建集群默认创建的部分日志和监控
enter image description here
enter image description here

回滚

在Knative 上对发布进行回滚,没有进行深度探索。大致理解如下

  • 回滚历史版本,通过流量配置修改,将流量切到老版本
  • 对应同版本回滚,找到如下回滚面板

enter image description here

CICD

持续集成持续交付这块,还在探索中。看到 GitHub 事件源add-on 组件,通过github 仓库的钩子事件能触发到
Knative平台去构建镜像、部署服务。另一种方式自己监听gitlab 钩子事件,构建推送镜像,调用平台OpenAPI接口 (如上图有个触发重新部署的接口)或者 自己的部署平台调用kubectl 命令行工具部署

总结

以上我们利用阿里云K8s+Istio+Knative 搭建Serverless平台

  • 部署了k8s集群
  • 部署了Istio
  • 部署了Knative 三大组件
  • 部署了业务服务,验证了弹性扩缩容
  • 自定义了域名 + 路由转发 到不同服务
  • 不停服蓝绿部署、按流量灰度发布, 同个服务多个版本

该平台提供可视化配置 + 以及其yaml配置文件,对一个新手认识、使用这个生态能力有很好的帮助。
整套方案对应传统服务迁移到Serverless平台上灵活性、友好性较高,未来大有可为。但目前开发者工具相关还不是这么丰富,平台在公测中,整体使用成本和门槛相对阿里云函数计算更高些。因为最低集群3台worker要求,一直占用, 我目前是体验,选择了低配置,大概是4元多一个小时 (不知道能不能更低)

这里还有篇我对阿里云函数计算整体调研的文章: https://yq.aliyun.com/articles/743665
希望两篇文章对大家整体上认识两款产品,以及搭建serverless有帮助。
如有理解有误,欢迎指出,共同成长。
其间感谢阿里云 @元毅 的帮助与解答。

相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。     相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
目录
相关文章
|
6月前
|
存储 Kubernetes 网络安全
关于阿里云 Kubernetes 容器服务(ACK)添加镜像仓库的快速说明
本文介绍了在中国大陆地区因网络限制无法正常拉取 Docker 镜像的解决方案。作者所在的阿里云 Kubernetes 集群使用的是较旧版本的 containerd(1.2x),且无法直接通过 SSH 修改节点配置,因此采用了一种无需更改 Kubernetes 配置文件的方法。通过为 `docker.io` 添加 containerd 的镜像源,并使用脚本自动修改 containerd 配置文件中的路径错误(将错误的 `cert.d` 改为 `certs.d`),最终实现了通过多个镜像站点拉取镜像。作者还提供了一个可重复运行的脚本,用于动态配置镜像源。虽然该方案能缓解镜像拉取问题,
735 2
|
10月前
|
人工智能 运维 安全
阿里云 Serverless 助力海牙湾构建弹性、高效、智能的 AI 数字化平台
海牙湾(G-Town)是一家以“供应链+场景+技术+AI”为核心驱动力的科技公司,致力于为各行业提供数字化转型解决方案。通过采用阿里云Serverless架构,解决了弹性能力不足、资源浪费与运维低效的问题。SAE全托管特性降低了技术复杂度,并计划进一步探索Serverless与AI结合,推动智能数字化发展。海牙湾业务覆盖金融、美妆、能源等领域,与多家知名企业建立战略合作,持续优化用户体验和供应链决策能力,保障信息安全并创造可量化的商业价值。未来,公司将深化云原生技术应用,助力更多行业实现高效数字化转型。
708 19
|
Cloud Native Serverless 数据中心
阿里云ACK One:注册集群支持ACS算力——云原生时代的计算新引擎
ACK One注册集群已正式支持ACS(容器计算服务)算力,为企业的容器化工作负载提供更多选择和更强大的计算能力。
|
Cloud Native Serverless 数据中心
阿里云ACK One:注册集群支持ACS算力——云原生时代的计算新引擎
阿里云ACK One:注册集群支持ACS算力——云原生时代的计算新引擎
414 10
|
边缘计算 调度 对象存储
部署DeepSeek但IDC GPU不足,阿里云ACK Edge虚拟节点来帮忙
介绍如何使用ACK Edge与虚拟节点满足DeepSeek部署的弹性需求。
|
Kubernetes 监控 Serverless
基于阿里云Serverless Kubernetes(ASK)的无服务器架构设计与实践
无服务器架构(Serverless Architecture)在云原生技术中备受关注,开发者只需专注于业务逻辑,无需管理服务器。阿里云Serverless Kubernetes(ASK)是基于Kubernetes的托管服务,提供极致弹性和按需付费能力。本文深入探讨如何使用ASK设计和实现无服务器架构,涵盖事件驱动、自动扩展、无状态设计、监控与日志及成本优化等方面,并通过图片处理服务案例展示具体实践,帮助构建高效可靠的无服务器应用。
|
安全 持续交付 云计算
课时5:阿里云容器服务:最原生的集成Docker和云服务
阿里云容器服务以服务化形式构建容器基础设施,大幅提升开发效率,简化应用部署流程。通过Docker容器和DevOps工具(如Jenkins),实现自动化部署与迭代,优化企业内部复杂部署问题。该服务支持GPU调度、混合云架构无缝迁移,并与阿里云产品体系无缝集成,提供安全防护、网络负载均衡等多重功能支持。凭借微服务架构,帮助企业突破业务瓶颈,提高资源利用率,轻松应对海量流量。
437 0
课时5:阿里云容器服务:最原生的集成Docker和云服务
|
Kubernetes 持续交付 开发工具
阿里云协同万兴科技落地ACK One GitOps方案,全球多机房应用自动化发布,效率提升50%
阿里云协同万兴科技落地ACK One GitOps方案,全球多机房应用自动化发布,效率提升50%
729 2
|
弹性计算 人工智能 资源调度
DeepSeek大解读系列公开课上新!阿里云专家主讲云上智能算力、Kubernetes容器服务、DeepSeek私有化部署
智猩猩「DeepSeek大解读」系列公开课第三期即将开讲,聚焦阿里云弹性计算助力大模型训练与部署。三位专家将分别讲解智能算力支撑、Kubernetes容器服务在AI场景的应用实践、以及DeepSeek一键部署和多渠道应用集成,分享云计算如何赋能大模型发展。欲观看直播,可关注【智猩猩GenAI视频号】预约。 (239字符)
|
监控 Kubernetes Cloud Native
基于阿里云容器服务Kubernetes版(ACK)的微服务架构设计与实践
本文介绍了如何基于阿里云容器服务Kubernetes版(ACK)设计和实现微服务架构。首先概述了微服务架构的优势与挑战,如模块化、可扩展性及技术多样性。接着详细描述了ACK的核心功能,包括集群管理、应用管理、网络与安全、监控与日志等。在设计基于ACK的微服务架构时,需考虑服务拆分、通信、发现与负载均衡、配置管理、监控与日志以及CI/CD等方面。通过一个电商应用案例,展示了用户服务、商品服务、订单服务和支付服务的具体部署步骤。最后总结了ACK为微服务架构提供的强大支持,帮助应对各种挑战,构建高效可靠的云原生应用。

相关产品

  • 函数计算
  • 推荐镜像

    更多