夏日清风 - 基于Docker Swarm的极简Serverless实践
在今年4月份的DockerCon压轴的 Mobys Cool Hack Session上,Alex Ellis给大家展现了一个名为Function as a Service (FaaS)项目。FaaS基于Docker Swarm集群上实现了一个极简的Serverless框架,支持将任意Unix进程作为函数实现来对外提供服务。
FaaS 架构在 FaaS 原型系统中
任何进程都可以转化成为一个函数,并利用Docker镜像进行打包和交付 利用 Docker Swarm 集群的资源调度和routing mesh的负载均衡能力简洁地实现了函数的调度能力。其中每个函数对应一个Docker集群中的服务 基于 Prometheus 实现函数调用监控和自动伸缩其设计架构非常简单,其中
API Gateway 负责接受服务调用,路由请求到后端函数实现,并采集服务调用的指标发送给 Prometheus。 Prometheus 则会根据一段时间内服务调用的次数,回调API Gateway 来动态伸缩服务容器实例数量。 Function Watchdog 将HTTP请求转发为进程调用,并将请求数据通过 STDIN 传递给进程,而将进程的 STDOUT 作为 HTTP 响应的结果返回给调用者。将函数进程和Function Watchdog打包成一个容器镜像进行部署。其调用流程如下:首先你需要准备一个本地的Docker Swarm集群,如果没有,可以安装最新Docker Engine并执行下面命令:
docker swarm init
执行如下命令来部署FaaS
git clone https://github.com/alexellis/faas cd faas ./deploy_stack.sh
在部署完成之后,我们可以通过如下命令检查FaaS的状态
$ docker stack services func ID NAME MODE REPLICAS IMAGE 1a8b2tb19ulk func_gateway replicated 1/1 functions/gateway:0.5.6 4jdexem6kppg func_webhookstash replicated 1/1 functions/webhookstash:latest 9ju4er5jur9l func_wordcount replicated 1/1 functions/alpine:health e190suippx7i func_markdown replicated 1/1 alexellis2/faas-markdownrender:latest l70j4c7kf99t func_alertmanager replicated 1/1 functions/alertmanager:latest mgujgoa2u8f3 func_decodebase64 replicated 1/1 functions/alpine:health o44asbnhqbda func_hubstats replicated 1/1 alexellis2/faas-dockerhubstats:latest q8rx49ow3may func_echoit replicated 1/1 functions/alpine:health t1ao5psnsj0s func_base64 replicated 1/1 functions/alpine:health vj5z7rpdlo48 func_prometheus replicated 1/1 functions/prometheus:latest xmwzd4z7l4dv func_nodeinfo replicated 1/1 functions/nodeinfo:latest
随后通过浏览器来访问 http://127.0.0.1:8080/ui FaaS
整个流程非常简单,就像夏日的清风,让人感到自然愉悦。
在阿里云上测试FaaS由于FaaS是基于Docker Swarm mode集群进行部署的,你首先需要在阿里云容器服务创建一个Swarm mode集群
然后利用如下模板来部署应用
version: "3" services: # Core API services are pinned, HA is provided for functions. gateway: volumes: - "/var/run/docker.sock:/var/run/docker.sock" ports: - 8080:8080 labels: aliyun.routing.port_8080: faas image: functions/gateway:0.5.6 networks: - functions environment: dnsrr: "true" # Temporarily use dnsrr in place of VIP while issue persists on PWD deploy: placement: constraints: [node.role == manager] prometheus: image: functions/prometheus:latest # autobuild from Dockerfile in repo. command: "-config.file=/etc/prometheus/prometheus.yml -storage.local.path=/prometheus -storage.local.memory-chunks=10000 --alertmanager.url=http://alertmanager:9093" ports: - 9090:9090 depends_on: - gateway - alertmanager labels: aliyun.routing.port_9090: prometheus environment: no_proxy: "gateway" networks: - functions deploy: placement: constraints: [node.role == manager] alertmanager: image: functions/alertmanager:latest # autobuild from Dockerfile in repo. environment: no_proxy: "gateway" command: - -config.file=/alertmanager.yml networks: - functions ports: - 9093:9093 deploy: placement: constraints: [node.role == manager] # Sample functions go here. # Service label of "function" allows functions to show up in UI on http://gateway:8080/ webhookstash: image: functions/webhookstash:latest labels: function: "true" depends_on: - gateway networks: - functions environment: no_proxy: "gateway" https_proxy: $https_proxy # Pass a username as an argument to find how many images user has pushed to Docker Hub. hubstats: image: alexellis2/faas-dockerhubstats:latest labels: function: "true" depends_on: - gateway networks: - functions environment: no_proxy: "gateway" https_proxy: $https_proxy # Node.js gives OS info about the node (Host) nodeinfo: image: functions/nodeinfo:latest labels: function: "true" depends_on: - gateway networks: - functions environment: no_proxy: "gateway" https_proxy: $https_proxy # Uses `cat` to echo back response, fastest function to execute. echoit: image: functions/alpine:health labels: function: "true" depends_on: - gateway networks: - functions environment: fprocess: "cat" no_proxy: "gateway" https_proxy: $https_proxy # Counts words in request with `wc` utility wordcount: image: functions/alpine:health labels: function: "true" com.faas.max_replicas: "10" depends_on: - gateway networks: - functions environment: fprocess: "wc" no_proxy: "gateway" https_proxy: $https_proxy # Calculates base64 representation of request body. base64: image: functions/alpine:health labels: function: "true" depends_on: - gateway networks: - functions environment: fprocess: "base64" no_proxy: "gateway" https_proxy: $https_proxy # Decodes base64 representation of request body. decodebase64: image: functions/alpine:health labels: function: "true" depends_on: - gateway networks: - functions environment: fprocess: "base64 -d" no_proxy: "gateway" https_proxy: $https_proxy # Converts body in (markdown format) - (html) markdown: image: alexellis2/faas-markdownrender:latest labels: function: "true" depends_on: - gateway networks: - functions environment: no_proxy: "gateway" https_proxy: $https_proxy networks: functions: driver: overlay
和本地部署相比只是增加了两个 label,定义了API Gatway和Prometheus的路由
"aliyun.routing.port_8080: faas" : API Gatway的虚拟域名 "aliyun.routing.port_9090: prometheus" : prometheus服务的虚拟域名然后基于上面模板创建应用,
注:这里的应用名为 “faas_default”,部署完成之后所有函数服务和访问的名空间都基于这个名称。
部署完成之后,我们可以看见相应的服务列表
选择路由列表标签,我们可以看到之前定义的路由地址已经出现在列表中
可以点击连接上面连接访问FaaS的API Gateway和Prometheus服务界面
下面我们来进行一个测试来验证服务的伸缩性,首先,我们参照文档将Prometheus的URL修改为
http:// prometheus-endpoint /graph?g0.range_input=15m g0.expr=gateway_service_count g0.tab=0 g1.range_input=15m g1.expr=rate(gateway_function_invocation_total%5B20s%5D) g1.tab=0 g2.range_input=15m g2.expr=gateway_functions_seconds_sum+%2F+gateway_functions_seconds_count g2.tab=0
注:其中URL的prometheus-endpoint需要替换为上文中端点地址
然后在本地运行如下命令
while [ true ] ; do curl -X POST http:// faas-endpoint /function/faas-default_echoit -d Hello, Function as a Service; done
注:命令中路径需要替换faas-endpoint,如果服务名称与faas-default_echoit不同,也请自行调整。
在Prometheus界面可以看到服务调用量的变化
在容器服务的应用服务列表界面,可以看到,faas-default_echoit的容器实例从1个扩容到20个。
当结束测试之后,服务实例也会缩容到一个
如果对创建自己的函数感兴趣,可以参考 Alex 的博客,本文不再赘述
https://blog.alexellis.io/build-and-deploy-with-faas/
FaaS基于Docker Swarm集群技术,实现了一个极简的Serverless框架,支持将任意Unix进程作为函数来对外提供服务。FaaS目前还是一个原型系统,如果大家需要完备的Function as a Service能力,体验无服务器运维,还是建议采用阿里云 FunctionCompute服务。
FaaS框架展示了一些有趣的可能性
将现有程序封装成为函数,可以作为服务方便地集成到应用业务逻辑中。将函数计算和现有微服务架构应用有机结合在一起。 基于Docker和Swarm集群技术,部署运维非常简单。可以在任何地方部署,甚至是ARM设备上。下图来自RICHARD GEE,演示了在树莓派集群上运行FaaS。Docker 多容器编排Swarm(六) Docker Swarm 和 Docker Compose 一样,都是 Docker 官方容器编排项目,但不同的是,Docker Compose 是一个在单个服务器或主机上创建多个容器的工具,而 Docker Swarm 则可以在多个服务器或主机上创建容器集群服务,对于微服务的部署,显然 Docker Swarm 会更加适合。
易立 易立,阿里云资深专家,目前负责阿里云容器服务和区块链服务研发。之前曾在IBM中国开发中心工作,担任资深技术专员。关注Docker/Kubernetes等云原生计算和Hyperledger Fabric/Ethereum等区块链技术。
相关文章
- docker desktop troubleshooting
- 一文读懂,用 jenkins+docker 实现主从模式
- linux-Ubantu系统,基于java基础镜像,dockerfile源码编译安装opencv,重新制作docker镜像
- Docker-数据管理
- Docker中mysql修改配置导致无法启动的docker容器
- 基于Alpine构建轻量级带有cURL功能的Docker镜像
- Mac 下Docker操作SQLServer数据库
- 基于Docker的开发模式驱动持续集成落地实施
- Docker 简明教程
- 如何交互式地创建一个Docker容器
- Docker安装Zookeeper并进行操作
- Centos 6.x 安装 docker
- docker搭建PHP环境
- 基于Docker搭建MySQL主从复制
- 虚拟化+docker概念基本介绍
- 欢迎阅读daxnet的新博客:一个基于Microsoft Azure、ASP.NET Core和Docker的博客系统
- Docker容器重启策略以及docker run的--restart选项详解
- Docker容器怎么操作
- 如何规划基于Docker的微服务?
- 基于docker创建的Jenkins,settings.xml文件放在哪里
- Docker+Selenium Grid+Python搭建分布式测试环境
- 基于Docker安装RabbitMQ及基本使用
- Centos 上安装Docker步骤
- 品高公开课 | 基于Docker容器的微服务架构实践
- Docker启动报错docker: Error response from daemon: Conflict. The container name “/redis6“ is already in u
- CentOS7下Docker Storage Pool扩容
- Docker安装Jenkins