前言
首先介紹下在本文出現的幾個比較重要的概念:
函數計算(Function Compute): 函數計算是一個事件驅動的服務,通過函數計算,使用者無需管理伺服器等運作情況,隻需編寫代碼并上傳。函數計算準備計算資源,并以彈性伸縮的方式運作使用者代碼,而使用者隻需根據實際代碼運作所消耗的資源進行付費。函數計算更多資訊 參考。
Fun: Fun 是一個用于支援 Serverless 應用部署的工具,能幫助您便捷地管理函數計算、API 網關、日志服務等資源。它通過一個資源配置檔案(template.yml),協助您進行開發、建構、部署操作。Fun 的更多文檔
fun install: fun install 是 fun 工具的一個子指令,用于安裝 pip 和 apt 依賴,提供了指令行接口和 fun.yml 描述檔案兩種形式。
備注: 本文介紹的技巧需要 Fun 版本大于等于 2.9.3。
函數計算安裝第三方依賴一大痛點,文章
函數計算安裝依賴庫方法小結對可能會遇到的問題和解決方法做了細緻總結,fun install 是基于之前的經驗和成果将最佳實踐的方法固化到工具中,友善使用者便捷的安裝依賴。
初始化
使用
fun install init
在目前目錄初始化一個 fun.yml 檔案。(這一步不是必須的,如果您打算手寫 fun.yml 然後通過 fun install 指令批量執行 task,init 是一個好的開始。)
在函數計算項目根目錄執行
fun install init
指令,選擇一個 runtime。
$ fun install init
? Select runtime (Use arrow keys)
python2.7
python3
nodejs6
nodejs8
java8
php7.2
然後會在目前目錄生成一個 fun.yml 檔案,内容如下:
runtime: python2.7
tasks: []
安裝 pip 包依賴
下面的指令安裝 python 的 tensorflow 包
$ fun install --runtime python2.7 --package-type pip tensorflow
skip pulling image aliyunfc/runtime-python2.7:build-1.2.0...
Task => [UNNAMED]
=> PYTHONUSERBASE=/code/.fun/python pip install --user tensorflow
說明
-
指定 runtime,如果已經初始化 fun.yml 檔案, 由于 fun.yml 裡聲明了 runtime ,該選項可以省略。--runtime
-
指定安裝依賴的類型,pip 和 apt 是目前的兩個可選值。--package-type
- tensorflow 是一個 pip 包名。
指令執行在 fc-docker 提供的 container 中,容器内部執行的指令會逐行列印出來,比如上面指令中内部真實執行了
PYTHONUSERBASE=/code/.fun/python pip install --user tensorflow
指令。
安裝完成以後會在生成一個 .fun 目錄, 可執行檔案會被放置到
.fun/python/bin
目錄下,庫檔案放置到
.fun/python/lib/python2.7/site-packages
下。
.fun
└── python
├── bin
│ ├── freeze_graph
│ ├── markdown_py
│ ├── pbr
│ ├── saved_model_cli
│ ├── tensorboard
│ ├── tflite_convert
│ ├── toco
│ └── toco_from_protos
└── lib
└── python2.7
└── site-packages
├── tensorboard
├── tensorboard-1.12.2.dist-info
├── tensorflow
├── tensorflow-1.12.0.dist-info
├── termcolor-1.1.0.dist-info
...
相比之前的
pip install -t . <package-name>
方式,fun install 安裝檔案的存放位置更有組織,依賴檔案和代碼檔案分離開了,便于清理、拆分後借助 OSS 或 NAS 初始化依賴檔案。但是組織過後也帶來一個新問題,需要使用者自定義環境變量庫檔案才能被程式找到。為了友善使用者使用提供了一個
fun install env
列印出必要的環境變量。
$ fun install env
LD_LIBRARY_PATH=/code/.fun/root/usr/lib/x86_64-linux-gnu:/code:/code/lib:/usr/local/lib
PATH=/code/.fun/root/usr/local/bin:/code/.fun/root/usr/local/sbin:/code/.fun/root/usr/bin:/code/.fun/root/usr/sbin:/code/.fun/root/sbin:/code/.fun/root/bin:/code/.fun/python/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/sbin:/bin
PYTHONUSERBASE=/code/.fun/python
關于如果設定函數計算的環境變量,請參考
https://help.aliyun.com/document_detail/69777.html。如果您使用
fun local
和
fun deploy
進行調試和部署,您無需關注環境變量問題,已經幫您設定好了。
使用 --save 持久化
install 指令加上 --save 參數,會将指令持久化成 task 儲存到 fun.yml 檔案中。
$ fun install --runtime python2.7 --package-type pip --save tensorflow
skip pulling image aliyunfc/runtime-python2.7:build-1.2.0...
Task => [UNNAMED]
=> PYTHONUSERBASE=/code/.fun/python pip install --user tensorflow
上面的指令多加了一行
--save
參數,檢視 fun.yml 内容:
runtime: python2.7
tasks:
- pip: tensorflow
local: true
之後直接執行
fun install
不帶參數,就可以依次執行任務。
$ fun install
skip pulling image aliyunfc/runtime-python2.7:build-1.2.0...
Task => [UNNAMED]
=> PYTHONUSERBASE=/code/.fun/python pip install --user tensorflow
使用 -v 顯示詳細日志
$ fun install -v
skip pulling image aliyunfc/runtime-python3.6:build-1.2.0...
Task => [UNNAMED]
=> apt-get update (if need)
Ign http://mirrors.aliyun.com stretch InRelease
Get:1 http://mirrors.aliyun.com stretch-updates InRelease [91.0 kB]
Get:2 http://mirrors.aliyun.com stretch-backports InRelease [91.8 kB]
Get:3 http://mirrors.aliyun.com stretch/updates InRelease [94.3 kB]
Hit http://mirrors.aliyun.com stretch Release.gpg
Hit http://mirrors.aliyun.com stretch Release
Get:4 http://mirrors.aliyun.com stretch-updates/main Sources [3911 B]
....
安裝 apt 包依賴
函數計算使用 apt-get 安裝依賴是另一類常見的安裝問題,使用 fun install 也可以友善的安裝。
$ fun install --runtime python3 --package-type apt libzbar0
skip pulling image aliyunfc/runtime-python3.6:build-1.2.0...
Task => [UNNAMED]
=> apt-get update (if need)
=> apt-get install -y -d -o=dir::cache=/code/.fun/tmp libzbar0
=> bash -c 'for f in $(ls /code/.fun/tmp/archives/*.deb); do dpkg -x $f /code/.fun/root; done;'
=> bash -c 'rm -rf /code/.fun/tmp/archives'
使用方法及其參數和 pip 包依賴類似,隻需要将
--package-type
設定成
apt
, 包名使用日常 apt-get 可以安裝的 deb 包名即可。
使用 fun.yml
fun.yml 由一組 task 組成,執行 fun install 指令時會依次執行 task ,達到批量安裝的效果。
fun.yml 的檔案格式如下
runtime: python3
tasks:
- name: install libzbar0
apt: libzbar0
local: true
- name install Pillow by pip
pip: Pillow
local: true
- name: just test shell task
shell: echo '111' > 1.txt
runtime
是必填的字段。目前 task 有三種類型:apt, pip 和 shell。fun.yml 檔案放置在 template.yml 檔案中函數 codeUri 指向的目錄,如果 template.yml 裡聲明了多個函數,并且放置在不同的 codeUri 目錄,需要建立多個 fun.yml 檔案。
所有 task 的 name 字段是可選的,沒有 name 字段的時候執行的時候會輸出為
Task => [UNNAMED]
apt/pip task
apt 和 pip 類型的 task 都是 install task 的子類型,描述格式類似
name: install libzbar0
apt: libzbar0
local: true
上面的 task 描述與下面的指令是等價的
fun install --package-type apt libzbar0
在使用 fun install 安裝的過程中,使用
--save
參數可以在目前目錄的 fun.yml 檔案中生成上面 task 的描述結構。
local
字段預設為 true,表示依賴會被裝在目前目錄的 .fun 子目錄下,打包 zip 的時候回一并打包進去。設定為 false,依賴安裝到系統目錄,這種情況一般用于編譯依賴,比如某個執行檔案或者庫是編譯或者建構期需要的,運作期不要,那可以設定
local: false
,打包的時候會被忽略,不影響最終 zip 包的檔案尺寸。
shell task
shell 類型的 task 是為基于源碼編碼的安裝場景設計的。
name: install from source
shell: ./autogen.sh --disable-report-builder --disable-lpsolve --disable-coinmp
示例
下面是一個 python3 實作簡單二維碼識别程式部署到函數計算的例子。源碼位于
https://github.com/aliyun/fun/tree/master/examples/install/pyzbar_example本例子使用 pip 的 pyzbar 庫進行二維碼識别,pyzbar 依賴 apt-get 安裝的 libzbar0 庫。裝載圖檔需要 pip 的 Pillow 庫。是以 fun.yml 的檔案描述如下
runtime: python3
tasks:
- apt: libzbar0
local: true
- pip: Pillow
local: true
- pip: pyzbar
local: true
使用 fun install 安裝依賴
$ fun install
skip pulling image aliyunfc/runtime-python3.6:build-1.2.0...
Task => [UNNAMED]
=> apt-get update (if need)
=> apt-get install -y -d -o=dir::cache=/code/.fun/tmp libzbar0
=> bash -c 'for f in $(ls /code/.fun/tmp/archives/*.deb); do dpkg -x $f /code/.fun/root; done;'
=> bash -c 'rm -rf /code/.fun/tmp/archives'
Task => [UNNAMED]
=> PYTHONUSERBASE=/code/.fun/python pip install --user Pillow
Task => [UNNAMED]
=> PYTHONUSERBASE=/code/.fun/python pip install --user pyzbar
template.yml 檔案内容如下
ROSTemplateFormatVersion: '2015-09-01'
Transform: 'Aliyun::Serverless-2018-04-03'
Resources:
pyzbar-srv:
Type: 'Aliyun::Serverless::Service'
pyzbar-fun:
Type: 'Aliyun::Serverless::Function'
Properties:
Handler: index.handler
Runtime: python3
Timeout: 60
MemorySize: 128
CodeUri: .
index.py 檔案内容如下:
from pyzbar.pyzbar import decode
from pyzbar.pyzbar import ZBarSymbol
from PIL import Image
def handler(event, context):
img = Image.open('./qrcode.png')
return decode(img, symbols=[ZBarSymbol.QRCODE])[0].data
使用 fun local 在本地執行
fun local invoke pyzbar-fun
skip pulling image aliyunfc/runtime-python3.6:1.2.0...
Thalassiodracon
RequestId: 964980d1-1f1b-4f91-bfd8-eadd26a307b3 Billed Duration: 630 ms Memory Size: 1998 MB Max Memory Used: 32 MB
Thalassiodracon
即為識别後的輸出結果。
小結
本文介紹了 fun 工具的一個新特性 fun install ,使用 fun install 可以友善的安裝 apt 和 pip 軟體包,對于多次安裝的工程化需求可以考慮将安裝步驟持久化為 fun.yml 檔案. fun.yml 檔案提供了比指令行更多的功能,可以編寫 shell 類型的 task,以支援源碼安裝的場景。可以通過設定
local: false
将依賴安裝的系統目錄,以解決編譯依賴而非運作依賴的情況。