基于 Wasm 和 ORAS 简化扩展服务网格功能

alicloudnative阅读(1997)评论(0)

头图.png

作者 | 王夕宁  阿里云高级技术专家
来源 | 阿里巴巴云原生公众号

本文将介绍如何使用 ORAS 客户端将具有允许的媒体类型的 Wasm 模块推送到 ACR 注册库(一个 OCI 兼容的注册库)中,然后通过 ASM 控制器将 Wasm Filter 部署到指定工作负载对应的 Pod 中。Wasm Filter 部署中的所有步骤都使用声明方式,也就是说可以创建一个自定义资源 CRD 来描述 Wasm Filter 的部署。一旦该 CRD 创建之后,ASM 控制器可以将 Wasm 模块加载到数据平面层中的相应 Envoy 代理中,同时在控制平面层中也会创建相应的 Istio EnvoyFilter 自定义资源。

Envoy Filter 介绍

首先回顾一下 EnvoyProxy 的实现机制。Envoy 的核心是一个 L3/L4 网络代理,并支持 L7 代理,通过提供可插入 filter chain 机制允许开发人员编写 filter 来执行不同的任务,譬如我们常用到的 HTTP connection manager,将原始字节转换为 HTTP 级别的消息和事件,还处理所有 HTTP 连接和请求共有的功能包括访问日志、tracing 等。

1.png

上图可以看到:Downstream 作为连接到 Envoy 并发送请求以及接收响应的客户端部分, 监听器 Listener 组件用于绑定到 IP 地址/端口并接收来自 Downstream 下游的连接。通过配置 Listener,用户可以启用通过代理的流量管理能力,然后使用多个 Filter 增强数据流,多个 Filter 构成了一个 Filter Chain。可以看到经过这些 Filter chain 处理之后, 会把请求映射到相应的 Cluster(此处的 Cluster 集群是指 Envoy 连接到的逻辑上相同的一组上游主机,与下文中提交的 Kubernetes 集群没有关系),而 Cluster 的作用是负责连接到一组上游节点服务, 并使用关联的负载均衡策略转发这些请求。

根据处理任务的不同,Envoy Filter 分为三类:

  • Listener Filter:用于操作处理 L4 连接中的元数据。
  • Network Filter:用于操作处理 L4 连接中的原始数据。
  • HTTP Filter:用于操作处理 L7 连接中的 HTTP 请求与响应。

除了这些 built-in Filter 之外,还可以开发自定义的 Filter,可使用 native c++ 编译方式,或是通过 wasm 技术构建 Filter。

此外,Envoy 提供了一组 API,也就是我们常说的 xDS API。通过这些 API,控制平面可以动态地配置 Envoy 代理。

2.png

如上图所示,与进站流量类似,对于出站流量来说,监听器在配置的地址或者端口进行监听网络流量的请求。每个监听器同样会定义一组位于数据路径中的 Filter,并形成一组过滤器链 Filter Chain。通过这样的一组过滤器,用户可以配置 Envoy 来针对出站流量做特定的任务,包括数据协议处理、生成调用的统计信息、执行 RBAC 权限等。

3.png

为了更好地理解这些 Envoy Filter 以及 Filter Chain,下面来看一个实际的例子。这个就是 Istio 官方示例 bookinfo 中的第一个服务 productpage。首先, productpage pod 中 Envoy Proxy 配置了一个监听 9080 端口的监听器,进入这个 pod 的端口 9080 上的流量请求都会被拦截到这个 proxy 中,然后请求就会经过这些 Filter Chain 进行处理。具体如下:

  • 第一个 filter 是 envoy.filters.network.metadata_exchange,它的主要作用顾名思义,用来在 filter 之间交换元数据。
  • 第二个 filter: envoy.http_connection_manager,它下面通常会有以下几个跟 http 特定的 filter,包括:
    • envoy.filters.http.wasm/envoy.wasm.metadata_exchange(用于元数据交互)
    • Istio_authn filter(用于授权认证)
    • envoy.filters.http.cors(处理跨域资源共享的 filter)
    • envoy.filters.http.fault(故障注入过滤器,可以用来测试微服务架构中容错能力,用户可以自定义错误代码来实现延时注入或者终止请求,在不同的失败场景下提供错误处理的能力,例如服务失败、服务过载、服务高延时等情况,这个也是较为常用的 filter)
    • envoy.filters.http.wasm/envoy.wasm.stats、envoy.filters.http.wasm/xxx-wasmfilter(用户自定义的 wasm 实现的filter)
    • envoy.filters.http.router(实现 HTTP 转发,几乎所有 HTTP 场景下都会使用到这一过滤器)

备注:可以通过请求这个 URL 地址获取配置信息:kubectl exec -it [productpage-xxx] -c istio-proxy curl localhost:15000/config_dump

添加新的 Filter

Envoy 社区已经提供了若干个 Built-in Filters,具体参见:https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/http_filters

在服务网格中,可以通过 API 启用这些 Built-in Filter 能力。

如果这些 Built-in Filter 无法满足需求,还可以通过自定义 Filter 实现,有以下两种方式:

  • 静态预编译
    • 将其他过滤器集成到 Envoy 的源代码中,并编译新的 Envoy 版本。
    • 这种方法的缺点是您需要维护 Envoy 版本,并不断使其与官方发行版保持同步。
    • 由于 Envoy 是用 C++ 实现的,因此新开发的过滤器也必须用 C++ 实现。
  • 动态运行时加载
    • 在运行时将新的过滤器动态加载到 Envoy 代理中。
    • 为了简化扩展 Envoy 的过程, 通过引入 WebAssembly 技术 – 它是一种有效的可移植二进制指令格式,提供了可嵌入和隔离的执行环境。

使用 Wasm 扩展 Envoy Proxy 的优缺点

在实际应用中,会根据以下优缺点来决定是否使用 Wasm 这种方式扩展 Envoy Filter。

Pros

  • 敏捷性:过滤器可以动态加载到正在运行的 Envoy 进程中,而无需停止或重新编译。
  • 可维护性:不必更改 Envoy 自身基础代码库即可扩展其功能。
  • 多样性:可以将流行的编程语言(例如 C/C++ 和 Rust)编译为 WASM,因此开发人员可以选择实现过滤器的编程语言。
  • 可靠性和隔离性:过滤器会被部署到 VM 沙箱中,因此与 Envoy 进程本身是隔离的;即使当 WASM Filter 出现问题导致崩溃时,它也不会影响 Envoy 进程。
  • 安全性:过滤器通过预定义 API 与 Envoy 代理进行通信,因此它们可以访问并只能修改有限数量的连接或请求属性。

Cons

  • 性能约为 C++ 编写的原生静态编译的 Filter 的 70%。
  • 由于需要启动一个或多个 WASM 虚拟机,因此会消耗一定的内存使用量。
  • The WebAssembly ecosystem is still young。

envoy-wasm 运行机制

如下图所示,envoy-wasm 运行机制包括以下几个步骤:

4.png

  • Wasm 二进制代码需要能够被动态加载进来,无论是通过 local file 方式还是 xds 远程获取方式。
  • 一个 Wasm filter 是否被允许加载,需要一致性校验:https://github.com/proxy-wasm/spec
  • 一旦被加载之后,Wasm filter 就成为 filter chain 的一部分,当新的请求进来之后,还是先进入到原生的 filter,之后进入到 Proxy-Wasm 扩展控制器。
  • Proxy-Wasm 扩展控制器会根据在 filter chain 中定义的 configuration 信息,调用并执行注册的校验过的这些 Wasm filter。
  • 内置的 Wasm runtime 支持:LLVM-based WAVM ~20MB, and V8 ~10MB。
  • 事件驱动模型。
  • 兼容 native filter 调用方式。

如下所示,是下发到 Envoy Proxy 侧的一个 Wasm Filter 的配置内容。

5.png

以上讲述了 Envoy Filter 以及通过 Wasm 扩展的方式,引出了 Wasm filter 机制,这将是未来的主流方式。

在一个服务网格体系中,如何以有效并且简单的方式来管理 Wasm filter 的部署运行,将是云产品需要解决的一个问题。

OPAS 及 Wasm filter 注册库

在 Cloud Native 生态系统中,如何管理一个 Artifact 文件,相信绝大多数人会想到 oci 规范标准,是否可以像管理 Docker 镜像那样去管理这些 Wasm filter。

ORAS 项目就是用来解决这个问题的,它的全称为 OCI Registry As Storage。ORAS 是 OCI Artifacts 项目的参考实现,可以显著地简化 OCI 注册库中任意内容的存储。

使用 ORAS API/SDK Library 可以构建自定义工具,完成以下功能:

  • 将 WebAssembly 模块推入到 OCI 注册库中。
  • 从 OCI 注册库中拉取 WebAssembly 模块。

oras cli 的使用类似于 docker cli,如下所示:

6.png

以阿里云容器镜像服务企业版 ACR EE 为例,作为企业级云原生应用制品管理平台,已经提供了容器镜像、Helm Chart 以及符合 OCI 规范的制品的生命周期管理。开通之后,创建一个镜像仓库,会分配一个地址,提供了 vpc 和公网两种方式。

使用 oras login 命令行登录, 执行以下命令:

oras login –username=<登录账号> acree-1-registry.cn-hangzhou.cr.aliyuncs.com

通过oras push命令推送, 执行以下命令:

oras push acree-1-registry.cn-hangzhou.cr.aliyuncs.com//asm-test:v0.1 –manifest-config runtime-config.json:application/vnd.module.wasm.config.v1+json  example-filter.wasm:application/vnd.module.wasm.content.layer.v1+wasm

注意参数 –manifest-config,可以参考 Wasm Artifact 镜像规范。

Wasm filter 被推送到 ACR EE 注册库中之后,可以查看相关信息,如下:

7.png

阿里云服务网格 ASM 架构

在阿里云服务网格 ASM 产品中是如何使用 Wasm 技术呢?首先我们了解一下 ASM 产品的技术架构,如下图所示。作为业内首个全托管 Istio 兼容的服务网格产品,ASM 的定位是专注打造全托管、安全、稳定、易用的服务网格,以及支持跨地域多集群、多云混合云服务的统一治理。控制平面的组件托管在阿里云侧,与数据面侧的用户集群解耦独立,降低用户使用的复杂度,用户只需要专注于业务应用的开发部署。在托管模式下,保持与 Istio 的兼容,支持声明式的方式定义灵活的路由规则,支持多个 Kubernetes 集群的统一流量管理。

8.png

服务网格 ASM 作为连接上层应用和下层计算基础设施的重要环节,可以分为 3 个角度来理解:

  • 从向下与基础设施融合的角度
  • 服务网格自身的能力建设的角度
  • 向上支持应用层以及被集成能力的角度

其中, 从服务网格自身的能力建设来看,ASM 作为一个托管的服务网格产品,提供了柔性架构,可以支持不同版本的、定制的 Istio 控制面与数据面 Proxy 代理。

  • 在托管侧,将控制面核心组件进行改造托管,并负责整个控制面和数据面组件的生命周期管理。在产品能力方面,ASM 在 Mesh CA、安全审计方面做了增强提升网格实例的安全度;把客户场景的常见问题形成了诊断规则,用户可以自行运行诊断分析。
  • 在做核心托管侧的建设之外,ASM 优化整合了阿里云的多个产品服务,如:在可观测性方面,整合了 xtrace、arms、日志服务等;在跨 vpc 网络打通方面整合了 cen,实现多集群的互联互通;在限流方面集成了 AHAS 的限流服务。
  • ASM 还集成扩展了社区开源的组件能力,包括在安全方面的 OPA 安全引擎的支持、spiffe/spire 的支持、envoyfilter 的扩展支持等。所以这一部分需要提供一种简单有效的方式帮助用户轻松扩展这些能力。

在阿里云 ASM 中使用 Wasm

随着新架构的优化,WebAssembly 技术被引入服务网格中,解决代理扩展的问题。这样一来, ASM 架构就变成了“托管的高可用弹性控制平面 + 可扩展的插件式的数据平面“的模式。

阿里云服务网格 ASM 产品中提供了对 WebAssembly(WASM)技术的支持,服务网格使用人员可以把扩展的 WASM Filter 通过 ASM 部署到数据面集群中相应的 Envoy 代理中。通过 ASMFilterDeployment  Controller 组件,  可以支持动态加载插件、简单易用、以及支持热更新等能力。

9.png

通过这种过滤器扩展机制,可以轻松扩展 Envoy 的功能并将其在服务网格中的应用推向了新的高度。

下面我们具体来看在 ASM 实例中是怎样启用这个能力的?

部署一个 ASM 实例之后,默认该功能是没有开启的,用户需要主动去开启。例如通过如下 aliyun cli 方式:

aliyun servicemesh UpdateMeshFeature  --ServiceMeshId=xxxxxx --WebAssemblyFilterEnabled=true

开启该功能之后,ASM 实例会部署相关组件并执行如下任务:

  • 部署一个 DaemonSet(asmwasm-controller) 到 K8s 集群中。
  • asmwasm-controller 监听一个 configmap,该 configmap 存放要拉取的 wasm filter 的地址,例如:acree-1-registry.cn-hangzhou.cr.aliyuncs.com/*/sample:v0.1。
  • 如果需要授权认证,该 asmwasm-controller 会根据定义的 pullSecret 值获得相应的 secret 值。
  • 然后,调用 oras API 从注册库中动态拉取 Wasm filter。
  • 该 asmwasm-controller 使用 HostPath 方式挂载 volume,所以拉取的 Wasm filter 会落盘到对应的节点上。

启用了该功能之后,如何开始部署一个 Wasm filter 并挂载到对应 workload 的 Envoy Proxy 中呢?

10.png

阿里云服务网格 ASM 产品提供了一个新的 CRD ASMFilterDeployment 以及相关的 controller 组件。这个 controller 组件会监听 ASMFilterDeployment 资源对象的情况,会做 2 个方面的事情:

  • 创建出用于控制面的 Istio EnvoyFilter Custom Resource,并推送到对应的 asm 控制面 istiod 中。
  • 从 OCI 注册库中拉取对应的 wasm filter 镜像,并挂载到对应的 workload pod 中。

以下是一个 ASMFilterDeployment CR 示例:

apiVersion: istio.alibabacloud.com/v1beta1
kind: ASMFilterDeployment
metadata:
  name: details-v1-wasmfiltersample
spec:
  workload:
    kind: Deployment
    labels:
      app: details
      version: v1
  filter:
    parameters: '{"name":"hello","value":"hello details"}'
    image: 'acree-1-registry.cn-hangzhou.cr.aliyuncs.com/asm/asm-test:v0.1'
    imagePullOptions: 
      pullSecret: 'asmwasm-cache'
    rootID: 'my_root_id'
    id: 'details-v1-wasmfiltersample.default'

生成的 Istio Envoy Filter 资源如下所示:

11.png

其中,match 片段中定义了 envoy.router 这个 filter、patch 片段中定义了 INSERT_BEFORE 操作,插入一个 Wasm filter,如下:

12.png

挂载了 Wasm filter 的工作负载定义更新后如下,其中以 hostpath 方式挂载 Wasm filter 文件到 Proxy 容器中:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
.…
spec:
   ….
   template:
      metadata:
          annotations:
              sidecar.istio.io/userVolume: '[{"name":"wasmfilters-dir","hostPath":{"path":"/var/local/lib/wasm-filters"}}]’
              sidecar.istio.io/userVolumeMount: '[{"mountPath":"/var/local/lib/wasm-filters","name":"wasmfilters-dir"}]'

确认 Wasm filter 是否生效。登录到 productpage Pod 的 istio-proxy 容器中,执行以下命令,将一些流量发送到 details 服务上。在响应中,可以看到过滤器的头添加到响应头中。

kubectl exec -ti  deploy/productpage-v1 -c istio-proxy -- curl -v http://details:9080/details/123
*   Trying 172.21.9.191...
* TCP_NODELAY set
* Connected to details (172.21.9.191) port 9080 (#0)
> GET /details/123 HTTP/1.1
> Host: details:9080
> User-Agent: curl/7.58.0
> Accept: */*
>
< HTTP/1.1 200 OK
xxxxxxx
< resp-header-demo: added by our filter
xxxxx
* Connection #0 to host details left intact
xxxxx

总结

在开发阶段:

按照如下流程,使用适当的 wasm sdk/编程语言,创建编译出一个 wasm 二进制文件,通过使用 oras cli 上传到 oci 镜像仓库中。

13.png

在部署运行阶段:

首先确认已经在 ASM 中开启 Wasm 支持能力,然后创建一个 ASMFilterDeployment 自定义资源,注意这个 CR 是在服务网格 ASM 实例对应的 apiserver 中创建。一旦创建,相应的 crd controller 会监听同步相应的资源,一方面生成一个 Istio EnvoyFilter CR 并发送到 ASM 实例的控制面 apiserver 中,用户可以查看生成的这个 Istio Envoyfilter CR 是否满足期望。

14.png

另一方面,确认 Workload 部署变更生效,包括:

  • 可以登录到 proxy container 进行查看 Wasm filter 是否挂载成功。
  • 通过调整 wasm log level 来打印相关信息。

作为业内首个全托管 Istio 兼容的服务网格产品,阿里云服务网格(简称 ASM)是一个统一管理微服务应用流量、兼容 Istio 的托管式平台,专注打造全托管、安全、稳定、易用的服务网格,支持跨地域多集群、多云混合云服务的统一治理。通过流量控制、网格观测以及服务间通信安全等功能,服务网格 ASM 可以全方位地简化您的服务治理,并为运行在异构计算基础设施上的服务提供统一的管理能力,适用于 Kubernetes 集群、Serverless Kubernetes 集群、ECS 虚拟机以及自建集群。

欢迎登录到阿里云服务网格 ASM 产品官网进行体验!

作者简介

王夕宁  阿里云高级技术专家,阿里云服务网格 ASM 技术负责人,专注于 Kubernetes、服务网格以及其他云原生领域。之前曾在 IBM 中国开发中心工作,曾担任专利技术评审委员会主席,作为架构师和主要开发人员负责或参与了一系列在 SOA 中间件、云计算等领域的工作,拥有 50 多项相关领域的国际技术专利。曾在多个技术大会如 Kubecon、ArchSummit、云栖大会等参与技术分享。编写《服务网格技术解析与实践》并在多个技术社区发布文章若干。

使用 GPU-Operator 与 KubeSphere 简化深度学习训练与 GPU 监控

KubeSphere阅读(3916)评论(0)

本文将从 GPU-Operator 概念介绍、安装部署、深度训练测试应用部署,以及在 KubeSphere 使用自定义监控面板对接 GPU 监控,从原理到实践,逐步浅析介绍与实践 GPU-Operator。

GPU-Operator简介

众所周知,Kubernetes 平台通过设备插件框架提供对特殊硬件资源的访问,如 NVIDIA GPU、网卡、Infiniband 适配器和其他设备。然而,使用这些硬件资源配置和管理节点需要配置多个软件组件,如驱动程序、容器运行时或其他依赖库,这是困难的和容易出错的。

NVIDIA GPU Operator 由 Nvidia 公司开源,利用了 Kubernetes 平台的 Operator 控制模式,方便地自动化集成管理 GPU 所需的 NVIDIA 设备组件,有效地解决了上述GPU设备集成的痛点。这些组件包括 NVIDIA 驱动程序(用于启用 CUDA )、用于 GPU 的 Kubernetes 设备插件、NVIDIA Container 运行时、自动节点标签、基于 DCGM 的监控等。

NVIDIA GPU Operator 的不仅实现了设备和组件一体化集成,而且它管理 GPU 节点就像管理 CPU 节点一样方便,无需单独为 GPU 节点提供特殊的操作系统。值得关注的是,它将GPU各组件容器化,提供 GPU 能力,非常适合快速扩展和管理规模 GPU 节点。当然,对于已经为GPU组件构建了特殊操作系统的应用场景来说,显得并不是那么合适了。

GPU-Operator 架构原理

前文提到,NVIDIA GPU Operator 管理 GPU 节点就像管理 CPU 节点一样方便,那么它是如何实现这一能力呢?

我们一起来看看 GPU-Operator 运行时的架构图:

通过图中的描述,我们可以知道, GPU-Operator 是通过实现了 Nvidia 容器运行时,以runC作为输入,在runCpreStart hook中注入了一个名叫nvidia-container-toolkit的脚本,该脚本调用libnvidia-container CLI设置一系列合适的flags,使得容器运行后具有 GPU 能力。

GPU-Operator 安装说明

前提条件

在安装 GPU Operator 之前,请配置好安装环境如下:

  • 所有节点不需要预先安装NVIDIA组件(driver,container runtime,device plugin);
  • 所有节点必须配置Docker,cri-o, 或者containerd.对于 docker 来说,可以参考这里
  • 如果使用HWE内核(e.g. kernel 5.x) 的 Ubuntu 18.04 LTS 环境下,需要给nouveau driver添加黑名单,需要更新initramfs
$ sudo vim /etc/modprobe.d/blacklist.conf # 在尾部添加黑名单
blacklist nouveau
options nouveau modeset=0
$ sudo update-initramfs -u
$ reboot
$ lsmod | grep nouveau # 验证nouveau是否已禁用
$ cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq -c  #本文测试时处理器架构代号为Broadwell
16 Intel Core Processor (Broadwell)
  • 节点发现(NFD) 需要在每个节点上配置,默认情况会直接安装,如果已经配置,请在Helm chart变量设置nfd.enabledfalse, 再安装;
  • 如果使用 Kubernetes 1.13和1.14, 需要激活 KubeletPodResources

支持的linux版本

OS Name / Version Identifier amd64 / x86_64 ppc64le arm64 / aarch64
Amazon Linux 1 amzn1 X
Amazon Linux 2 amzn2 X
Amazon Linux 2017.09 amzn2017.09 X
Amazon Linux 2018.03 amzn2018.03 X
Open Suse Leap 15.0 sles15.0 X
Open Suse Leap 15.1 sles15.1 X
Debian Linux 9 debian9 X
Debian Linux 10 debian10 X
Centos 7 centos7 X X
Centos 8 centos8 X X X
RHEL 7.4 rhel7.4 X X
RHEL 7.5 rhel7.5 X X
RHEL 7.6 rhel7.6 X X
RHEL 7.7 rhel7.7 X X
RHEL 8.0 rhel8.0 X X X
RHEL 8.1 rhel8.1 X X X
RHEL 8.2 rhel8.2 X X X
Ubuntu 16.04 ubuntu16.04 X X
Ubuntu 18.04 ubuntu18.04 X X X
Ubuntu 20.04 ubuntu20.04 X X X

支持的容器运行时

OS Name / Version amd64 / x86_64 ppc64le arm64 / aarch64
Docker 18.09 X X X
Docker 19.03 X X X
RHEL/CentOS 8 podman X
CentOS 8 Docker X
RHEL/CentOS 7 Docker X

安装doker环境

可参考 Docker 官方文档

安装NVIDIA Docker

配置 stable 仓库和 GPG key :

$ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) \
&& curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add - \
&& curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list

更新软件仓库后安装nvidia-docker2并添加运行时配置:

$ sudo apt-get update
$ sudo apt-get install -y nvidia-docker2
-----
What would you like to do about it ?  Your options are:
Y or I  : install the package maintainer's version
N or O  : keep your currently-installed version
D     : show the differences between the versions
Z     : start a shell to examine the situation
-----
# 初次安装,遇到以上交互式问题可选择N
# 如果选择Y会覆盖你的一些默认配置
# 选择N后,将以下配置添加到etc/docker/daemon.json
{
  "runtimes": {
      "nvidia": {
          "path": "/usr/bin/nvidia-container-runtime",
          "runtimeArgs": []
      }
  }
}

重启docker:

$ sudo systemctl restart docker

安装Helm

$ curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 \
   && chmod 700 get_helm.sh \
   && ./get_helm.sh

添加helm仓库

$ helm repo add nvidia https://nvidia.github.io/gpu-operator \
   && helm repo update

安装 NVIDIA GPU Operator

docker as runtime

$ kubectl create ns gpu-operator-resources
$ helm install gpu-operator nvidia/gpu-operator -n gpu-operator-resources --wait

如果需要指定驱动版本,可参考如下:

$ helm install gpu-operator nvidia/gpu-operator -n gpu-operator-resources \
--set driver.version="450.80.02"

crio as runtime

helm install gpu-operator nvidia/gpu-operator -n gpu-operator-resources\
   --set operator.defaultRuntime=crio

containerd as runtime

helm install gpu-operator nvidia/gpu-operator -n gpu-operator-resources\
   --set operator.defaultRuntime=containerd
   
Furthermore, when setting containerd as the defaultRuntime the following options are also available:
toolkit:
  env:
  - name: CONTAINERD_CONFIG
    value: /etc/containerd/config.toml
  - name: CONTAINERD_SOCKET
    value: /run/containerd/containerd.sock
  - name: CONTAINERD_RUNTIME_CLASS
    value: nvidia
  - name: CONTAINERD_SET_AS_DEFAULT
    value: true

由于安装的镜像比较大,所以初次安装过程中可能会出现超时的情形,请检查你的镜像是否在拉取中!可以考虑使用离线安装解决该类问题,参考离线安装的链接。

使用 values.yaml 安装

$ helm install gpu-operator nvidia/gpu-operator -n gpu-operator-resources -f values.yaml

考虑离线安装

应用部署

检查已部署 operator 服务状态

检查 pods 状态

$ kubectl get pods -n gpu-operator-resources
NAME                                                          READY   STATUS      RESTARTS   AGE
gpu-feature-discovery-4gk78                                   1/1     Running     0          35s
gpu-operator-858fc55fdb-jv488                                 1/1     Running     0          2m52s
gpu-operator-node-feature-discovery-master-7f9ccc4c7b-2sg6r   1/1     Running     0          2m52s
gpu-operator-node-feature-discovery-worker-cbkhn              1/1     Running     0          2m52s
gpu-operator-node-feature-discovery-worker-m8jcm              1/1     Running     0          2m52s
nvidia-container-toolkit-daemonset-tfwqt                      1/1     Running     0          2m42s
nvidia-dcgm-exporter-mqns5                                    1/1     Running     0          38s
nvidia-device-plugin-daemonset-7npbs                          1/1     Running     0          53s
nvidia-device-plugin-validation                               0/1     Completed   0          49s
nvidia-driver-daemonset-hgv6s                                 1/1     Running     0          2m47s

检查节点资源是否处于可分配

$ kubectl describe node worker-gpu-001
---
Allocatable:
  cpu:                15600m
  ephemeral-storage:  82435528Ki
  hugepages-2Mi:      0
  memory:             63649242267
  nvidia.com/gpu:     1  #check here
  pods:               110
---

部署官方文档中的两个实例

实例一

$ cat cuda-load-generator.yaml
apiVersion: v1
kind: Pod
metadata:
   name: dcgmproftester
spec:
   restartPolicy: OnFailure
   containers:
   - name: dcgmproftester11
   image: nvidia/samples:dcgmproftester-2.0.10-cuda11.0-ubuntu18.04
   args: ["--no-dcgm-validation", "-t 1004", "-d 120"]
   resources:
      limits:
         nvidia.com/gpu: 1
   securityContext:
      capabilities:
         add: ["SYS_ADMIN"]
EOF

实例二

$ curl -LO https://nvidia.github.io/gpu-operator/notebook-example.yml
$ cat notebook-example.yml
apiVersion: v1
kind: Service
metadata:
  name: tf-notebook
  labels:
    app: tf-notebook
spec:
  type: NodePort
  ports:
  - port: 80
    name: http
    targetPort: 8888
    nodePort: 30001
  selector:
    app: tf-notebook
---
apiVersion: v1
kind: Pod
metadata:
  name: tf-notebook
  labels:
    app: tf-notebook
spec:
  securityContext:
    fsGroup: 0
  containers:
  - name: tf-notebook
    image: tensorflow/tensorflow:latest-gpu-jupyter
    resources:
      limits:
        nvidia.com/gpu: 1
    ports:
    - containerPort: 8

基于 Jupyter Notebook 应用运行深度学习训练任务

部署应用

$ kubectl apply -f cuda-load-generator.yaml 
pod/dcgmproftester created
$ kubectl apply -f notebook-example.yml       
service/tf-notebook created
pod/tf-notebook created

查看 GPU 处于已分配状态:

$ kubectl describe node worker-gpu-001
---
Allocated resources:
  (Total limits may be over 100 percent, i.e., overcommitted.)
  Resource           Requests     Limits
  --------           --------     ------
  cpu                1087m (6%)   1680m (10%)
  memory             1440Mi (2%)  1510Mi (2%)
  ephemeral-storage  0 (0%)       0 (0%)
  nvidia.com/gpu     1            1 #check this
Events:              <none>

当有 GPU 任务发布给平台时,GPU 资源从可分配状态转变为已分配状态,安装任务发布的先后顺序,第二个任务在第一个任务运行结束后开始运行:

$ kubectl get pods --watch
NAME             READY   STATUS    RESTARTS   AGE
dcgmproftester   1/1     Running   0          76s
tf-notebook      0/1     Pending   0          58s
------
NAME             READY   STATUS      RESTARTS   AGE
dcgmproftester   0/1     Completed   0          4m22s
tf-notebook      1/1     Running     0          4m4s

获取应用端口信息:

$ kubectl get svc # get the nodeport of the svc, 30001
gpu-operator-1611672791-node-feature-discovery   ClusterIP   10.233.10.222   <none>        8080/TCP       12h
kubernetes                                       ClusterIP   10.233.0.1      <none>        443/TCP        12h
tf-notebook                                      NodePort    10.233.53.116   <none>        80:30001/TCP   7m52s

查看日志,获取登录口令:

$ kubectl logs tf-notebook 
[I 21:50:23.188 NotebookApp] Writing notebook server cookie secret to /root/.local/share/jupyter/runtime/notebook_cookie_secret
[I 21:50:23.390 NotebookApp] Serving notebooks from local directory: /tf
[I 21:50:23.391 NotebookApp] The Jupyter Notebook is running at:
[I 21:50:23.391 NotebookApp] http://tf-notebook:8888/?token=3660c9ee9b225458faaf853200bc512ff2206f635ab2b1d9
[I 21:50:23.391 NotebookApp]  or http://127.0.0.1:8888/?token=3660c9ee9b225458faaf853200bc512ff2206f635ab2b1d9
[I 21:50:23.391 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).
[C 21:50:23.394 NotebookApp]
   To access the notebook, open this file in a browser:
      file:///root/.local/share/jupyter/runtime/nbserver-1-open.html
   Or copy and paste one of these URLs:
      http://tf-notebook:8888/?token=3660c9ee9b225458faaf853200bc512ff2206f635ab2b1d9
   or http://127.0.0.1:8888/?token=3660c9ee9b225458faaf853200bc512ff2206f635ab2b1d9

运行深度学习任务

进入jupyter notebook 环境后,尝试进入终端,运行深度学习任务:

进入terminal后拉取tersorflow测试代码并运行:

与此同时,开启另外一个终端运行nvidia-smi查看 GPU 监控使用情况:

利用 KubeSphere 自定义监控功能监控 GPU

部署 ServiceMonitor

gpu-operator帮我们提供了nvidia-dcgm-exporter这个exportor, 只需要将它集成到Prometheus的可采集对象中,也就是ServiceMonitor中,我们就能获取GPU监控数据了:

$ kubectl get pods -n gpu-operator-resources
NAME                                       READY   STATUS      RESTARTS   AGE
gpu-feature-discovery-ff4ng                1/1     Running     2          15h
nvidia-container-toolkit-daemonset-2vxjz   1/1     Running     0          15h
nvidia-dcgm-exporter-pqwfv                 1/1     Running     0          5h27m #here
nvidia-device-plugin-daemonset-42n74       1/1     Running     0          5h27m
nvidia-device-plugin-validation            0/1     Completed   0          5h27m
nvidia-driver-daemonset-dvd9r              1/1     Running     3          15h

可以构建一个busybox查看该exporter暴露的指标:

$ kubectl get svc -n gpu-operator-resources
NAME                                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
gpu-operator-node-feature-discovery   ClusterIP   10.233.54.111   <none>        8080/TCP   56m
nvidia-dcgm-exporter                  ClusterIP   10.233.53.196   <none>        9400/TCP   54m
$ kubectl exec -it busybox-sleep -- sh
$ wget http://nvidia-dcgm-exporter.gpu-operator-resources:9400/metrics
$ cat metrics
----
DCGM_FI_DEV_SM_CLOCK{gpu="0",UUID="GPU-eeff7856-475a-2eb7-6408-48d023d9dd28",device="nvidia0",container="tf-notebook",namespace="default",pod="tf-notebook"} 405
DCGM_FI_DEV_MEM_CLOCK{gpu="0",UUID="GPU-eeff7856-475a-2eb7-6408-48d023d9dd28",device="nvidia0",container="tf-notebook",namespace="default",pod="tf-notebook"} 715
DCGM_FI_DEV_GPU_TEMP{gpu="0",UUID="GPU-eeff7856-475a-2eb7-6408-48d023d9dd28",device="nvidia0",container="tf-notebook",namespace="default",pod="tf-notebook"} 30
----

查看nvidia-dcgm-exporter暴露的svcep

$ kubectl describe svc nvidia-dcgm-exporter -n gpu-operator-resources
Name:                     nvidia-dcgm-exporter
Namespace:                gpu-operator-resources
Labels:                   app=nvidia-dcgm-exporter
Annotations:              prometheus.io/scrape: true
Selector:                 app=nvidia-dcgm-exporter
Type:                     NodePort
IP:                       10.233.28.200
Port:                     gpu-metrics  9400/TCP
TargetPort:               9400/TCP
NodePort:                 gpu-metrics  31129/TCP
Endpoints:                10.233.84.54:9400
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

配置ServiceMonitor定义清单:

$ cat custom/gpu-servicemonitor.yaml 
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: nvidia-dcgm-exporter
  namespace: gpu-operator-resources 
  labels:
     app: nvidia-dcgm-exporter
spec:
  jobLabel: nvidia-gpu
  endpoints:
  - port: gpu-metrics
    interval: 15s
  selector:
    matchLabels:
      app: nvidia-dcgm-exporter
  namespaceSelector:
    matchNames:
    - gpu-operator-resources
$ kubectl apply -f custom/gpu-servicemonitor.yaml

检查 GPU 指标是否被采集到(可选)

servicemonitor提交给kubesphere平台后,通过暴露prometheus-k8sNodePort,我们可以在PrometheusUI上验证一下是否采集到的相关指标:

创建 KubeSphere GPU 自定义监控面板

KubeSphere 3.0

如果部署的 KubeSphere 版本是KubeSphere 3.0,需要简单地配置以下几个步骤,便可顺利完成可观察性监控。

首先, 登录kubsphere console后,创建一个企业空间名称为ks-monitoring-demo, 名称可按需创建;

其次,需要将ServiceMonitor所在的目标名称空间gpu-operator-resources分配为已存在的企业空间中,以便纳入监控。

最后,进入目标企业空间,在纳管的项目找到gpu-operator-resources, 点击后找到可自定义监控界面, 即可添加自定义监控。

后续版本

后续版本可选择添加集群监控

创建自定义监控

下载dashboard以及配置namespace:

$ curl -LO https://raw.githubusercontent.com/kubesphere/monitoring-dashboard/master/contrib/gallery/nvidia-gpu-dcgm-exporter-dashboard.yaml
$ cat nvidia-gpu-dcgm-exporter-dashboard.yaml
----
apiVersion: monitoring.kubesphere.io/v1alpha1
kind: Dashboard
metadata:
  name: nvidia-dcgm-exporter-dashboard-rev1
  namespace: gpu-operator-resources  # check here
spec:
-----

可以直接命令行apply或者在自定义监控面板中选择编辑模式进行导入:

正确导入后:

在上面创建的jupyter notebook运行深度学习测试任务后,可以明显地观察到相关GPU指标变化:

卸载

$ helm list -n gpu-operator-resources
NAME            NAMESPACE               REVISION        UPDATED                                 STATUS          CHART                   APP VERSION
gpu-operator    gpu-operator-resources  1               2021-02-20 11:50:56.162559286 +0800 CST deployed        gpu-operator-1.5.2      1.5.2     
$ helm uninstall gpu-operator -n gpu-operator-resources

重启无法使用 GPU

关于已部署正常运行的gpu-operator和AI应用的集群,重启GPU主机后会出现没法用上 GPU 的情况,极有可能是因为插件还没加载,应用优先进行了载入,就会导致这种问题。这时,只需要优先保证插件运行正常,然后重新部署应用即可。

GPU-Operator 常见问题

GPU-Operator 重启后无法使用

答:关于已部署正常运行的gpu-operator和 AI 应用的集群,重启 GPU 主机后会出现没法用上 GPU 的情况,极有可能是因为插件还没加载,应用优先进行了载入,就会导致这种问题。这时,只需要优先保证插件运行正常,然后重新部署应用即可。

Nvidia k8s-device-plugin 与 GPU-Operator 方案对比?

我之前针对GPU使用的是 https://github.com/NVIDIA/k8s-device-plugin 和 https://github.com/NVIDIA/gpu-monitoring-tools 相结合的方案来监控 GPU,请问这个方案与 GPU-Operator的方案相比,孰优孰劣一些?

答:个人认为 GPU-Operator 更简单易用,其自带 GPU 注入能力不需要构建专用的 OS,并且支持节点发现与可插拔,能够自动化集成管理 GPU 所需的 NVIDIA 设备组件,相对来说还是很省事的。

有没有 KubeSphere 自定义监控的详细使用教程?

答:可以参考 KubeSphere 官方文档来使用自定义监控。

参考资料

官方代码仓库

官方文档

关于 KubeSphere

KubeSphere (https://kubesphere.io)是在 Kubernetes 之上构建的开源容器混合云,提供全栈的 IT 自动化运维的能力,简化企业的 DevOps 工作流。
KubeSphere 已被 Aqara 智能家居、本来生活、新浪、华夏银行、四川航空、国药集团、微众银行、紫金保险、中通、中国人保寿险、中国太平保险、中移金科、Radore、ZaloPay 等海内外数千家企业采用。KubeSphere 提供了开发者友好的向导式操作界面和丰富的企业级功能,包括多云与多集群管理、Kubernetes 资源管理、DevOps (CI/CD)、应用生命周期管理、微服务治理 (Service Mesh)、多租户管理、监控日志、告警通知、审计事件、存储与网络管理、GPU support 等功能,帮助企业快速构建一个强大和功能丰富的容器云平台。

GitHubhttps://github.com/kubesphere
官网(中国站)https://kubesphere.com.cn
微信群:请搜索添加群助手微信号 kubesphere

基于 WeDataSphere Prophecis 与 KubeSphere 构建云原生机器学习平台

KubeSphere阅读(3697)评论(0)

KubeSphere 开源社区的小伙伴们,大家好。我是微众银行大数据平台的工程师周可,接下来给大家分享的是基于 WeDataSphere 和 KubeSphere 这两个开源社区的产品去构建一个云原生机器学习平台 Prophecis。

Prophecis 是什么?

首先我介绍一下什么是 Prophecis (Prophecy In WeDataSphere)?它的中文含义就是预言的意思。

Prophecis 是微众银行大数据平台团队开发的一站式机器学习平台,我们是基于KubeSphere管理的这一套多租户的容器化的高性能计算平台之上,搭建了我们提供给数据科学和算法工程师,以及我们的IT运维去使用的机器学习平台。 在交互界面层,大家可以看到最上面我们是有面向普通用户的一套机器学习应用开发界面,以及面向我们运维管理员的一套管理界面,其中管理员的界面基本上就是基于 KubeSpehre 之上做了一些定制和开发;中间的服务层是我们机器学习平台的几个关键服务,主要为:

Prophecis Machine Learning Flow:机器学习分布式建模工具,具备单机和分布式模式模型训练能力,支持Tensorflow、Pytorch、XGBoost等多种机器学习框架,支持从机器学习建模到部署的完整Pipeline;
Prophecis MLLabis:机器学习开发探索工具,提供开发探索服务,是一款基于Jupyter Lab的在线IDE,同时支持GPU及Hadoop集群的机器学习建模任务,支持Python、R、Julia多种语言,集成Debug、TensorBoard多种插件;
Prophecis Model Factory:机器学习模型工厂,提供机器学习模型存储、模型部署测试、模型管理等服务;
Prophecis Data Factory:机器学习数据工厂,提供特征工程工具、数据标注工具和物料管理等服务;
Prophecis Application Factory:机器学习应用工厂,由微众银行大数据平台团队和AI部门联合共建,基于青云(QingCloud)开源的 KubeSphere 定制开发,提供 CI/CD 和 DevOps 工具,GPU 集群的监控及告警能力。
最底层的基础平台就是 KubeSphere 管理的高性能容器化计算平台。

我们去构建这样一套面向我们当前金融场景或者互联网场景的机器学习平台的时候,我们有两个考虑的点:

第一个点是一站式,就是工具要全,从整个机器学习应用开发的整体的Pipeline去提供一个完整的生态链工具给到用户去使用;

另外一个关注点是全联通,我们去做我们去做机学习应用开发的时候有一个很大的痛点,大家可能之前看到 Google 有一张图,可能 90% 的工作都是在做机器学习之外的工作,然后真正去做模型调参这些东西的时候,可能就 10% 的工作。

因为前面的数据处理其实是有很大工作量的。我们去做的一个工作就是,通过插件化接入的方式把我们的 Prophecis 的服务组件,跟我们 WeDataSphere 上面目前已经提供的调度系统 Schedulis、数据中间件 DataMap、计算中间件 Linkis、还有面向数据应用开发门户的 DataSphere Stduio 这一整套工具链进行打通,构建一个全联通的机器学习平台。

Prophecis 功能组件简介

接下来,简单介绍一下我们机器学习平台 Prophecis 的各个组件的功能。

第一个是我们目前已经放到开源社区的组件叫 MLLabis,其实跟 AWS 的提供给机器学习开发人员去用的 SageMaker Studio 差不多。

我们在 Jupyter Notebook 做了一些定制开发,总体的架构其实就是左上角的这张图,其实主要的核心有两个组件,一个是 Notebook Server (Restful Server),提供 Notebook 生命周期管理的各种API接口;另外一个是 Notebook Controller (Jupyter Notebook CRD),管理 Notebook 的状态。

用户创建 Notebook 的时候,他只需要选择有权限的命名空间 (Kubernetes Namespace),然后去设置 Notebook运行时需要的一些参数,比如说 CPU、内存、 GPU 或者是它要挂载的存储,如果一切正常,这个 Notebook 容器组就会在对应的 Namespace 启动并提供服务。

我们在这里做了一个比较加强的功能,就是提供一个叫 LinkisMagic 的组件。如果了解到我们的 WeDataSphere 开源产品的话,有个组件叫 Linkis,它提供大数据平台计算治理能力,打通各个底层的计算、存储组件,然后给到上层去构建数据应用。

我们的 LinkisMagic 通过调用 Linkis 的接口,就可以将 Jupyter Notebook 中写好的数据处理的代码提交到大数据平台上去执行;我们可以把处理好的特征数据通过 Linkis 的数据下载接口拉到 Notebook 的挂载存储中去,这样我们就可以在我们的容器平台里面用 GPU 去做一些加速的训练。 存储方面,目前 MLLabis 提供两种数据存储,一种是 Ceph;一种是我们的大数据平台 HDFS,关于 HDFS 这里提一句,我们其实就是把 HDFS Client 和 HDFS 的配置文件通过 Mount 到容器中,并且控制好权限,就可以在容器内跟 HDFS 交互了。

这是我们 MLLabis 的 Notebook 列表页面;

这是我们从列表页面进到 Notebook 的界面。

接下来,介绍我们另外一个组件 MLFlow。

我们构建了一个分布式的机器学习实验管理服务。它既可以管理单个建模任务,也可以通过跟我们 WeDataSphere 一站式数据开发门户 DataSphere Studio 打通,构建一个完整的机器学习实验。这里的实验任务通过 Job Controller (tf-operator、pytorch-operator、xgboost-operator 等)管理运行在容器平台上,也可以通过 Linkis 提及到数据平台运行。

这里再说明一下,MLFlow 与 DataSphere Studio 之间通过 AppJoint 的方式交互,这样既可以复用 DSS 已经提供的工作流管理能力,又可以将 MLFlow 实验作为子工作流接入到 DSS 这个大的数据工作流中去,这样构建一个从数据预处理到机器学习应用开发的 Pipeline。

这个是我们数据处理和机器学习实验组成的完成数据科学工作流。

这个是 MLFlow 的机器学习实验 DAG 界面,目前提供 GPU 和 CPU 两种任务类型,支持 TensorFlow、PyTorch、xgboost 等机器学习框架任务的单机和分布式执行。

接下来给大家介绍我们的机器学习模型工厂:Model Factory。我们模型建好之后,我们怎么去管理这些模型,它的模型的版本怎么管理,它的部署怎么管理,模型的校验怎么做,我们用的就是 Model Factory。

这个服务我们主要是基于 Seldon Core 进行二次开发,提供模型解释、模型存储、模型部署三块的能力。要强调的一点是这一块的服务接口我们也可以接入到 MLFlow 中去,作为一个 Node 接入到机器学习实验中,这样训练好的模型,可以通过界面配置快速部署,然后进行模型验证。 另外一个要说明的是,如果我们只是单模型的验证,我们主要是使用MF提供的基于 Helm 的部署能力。如果是构建一个复杂的生产可用的推理引擎,我们还是会用 KubeSphere提供的 CI/CD、微服务治理能力去构建和管理模型推理服务。

接着要介绍的组件是我们数据工厂 Data Factory。

我们这个数据工厂的话,我们通过数据发现服务从 Hive、MySQL、HBase、Kafka 等数据组件中获取基础的元数据,并提供数据预览和数据血缘分析能力,告诉我们数据科学和建模人员,他要使用的数据是长什么样子的,可以怎么用。未来也会提供一些数据标注的工具,或者是数据众包的工具,让我们的数据开发同学来完成数据标注的这块的工作。

最后一个要介绍的组件,就是机器学习应用工厂 Application Factory。

就是刚才说的,我们如果对一些复杂的模型去构建一些复杂的 Inference Sevice 的时候,其实我们用一个简单的单容器服务其实是不够的,我们要去构成一整套的类似于 DAG 的一个推理的过程,这个时候其实我们就需要更复杂的容器应用的管理的能力。

Application Factory 这一块我们就是基于 KubeSphere 去做的,我们在前面做好这些模型的准备之后,我们会使用 KubeSphere 提供的 CI/CD 工作流去完成整体的模型应用发布流程,模型服务上线之后,使用 KubeSphere 提供的各种 OPS 工具去运维和管理各个业务方的服务。

KubeSphere应用实践

接下来进入到 KubeSphere 在我们微众银行应用实践部分。

我们在引入 KubeSphere 之前,其实我们面对的问题,主要还是一些运维的问题。当时,我们内部也有用我们自己写的一些脚本或者是 Ansible Playbook 去管理我们这一套或者几套 K8s 集群,包括我们在公有云上面的开发测试集群,以及行内私有云的几套生产K8s集群。但是这一块的话,因为我们的运维人力有限,去管理这块东西的时候其实是非常复杂的;我们的建好的模型是面向银行业务使用,有的是跟风控相关的,对于整体服务的可用性的要求还是很高的,我们如何做好各个业务方的租户管理、资源使用管控、以及怎么去构成一个完整的监控体系,也是我们去需要重点关注的;还有就是本身 Kubernetes Dashboard 基本上没什么可以管理的能力,所以我们还是希望有一套好用的管理界面给了我们的运维人员,让他们的运维效率更高一些。

因此,我们构建这样一个基于 KubeSphere 为基础运维管理基座的机器学习容器平台。

整体的服务架构基本是跟 KubeSphere 当前的 API 架构差不多,用户的请求进来之后,它通过 API Gateway 定位要访问服务,这些服务就是刚才介绍那些组件,Gateway 将请求分发到对应的微服务当中去。各个服务依赖的那些容器平台的管理,就是 KubeSphere 这一套能力去给我们提供的能力:CI/CD、监控、日志管理,还有代码扫描工具等,然后我们在这一套解决方案之上做了一些改造点,但总体来说改造的东西也不是特别多,因为当前开源的 KubeSphere 提供的这些能力基本上能满足我们的需求。

我们内部使用的版本是 KubeSphere 的 v2.1.1,我们改造主要如下:

监控和告警:我们把 KubeSphere Notification 和我们行内的监控告警心态进行了打通,同时将容器实例的配置信息和我们的 CMDB 系统中管理的业务信息进行关联,这样某个容器出现异常就可以通过我们告警信息发出告警消息,并告诉我们影响的是哪个业务系统;

资源管理:我们在 KubeSphere Namespace 资源配额管理上做了一点小小的拓展,支持 Namespace 的 GPU 资源配额管理,可以限制各个租户可以用使用的基础 GPU 资源和最大 GPU 资源;

持久化存储:我们将容器的内的关键服务存储都挂载到我们行内的高可用的分布式存储 (Ceph) 和数据库 (MySQL) 上,保障数据存储的安全性和稳定性。

这是我们测试环境的一个管理界面。

然后这个是我们刚才说的,其实我们这一块的话做两个事情,一个事情是说我们把整个监控的对象跟我们行内的这一套 CMDB 系统进行一个结合。告警的时候,我们通过跟这套 CMDB 系统去做配置关联的,我们可以知道这一个告警实例它影响了的业务系统是哪些,然后一旦出现异常的时候,我们就会通过调用我们的告警系统,这里是一个企业微信的一个告警信息,当然它也可以发微信,也可以打电话,也可以发邮件。

以上这一块是我们做的 GPU 资源配额定制。

这一块是我们基于 KubeSphere 的日志查询界面。

接下来说下未来的展望,其实说到这里的话,我们当前因为我们人力非常有限,然后各个组件开发的压力也比较大,然后目前的话我们还是基于之前的 KubeSphere v2.1.1 的版本去做的,我们接下来的话会去考虑会把 KubeSphere 3.0 这块的东西去跟我们现有开发的一些能力做结合和适配。

第二,目前 KubeSphere还是没有 GPU 监控和统计指标管理的一些能力,我们也会考虑去把我们之前做的一些东西或者一些界面能力迁移到 KubeSphere Console 里面去。

最后一个是我们整个 WeDataSphere 各个的组件基于 KubeSphere 的容器化适配和改造,我们最终是希望各个组件都完成容器化,进一步降低运维管理成本和提升资源利用率。

关于 WeDataSphere
说到这里,我就简单再介绍一下我们微众银行大数据平台 WeDataSphere。

WeDataSphere 是我们大数据平台实现的一整套金融级的一站式机器学习大数据平台套件。它提供从数据应用开发、到中间件、在到底层的各个组件功能能力,还有包括我们的整个平台的运维管理门户、到我们的一些安全管控、还有运维支持的这块一整套的运营管控能力。

目前的话,这些组件当中没有置灰的这部分已经开源了,如果大家感兴趣的话可以关注一下。

再展望一下,我们 WeDataSpehre 跟 KubeSphere 的未来,目前我们两个社区已经官宣开源合作。

我们计划把我们 WeDataSphere 大数据平台这些组件全部能容器化,然后贡献到 KubeSpehre 应用商店中,帮助我们用户去快速和高效的完成我们这些组件与应用的生命周期管理、发布。

欢迎大家关注我们 Prophecis 这个开源项目以及我们 WeDataSphere 开源社区助手,如果大家对这套开源的云原生机器学习平台有任何问题,可以跟我们进一步交流,谢谢大家。

关于 KubeSphere

KubeSphere 是在 Kubernetes 之上构建的容器混合云,提供全栈的 IT 自动化运维的能力,简化企业的 DevOps 工作流。

KubeSphere 已被 Aqara 智能家居、本来生活、新浪、中国人保寿险、华夏银行、浦发硅谷银行、四川航空、国药集团、微众银行、紫金保险、Radore、ZaloPay 等海内外数千家企业采用。KubeSphere 提供了运维友好的向导式操作界面和丰富的企业级功能,包括多云与多集群管理、Kubernetes 资源管理、DevOps (CI/CD)、应用生命周期管理、微服务治理 (Service Mesh)、多租户管理、监控日志、告警通知、存储与网络管理、GPU support 等功能,帮助企业快速构建一个强大和功能丰富的容器云平台。

KubeSphere 官网:https://kubesphere.io/ KubeSphere

GitHub:https://github.com/kubesphere/kubesphere

Serverless 如何在阿里巴巴实现规模化落地?

alicloudnative阅读(1690)评论(0)

头图.jpg

作者 | 赵庆杰(卢令)

一、Serverless 规模化落地集团的成果

2020 年,我们在 Serverless 底层基建上做了非常大的升级,比如计算升级到了第四代神龙架构,存储上升级到了盘古 2.0,网络上进入了百 G 洛神网络,整体升级之后性能提升两倍;BaaS 层面也进行了很大的拓展,比如支持了 Event Bridge、Serverless Workflow,进一步提升了系统能力。

除此以外,我们还与集团内十几个 BU 进行了合作共建,帮助业务方落地 Serverless 产品,其中包含 双11 核心的应用场景,帮助其顺利通过 双11 流量峰值大考,证明了 Serverless 在核心的应用场景下,依然表现得非常稳定。

1.jpg

二、两大背景,两大优势 – 加速 Serverless 落地

1. Serverless 两大背景

为什么在集团内部能快速实现规模化地落地 Serverless?首先我们有两大前提背景:

第一个背景是上云,集团上云是重要的前提,只有上云才能享受到云上的弹性红利,如果还是自己内部的一朵云,后续的起效降本其实非常难达成,所以 2019 年双十一阿里实现了核心系统 100% 上云,有了上云前提,Serverless 才有了发挥非常作用的空间。

第二个背景是全面云原生化,打造了一个强大的云原生产品的云家族,对集团内部业务进行赋能,帮助业务达成了在上云基础上的两个主要目标:提高效能和降低成本, 2020 年天猫双十一核心系统全面云原生化,效率提升 100%,成本降低 80%。

2. Serverless 两大优势

  • 提高效能

2.jpg

一个标准的云原生应用,从研发到上线到运维,需要完成上图中所有标橙色的工作项,才能完成正式的微服务应用上线,首先是 CI/CD 代码构建,另外是系统运维的可视化工作项目,不仅要配置、对接,还需对整体数据链路进行流量评估、安全评估、流量管理等,这显然对人力门槛要求已经非常高。除此以外,为了提升资源利用率,我们还需要对各个业务进行混部,门槛会进一步的提高。

可以看出,整体的云原生传统应用,要实现微服务上线所需要完成的工作项,对于开发者来说非常艰难,需要由多个角色进行完成,但是如果到 Serverless 时代,开发者只要完成上图中标蓝色的框 coding,后续剩下的所有工作项,Serverless 的研发平台可以直接帮助业务完成上线。

  • 降低成本

提高效能主要指的是人力成本的节省,而降低成本则针对的是应用的资源利用率。普通应用我们需要为峰值预留资源,但波谷就会造成极大浪费。在 Serverless 场景下,我们只需要按需付费,拒绝为峰值预留资源,这是 Serverless 降低成本的最大优势。

3.jpg

以上两大背景和两大优势,符合技术上云的趋势,所以集团内部的业务方一拍即合,一些大的 BU 已经把 Serverless 落地升级为战役层面,加速业务落地的 Serverless 场景。目前在集团落地的 Serverless 场景已经非常丰富,涉及到了核心的一些应用、个性化推荐、视频处理,还有 AI 推理、业务巡检等等。

三、Serverless 落地场景 – 前端轻应用

目前,集团内前端场景是应用 Serverless 最快、最广的场景,包含淘系、高德、飞猪、优酷、闲鱼等 10+ 以上 BU。那为什么前端场景适合 Serverless 呢?

4.jpg

上图是全栈工程师的能力模型图,一般的微应用中需要有三个角色:前端工程师、后端开发工程师,运维工程师,三者共同完成应用的上线发布。为了提高效能,最近几年出现了全栈工程师的角色,作为全栈工程师,他要具备这三个角色的能力,不仅需要前端的应用开发技术,还需要后端系统层面的开发技能,并且要关注底层的内核、系统资源管理等,这对于前端工程师来说门槛显然非常高。

最近几年 Node.js 技术兴起,能够替代后端开发工程师角色,前端工程师只要具备前端开发能力,就可以充当两个角色,即前端工程师和后端开发工程师,但运维工程师仍然无法被取代。

而 Serverless 平台,解决的就是上图三角形结构中的底部三层,极大降低了前端工程师转变为全栈工程师的门槛,这对前端业务开发者来说非常有诱惑力。

5.jpg

另外一个原因是业务特性符合,大部分的前端应用具有流量洪峰的特性,需要业务评估前置,存在评估成本;同时前端场景更新迭代快,快上快下,运维成本高;且缺乏动态扩缩能力,存在资源碎片及资源浪费。而如果使用 Serverless,平台会自动帮你解决以上所有的后顾之忧,所以 Serverless 对前端场景的诱惑力非常大。

1. 前端落地场景

6.png

上图列举了前端落地的几个主要场景和技术点:

BFF 转换成 SFF 层:BFF 主要是 Backend For Frontend,前端工程师做主要运维,但到了 Serverless 时代,运维完全交于 Serverless 平台,前端工程师只需要写业务代码,就可以完成这项工作。

瘦身:把前端的业务逻辑下沉到 SFF 层,由 SFF 层去做逻辑的复用,把运维的能力也交给 Serverless 平台,实现客户端轻量化,提效功能下沉。

云端一体化:一处代码多端应用,这是非常流行的开发框架,同样需要 SFF 作为支撑。

CSR/SSR:通过 Serverless 满足服务端渲染、客户端渲染等,来实现前端首屏的快速展现,Serverless 结合 CDN 整体可以作为前端加速的解决方案。

NoCode:相当于在 Serverless 平台上做了封装,只需拖拽几个组件,就可以搭建一个前端页面,每个组件都可以用 Serverless 进行包装、功能聚合等,达到 NoCode 的效果。

中后台场景:主要是单体的富应用场景,单体应用可以完全用 Serverless 模式进行托管,完成中后台应用上线,这同样也可以节省运维能力、减少成本。

2. 前端 Coding 变化

在前端场景应用 Serverless 之后,coding 有哪些变化呢?

7.jpg

对前端有一定了解的都知道,前端一般分三层:State、View 和 Logic Engine,同时会把一些抽象的业务逻辑下沉到 FaaS 层云函数上,然后用云函数作为 FaaS API 来提供服务,在代码编写上可以抽象各类 Aaction,每个 Aaction 可以有 FaaS 函数 API 提供服务。

8.jpg

以一个简单的页面为例,页面左侧是一些渲染接口,可以获取商品详情、收货地址等,这是基于 Faas API 实现的;右侧的是一些交互逻辑,比如购买、添加等,这也是 Faas API 可以继续完成的任务。

页面设计中,所有的 Faas API 不是只能为一个页面所使用,它可以为多个页面复用。复用这些 API 或者进行拖拽之后,就可以完成前端页面的组装,这对于前端来说是非常方便的。

3. 前端轻应用研发提效:1-5-10

9.jpg

在前端应用 Serverless 之后,我们把 Serverless 对前端的研发效能的提效简单总结为 1-5-10,其含义是:

1 分钟的快速开始:我们把各类主要场景做一个总结,将其归类为应用模板,每个用户或者业务方新起一个业务时,只需要选择相应的应用启动模板,就会帮助用户快速生成业务代码,用户只需要写自己的业务函数代码就可以快速开始。

5 分钟上线应用:完全复用 Serverless 的运维平台,利用平台天然能力,帮助用户完成灰度发布等能力;并且配合前端网关、切流等完成金丝雀测试等功能。

10 分钟排查问题:基于上线之后的 Serverless 函数,提供业务指标或系统指标的展示,通过指标不仅可以设置报警,还可以在控制台上给用户推送错误日志等,帮助用户快速定位问题、分析问题,10 分钟内掌握整个 Serverless 函数的健康状态。

4. 前端落地 Serverless 效果

前端实现 Serverless 的场景后效果如何?我们将 3 款 APP 在传统应用研发模式下所需要的性能和工时与应用 Faas 场景之后进行对比,可以明显看到,在原有的云原生基础上,效能还能提升 38.89%,这对于 Serverless 应用或前端应用来说效果非常可观,目前 Serverless 场景已经几乎覆盖整个集团内部,帮助业务方实现 Serverless 化,实现提高效能降低成本两个主要目标。

四、技术输出,拓展新场景

在集团的 Serverless 落地过程中,我们发现了很多新的业务诉求,比如存量业务如何快速实现迁移并节省成本?执行时间是否可以调大或者调长?资源配置是否可以调高?等等,针对这些问题我们提出了一些解决方案,基于这些解决方案我们抽象出了产品的一些功能,接下来介绍几个比较重要的功能:

1. 自定义镜像

10.jpg

自定义镜像主要目的是实现存量业务的无缝迁移,帮助用户实现零代码改造,并且把业务代码完全迁移到 Serverless 平台上。

存量业务的迁移是非常大的痛点,在一个团队内,不可能长期存在两种研发模式,这会造成极大内耗。想让业务方迁移到 Serverless 研发体系下,必须推出彻底的改造方案,帮助用户实现 Serverless 体系改造,不仅需要支持新业务使用 Serverless,还要帮助存量业务实现零成本快速迁移,所以我们推出了自定义容器功能。

11.jpg

传统 Web 单体应用场景特性

  • 应用现代化细粒度责任拆分、服务治理等运维负担;
  • 历史包袱不易 Serverless 化:云上云下业务代码,依赖、配置不统一;
  • 容量规划,自建运维、监控体系;
  • 资源利用率低 (低流量服务独占资源)。

函数计算 + 容器镜像优势

  • 低成本迁移单体应用;
  • 免运维;
  • 无需容量规划,自动伸缩;
  • 100% 资源利用率,优化闲置成本。

自定义容器功能,可以让传统 Web 单体应用(比如 SpringBoot、Wordpress、Flask、Express、Rails 等框架)不需任何改造,就可以以镜像的方式迁移到函数计算上,避免低流量业务独占服务器造成资源浪费。同时也可以享受到无需为应用做容量规划、自动伸缩、免运费等效益。

2. 性能实例

12.jpg

高性能实例,减少使用限制,拓展更多场景。比如:代码包从原来的 50M 上升到 500M,执行时间从原来的 10 分钟提高到 2 小时,性能规格比原先提升 4 倍多,能够最大支持 16G 和 32G 的大规格实例,来帮助用户运行一些非常耗时的长任务等等。

13.jpg

函数计算服务了很多场景,在服务过程中我们收到了很多诉求,比如约束条件多、使用门槛高、计算场景资源不足等问题。所以针对这些场景,我们推出了性能实例功能,目标是减少函数计算应用场景的使用限制,降低使用门槛,并且在执行时长上、各种指标上,用户可以灵活配置、按需配置。

目前我们支持的 16 核 32G 完全具备与同规格 ECS 一模一样的计算能力,可以适用于高性能的业务场景如 AI 推理、音视频转码等。这个功能对后续拓展应用场景来说非常重要。

挑战

  • 弹性实例约束条件多,有一定使用门槛,如执行时长、实例规格等;
  • 传统单体应用、音视频等重计算场景下,业务需要拆分改造,增加负担;
  • vCPU、内存、带宽等资源维度,弹性实例未给出明确承诺。

目标

  • 减小函数计算的使用限制,降低企业使用门槛;
  • 兼容传统应用和重计算场景;
  • 给用户明确的资源承诺。

做法

  • 推出更高规格、资源承诺更明确的性能实例;
  • 未来,性能实例将具备更高的稳定性 SLA、更丰富的功能配置。

主打场景
计算型任务、long-running 任务、弹性伸缩不敏感任务。

  • 音视频转码处理;
  • AI 推理;
  • 其它需求高规格的计算场景。

优势

性能实例除放宽限制外,仍保留当前函数计算产品所具备的所有能力:按量付费、预留模式、单实例多请求、多种事件源集成、多可用区容灾、自动伸缩、应用的构建部署及免运维等。

3. 链路追踪

14.jpg

链路追踪功能包括:链路还原、拓扑分析、问题定位。

一个正常的微服务,不是一个函数就能完成所有工作,需要依赖上下游服务。在上下游业务都是正常的情况下,一般不需要链路追踪,但是如果下游服务出现了异常,如何定位问题?这时就可以依赖链路追踪功能,迅速分析上下游的性能瓶颈或者定位问题的发生点等。

函数计算也调研了很多集团内外的开源技术方案,目前已经支持 X-trace 功能,并且兼容了开源方案,拥抱开源,提供了兼容 OpenTracing 的产品能力。

15.jpg
16.jpg

上图是链路追踪的 Demo 图,通过计算 tracing 可以可视化看到后端服务的数据库访问开销,避免大量服务间的复杂校验关系增加问题排查的难度等。函数计算还支持函数代码级的链路分析能力,帮助用户优化冷启动、关键代码实现等。

Serverless 产品在业务角度上带来了巨大收益,但是封装也带来了一个阶段性难题——黑盒问题。当我们向用户提供链路追踪技术,同时也把黑盒问题暴露给用户,用户也可以通过这些黑盒问题提升自身的业务能力。这也是 Serverless 未来提高用户体验的方向,后续我们会在这方面继续加大投入,降低用户使用 Serverless 的成本。

挑战

  • Serverless 产品在业务角度有巨大收益,但封装带来黑盒问题;
  • Serverless 连接云生态,大量的云服务造成调用关系复杂;
  • Serverless 开发者依然有链路还原、拓扑分析、问题定位等需求。

FC + x-trace 主要优势

  • 函数代码级链路分析,帮助优化冷启动等关键代码实现;
  • 服务调用级链路追踪,帮助串联云生态服务,分布式链路分析。

4. 异步配置

17.jpg

在 Serverless 场景下,我们提供了离线任务处理、消息对立消费等功能,在函数计算中这类功能的使用率占比 50% 左右。在大量消息消费中,存在很多异步配置问题经常被业务方挑战,比如,这些消息是从哪里来?又去到哪里?被什么服务消费?消费的时间?消费的成功率如何?等等。这些问题的可视化/可配置,是目前需要主要解决的重要课题。

18.jpg

上图为异步配置的工作原理,首先从用户指定的事件源开始触发异步调用,函数计算立即返回请求 ID,同时也可以调用执行函数,返回执行结果到函数计算或者消息队列 MNS 里面。然后通过事件源可配置触发器等等,这些效果或者主题消费,可以进行消息的再次消费。比如,如果一个消息处理失败了,可以配置一下进行二次处理。

19.jpg

典型的应用场景

  • 一是事件闭环,比如对投递结果(如收集监控指标、报警配置)进行结果分析;生产事件上客户不仅可以利用 FC 消费事件,也可以利用 FC 主动生产事件。
  • 二是日常的异常处理,比如失败处理、重试策略等。
  • 三是资源回收,用户可以自定义存货时间,及时丢弃无用消息,节省资源,这是异步场景非常大的优化。

作者简介
赵庆杰(卢令),目前就职于阿里云云原生 Serverless 团队,专注于 Serverless 、PaaS,分布式系统架构等方向,致力于打造新一代的 Serverless 技术平台,把平台技术做到更加普惠。曾就职于百度,负责内部最大的 PaaS 平台,承接了 80% 的在线业务,在 PaaS 方向,后端分布式系统架构等领域有丰富的经验。

本文整理自【Serverless Live 系列直播】1 月 26 日场
直播回看链接:https://developer.aliyun.com/topic/serverless/practices

开源微服务运行时 Dapr 发布 1.0 版本

alicloudnative阅读(2025)评论(0)

1.png

作者 | Dapr 社区
译者 | 敖小剑
来源|阿里巴巴云原生公众号

Dapr 是 2019 年 10 月开源的分布式运行时。早在 Dapr 开源初期,阿里云就开始参与 Dapr 社区建设和代码开发,目前已有两位 Dapr 成员,是 Dapr 项目中除微软之外代码贡献最多的公司。作为 Dapr 项目的早期采用者,阿里在 Dapr v1.0 发布之前就在内部小规模的试点。本文由 Dapr 社区成员敖小剑翻译。

分布式应用程序运行时现在已经生产就绪啦!

今天,我们很高兴地发布分布式应用运行时(Distributed APplication Runtime / Dapr)的 v1.0 版本,它已经达到了生产就绪所需的稳定性和企业准备。Dapr 是一个开源、可移植、事件驱动的运行时,它使开发人员能够轻松地构建运行在云平台和边缘的弹性而微服务化的应用程序,无论是无状态还是有状态。Dapr 让开发人员能够专注于编写业务逻辑,而不是解决分布式系统的挑战,从而显著提高生产力并减少开发时间。Dapr 降低了基于微服务架构构建现代云原生应用的准入门槛,而通过此次发布的 v1.0 版本,Dapr 应用可以部署到生产场景中的自托管基础设施或 Kubernetes 集群。

自 2019 年 10 月首次发布 以来,Dapr 已有 14 个版本,每个版本都建立在大量的社区和用户反馈基础上,以推动改进、稳定性和性能。这些版本立足于构建真实的应用,反映了当今开发者在开发云原生应用时的实际情况;无论是在云平台、边缘还是私有基础设施上,社区都在加紧贡献与 Azure、AWS、阿里巴巴和 Google cloud 集成的 Dapr 组件。

解决现实世界场景中的分布式应用挑战

从成立之初开始,Dapr 开源项目就面向那些正在构建新的现实世界绿色地带(greenfield)应用的开发者,以及那些在云原生架构中迁移和利用现有应用和组件的开发者。Dapr 方法的关键是满足开发者和企业的现状,帮助他们实现应用的现代化,并利用他们在云原生和微服务架构中的现有技能。在 v1.0 版本中,我们专注于将 Kubernetes 作为运行生产应用的主要托管环境,随着 Dapr 的进一步成熟,我们希望在无服务器(serverless)环境中看到 Dapr。在过去的一年半时间中,我们与早期采用者和合作伙伴紧密合作,因此 Dapr 现在已经成为多个基于 Kubernetes 的生产和预生产应用的核心。在这个用户驱动的过程中,Dapr 社区改进了 Java、.NET 和 Python SDK 的原生语言体验,用真实的工作负载测试了规模和性能,增加了安全特性,并证明了 Dapr 的 Actor 编程模型是工作流和物联网(IoT)场景的最佳选择。以下是一些早期采用者的故事,以凸显 Dapr 如今的使用情况。

蔡司:光学和光电子领域的国际技术领导者

ZEISS 面临的挑战是维护和更新一个具有 20 年历史的带有硬编码业务规则的后端系统。原来的订单验证和路由解决方案是基于一个具有固定容量的单体架构,开发人员在不直接在系统中重新配置表格的情况下,无法轻松的更新、重新路由或跟踪订单。此外,业务部门无法直接控制其订单处理流程。由于存在大量的系统依赖,变更总是需要代价高昂而耗时的开发人员干预。为了解决这个问题,ZEISS 使用 Azure 和 Dapr 开发了一个新的应用程序,可以更快地完成客户订单,同时还加快了开发速度,并改善了公司的业务连续性。你可以在 这里 阅读更多关于他们的故事。

2.png

Ignition Group:一家位于南非的技术企业,专注于客户承诺和销售支持工具

Ignition Group 打造的订单处理软件可以跟踪产品、管理订阅和处理来自各种来源的支付。订单处理涉及许多依赖,有一个采购跟踪机制,这个机制会调用客户订阅,触发会计和计费流程,并确定适当的支付渠道。Ignition Group 希望微服务能给其工作流逻辑带来好处——高可用性、弹性、可扩展性和性能。使用 Dapr 和 .NET Core,Ignition Group 构建了一个新的、可扩展性更好的、可维护的订单处理和支付系统,该系统目前已在生产中运行。Ignition Group 今天已经运行在生产中,你可以在 这里 阅读更多关于他们的故事。

Roadwork:采集数据洞若观火

Roadwork 是一家为自主系统提供端到端平台的初创公司,让用户产生可执行的洞察力并据此行动。目前,他们专注于数据提取技术,并以全面集成自主系统为路径。通过对 Dapr 与 KEDA 的梳理,他们在 Kubernetes 上创建了一个生产服务,根据传入的客户负载请求,自动扩展应用和集群。Dapr 提供了使用 RabbitMQ 的 pub/sub 的抽象和集成,其能够轻松拥有 竞争消费者模式。今天,Roadwork 的第一个产品 Scraper.ai 已经在生产中运行。在 这里 了解更多信息。

社区和生态系统

是社区的努力让 Dapr 成长到 v1.0。自 Dapr 首次公布以来,开源社区团结在 Dapr 周围并不断成长,令人惊叹——从 2019 年 10 月的 114 个贡献者增长到今天的 700 个。在短短的 16 个月内,增长了 6 倍多!

社区对项目的贡献涉及到 Dapr 的每一个仓库,范围包括提交问题、参与功能提案讨论、提供样本,当然也包括贡献代码。社区成员对项目贡献最大的部分包括 Dapr 运行时、文档、CLI 和 SDK。另外一个关键的贡献领域是创建了一个丰富的组件生态系统。可供开发人员使用的组件超过 70 个,使 Dapr 成为一个可以适用于广泛场景的解决方案,包括开源技术和云提供商的特定集成。当开发人员希望创建具有高可移植性的云平台无关的应用程序时,这些使得 Dapr 成为一个有吸引力的选择。

贡献并不局限于个人,还包括阿里云、HashiCorp、微软等组织,以及上文提到的 ZEISS 和 Ignition Group 等早期采用者。Dapr 生态系统还包括合作伙伴的技术栈,这些技术栈为使用 Dapr 的开发者提供了附加值。例如,New Relic 提供了关于他们的监控工具如何与 Dapr 无缝工作的指导,这要归功于 Dapr 使用的标准跟踪协议,这些协议可以在不改变任何代码的情况下轻松地检测您的应用程序。

培养一个开放和包容的社区是 Dapr 项目的首要目标。作为该承诺的一部分,我们分享了 向开放治理模式的过渡,这也是我们保持 Dapr 开放、供应商中立和包容性的方式。我们的愿景是继续这一旅程,并打算在不久的将来让 Dapr 加入一个开放软件基金会。同时,我们邀请您通过 GitHub、Dapr 社区定期会议 和最近推出的 Discord 服务器 与 Dapr 社区互动。

“在阿里云,我们相信 Dapr 将引领微服务的发展。通过采用 Dapr,我们的客户现在可以以更快的速度来构建可移植和健壮的分布式系统。”—— 阿里云资深技术专家 李响

发布亮点

在最近的几个月中,我们已经发布了三个 v1.0 版本的候选版本,专注于从社区获得反馈,并为 v1.0 版本做准备。在性能、安全、高可用性(HA)和一致性等方面更深入地关注于生产就绪。完整的发布说明可以在 这里 获得,以下是一些亮点:

作为生产环境的 Kubernetes

对于 v1.0 版本,Kubernetes 是首选的托管环境,它与 Dapr 控制平面和 Dapr sidecar架构深度集成。例如,在运维上,通过 Dapr CLI “init” 和 “upgrade” 命令简化了 Dapr 在 Kubernetes 上的安装和升级,这些命令可以拉取正确的 Dapr 运行时版本,并确保这些版本以受控的方式推出,包括迁移正在使用中的证书。您可以在 HA 模式下安装 Dapr 控制平面,确保多个实例同时运行,而且 Dapr sidecar 有一个健康端点,可以实现 Kubernetes 就绪(readiness)和活泼度(liveness)探针以确定其健康状态。在整个发布候选版本的过程中,我们与早期采用者密切合作,以确保他们能够以可运维的方式迁移到每个 Dapr 运行时版本,而不是构建新的集群。请参阅 生产部署指南 以了解更多信息。

性能、一致性和支持

在云原生应用中,性能是至关重要的,而 Dapr 对高性能非常重视。一个经常被提起的话题是,由 sidecar 模型为应用程序完成所有繁重工作所带来的影响,以及数据平面性能的权衡取舍。其中一个特别关注的领域是服务调用构建块,在这里,当通过两个 Dapr sidecar 在两个应用之间调用并收到响应时,Dapr 在 p90 时增加了约 1.2ms 的端到端延迟,在 p99 时增加了约 2ms。由此可见,Dapr 具有极低的服务间延迟,并针对高吞吐量场景进行了优化。

Dapr 有超过 70 个由社区开发的组件,为了确保对这些组件的使用信心,它们要经过一系列的一致性测试。组件首先从 alpha 状态开始,最终达到 GA 状态,并需要用户在生产中使用它们。对于 v1.0 版本,只有部分已经在生产中广泛使用的组件被批准为 GA,其他组件在满足标准后也将加入其中。与众多开源云原生技术一样,变更、修复和改进的引入速度很快,这意味着受支持版本存在滚动窗口。重要的是,Dapr v1.0 版本宣称 API 层面是稳定的,如果未来需要修改,将通过 版本机制 来保证 API 的完全向后兼容,如果需要破坏性的修改,则会提前几个版本注明。最后,从支持的角度来看,当前和之前的版本都将支持 在出现关键问题或安全问题时进行补丁更新。

安全

安全一直是 Dapr 的核心主题,因为我们已经认识到基于微服务架构构建安全的现代分布式应用的复杂性,而 Dapr 已经通过了多项独立的安全审计。为了抵御应用程序之间的中间人攻击,您需要进行加密,而 Dapr 通过其控制平面服务发出的 x.509 证书提供加密,这些证书会自动更新和滚动。为了提供对资源的访问控制,如状态存储、密钥、服务间调用,或发布/订阅特定主题的能力,您需要细粒度的访问控制策略(ACL)。当使用 spiffe 作为身份标准访问资源时,Dapr 提供了广泛的 ACL。当运行应用程序时,您可以将这些应用程序隔离在不同的命名空间中,以便进行运维部署和隔离。这些广泛的安全能力在下图中显示,这里有三个利用 Dapr 安全特性的微服务:

3.png

编程语言和 SDK

Dapr 以其编程语言、框架和工具拥抱所有的开发者社区。Dapr 被设计为可以通过 HTTP 和 gRPC 协议从任何编程语言中使用,这意味着您不需要在编译时包含任何依赖关系。当然,为了改善开发者的原生语言体验,Java、.NET、Python 和 Go 的 SDK 也以 v1.0 生产就绪的形式发布,这反映了它们在社区和组织中的成熟应用。这些 SDK 可以让您作为开发者,使用您最喜欢的开发环境,如 VS Code 或 IntelliJ。JavaScript/Node.js、C++、Rust 和 PHP 的 SDK 目前处于预览阶段,随后将发布 v1.0 版本。PHP SDK 包括对 Actor 的支持,这是社区为 Dapr 广泛且不断增长的编程语言列表做出贡献的一个极佳的例子。

4.png

展望未来

通过这个 v1.0 版本,我们为构建现代云原生应用所需的基本构建块奠定基础的旅程才刚刚起步。社区驱动意味着社区将在未来的版本中设定项目的优先级,其中许多优先级已经被投票通过。例如,增强现有构建块的亮点,包括在状态管理中使用 OData 查询和过滤多个值的能力。在 pub/sub 中,支持 CloudEvents v1.0 过滤功能,以根据消息内容过滤出用户感兴趣的事件。在可观测性方面,提供一个 API 用于 从应用中追踪事件,防止您不得不绑定到特定的监控类库,并使 actor 能够直接订阅 pub/sub 事件,从而开启了丰富的事件驱动场景。

新的构建块提案包括用于读写应用程序配置数据的配置 API,例如来自 Azure Configuration Manager 或 GCP Configuration Management。领导者选举构建块,提供创建单例实例、同步或锁定语义能力。用于网络级服务调用的透明代理构建块,使您能够根据 URL 或 DNS 地址来路由消息,以及用于熔断器、隔离舱和超时等模式的更多弹性构建块。

最后,在 v1.0 版本中,Dapr 集成了多个开发者框架,包括 ASP.NET Core、Java Spring Boot、Azure Functions 和 Logic Apps,而我们认为这还将继续,更多的开源框架如 Django、Nodejs 和 Kyma 都是潜在的例子。此外,考虑到 Dapr 的托管平台独立性,在虚拟机、边缘平台(如 Azure Stack Hub 或 AWS Outpost)和其他分布式系统平台上提供对 Dapr 控制平面一流的支持,可以实现应用的可移植性。

开始和贡献

我们希望您能试用 Dapr v1.0。您可以使用文档中的 入门指南 进行学习,然后通过 快速入门 来深入了解。如果你需要更多信息,样本库 是 Dapr 社区捐赠的不同的应用程序的展示。Dapr 文档 docs.dapr.io 是全面的指南,还有几本书,包括《 Learning Dapr》《使用 Dapr 和 .NET 实践微服务》以及最新发布的免费电子书《Dapr for .NET 开发者》。如果您有任何疑问,遇到问题或想与社区的其他成员交流,Dapr 社区随时在 Discord 上欢迎您的到来。

对于 Dapr 来说,v1.0 版本的发布只是一个开始,在这个过程中,我们感谢并鼓励您的持续帮助、反馈和贡献。无论是编写新的组件,提出建议,贡献新的构建块,还是增强您最喜欢的语言的 SDK,我们都希望听到您的意见并与您一起参与。在这个微服务开发的时代,作为一名开发者,这是一个令人兴奋的时刻,Dapr 将释放您的生产力和创造力,轻松构建现代化的分布式应用。我们非常高兴的看到您继续使用这个项目,看到您使用它进行构建,并对 Dapr 的发展保持关注。

译者注

  1. 英文原文来自 Dapr 官方网站博客文章 Announcing Dapr v1.0
  2. 译者所在的阿里云云原生团队深度参与了 Dapr 1.0 的开发,同时也正在内部小规模的试点 Dapr ,稍后将分享阿里云在 Dapr 上的实践。
  3. 文中提到的 《 Learning Dapr》 一书,译者所在的团队正在翻译中,预计很快就将出版发行,欢迎关注。
  4. Dapr 中文社区 目前正在组织翻译 Dapr 的官方文档,预计不久将完成部分章节并在官方上线,同样欢迎关注,更欢迎一起参与。

译者简介

敖小剑,资深码农,十九年软件开发经验,微服务专家,Service Mesh 布道师,Servicemesher 社区联合创始人。专注于基础架构,Cloud Native 拥护者,敏捷实践者,坚守开发一线打磨匠艺的架构师。曾在亚信、爱立信、唯品会、蚂蚁金服等任职,对基础架构和微服务有过深入研究和实践。目前就职于阿里云云原生应用平台从事 Service Mesh、Serverless、Multiple Runtime 等云原生产品设计和开发。

Rainbond 5.3.0 发布,从 Kubernetes 到云原生应用管理

好雨云阅读(1462)评论(0)

2021新年开工,Rainbond迎来了重量级版本5.3发布,我们在云原生应用的治理、观测方面进一步耕耘,为社区用户带来了更多开箱即用的能力。为了进一步降低新用户安装和多集群部署的门槛,我们重新实现了产品安装流程,支持UI化对接公有云资源和自建基础设施。同时在应用交付、应用运维和平台管理方面做了大量的优化改进。

Rainbond 是云原生且易用的云原生应用管理平台。云原生应用交付的最佳实践,简单易用。专注于以应用为中心的理念。赋能企业搭建云原生开发云、云原生交付云。

对于企业: Rainbond 是开箱即用的云原生平台,借助 Rainbond 可以快速完成企业研发和交付体系的云原生转型。

对于开发者: 基于 Rainbond 开发、测试和运维企业业务应用,开箱即用地获得全方位的云原生技术能力。包括但不仅限于持续集成、服务治理、架构支撑、多维度应用观测、流量管理。

对于项目交付: 基于 Rainbond 搭建产品版本化管理体系,搭建标准化客户交付环境,使传统的交付流程可以自动化、简单化和可管理。

重要新特性

支持云原生应用治理模式切换

应用治理模式切换是指可以无侵入地变更应用下组件间通信治理模式,过去的版本中Rainbond默认为内置的ServiceMesh模式。 Rainbond 致力于无侵入,松耦合的应用管理理念。松耦合体现在多个方面,应用治理模式可切换就是其中之一。

  • 服务间松耦合

对于微服务的核心理念是,系统中的各个服务可被独立开发、独立部署,独立升级,各个服务之间是松耦合的。云原生应用架构理念是进一步强调架构的松耦合,降低服务之间相互依赖的程度。Rainbond 开箱即用的服务治理思想使部署到平台的应用天然形成微服务架构。

  • 应用和运行环境松耦合

应用研发、打包独立化、标准化,通过标准化的平台实现交付到任何运行环境中。Rainbond 提供了应用模型开发、发布、分享、安装全链路支持,服务于应用交付场景。

  • 服务治理能力与业务逻辑解耦

这是我们新版本的重点,我们引入了应用级治理模式切换功能,实现服务治理能力可动态切换,无需业务逻辑变更,为业务提供不同的治理能力。当前版本我们支持在内置 ServiceMesh 治理模式和 Kubernetes 原生模式直接切换。有了这套体系,未来的版本中将实现用户自定义治理模式,引入 Istio、Linkd 等成熟的 ServiceMesh 框架。

详细使用说明参考文档 应用治理模式切换

image-20210221143301916

支持组件自定义业务监控和可视化

Rainbond 希望提供给开发者对应用全方位的监控能力。过去的版本中已经包括资源监控、性能分析、状态检测等维度。本次更新,提供给开发者在业务维度自定义监控及可视化的能力。Prometheus 已经成功云原生监控领域的事实规范,Rainbond 支持开发者基于 Prometheus 规范定义业务监控指标,通过配置监控点后由 Rainbond 自动发现并收集监控数据,并提供给用户进行历史数据查询和可视化。用户可以借助插件安装社区已有的 Exporter 插件,便捷的扩展业务监控能力。在自定义可视化面板中用户可以绘制关于应用资源占用、业务性能、网关流量全方位的观察指标图形。

详细使用说明参考文档 业务自定义监控

全新的控制台和集群安装方式

为了进一步降低用户的使用 Rainbond 的门槛,在 5.3 版本中我们将控制台的安装运维和集群端的安装运维解耦合。用户仅需一条 Docker run 命令即可再任意有 Docker 环境中将 Rainbond 控制台运行起来。在集群安装维度,新增了阿里云 ACK集群、对接已有 Kubernetes 集群、从主机便捷安装集群等多种途径,帮助用户快速完成资源池化。开箱即用的能力可以帮助用户在云端或私有设施中快速的搭建Kubernetes集群。

详细使用说明参考文档 快速安装

应用配置组

云原生应用推荐使用环境变量进行配置管理。因此我们经常需要在同一个应用的多个组件中添加相同的配置。比如一个应用下有多个组件使用同一个 Oracle 数据库,我们通过环境变量来配置 Oracle 数据库的连接信息。管理和配置需要做很多重复的事。借助应用配置组即可将配置信息在应用级统一管理,批量更改生效,大大降低开发者的操作次数。

详细使用参考文档 应用配置组

其他新特性和变化

  • 应用组件库支持应用模型的版本管理和详情设置。

  • 应用模型离线导出规范改进,导出文件大小显著降低(向下不兼容)。

  • 应用模版离线导入改进,支持并行导入多个应用模型。

  • 支持控制台数据备份和迁移。

  • 改进 Oauth2.0 支持,现已支持 Github,Gitlab,Gitee,钉钉,阿里云等第三方Oauth认证。

  • 应用网关新增支持会话保持负载均衡算法,对无法实现完全无状态化的应用可实现水平扩容。

  • 团队视图应用列表排序改进,基于应用操作活跃情况进行排序,便于开发者快速定位操作的应用。

  • 新增应用维度资源占用情况数据统计和展示,应用整体状况更容易掌握。

  • 应用发布流程改进,支持发布时灵活编辑发布的组件数量,移除了安装的组件不能发布的限制。

  • 应用升级体系增加了对插件、配置组等属性的支持。

  • 支持 Java Maven 配置管理,移除了maven.goodrain.me的支持,默认采用阿里云Maven源,用户可自定义配置。

  • 移除 rbd-repo 组件降低资源消耗,源代码构建资源下载和缓存能力由新增的rbd-resource-proxy提供。

  • Rainbond 项目切换为 gomod 管理。

  • Rainbond console 开发语言 python 版本从2.7升级到 3.6。

  • Rainbond console 支持SQLite3数据库。

了解更多

学习更多Rainbond知识,访问Rainbond项目官网:https://www.rainbond.com

关注Rainbond开源项目: https://github.com/goodrain/rainbond

开始快速安装体验: 安装参考文档

加入Rainbond社区 钉钉群,随时参与社区交流,近期会举办多场以5.3.0新版本为主题的在线分享,进群关注。

在游戏运营行业,Serverless 如何解决数据采集分析痛点?

alicloudnative阅读(1629)评论(0)

头图.png

作者 | 计缘
来源|阿里巴巴云原生公众号

众所周知,游戏行业在当今的互联网行业中算是一棵常青树。在疫情之前的 2019 年,中国游戏市场营收规模约 2884.8 亿元,同比增长 17.1%。2020 年因为疫情,游戏行业更是突飞猛进。玩游戏本就是中国网民最普遍的娱乐方式之一,疫情期间更甚。据不完全统计,截至 2019 年,中国移动游戏用户规模约 6.6 亿人,占中国总网民规模 8.47 亿的 77.92%,可见游戏作为一种低门槛、低成本的娱乐手段,已成为大部分人生活中习以为常的一部分。

对于玩家而言,市面上的游戏数量多如牛毛,那么玩家如何能发现和认知到一款游戏,并且持续的玩下去恐怕是所有游戏厂商需要思考的问题。加之 2018 年游戏版号停发事件,游戏厂商更加珍惜每一个已获得版号的游戏产品,所以这也使得“深度打磨产品质量”和“提高运营精细程度”这两个游戏产业发展方向成为广大游戏厂商的发展思路,无论是新游戏还是老游戏都在努力落实这两点:

  • 新游戏:面向玩家需要提供更充足的推广资源和更完整的游戏内容。
  • 老游戏:通过用户行为分析,投入更多的精力和成本,制作更优质的版本内容。

这里我们重点来看新游戏。一家游戏企业辛辛苦苦研发三年,等着新游戏发售时一飞冲天。那么问题来了,新游戏如何被广大玩家看到?

首先来看看游戏行业公司的分类:

1.png

  • 游戏研发商:研发游戏的公司,生产和制作游戏内容。比如王者荣耀的所有英雄设计、游戏战斗场景、战斗逻辑等,全部由游戏研发公司提供。
  • 游戏发行商:游戏发行商的主要工作分三大块:市场工作、运营工作、客服工作。游戏发行商把控游戏命脉,市场工作核心是导入玩家,运营工作核心是将用户价值最大化、赚取更多利益。

2.png

  • 游戏平台/渠道商:游戏平台和渠道商的核心目的就是曝光游戏,让尽量多的人能发现你的游戏。

这三种类型的业务,有专注于其中某一领域的独立公司,也有能承接全部业务的公司,但无论那一种,这三者之间的关系是不会变的:

3.png

所以不难理解,想让更多的玩家看到你的游戏,游戏发行和运营是关键。通俗来讲,如果你的游戏出现在目前所有大家熟知的平台广告中,那么最起码游戏的新用户注册数量是很可观的。因此这就引入了一个关键词:买量

根据数据显示,2019 年月均买量手游数达 6000+ 款,而 2018 年仅为 4200 款。另一方面,随着抖音、微博等超级 APP 在游戏买量市场的资源倾斜,也助推手游买量的效果和效率有所提升,游戏厂商更愿意使用买量的方式来吸引用户。

但需要注意的是,在游戏买量的精准化程度不断提高的同时,买量的成本也在节节攀升,唯有合理配置买量、渠道与整合营销之间的关系,才能将宣发资源发挥到最大的效果。

通俗来讲,买量其实就是在各大主流平台投放广告,广大用户看到游戏广告后,有可能会点击广告,然后进入游戏厂商的宣传页面,同时会采集用户的一些信息,然后游戏厂商对采集到的用户信息进行大数据分析,进行进一步的定向推广。

游戏运营核心诉求

游戏厂商花钱买量,换来的用户信息以及新用户注册信息是为持续的游戏运营服务的,那么这个场景的核心诉求就是采集用户信息的完整性。

比如说,某游戏厂商一天花 5000w 投放广告,在某平台某时段产生了每秒 1w 次的广告点击率,那么在这个时段内每一个点击广告的用户信息要完整的被采集到,然后入库进行后续分析。这就对数据采集系统提出了很高的要求。

这其中,最核心的一点就是系统暴露接口的环节要能够平稳承载买量期间不定时的流量脉冲。在买量期间,游戏厂商通常会在多个平台投放广告,每个平台投放广告的时间是不一样的,所以就会出现全天不定时的流量脉冲现象。如果这个环节出现问题,那么相当于买量的钱就打水漂了。

数据采集系统传统架构

4.png

上图是一个相对传统的数据采集系统架构,最关键的就是暴露 HTTP 接口回传数据这部分,这部分如果出问题,那么采集数据的链路就断了。但这部分往往会面临两个挑战:

  • 当流量脉冲来的时候,这部分是否可以快速扩容以应对流量冲击。
  • 游戏运营具备潮汐特性,并非天天都在进行,这就需要考虑如何优化资源利用率。

通常情况下,在游戏有运营活动之前,会提前通知运维同学,对这个环节的服务增加节点,但要增加多少其实是无法预估的,只能大概拍一个数字。这是在传统架构下经常会出现的场景,这就会导致两个问题:

  • 流量太大,节点加少了,导致一部分流量的数据没有采集到。
  • 流量没有预期那么大,节点加多了,导致资源浪费。

数据采集系统 Serverless 架构

我们可以通过函数计算 FC 来取代传统架构中暴露 HTTP 回传数据这部分,从而完美解决传统架构中存在问题,参考文章:《资源成本双优化!看 Serverless 颠覆编程教育的创新实践》。

先来看架构图:

5.png

传统架构中的两个问题均可以通过函数计算百毫秒弹性的特性来解决。我们并不需要去估算营销活动会带来多大的流量,也不需要去担心和考虑对数据采集系统的性能,运维同学更不需要提前预备 ECS。

因为函数计算的极致弹性特性,当没有买量、没有营销活动的时候,函数计算的运行实例是零。有买量活动时,在流量脉冲的情况下,函数计算会快速拉起实例来承载流量压力;当流量减少时,函数计算会及时释放没有请求的实例进行缩容。所以 Serverless 架构带来的优势有以下三点:

  • 无需运维介入,研发同学就可以很快的搭建出来。
  • 无论流量大小,均可以平稳的承接。
  • 函数计算拉起的实例数量可以紧贴流量大小的曲线,做到资源利用率最优化,再加上按量计费的模式,可以最大程度优化成本。

架构解析

从上面的架构图可以看到,整个采集数据阶段,分了两个函数来实现,第一个函数的作用是单纯的暴露 HTTP 接口接收数据,第二个函数用于处理数据,然后将数据发送至消息队列 Kafka 和数据库 RDS。

1. 接收数据函数

我们打开函数计算控制台,创建一个函数:

  • 函数类型:HTTP(即触发器为 HTTP)
  • 函数名称:receiveData
  • 运行环境:Python3

6.png

  • 函数实例类型:弹性实例
  • 函数执行内存:512MB
  • 函数运行超时时间:60 秒
  • 函数单实例并发度:1

7.png

  • 触发器类型:HTTP 触发器
  • 触发器名称:defaultTrigger
  • 认证方式:anonymous(即无需认证)
  • 请求方式:GET,POST

8.png

创建好函数之后,我们通过在线编辑器编写代码:

# -*- coding: utf-8 -*-
import logging
import json
import urllib.parse
HELLO_WORLD = b'Hello world!\n'
def handler(environ, start_response):
    logger = logging.getLogger() 
    context = environ['fc.context']
    request_uri = environ['fc.request_uri']
    for k, v in environ.items():
      if k.startswith('HTTP_'):
        # process custom request headers
        pass
    try:        
        request_body_size = int(environ.get('CONTENT_LENGTH', 0))    
    except (ValueError):        
        request_body_size = 0   
    # 接收回传的数据
    request_body = environ['wsgi.input'].read(request_body_size)  
    request_body_str = urllib.parse.unquote(request_body.decode("GBK"))
    request_body_obj = json.loads(request_body_str)
    logger.info(request_body_obj["action"])
    logger.info(request_body_obj["articleAuthorId"])

    status = '200 OK'
    response_headers = [('Content-type', 'text/plain')]
    start_response(status, response_headers)
    return [HELLO_WORLD]

此时的代码非常简单,就是接收用户传来的参数,我们可以调用接口进行验证:

9.png

可以在函数的日志查询中看到此次调用的日志:

10.png

同时,我们也可以查看函数的链路追踪来分析每一个步骤的调用耗时,比如函数接到请求→冷启动(无活跃实例时)→准备代码→执行初始化方法→执行入口函数逻辑这个过程:

11.png

12.png

从调用链路图中可以看到,刚才的那次请求包含了冷启动的时间,因为当时没有活跃实例,整个过程耗时 418 毫秒,真正执行入口函数代码的时间为 8 毫秒。

当再次调用接口时,可以看到就直接执行了入口函数的逻辑,因为此时已经有实例在运行,整个耗时只有 2.3 毫秒:

13.png

2. 处理数据的函数

第一个函数是通过在函数计算控制台在界面上创建的,选择了运行环境是 Python3,我们可以在官方文档中查看预置的 Python3 运行环境内置了哪些模块,因为第二个函数要操作 Kafka 和 RDS,所以需要我们确认对应的模块。

14.png

从文档中可以看到,内置的模块中包含 RDS 的 SDK 模块,但是没有 Kafka 的 SDK 模块,此时就需要我们手动安装 Kafka SDK 模块,并且创建函数也会使用另一种方式。

1)Funcraft

Funcraft 是一个用于支持 Serverless 应用部署的命令行工具,能帮助我们便捷地管理函数计算、API 网关、日志服务等资源。它通过一个资源配置文件(template.yml),协助我们进行开发、构建、部署操作。
所以第二个函数我们需要使用 Fun 来进行操作,整个操作分为四个步骤:

  • 安装 Fun 工具。
  • 编写 template.yml 模板文件,用来描述函数。
  • 安装我们需要的第三方依赖。
  • 上传部署函数。

2)安装 Fun

Fun 提供了三种安装方式:

  • 通过 npm 包管理安装 —— 适合所有平台(Windows/Mac/Linux)且已经预装了 npm 的开发者。
  • 通过下载二进制安装 —— 适合所有平台(Windows/Mac/Linux)。
  • 通过 Homebrew 包管理器安装 —— 适合 Mac 平台,更符合 MacOS 开发者习惯。

文本示例环境为 Mac,所以使用 npm 方式安装,非常的简单,一行命令搞定:

sudo npm install @alicloud/fun -g

安装完成之后。在控制终端输入 fun 命令可以查看版本信息:

$ fun --version
3.6.20

在第一次使用 fun 之前需要先执行 fun config 命令进行配置,按照提示,依次配置 Account ID、Access Key Id、Secret Access Key、 Default Region Name 即可。其中 Account ID、Access Key Id 你可以从函数计算控制台首页的右上方获得:

fun config

? Aliyun Account ID *01
? Aliyun Access Key ID *qef6j
? Aliyun Access Key Secret *UFJG
? Default region name cn-hangzhou
? The timeout in seconds for each SDK client invoking 60
? The maximum number of retries for each SDK client 3

3)编写 template.yml

新建一个目录,在该目录下创建一个名为 template.yml 的 YAML 文件,该文件主要描述要创建的函数的各项配置,说白了就是将函数计算控制台上配置的那些配置信息以 YAML 格式写在文件里:

ROSTemplateFormatVersion: '2015-09-01'
Transform: 'Aliyun::Serverless-2018-04-03'
Resources:
FCBigDataDemo:
Type: 'Aliyun::Serverless::Service'
Properties:
Description: 'local invoke demo'
VpcConfig:
VpcId: 'vpc-xxxxxxxxxxx'
VSwitchIds: [ 'vsw-xxxxxxxxxx' ]
SecurityGroupId: 'sg-xxxxxxxxx'
LogConfig:
Project: fcdemo
Logstore: fc_demo_store
dataToKafka:
Type: 'Aliyun::Serverless::Function'
Properties:
Initializer: index.my_initializer
Handler: index.handler
CodeUri: './'
Description: ''
Runtime: python3

我们来解析以上文件的核心内容:

  • FCBigDataDemo:自定义的服务名称。通过下面的 Type 属性标明是服务,即 Aliyun::Serverless::Service。
  • Properties:Properties 下的属性都是该服务的各配置项。
  • VpcConfig:服务的 VPC 配置,包含:
    • VpcId:VPC ID。
    • VSwitchIds:交换机 ID,这里是数组,可以配置多个交换机。
    • SecurityGroupId:安全组 ID。
  • LogConfig:服务绑定的日志服务(SLS)配置,包含:
    • Project:日志服务项目。
    • Logstore:LogStore 名称。
  • dataToKafka:该服务下自定义的函数名称。通过下面的 Type 属性标明是函数,即 Aliyun::Serverless::Function。
  • Properties:Properties下的属性都是该函数的各配置项。
  • Initializer:配置初始化函数。
  • Handler:配置入口函数。
  • Runtime:函数运行环境。

目录结构为:

15.png

4)安装第三方依赖

服务和函数的模板创建好之后,我们来安装需要使用的第三方依赖。在这个示例的场景中,第二个函数需要使用 Kafka SDK,所以可以通过 fun 工具结合 Python 包管理工具 pip 进行安装:

fun install --runtime python3 --package-type pip kafka-python

执行命令后有如下提示信息:

16.png

此时我们会发现在目录下会生成一个.fun文件夹 ,我们安装的依赖包就在该目录下:

17.png

5)部署函数

现在编写好了模板文件以及安装好了我们需要的 Kafka SDK 后,还需要添加我们的代码文件 index.py,代码内容如下:

# -*- coding: utf-8 -*-
import logging
import json
import urllib.parse
from kafka import KafkaProducer
producer = None
def my_initializer(context):    
    logger = logging.getLogger() 
    logger.info("init kafka producer")
    global producer
    producer = KafkaProducer(bootstrap_servers='XX.XX.XX.XX:9092,XX.XX.XX.XX:9092,XX.XX.XX.XX:9092')
def handler(event, context):
    logger = logging.getLogger()   
    # 接收回传的数据
    event_str = json.loads(event)
    event_obj = json.loads(event_str)
    logger.info(event_obj["action"])
    logger.info(event_obj["articleAuthorId"])
    # 向Kafka发送消息
    global producer
    producer.send('ikf-demo', json.dumps(event_str).encode('utf-8'))
    producer.close()
    return 'hello world'

代码很简单,这里做以简单的解析:

  • my_initializer:函数实例被拉起时会先执行该函数,然后再执行 handler 函数 ,当函数实例在运行时,之后的请求都不会执行 my_initializer 函数 。一般用于各种连接的初始化工作,这里将初始化 Kafka Producer 的方法放在了这里,避免反复初始化 Produer。
  •  handler:该函数只有两个逻辑,接收回传的数据和将数据发送至 Kafka 的指定 Topic。
  • 下面通过 fun deploy 命令部署函数,该命令会做两件事:
    • 根据 template.yml 中的配置创建服务和函数。
    • 将 index.py 和 .fun 上传至函数中。

18.png

登录函数计算控制台,可以看到通过 fun 命令部署的服务和函数:

19.png

进入函数,也可以清晰的看到第三方依赖包的目录结构:

20.png

3. 函数之间调用

目前两个函数都创建好了,下面的工作就是由第一个函数接收到数据后拉起第二个函数发送消息给 Kafka。我们只需要对第一个函数做些许改动即可:

# -*- coding: utf-8 -*-
import logging
import json
import urllib.parse
import fc2
HELLO_WORLD = b'Hello world!\n'
client = None
def my_initializer(context):    
    logger = logging.getLogger() 
    logger.info("init fc client")
    global client
    client = fc2.Client(
        endpoint="http://your_account_id.cn-hangzhou-internal.fc.aliyuncs.com",
        accessKeyID="your_ak",
        accessKeySecret="your_sk"
    )
def handler(environ, start_response):
    logger = logging.getLogger() 
    context = environ['fc.context']
    request_uri = environ['fc.request_uri']
    for k, v in environ.items():
      if k.startswith('HTTP_'):
        # process custom request headers
        pass
    try:        
        request_body_size = int(environ.get('CONTENT_LENGTH', 0))    
    except (ValueError):        
        request_body_size = 0   
    # 接收回传的数据
    request_body = environ['wsgi.input'].read(request_body_size)  
    request_body_str = urllib.parse.unquote(request_body.decode("GBK"))
    request_body_obj = json.loads(request_body_str)
    logger.info(request_body_obj["action"])
    logger.info(request_body_obj["articleAuthorId"])
    global client
    client.invoke_function(
        'FCBigDataDemo',
        'dataToKafka',
        payload=json.dumps(request_body_str),
        headers = {'x-fc-invocation-type': 'Async'}
    )

    status = '200 OK'
    response_headers = [('Content-type', 'text/plain')]
    start_response(status, response_headers)
    return [HELLO_WORLD]

如上面代码所示,对第一个函数的代码做了三个地方的改动:

  • 导入函数计算的库:import fc2
  • 添加初始化方法,用于创建函数计算 Client:
def my_initializer(context):
        logger = logging.getLogger()
        logger.info("init fc client")
        global client
        client = fc2.Client(
            endpoint="http://your_account_id.cn-hangzhou-internal.fc.aliyuncs.com",
            accessKeyID="your_ak",
            accessKeySecret="your_sk"
)

这里需要注意的时,当我们在代码里增加了初始化方法后,需要在函数配置中指定初始化方法的入口:

21.png

  • 通过函数计算 Client 调用第二个函数
global client
    client.invoke_function(
            'FCBigDataDemo',
            'dataToKafka',
          payload=json.dumps(request_body_str),
            headers = {'x-fc-invocation-type': 'Async'}
)

invoke_function 函数有四个参数:

  • 第一个参数:调用函数所在的服务名称。
  • 第二个参数:调用函数的函数名称。
  • 第三个参数:向调用函数传的数据。
  • 第四个参数:调用第二个函数 Request Header 信息。这里主要通过 x-fc-invocation-type 这个 Key 来设置是同步调用还是异步调用。这里设置 Async 为异步调用。

如此设置,我们便可以验证通过第一个函数提供的 HTTP 接口发起请求→采集数据→调用第二个函数→将数据作为消息传给 Kafka 这个流程了。

使用两个函数的目的

到这里有些同学可能会有疑问,为什么需要两个函数,而不在第一个函数里直接向 Kafka 发送数据呢?我们先来看这张图:

22.png

当我们使用异步调用函数时,在函数内部会默认先将请求的数据放入消息队列进行第一道削峰填谷,然后每一个队列在对应函数实例,通过函数实例的弹性拉起多个实例进行第二道削峰填谷。所以这也就是为什么这个架构能稳定承载大并发请求的核心原因之一。

4. 配置 Kafka

在游戏运营这个场景中,数据量是比较大的,所以对 Kafka 的性能要求也是比较高的,相比开源自建,使用云上的 Kafka 省去很多的运维操作,比如:

  • 我们不再需要再维护 Kafka 集群的各个节点。
  • 不需要关心主从节点数据同步问题。
  • 可以快速、动态扩展 Kafka 集群规格,动态增加 Topic,动态增加分区数。
  • 完善的指标监控功能,消息查询功能。

总的来说,就是一切 SLA 都有云上兜底,我们只需要关注在消息发送和消息消费即可。

所以我们可以打开 Kafka 开通界面,根据实际场景的需求一键开通 Kafka 实例,开通 Kafka 后登录控制台,在基本信息中可以看到 Kafka 的接入点:

  • 默认接入点:走 VPC 内网场景的接入点。
  • SSL 接入点:走公网场景的接入点。

将默认接入点配置到函数计算的第二个函数中即可。

....
producer = KafkaProducer(bootstrap_servers='XX.XX.XX.XX:9092,XX.XX.XX.XX:9092,XX.XX.XX.XX:9092')
....

然后点击左侧控制台 Topic 管理,创建 Topic:

23.png

将创建好的 Topic 配置到函数计算的第二个函数中即可。

...
# 第一个参数为Topic名称
producer.send('ikf-demo', json.dumps(event_str).encode('utf-8'))
...

上文已经列举过云上 Kafka 的优势,比如动态增加 Topic 的分区数,我们可以在 Topic 列表中,对 Topic 的分区数进行动态调整:

24.png

25.png

单 Topic 最大支持到 360 个分区,这是开源自建无法做到的。

接下来点击控制台左侧 Consumer Group 管理,创建 Consumer Group:

26.png

至此,云上的 Kafka 就算配置完毕了,即 Producer 可以往刚刚创建的 Topic 中发消息了,Consumer 可以设置刚刚创建的 GID 以及订阅 Topic 进行消息接受和消费。

Flink Kafka 消费者

在这个场景中,Kafka 后面往往会跟着 Flink,所以这里简要给大家介绍一下在 Flink 中如何创建 Kafka Consumer 并消费数据。代码片段如下:

final ParameterTool parameterTool = ParameterTool.fromArgs(args);
String kafkaTopic = parameterTool.get("kafka-topic","ikf-demo");
String brokers = parameterTool.get("brokers", "XX.XX.XX.XX:9092,XX.XX.XX.XX:9092,XX.XX.XX.XX:9092");
Properties kafkaProps = new Properties();
kafkaProps.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, brokers);
kafkaProps.put(ConsumerConfig.GROUP_ID_CONFIG, "ikf-demo");
FlinkKafkaConsumer<UserBehaviorEvent> kafka = new FlinkKafkaConsumer<>(kafkaTopic, new UserBehaviorEventSchema(), kafkaProps);
kafka.setStartFromLatest();
kafka.setCommitOffsetsOnCheckpoints(false);
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
DataStreamSource<UserBehaviorEvent> dataStreamByEventTime = env.addSource(kafka);

以上就是构建 Flink Kafka Consumer 和添加 Kafka Source 的代码片段,还是非常简单的。

压测验证

至此,整个数据采集的架构就搭建完毕了,下面我们通过压测来检验一下整个架构的性能。这里使用阿里云 PTS 来进行压测。

创建压测场景

打开 PTS 控制台,点击左侧菜单创建压测/创建 PTS 场景:

27.png

在场景配置中,将第一个函数计算函数暴露的 HTTP 接口作为串联链路,配置如下图所示:

28.png

29.png

接口配置完后,我们来配置施压:

30.png

  • 压力模式:
    • 并发模式:指定有多少并发用户同时发请求。
    • RPS模式:指定每秒有多少请求数。
  • 递增模式:在压测过程中可以通过手动调节压力,也可以自动按百分比递增压力。
  • 最大并发:同时有多少个虚拟用户发起请求。
  • 递增百分比:如果是自动递增的话,按这里的百分比递增。
  • 单量级持续时长:在未完全达到压力全量的时候,每一级梯度的压力保持的时长。
  • 压测总时长:一共需要压测的时长。

这里因为资源成本原因,并发用户数设置为 2500 来进行验证。

31.png

32.png

从上图压测中的情况来看,TPS 达到了 2w 的封顶,549w+ 的请求,99.99% 的请求是成功的,那 369 个异常也可以点击查看,都是压测工具请求超时导致的。

总结

至此,整个基于 Serverless 搭建的大数据采集传输的架构就搭建好了,并且进行了压测验证,整体的性能也是不错的,并且整个架构搭建起来也非常简单和容易理解。这个架构不光适用于游戏运营行业,其实任何大数据采集传输的场景都是适用的,目前也已经有很多客户正在基于 Serverless 的架构跑在生产环境,或者正走在改造 Serverless 架构的路上。

阿里新晋 CNCF TOC 委员张磊:“云原生”为什么对云计算生态充满吸引力?

alicloudnative阅读(2997)评论(0)

来源|阿里巴巴云原生公众号

美国当地时间 2021 年 2 月 2 日,全球顶级开源社区云原生计算基金会(Cloud Native Computing Foundation,简称 CNCF)正式宣布其新一届技术监督委员会(Technical Oversight Committee,简称 TOC)席位改选结果。阿里云高级技术专家张磊入选,成为本届 TOC 11 个席位中唯一一位来自中国的代表。

1.png

CNCF 在官方公告中表示,张磊的入选是因为其在 Kubernetes 领域所做的突出贡献:“张磊是 Kubernetes 社区的共同维护者,也是 CNCF App Delivery SIG 的 Co-chair,在阿里巴巴主导 Kubernetes 和大型集群管理系统等工作。”

唯一一位来自中国的现任 CNCF TOC 委员

CNCF 成立于 2015 年 7 月,隶属于 Linux 基金会,围绕“云原生”服务云计算,致力于维护和集成开源技术,支持编排容器化微服务架构应用。目前,CNCF 有会员公司超过 300 家,其中包括 AWS、Azure、Google、阿里云等大型云计算厂商。CNCF 的技术监督委员会由 11 位具有丰富技术知识和行业背景的代表组成,为云原生社区提供技术领导。

自 2017 年以来,阿里巴巴在云原生技术领域投入了巨大力量,深度参与到 ETCD、Kubernetes、ContainerD 等多个顶级开源项目的开发与维护当中,并通过云原生技术栈完成了整体基础架构体系的自我升级,如自主开源 Dubbo、RocketMQ 等明星项目,捐献给 Apache 基金会并以顶级项目的身份毕业;Spring Cloud Alibaba 开源两年已经成为 Spring Cloud 最活跃、开发体验最好的 Spring Cloud 实现;Dragonfly 晋升成为 CNCF 孵化项目,OpenYurt、OpenKruise 进入CNCF Sandbox;联合微软云发布全球首个开放应用模型 OAM,共同引领云原生标准应用交付生态,随后推出了基于 OAM 的云原生平台核心引擎 KubeVela ,填补了Kubernetes 生态在构建标准应用交付系统领域的空白;联合南京大学开源了云原生基础架构项目 Fluid,补齐了 CNCF 全景中让大数据和 AI 拥抱云原生的重要组件;Serverless Devs 开发者平台源,成为国内首个进驻 CNCF Landsacpe Tools 的 Serverless 工具等。

截至 2020 年底,阿里巴巴已有超过 10 个项目进入 CNCF Landscape;对 Kubernetes 项目的贡献量也位居全球前 10。

来自阿里云的张磊成为现任 CNCF TOC 中唯一一位来自中国的委员。1989 年出生的他,是 Kubernetes 社区最年轻的早期维护者之一,曾发起和参与设计了 Kubernetes 多个基础特性如 CRI(容器运行时接口)、等价类调度、拓扑资源管理等。因在 Kubernetes 社区的持续影响力,张磊于 2016 年就被推举为 CNCF 官方大使,连续担任多届 KubeCon 评审、KeynoteSpeaker。2019 年,张磊以最高票当选为 CNCF 应用交付领域小组 co-chair,是至今为止 CNCF 7 大领域小组中唯一的华人 co-chair。

2.png

张磊,阿里云高级技术专家、CNCF 技术监督委员会委员

加入阿里云后,张磊重点参与设计了阿里云云原生应用基础设施,参与维护了国内最大公共云容器集群。他提出的“以应用为中心”的标准应用交付体系,催生出了一系列前瞻性的云原生应用管理领域头部开源技术。

此外,张磊还带领团队联合微软云 CTO Office 共同提出了“开放应用模型”开源项目(OAM),这是业界第一个云原生应用交付与管理领域的标准模型与框架项目,已经迅速成为了包括 MasterCard、第四范式等国内外十余家企业构建云原生应用平台的基础模型,并被工信部信通院标准化立项“云计算开放架构通用需求和参考框架”,被美国知名科技媒体 TheNewStack 评选为“Top Cloud Native Technology Trends from 2020”、InfoQ 评选为“2020 年十大新锐开源项目”。

张磊:云原生带来的全新应用交付方式正在成为主流

从 CNCF、阿里云和张磊一直专注的事情中,我们不难看到一个明确的发展趋势,那就是在今天,没有人再会去质疑一个平台团队采纳 Kubernetes 做为本身的基础设施的合理性。事实上,2020 年的 Kubernetes 项目已经很接近于完成了它最重要的使命,即:为云计算基础设施带来一层可让平台团队基于此构造“一切”的平台层抽象。

然而,“云原生”究竟是什么?它为什么对云计算生态充满吸引力?中国本土的云原生又该走向何方?我们一起听听新晋 CNCF TOC 成员张磊的看法。

Q:祝贺你成为 CNCF 全球 11 位 TOC 委员之一!先和大家介绍下自己吧?

张磊:我目前在阿里云负责云原生应用平台基础设施相关的技术工作,同时也在参与和推动 OAM/KubeVela,OpenKruise 和 OpenYurt 等阿里核心开源项目的建设工作。在加入阿里云之前,我主要工作在 Kubernetes 社区上游,是 CRI、调度器等多个核心特性的早期发起者与维护者之一,也是 KataContainers 项目组的成员。近期,我们正在同 CNCF TOC 和 40 多家参与公司一起推进一个厂商中立的 GitOps 应用交付工作组的成立。

Q:你如何看待 Cloud Native 近几年的发展和演变?

张磊:随着云原生技术的极大普及,我们已经看到这种全新的应用交付方式正在结合“标准应用模型”、“基于 Mesh 的渐进式发布”等关键技术一起,成为业界构建应用平台的主流方向。

今天大家所熟知的云原生(Cloud Native)理念,本质上是一套“以利用云计算技术为用户降本增效”的最佳实践与方法论。所以,云原生这个术语自诞生,到壮大,再到今天的极大普及,都处于一个不断的自我演进与革新的过程当中。

无论是 2014 年以 Docker 为代表的容器技术的巨大成功,还是 2019 年后以  Kubernetes 为代表的容器编排技术的迅速崛起,再到今天云原生几乎“包罗万象”般的无处不在,都是 Cloud Native 理念在从概念到实践,再沉淀出新的理念和架构过程的真实写照。这种以一个核心理念为基础的不断演进、逐步影响到整个云计算领域方方面面的过程,是近几年云原生生态发展壮大背后的一个主旋律。

Q:你在去年看到的云原生领域主要变化是什么?你认为它会带来什么影响? 

张磊:在 2020 年,我们能够看到云原生的迅速普及正在给越来越多的领域带来基于“云”的变革,并且通过云原生体系让这些领域迅速融入到了云计算的能力池当中,从而为最终用户直接带来了“降本增效”的巨大价值。仅以 CNCF 开源社区为例,在 2020 年,阿里云有 OpenYurt 边缘容器项目(边缘领域革新)和 OpenKruise 工作负载管理( 应用管理能力下沉)项目进入了 CNCF 沙箱,还有 Virtual Cluster (Serverless 基础设施领域革新)技术成为了 Kubernetes 官方子项目,更有多个核心项目比如 OAM/KubeVela (应用交付领域革新 + 能力下沉)正在孵化中。这些开源技术的涌现和普及,不仅为云原生生态的持续发展和演进提供了至关重要的牵引力,也正在不同领域里让“释放云计算红利”的核心目标真正成为现实。

2020 年的云原生依然是整个云计算生态中发展最迅速的一条主线脉络,而也正是伴随着这样的发展劲头,云原生在新的一年里,已经要开始思考它的下一步发展空间。事实上,咱们已经可以看到各类各样的厂商和团队在不一样的领域积极发力和探索。

Q:你认为 Cloud Native 未来将会走向何方?

张磊:今天云原生的发展趋势,正在离它所倡导的“软件天然生在云上、长在云上”越来越近,但也暴露出了原有的云原生技术底盘过分关注于基础设施抽象与管理、忽视了最终用户侧的体验和技术带来的诸多问题。而在 2020 年云原生领域的变化中,我们已能够看到云原生社区正逐步沿着“能力下沉、价值上浮”的路径向更贴近最终用户的方向靠拢。这也解释了为什么在 Kubernetes 之后,Service Mesh 正在迅速改变中间件与微服务治理技术,GitOps 正在对持续交付领域产生重至关重要的影响,而 OAM 和 Dapr 则正在进一步解决应用抽象模型与服务接入模型的问题。

我们预期在未来的几年内,云原生体系与生俱来的敏捷和用户粘性,会带着云计算的庞大能力池进一步普及到数据库、AI、边缘等更加垂直的领域当中,进而更广泛地影响云计算底层基础架构和云端应用的部署与分发方式。甚至可能会成为未来“云计算无处不在”的最真实写照。

Q:进入 TOC 之后,你会重点关注哪些领域?

张磊:在接下来,我会和 CNCF TOC 一起持续重点关注应用管理与交付、云原生编程模型、云端开发者体验等为最终用户带来直接价值的上层技术领域,联合社区的力量更好的孵化或者更多的吸纳这些领域中具备潜力的开源项目进入 CNCF。与此同时,TOC 也会把目光放的更长远,尤其是关注 WebAssembly、eBPF 等最近正在迅速崛起的底层关键技术。所以如果在不久的将来,CNCF 中最知名的项目不再是 Kubernetes 了,到时咱们千万不要觉得意外。

Q:对于如何推动中国本土环境下的云原生生态的发展,你有什么看法和建议吗?

张磊:实际上,今天在 CNCF 生态中大家正逐步形成一个非常好的认知,那就是今天全世界云原生普及最好、落地效果最扎实的社区,是中国的云原生社区,而不是自己都不用 Kubernetes 的 Google 或者 AWS。我们今天所具备的深度的人才储备和高速增长中的场景与大环境,既是让全世界云原生参与者羡慕不已的、得天独厚的条件,也是国内云原生生态取得迅速发展、能够最大程度释放云原生红利的重要原因之一。

在这个基础上,作为国内的云原生生态成员,我们实际上应该更加大胆的去创新,而不仅仅是 follow,同时也应该更大胆的去让我们的技术走向国际化舞台,积极借助像 CNCF 这样具有一定全球影响力的、并且咱们自己也有一定话语权的中立组织来构建属于我们自己的发声体系,主动吸纳来自北美、欧洲的用户、参与者与贡献者进入到我们的社区当中。当然,这里面自然少不了国内各个云原生领域厂商、社区成员和开源项目维护者们的通力协作。我的个人预期是,很快完全本土化运作的 KubeCon 峰会、跨公司跨地域的云原生编程马拉松等,都会在国内社区开花结果。

持续的生命力,是 “云原生”对云计算生态充满吸引力的源泉

云原生到底是什么?从云原生这个术语出现开始,就一直是很多初次接触云原生理念的工程师、团队和企业常常提出的困惑。

3.png

实际上,作为一套“以利用云计算技术为用户降本增效”的最佳实践与方法论,云原生都处于一个不断的自我演进与革新的过程当中。正如张磊在一篇文章中写道:这种“永远没有确切定义”的持续生命力,才正是“云原生”之所以对云计算生态充满吸引力的源泉。

“云原生的向前发展,需要依靠整个云原生社区不停歇的思考、沉淀与再创新进行补充和修正,才能让云原生的技术价值逐步‘上浮’,对最终用户产生直接的价值与体感,让构建简单、易用的云原生平台再也不是“阳春白雪”,这也是我一直在坚持的事情。”张磊表示。

谐云上榜“2020边缘计算力量TOP20”

谐云阅读(2930)评论(0)

2020年11月7日,以“5G·边缘计算“为主题的全球边缘计算大会在北京成功召开。此次活动吸引了政、产、学、研、用各界的行业权威技术机构与专家等参会。谐云作为边缘计算领域的先驱者,应邀出席大会,并获评“2020边缘计算力量TOP20”

全球最大客服云在云边协同中的案例分享

大会上,谐云高级架构师魏欢分享了谐云边缘计算在通信行业的大规模落地实践。截止目前,谐云为该通信行业巨头搭建的云边协同平台共完成:

  • 7省分公司机房、41台物理机节点的接入,可有效支撑无状态应用,中间件、数据库等有状态应用的跨区域调度部署
  • 为分公司业务场景提供定制开发,打造一套适配客户业务特性的分布式云边协同容器云平台,有效推动分公司20个属地化业务的容器迁移,边缘规模已经达到500+容器实例,分公司业务部署及故障隔离响应由10分钟级同步升级至秒级
  • 全面探索、研究、升级云边协同关键技术,通过自研云边协同框架模块实现了边缘访问代理、边缘自治、故障隔离、监控集成、云边流量闭环、云边混部、Debug工具套件等功能,对平台关键组件优化达50余项
  • 优化资源使用效率,分公司计算节点资源分配比降低50%、资源利用率提升至30%

打造轻量级“中心+边缘”的云边协同架构

因此,谐云研发出基于轻量级容器编排框架KubeEdge的云边协同技术,打造“中心+边缘”的云边协同架构,将容器云计算能力下沉至边缘节点,从基础设施层、系统组件层、容器化应用层全方位监控计算资源,提供节点分组分区域细粒度访问控制,立体资源管理能力,边缘节点区域自治能力,边缘节点故障隔离能力。根据应用场景不同,边缘节点资源类型不同,可选接入原生kubelet或者轻量化kubelet,同时可插拔化边缘设备管理能力。

作为国内外领先的云原生技术服务厂商,谐云始终坚持以云原生技术为核心,同时从云向边缘基础设施延伸,扩大云的范围,建立云原生产品生态、整体解决方案和产业应用相结合的完整生态体系。

欢 迎 免 费 试 用

联系方式:marketing&sales@harmonycloud.cn

20 行代码:Serverless 架构下用 Python 轻松搞定图像分类和预测

alicloudnative阅读(2320)评论(0)

头图.jpg

作者 | 江昱

前言

图像分类是人工智能领域的一个热门话题。通俗解释就是,根据各自在图像信息中所反映的不同特征,把不同类别的目标区分开来的图像处理方法。

它利用计算机对图像进行定量分析,把图像或图像中的每个像元或区域划归为若干个类别中的某一种,以代替人的视觉判读。

图像分类在实际生产生活中也是经常遇到的,而且针对不同领域或者需求有着很强的针对性。例如通过拍摄花朵识别花朵信息、通过人脸比对人物信息等。

通常情况下,这些图像识别或者分类的工具,都是在客户端进行数据采集,在服务端进行运算获得结果,也就是说一般情况下都是有专门的 API 实现图像识别的。例如各大云厂商都会为我们有偿提供类似的能力:

阿里云图像识别页面:

1.png

华为云图像识别页面:

2.png

本文将会通过一个有趣的 Python 库,快速将图像分类的功能搭建在云函数上,并且和 API 网关结合,对外提供 API 功能,实现一个 Serverless 架构的“图像分类 API”

首先和大家介绍一下需要的依赖库:ImageAI。通过该依赖的官方文档我们可以看到这样的描述:

ImageAI 是一个 python 库,旨在使开发人员能够使用简单的几行代码构建具有包含深度学习和计算机视觉功能的应用程序和系统。
ImageAI 本着简洁的原则,支持最先进的机器学习算法,用于图像预测、自定义图像预测、物体检测、视频检测、视频对象跟踪和图像预测训练。ImageAI 目前支持使用在 ImageNet-1000 数据集上训练的 4 种不同机器学习算法进行图像预测和训练。ImageAI 还支持使用在 COCO 数据集上训练的 RetinaNet 进行对象检测、视频检测和对象跟踪。最终,ImageAI 将为计算机视觉提供更广泛和更专业化的支持,包括但不限于特殊环境和特殊领域的图像识别。

也就是说这个依赖库,可以帮助我们完成基本的图像识别和视频的目标提取,虽然他给了一些数据集和模型,但是我们也可以根据自身需要对其进行额外的训练,进行定制化拓展。通过官方给的代码,我们可以看到一个简单的 Demo:

# -*- coding: utf-8 -*-
from imageai.Prediction import ImagePrediction

# 模型加载
prediction = ImagePrediction()
prediction.setModelTypeAsResNet()
prediction.setModelPath("resnet50_weights_tf_dim_ordering_tf_kernels.h5")
prediction.loadModel()

predictions, probabilities = prediction.predictImage("./picture.jpg", result_count=5 )
for eachPrediction, eachProbability in zip(predictions, probabilities):
    print(str(eachPrediction) + " : " + str(eachProbability))

当我们指定的 picture.jpg 图片为:

3.png

我们在执行之后的结果是:

laptop : 71.43893241882324
notebook : 16.265612840652466
modem : 4.899394512176514
hard_disc : 4.007557779550552
mouse : 1.2981942854821682

如果在使用过程中觉得模型 resnet50_weights_tf_dim_ordering_tf_kernels.h5 过大,耗时过长,可以按需求选择模型:

  • SqueezeNet(文件大小:4.82 MB,预测时间最短,精准度适中)
  • ResNet50 by Microsoft Research (文件大小:98 MB,预测时间较快,精准度高)
  • InceptionV3 by Google Brain team (文件大小:91.6 MB,预测时间慢,精度更高)
  • DenseNet121 by Facebook AI Research (文件大小:31.6 MB,预测时间较慢,精度最高)

模型下载地址可参考 Github 地址:
https://github.com/OlafenwaMoses/ImageAI/releases/tag/1.0

或者参考 ImageAI 官方文档:
https://imageai-cn.readthedocs.io/zh_CN/latest/ImageAI_Image_Prediction.html

项目 Serverless 化

将项目按照函数计算的需求,编写好入口方法,以及做好项目初始化,同时在当前项目下创建文件夹 model,并将模型文件拷贝到该文件夹:

4.png

项目整体流程:

5.png

实现代码:

# -*- coding: utf-8 -*-

from imageai.Prediction import ImagePrediction
import json
import uuid
import base64
import random

# Response
class Response:
    def __init__(self, start_response, response, errorCode=None):
        self.start = start_response
        responseBody = {
            'Error': {"Code": errorCode, "Message": response},
        } if errorCode else {
            'Response': response
        }
        # 默认增加uuid,便于后期定位
        responseBody['ResponseId'] = str(uuid.uuid1())
        print("Response: ", json.dumps(responseBody))
        self.response = json.dumps(responseBody)

    def __iter__(self):
        status = '200'
        response_headers = [('Content-type', 'application/json; charset=UTF-8')]
        self.start(status, response_headers)
        yield self.response.encode("utf-8")

# 随机字符串
randomStr = lambda num=5: "".join(random.sample('abcdefghijklmnopqrstuvwxyz', num))

# 模型加载
print("Init model")
prediction = ImagePrediction()
prediction.setModelTypeAsResNet()
print("Load model")
prediction.setModelPath("/mnt/auto/model/resnet50_weights_tf_dim_ordering_tf_kernels.h5")
prediction.loadModel()
print("Load complete")

def handler(environ, start_response):
    try:
        request_body_size = int(environ.get('CONTENT_LENGTH', 0))
    except (ValueError):
        request_body_size = 0
    requestBody = json.loads(environ['wsgi.input'].read(request_body_size).decode("utf-8"))

    # 图片获取
    print("Get pucture")
    imageName = randomStr(10)
    imageData = base64.b64decode(requestBody["image"])
    imagePath = "/tmp/" + imageName
    with open(imagePath, 'wb') as f:
        f.write(imageData)

    # 内容预测
    print("Predicting ... ")
    result = {}
    predictions, probabilities = prediction.predictImage(imagePath, result_count=5)
    print(zip(predictions, probabilities))
    for eachPrediction, eachProbability in zip(predictions, probabilities):
        result[str(eachPrediction)] = str(eachProbability)

    return Response(start_response, result)

所需要的依赖:

tensorflow==1.13.1
numpy==1.19.4
scipy==1.5.4
opencv-python==4.4.0.46
pillow==8.0.1
matplotlib==3.3.3
h5py==3.1.0
keras==2.4.3
imageai==2.1.5

编写部署所需要的配置文件:

ServerlessBookImageAIDemo:
  Component: fc
  Provider: alibaba
  Access: release
  Properties:
    Region: cn-beijing
    Service:
      Name: ServerlessBook
      Description: Serverless图书案例
      Log: Auto
      Nas: Auto
    Function:
      Name: serverless_imageAI
      Description: 图片目标检测
      CodeUri:
        Src: ./src
        Excludes:
          - src/.fun
          - src/model
      Handler: index.handler
      Environment:
        - Key: PYTHONUSERBASE
          Value: /mnt/auto/.fun/python
      MemorySize: 3072
      Runtime: python3
      Timeout: 60
      Triggers:
        - Name: ImageAI
          Type: HTTP
          Parameters:
            AuthType: ANONYMOUS
            Methods:
              - GET
              - POST
              - PUT
            Domains:
              - Domain: Auto

在代码与配置中,可以看到有目录:/mnt/auto/ 的存在,该部分实际上是 nas 挂载之后的地址,只需提前写入到代码中即可,下一个环节会进行 nas 的创建以及挂载点配置的具体操作。

项目部署与测试

在完成上述步骤之后,可以通过:

s deploy

进行项目部署,部署完成可以看到结果:

6.png

完成部署之后,可以通过:

s install docker

进行依赖的安装:

7.png

依赖安装完成可以看到在目录下生成了 .fun 的目录,该目录就是通过 docker 打包出来的依赖文件,这些依赖正是我们在 requirements.txt 文件中声明的依赖内容。

完成之后,我们通过:

s nas sync ./src/.fun

将依赖目录打包上传到 nas,成功之后再将 model 目录打包上传:

s nas sync ./src/model

完成之后可以通过:

s nas ls --all

查看目录详情:

8.png

完成之后,我们可以编写脚本进行测试,同样适用刚才的测试图片,通过代码:

import json
import urllib.request
import base64
import time

with open("picture.jpg", 'rb') as f:
    data = base64.b64encode(f.read()).decode()

url = 'http://35685264-1295939377467795.test.functioncompute.com/'

timeStart = time.time()
print(urllib.request.urlopen(urllib.request.Request(
    url=url,
    data=json.dumps({'image': data}).encode("utf-8")
)).read().decode("utf-8"))
print("Time: ", time.time() - timeStart)

可以看到结果:

{"Response": {"laptop": "71.43893837928772", "notebook": "16.265614330768585", "modem": "4.899385944008827", "hard_disc": "4.007565602660179", "mouse": "1.2981869280338287"}, "ResponseId": "1d74ae7e-298a-11eb-8374-024215000701"}
Time:  29.16020894050598

可以看到,函数计算顺利地返回了预期结果,但是整体耗时却超乎想象,有近 30s,此时我们再次执行一下测试脚本:

{"Response": {"laptop": "71.43893837928772", "notebook": "16.265614330768585", "modem": "4.899385944008827", "hard_disc": "4.007565602660179", "mouse": "1.2981869280338287"}, "ResponseId": "4b8be48a-298a-11eb-ba97-024215000501"}
Time:  1.1511380672454834

可以看到,再次执行的时间仅有 1.15 秒,比上次整整提升了 28 秒之多。

项目优化

在上一轮的测试中可以看到,项目首次启动和二次启动的耗时差距,其实这个时间差,主要是函数在加载模型的时候浪费了极长的时间。

即使在本地,我们也可以简单测试:

# -*- coding: utf-8 -*-

import time

timeStart = time.time()

# 模型加载
from imageai.Prediction import ImagePrediction

prediction = ImagePrediction()
prediction.setModelTypeAsResNet()
prediction.setModelPath("resnet50_weights_tf_dim_ordering_tf_kernels.h5")
prediction.loadModel()
print("Load Time: ", time.time() - timeStart)
timeStart = time.time()

predictions, probabilities = prediction.predictImage("./picture.jpg", result_count=5)
for eachPrediction, eachProbability in zip(predictions, probabilities):
    print(str(eachPrediction) + " : " + str(eachProbability))
print("Predict Time: ", time.time() - timeStart)

执行结果:

Load Time:  5.549695014953613
laptop : 71.43893241882324
notebook : 16.265612840652466
modem : 4.899394512176514
hard_disc : 4.007557779550552
mouse : 1.2981942854821682
Predict Time:  0.8137111663818359

可以看到,在加载 imageAI 模块以及加载模型文件的过程中,一共耗时 5.5 秒,在预测部分仅有不到 1 秒钟的时间。而在函数计算中,机器性能本身就没有我本地的性能高,此时为了避免每次装载模型导致的响应时间过长,在部署的代码中,可以看到模型装载过程实际上是被放在了入口方法之外。这样做的一个好处是,项目每次执行的时候,不一定会有冷启动,也就是说在某些复用的前提下是可以复用一些对象的,即无需每次都重新加载模型、导入依赖等。

所以在实际项目中,为了避免频繁请求,实例重复装载、创建某些资源,我们可以将部分资源放在初始化的时候进行。这样可以大幅度提高项目的整体性能,同时配合厂商所提供的预留能力,可以基本上杜绝函数冷启动带来的负面影响。

总结

近年来,人工智能与云计算的发展突飞猛进,在 Serverless 架构中,如何运行传统的人工智能项目已经逐渐成为很多人所需要了解的事情。本文主要介绍了通过一个已有的依赖库(ImageAI)实现一个图像分类和预测的接口。借助这个例子,其实有几个事情是可以被明确的:

  • Serverless 架构可以运行人工智能相关项目;
  • Serverless 可以很好地兼容 Tensorflow 等机器学习/深度学习的工具;
  • 虽然说函数计算本身有空间限制,但是实际上增加了硬盘挂载能力之后,函数计算本身的能力将会得到大幅度的拓展。

当然,本文也算是抛砖引玉,希望读者在本文之后,可以发挥自己的想象,将更多的 AI 项目与 Serverless 架构进行进一步结合。

阿里云技术专家解读:2021 年六大容器技术发展趋势

alicloudnative阅读(3829)评论(0)

头图.jpg

作者 | 阿里云容器服务团队
来源|阿里巴巴云原生公众号

2020 终于过去。在这一年,特殊的环境让企业的生存和发展充满着不确定性。在持续应对由变化带来的挑战过程中,数字化创新能力对于企业来说似乎比以往任何时候都更加重要。

疫情之下,越来越多的企业坚定了上云和实现数字化转型的信念和步伐,并且积极探索云原生架构转型落地。2020 年 双11,阿里巴巴实现了核心系统全面云原生化的重大技术突破。基于云原生架构,企业可以最大化使用云的能力,聚焦于自身业务发展,开发者也可以基于云原生的技术和产品,提升开发效率,将精力更多地聚焦于业务逻辑的实现。可以看出,以容器为代表的云原生技术正在成为释放云价值的最短路径

作为云原生发展的基石,容器技术的新趋势和新挑战备受关注。2021 年伊始,阿里云容器服务团队的技术专家们为大家带来了他们对新一年容器技术趋势的六个重要解读

趋势一:以 Kubernetes 为代表的容器技术,已成为云计算的新界面

汤志敏|阿里云容器服务资深技术专家

1.png

在最新发布的 “CNCF 2020 年中国云原生调查”中显示,有 72% 的中国受访者在生产中使用了 Kubernetes。过去一年,我们观察到的阿里云上云原生生态的蓬勃发展也印证着云原生技术正成为释放云价值的最短路径。从早期的无状态应用、到 AI 大数据和存储类应用都在拥抱容器技术。可以看见,以 Kubernetes 为代表的容器技术已成为云计算的新界面,并将继续带来更大价值。

1. 企业从上云,到通过云原生加速分布式云管理

  • 对于企业来讲,容器持续向下封装基础设施,屏蔽底层架构的差异性。
  • 而 Kubernetes 的新界面进一步促进云和边的基础能力对齐,推动“边”的产品能力丰富度和标准化,从而加速容器应用在边缘、IoT 和 5G 等场景的落地。

2. 容器应用的高密高频挑战,持续重构(Refactor)云计算的架构

  • 在容器应用的高密高频的应用场景推动下,面向容器优化的 OS、裸金属协同、硬件加速等技术持续演进,进一步催熟云计算架构的全栈优化和软硬一体,并给云计算用户带来极致的敏捷、弹性等红利。
  • 而在容器新界面之上的 Serverless、新一代的中间件、新一代的应用 PaaS 方兴未艾。

3. 容器大规模应用进入深水区,在自动化运维、企业 IT 治理、端到端安全等迎来挑战

  • 随着越来越多的工作负载、AI 大数据、数据库等应用容器化,如何统一容器和基础资源形成统一的人、财、物、权等企业 IT 治理能力,是大规模落地容器的关键述求。
  • 随着越来越多的自定义控制器、越来越丰富的云原生制品格式,如何保障大规模 K8s 集群的稳定性带来强需求,而数据化智能化的 K8s 自动化集群运维和细粒度的 SLO 能力更加迫切。
  • 零信任安全、容器身份认证、云原生制品生命周期管理、安全容器、机密计算等 DevSecOps 实践,持续打造端到端的容器安全网。

趋势二:围绕云原生应用的高度自动化

王思宇|阿里云技术专家,云原生应用自动化引擎开源项目 OpenKruise 作者&初创团队成员

2.png

得益于 Kubernetes 面向终态的理念,云原生架构天然具备高度自动化的能力。在应用云原生化的过程中会充分享用到自动化带来的优势,副本数维持、版本一致性、错误重试、异步事件驱动等能力,相比过去面向过程的运维模式而言是一次新理念、新技术带来的进步。在这片蓬勃发展的土壤之上,如何围绕云原生、为应用打造更加自动化的基础设施是未来 2021 年探索的重点方向之一:

  • 应用部署运维更加自动化:云原生业务类型及其多样化,不管是传统 IT、互联网,还是 Web 服务、搜索、游戏、AI、边缘等细分领域,每一种都会有自身特殊应用场景,而抽象、提炼出其中核心通用的部署运维诉求并转化为更加自动化的能力则是深耕云原生的必经之路。
  • 风险防控能力更加自动化:面向终态的自动化是一把 “双刃剑”,它既为应用带来了声明式的部署能力,同时也潜在地会将一些误操作行为被终态化放大,例如在发生操作故障时副本数维持、版本一致性、级联删除等机制反而很可能导致爆炸半径扩大。因此,通过防护、拦截、限流、熔断等防控自动化能力来抑制其他功能性自动化能力的缺陷和副作用,是伴随着云原生规模急剧扩大的必要防护措施。
  • Operator 运行时更加自动化:Kubernetes 能成为容器集群调度管理引擎的事实标准,其强大而又灵活的扩展能力功不可没。Operator 既是一种特殊的应用,也是不少有状态应用的自动化管理者。而过去社区整体 Operator 趋势还停留在数量野蛮增长、周边运行时机制却无太大进步,2021 年 Operator 的运行时将会在水平扩展、灰度升级、租户隔离、安全防护、可观测性等方面获得充分的自动化增强。

趋势三:以“应用”为中心构建高可扩展的上层平台

孙健波|阿里云技术专家,开放应用模型 OAM 开源项目负责人

3.png

随着容器技术的进一步成熟,越来越多的企业开始关注容器技术如何更好的为业务带来价值。我们可以看到以 Kubernetes 为交付界面的云原生生态日益庞大,越来越多的团队会基于 Kubernetes 构建上层抽象,增加更多的扩展能力,以“应用”为中心构建高可扩展的云原生平台。

  • 基于 Kubernetes 与标准应用模型构建的易用、可扩展的上层平台将取代传统 PaaS 成为主流。当前云原生生态的软件虽然日益丰富,但是学习和使用门槛依旧非常高,易用性将成为“以应用为中心”的首要突破点。除此之外,在易用的同时保证可扩展性,保证以 Kubernetes 为接入点的开源软件无需或只要较小改造便可接入使用,也是这样类型应用管理平台的重要特征。
  • “关注点分离”的标准化应用构建方式进一步深入人心。围绕 Kubernetes 构建应用交付平台已经逐渐成为共识,任何一个 PaaS 平台都不想把 Kubernetes 屏蔽掉。但是这并不意味着直接把 Kubernetes 所有的信息暴露给用户,PaaS 平台的构建者们极度渴望给用户最佳的体验。解决这个问题的突破点就是大家使用一个标准化的、关注点分离的应用构建模型,平台的构建者们关注 Kubernetes 接口(CRD 和 Operator),而平台的用户,也就是应用开发者们关注的则是一个标准化的抽象应用模型。
  • 应用中间件能力进一步下沉,应用逻辑与中间件逻辑逐步解耦。随着云原生以及整个生态的发展,中间件领域也在逐步发展变化,从原先的中心化 ESB 到如今通过 Sidecar 模式提供能力的 Service Mesh 。应用中间件不再是通过一个胖客户端提供能力,而是成为一个能力的标准接入层,能力的提供则由应用管理平台通过 Sidecar 的方式在应用运行时注入。相信 Sidecar 这种模式将在除流量治理、路由策略、访问控制之外的更多中间件场景中得到应用,“以应用为中心”,让业务更专注,更聚焦。

趋势四:“云边一体”迎来快速发展

黄玉奇|阿里云高级技术专家,边缘计算云原生开源项目 OpenYurt 负责人 

4.png

随着 5G、IoT、直播、CDN 等行业和业务的发展,越来越多的算力和业务开始下沉到距离数据源或者终端用户更近的位置,以期获得很好的响应时间和成本,这是一种明显区别于传统中心模式的计算方式——边缘计算。未来,边缘计算将存在三个非常明显的发展趋势:

  • AI、IoT 与边缘计算的融合,边缘计算场景中业务种类会越来越多、规模越来越大、复杂度越来越高。
  • 边缘计算作为云计算的延伸,将被广泛应用于混合云场景,这里面需要未来的基础设施能够去中心化、边缘设施自治、边缘云端托管能力。
  • 5G、IoT 等基础设施的发展将会引爆边缘计算的增长。

边缘计算的规模、复杂度正逐日攀升,而短缺的运维手段和运维能力也终于开始不堪重负。在这个背景下,“云边端一体化运维协同”已经开始成为一种架构共识。通过云原生加持,云边融合的进程也正在被急剧加速:

  • “云”层,让我们保留了原汁原味的云原生管控和丰富的产品能力,通过云边管控通道将之下沉到边缘,使海量边缘节点和边缘业务摇身一变成为云原生体系的工作负载。
  • “边”侧,通过流量管理和服务治理使其更好的和端进行交互,获得和云上一致的运维体验,更好的隔离性,安全性以及效率,从而完成业务、运维、生态的一体化。

边缘计算云原生即是云原生的新边界,也是边缘计算的新未来。

趋势五:云原生 AI 只是起点,云原生驱动数据变革是新主题

张凯|阿里云高级技术专家,负责容器服务和云原生 AI 解决方案研发 车漾 | 阿里云高级技术专家,开源项目 Fluid 联合发起人

5.png

数据是企业的核心资产,云原生为了更好地支撑企业 IT 数字化和智能化转型,拥抱数据驱动应用是其未来几年中最重要的使命之一。除了生在 Docker 里、长在 Kubernetes 下的云原生 AI 之外,如何能让传统的大数据和 HPC 应用也平滑迁移到 Kubernetes 平台上来,实际上也是云原生社区需要回答的问题。我们看到的趋势是致敬传统任务调度器、容器化资源精细调度、弹性数据任务全新场景、AI 与大数据的统一云原生底座。

  • 致敬传统任务调度器: Kubernetes 关注于资源调度,但是对于大数据和 HPC 的调度功能比起 Yarn 等离线传统调度器还有很多需要借鉴的地方,最近在 Kubernetes 的 Scheduler Plugin Framework 的灵活框架下,适配于大数据和 HPC 场景的批量调度,Capacity 调度正在逐步落地。
  • 容器化资源精细调度:Kubernetes 利用容器特性和插件化调度策略,可以原生地支持 GPU 资源共享调度,并且可以进行 GPU 资源隔离,Nvidia Ampere 的调度也在 Kubernetes 上做了 Mig 原生支持。这也是 Kubernetes 独特的能力。而资源共享不仅仅限于 GPU,对于 RDMA,NPU 甚至存储设备,这种调度能力都是必不可少的。
  • 弹性数据任务全新场景:随着大数据和 AI 应用的弹性化越来越普及,如何让数据也有弹性的能力,让数据像流体一样,在诸如 HDFS、OSS、Ceph 等存储源和 Kubernetes 上层云原生应用之间,灵活高效地移动、复制、驱逐、转换和管理,推动广阔云服务场景下的大数据、AI 落地新应用。
  • AI 与大数据的统一云原生底座:基于作业调度、资源利用率优化和数据编排这些原子能力,越来越多 AI、机器学习平台和大数据分析平台构建在容器集群之上。而 AI 与大数据对数据的依赖度,对计算、网络和存储资源的需求特点、工作负载特征、运行策略、对在线服务的重要性,甚至影响企业 IT 成本的因素,都有很多相似之处。因此如何以统一的云原生底座同时支持 AI 和大数据作业,将成为企业 CTO、CIO 思考的主题之一。

趋势六:容器安全成为重中之重

杨育兵|阿里云容器服务高级技术专家

6.png

容器已经成为应用交付的标准,也是云原生时代计算资源和配套设施的交付单元。以 runC 为代表的使用 linux container 技术实现的容器运行时,以轻量、高效、自包含、一次打包到处运行等优秀特性,深受广大容器开发者和使用者的喜爱。

容器技术及应用日渐普及,正成为云计算的新界面。但云计算下的容器技术正面对新的挑战。多个容器共享了同一内核,在隔离和安全性方面必然存在天然缺陷,并进一步限制了容器的应用场景和发展,使其只能应用于企业内部环境等单租场景。但云原生产品交付给不同租户的容器,即使运行在同一台宿主机上也必须具备强隔离的安全保证;在云原生产品时代,容器运行时除了需继续保持轻量、高效、自包含、一次打包到处运行的优秀特性外,还需进一步确保良好的安全隔离性,容器安全成为重中之重。以 KATA 为代表的使用轻量虚拟化实现的容器时逐渐成为多租场景的标准容器运行时。

除了运行时的安全隔离,网络、磁盘、镜像、K8s API 等层面的安全隔离也是必须要解决的问题。涉及到多租户和运行不可信代码,用户可接触到的一切资源都是需要隔离的,包含网络可达的目标,可以使用的存储,可以下载或本地访问的镜像内容都需要隔离。为了防止隔离实现本身有漏洞被用户利用,安全防护需要多层次的深度防护,网络防护除了 VPC 隔离,还需要网络策略细化隔离;计算的隔离除了虚拟化技术的隔离还需要有命名空间、系统调用等方面的隔离;存储的隔离除了有虚拟化相关的隔离,还需要在宿主机上面做 DiskQuota 隔离;镜像的隔离除了要做网络隔离,还需要做本地的镜像引用隔离。这些实现都是向强隔离、多层深度隔离方向发展。

容器安全技术也面对其它新的挑战:引入虚拟化后,容器技术实现不再轻量,如何对虚拟化技术优化,并尽可能轻量、高效成为我们必须要解决的问题;业界也有像 Google 的 gVisor 和 Crosvm、Amzon 的 Firecracker 等轻量虚拟化支持容器化的技术,阿里内部也有相应的 Daishu 虚拟化容器技术来解决这个问题。

下载《云原生大规模落地应用指南》,收藏更多云原生规模化落地实践经验!点击即可下载

Service Mesh安全:当入侵者突破边界,如何抵御攻击?| CNBPS 2020演讲实录

灵雀云阅读(2843)评论(0)

​大家好,我是来自灵雀云的邢海涛,今天演讲的主题是Service Mesh安全,主要从四个方面来跟大家做一下分享。首先介绍Service Mesh 安全需求,然后详细介绍Istio的安全实现,随后介绍两款Service Mesh产品的安全特性:LinkerD 和 Alauda Service Mesh。希望通过这个演讲,让大家了解Istio的无代码侵入,灵活的安全解决方案,启发大家思考自己的安全解决方案,以及如何迁移到Istio的安全模型。

01
Service Mesh安全需求
 

安全无处不在。为了适应企业数字业务的快速发展,企业应用架构正在从单体架构过渡到微服务架构。一方面,微服务架构带来更好的敏捷性,可伸缩性和更好的重用服务能力。另一方面,架构师不得不面对汹涌的网络攻击。

同时,结合无处不在的互联网访问,设备扩展和云计算,企业应用还要面对更多防火墙内部和外部的基础设施、系统和用户数量。企业应用不得不面对零信任网络环境。

我们认为,Service Mesh安全需求可以分为上面三类:网络攻击、服务访问控制和审计。防御网络中间人攻击,流量加密是必须的。为了提供对应用和用户的访问控制,Service Mesh需要双向TLS和细粒度的访问策略。为了确定谁在什么时候做了什么,需要审计工具。

02
全方位Istio安全

这张图来自Istio官网。Istio安全性的目标是:

  • 默认情况下的安全性:无需更改应用程序的代码和基础架构
  • 深度防御:与现有安全系统集成以提供多层防御
  • 零信任网络:在不受信任的网络上构建安全解决方案

说到底,Istio安全主要有两项功能:即无代码侵入前提下,实现流量加密和AAA(验证、授权、审计)。流量加密,用来解决零信任网络的问题。Istio的AAA是在集成现有安全协议/标准之上实现的,这些安全协议/标准包括双向TLS,JWT,OpenID Connect等。

其他描述都是支撑这两大功能:秘钥和证书管理都是为支撑流量加密的基础设施;identity用来支撑身份验证机制;policy用来支撑授权机制;endpoints,communication,data都是加密的对象。

这张图显示了Istio安全体系架构,构建于Istio控制平面和数据平面的基础架构之上。控制平面主要实现如下功能:

  • Citadel组件作为证书颁发机构(CA),用于密钥和证书管理
  • 接受来自API server下发的配置信息:认证策略、授权策略、安全的命名信息
  • Pilot组件负责下发配置信息给Sidecar proxy。

数据平面在安全方面则提供两大功能:

  • Sidecar和外围代理充当策略执行点 (PEP),以保证客户端和服务器之间的通信。
  • 一组Envoy代理扩展,用于管理遥测和审计

总之,控制平面处理来自API server的配置信息,并下发到数据平面,数据平面sidecar Envoy充当策略执行点执行安全策略。

双向TLS就是Service Mesh安全的基础,流量加密和AAA都是基于双向TLS实现的。双向TLS包含一个握手的过程,用于相互检查验证对方身份,这里都是可选操作,可以选择单向验证,甚至不验证。然后是交换对称秘钥,最后用对称秘钥加密通讯内容。

这里验证身份的过程就是利用证书来完成的,证书就是一个passport,由证书权威机构签发的,有时效性的包含你是谁的一段信息。这里签发就是用证书权威机构的私钥给这段信息的摘要签名的过程。

验证过程就是检查证书权威机构是否被信任,证书是否过期,以及检查证书持有者的IP,域名或服务名和证书是否一致。

Istio的安全模型都是围绕双向TLS实现的:

  • 自建证书权威机构,让私钥和证书轮换自动化
  • 强制双向的身份认证
  • 客户端检查服务端身份的同时,还要检查谁在运行服务端,这个人是否有资格运行服务端
  • 服务端检查客户端身份的同时,启动授权机制,检查客户端是否有权访问服务端的资源

 

Istio提供了一个相当灵活的身份模型。Istio使用service identity作为身份,可以表示人类用户,单个workload或一组workload。支持多种公有云平台,在没有服务身份的平台上,Istio可以使用服务名称作为Workload实例的身份。

Istio使用X.509证书为每个Workload设置强身份。Envoy代理、Istio agent和istiod协同一起工作,实现了密钥产生和证书轮换的自动化。

这个过程是这样的:Envoy通过Envoy 定义的API向Istio agent发送证书和密钥请求。Istio agent收到请求后,会先创建私钥和CSR证书签名请求,然后将请求及凭据发送到istiod。Istiod的CA验证CSR中携带的凭据,并对CSR签名以生成证书,并返回给istio agent。Istio agent 将收到的证书和私钥发送给Envoy。通过定期反复的上述过程,istio实现了密钥产生和证书轮换的自动化。

Istio身份验证包含两种类型:对等身份验证和请求身份验证。对等身份验证用于service to service的身份验证,请求身份验证用于对用户和人的身份验证。

对等身份验证用于service to service 的身份验证,以验证建立连接的客户端。Istio将来自客户端的出站流量重新路由到客户端的本地Sidecar Envoy。客户端Envoy与服务器端Envoy开始相互TLS握手。通常的TLS握手,会验证证书的签名,检查证书是否过期,以及证书里名称和域名一致。但Istio Envoy之间在握手,客户端Envoy还会进行安全的命名检查,而不是检查域名和证书是否一致,以验证服务器证书中提供的服务帐户service account是否有权运行目标服务。

客户端是通过服务发现或DNS检索证书中的服务名称的,能够防止HTTPS流量受到一般网络劫持。但是,不能防止DNS欺骗。这也说明Istio还要依赖于底层基础设施的安全保障。客户端Envoy和服务器端Envoy建立了相互TLS连接,Istio将流量从客户端Envoy转发到服务器端Envoy。授权后,服务器端Envoy通过本地TCP连接将流量转发到服务端的服务。

Istio通过使用JSON Web令牌(JWT)验证进行请求身份验证,便于集成使用OpenID Connect的应用。我们使用YAML文件来定义验证策略。部署后,策略将保存在Istio配置存储中。Istio控制器监控配置存储。在任何策略更改后,新策略都会转换为适当的配置,通知Envoy sidecar如何执行这些策略。验证策略可以包含用于验证JWT的公钥,以便传递给envoy sidecar。

Istio授权支持service to service的授权,以及针对最终用户和人的授权访问。Istio授权提供了一个CRD形式的灵活简单的API,我们可以自定义条件,使用DENY和ALLOW动作作为结果。

本地Envoy上执行的授权过程,保证了高性能。同时为了减轻运维人员的负担,Istio支持不同级别分级的授权机制,即从网关,到命名空间再到具体的workload的控制级别。

我们也能看到Istio授权机制的演进过程,从1.4版开始,支持基于策略的授权机制及PBAC,而之前提供的是RBAC的机制,通过左右对比,可以看到由两个CRD化简到一个CRD完成,语义功能上没有丝毫的减弱。

Istio 安全的审计功能比较简单。因为envoy的access log可以输出到标准输出,并可由kubectl logs访问。通常由PaaS平台统一收集处理,可以考虑增加过滤条件进一步便捷审计查询。

03
Linkerd安全

Linkerd是第一代service mesh,目前已经发展到第二代,由于第一代Linkerd十分笨重,第二代设计上放弃了可选实现的多样性选择。因此,第二代Linkerd非常轻量,性能非常高。Linkerd官网展示的4个案例,都是始于Istio,最终选择linkerd实施service mesh的。

默认情况下,Linkerd自动给mesh里的通讯加上双向TLS,但是对流入和流出的流量不强制加密。另外,LinkerD使用的kubenetes Service Account token目前是共享的,依赖kubernetes版本更新,将得以修复。

04
Alauda Service Mesh安全
 

Alauda Service Mesh是灵雀云推出的Service Mesh产品,基于原生Istio,运行在Kubernetes之上,提供了一键部署、可视化管理、可视化配置、便捷的灰度发布等功能,极大降低运维难度,降低了学习Service Mesh的成本。

Alauda service mesh目前支持针对工作负载workload级别的手动配置双向TLS,设置双向TLS的严格模式和兼容模式。

END