閱讀39 返回首頁    go 阿裏雲 go 技術社區[雲棲]


夏日清風 - 基於Docker Swarm的極簡Serverless實踐

15007215609278

在今年4月份的DockerCon壓軸的 Moby's Cool Hack Session上,Alex Ellis給大家展現了一個名為Function as a Service (FaaS)項目。FaaS基於Docker Swarm集群上實現了一個極簡的Serverless框架,支持將任意Unix進程作為函數實現來對外提供服務。

FaaS 架構

在 FaaS 原型係統中

  1. 任何進程都可以轉化成為一個函數,並利用Docker鏡像進行打包和交付
  2. 利用 Docker Swarm 集群的資源調度和routing mesh的負載均衡能力簡潔地實現了函數的調度能力。其中每個函數對應一個Docker集群中的服務
  3. 基於 Prometheus 實現函數調用監控和自動伸縮

image

其設計架構非常簡單,其中

  • API Gateway 負責接受服務調用,路由請求到後端函數實現,並采集服務調用的指標發送給 Prometheus。 Prometheus 則會根據一段時間內服務調用的次數,回調API Gateway 來動態伸縮服務容器實例數量。
  • Function Watchdog 將HTTP請求轉發為進程調用,並將請求數據通過 STDIN 傳遞給進程,而將進程的 STDOUT 作為 HTTP 響應的結果返回給調用者。將函數進程和Function Watchdog打包成一個容器鏡像進行部署。其調用流程如下:

image

FaaS 在本地部署非常簡單

首先你需要準備一個本地的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 

隨後通過瀏覽器來訪問 https://127.0.0.1:8080/ui FaaS

image

整個流程非常簡單,就像夏日的清風,讓人感到自然愉悅。

在阿裏雲上測試FaaS

由於FaaS是基於Docker Swarm mode集群進行部署的,你首先需要在阿裏雲容器服務創建一個Swarm mode集群

image

然後利用如下模板來部署應用

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=https://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 https://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服務的虛擬域名

然後基於上麵模板創建應用,

image

注:這裏的應用名為 “faas_default”,部署完成之後所有函數服務和訪問的名空間都基於這個名稱。

部署完成之後,我們可以看見相應的服務列表

image

選擇路由列表標簽,我們可以看到之前定義的路由地址已經出現在列表中

image

可以點擊連接上麵連接訪問FaaS的API Gateway和Prometheus服務界麵

image

image

下麵我們來進行一個測試來驗證服務的伸縮性,首先,我們參照文檔將Prometheus的URL修改為

https://<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 https://<faas-endpoint>/function/faas-default_echoit -d 'Hello, Function as a Service'; done

注:命令中路徑需要替換faas-endpoint,如果服務名稱與faas-default_echoit不同,也請自行調整。

在Prometheus界麵可以看到服務調用量的變化

image

在容器服務的應用服務列表界麵,可以看到,faas-default_echoit的容器實例從1個擴容到20個。

image

當結束測試之後,服務實例也會縮容到一個

image

如果對創建自己的函數感興趣,可以參考 Alex 的博客,本文不再贅述

https://blog.alexellis.io/build-and-deploy-with-faas/

image

總結

FaaS基於Docker Swarm集群技術,實現了一個極簡的Serverless框架,支持將任意Unix進程作為函數來對外提供服務。FaaS目前還是一個原型係統,如果大家需要完備的Function as a Service能力,體驗無服務器運維,還是建議采用阿裏雲 FunctionCompute服務。

FaaS框架展示了一些有趣的可能性

  • 將現有程序封裝成為函數,可以作為服務方便地集成到應用業務邏輯中。將函數計算和現有微服務架構應用有機結合在一起。
  • 基於Docker和Swarm集群技術,部署運維非常簡單。可以在任何地方部署,甚至是ARM設備上。下圖來自RICHARD GEE,演示了在樹莓派集群上運行FaaS。

image

最後更新:2017-07-23 20:39:40

  上一篇:go  【Linux shell】sed實踐(1)
  下一篇:go  CCAI 2017 | 譚鐵牛院士現場致辭:人工智能新熱潮下要保持清醒頭腦,設定科學的目標