由發(fā)布自定義 API 到華為云所想到的
在 SaaS 版本的零代碼平臺(tái)中,高級(jí)用戶希望能上傳自己編寫的 WebAPI ,來(lái)實(shí)現(xiàn)一些復(fù)雜場(chǎng)景下的業(yè)務(wù)。就需要添加可以通過(guò)上傳程序包進(jìn)行發(fā)布部署的功能。
假設(shè)云服務(wù)器采用華為云,將一個(gè)自定義程序發(fā)布到華為云可以總結(jié)為三個(gè)步驟:
1、將自定義程序包構(gòu)建成鏡像推送到華為云的鏡像倉(cāng)庫(kù);
2、通過(guò) API 的方式創(chuàng)建 Deploment (無(wú)狀態(tài)負(fù)載);
2、通過(guò) API 的方式創(chuàng)建 Service ,并和 Deploment 關(guān)聯(lián);
下面看下簡(jiǎn)單實(shí)現(xiàn)這三個(gè)步驟需要怎么做。
在服務(wù)器上創(chuàng)建目錄 pub ,目錄中創(chuàng)建 Dockerfile 文件,內(nèi)容如下:
FROM?swr.cn-north-4.myhuaweicloud.com/xxx/openjdk:latest
ENV?PARAMS=""
ENV?TZ=PRC
ADD?auto-deploy-demo-0.0.1-SNAPSHOT.jar?/auto-deploy-demo-0.0.1-SNAPSHOT.jar
ENTRYPOINT?["sh","-c","java?-jar?/auto-deploy-demo-0.0.1-SNAPSHOT.jar??$PARAMS"]
From 后面的是在華為云上構(gòu)建的基礎(chǔ) openjdk 鏡像 auto-deploy-demo-0.0.1-SNAPSHOT.jar 為上傳的 jar 包名稱
在 pub 目錄中再創(chuàng)建一個(gè) pub.sh 文件,用來(lái)構(gòu)建鏡像并將鏡像推送到華為云鏡像倉(cāng)庫(kù),pub.sh 內(nèi)容如下:
docker?build?-t?deploy-test?.
docker?login?-u?cn-xxxxxx-4@QYL2XOIAQQLUNJQXU6C7?-p?6ba6cbe87d61045efc9505fcd463cfc1aeceb6?swr.cn-xxxxxx.myhuaweicloud.com
docker?tag?deploy-test:latest?swr.cn-xxxxxx.myhuaweicloud.com/xxxxxx/deploy-test:v1.0
docker?push?swr.cn-xxxxxx.myhuaweicloud.com/xxxxxx/deploy-test:v1.0
首先構(gòu)建本地鏡像 登錄華為云的鏡像倉(cāng)庫(kù) 設(shè)置 tag 并推送鏡像
上傳 jar 包的代碼這里就不放了,下面是連接服務(wù)器并執(zhí)行 pub.sh ?文件的代碼:
@GetMapping("/pushImage")
public?String?pushImage()?throws?IOException?{
????SshClient?sshClient?=?SshClientFactory.createSsh("root","xxxxxx","10.211.55.3",22);
????sshClient.exec("sh?/root/pub/pub.sh",?log?->?{
????});
????return?"ok";
}
可以看到,上面 jar 包的名稱和鏡像的名稱都是寫死的,真實(shí)場(chǎng)景中,會(huì)根據(jù)上傳的包名和配置的鏡像名來(lái)進(jìn)行替換。
鏡像有了,下一步就是創(chuàng)建 Deploment ,也就是華為云的無(wú)狀態(tài)負(fù)載,使用接口的方式來(lái)進(jìn)行創(chuàng)建。
調(diào)用華為云的接口,需要先獲取 token :
private?String?getToken(){
????String?url="https://iam.xxxxxx.myhuaweicloud.com/v3/auth/tokens";
????Map?headerMap?=?new?HashMap<>(8);
????headerMap.put("Content-Type","application/json");
????String?tokenBody="{\n"?+
????"????\"auth\":?{\n"?+
????"????????\"identity\":?{\n"?+
????"????????????\"methods\":?[\n"?+
????"????????????????\"password\"\n"?+
????"????????????],\n"?+
????"????????????\"password\":?{\n"?+
????"????????????????\"user\":?{\n"?+
????"????????????????????\"name\":?\"tokenuser\",\n"?+
????"????????????????????\"password\":?\"password\",\n"?+
????"????????????????????\"domain\":?{\n"?+
????"????????????????????????\"name\":?\"domain\"\n"?+
????"????????????????????}\n"?+
????"????????????????}\n"?+
????"????????????}\n"?+
????"????????},\n"?+
????"????????\"scope\":?{\n"?+
????"????????????\"project\":?{\n"?+
????"????????????????\"name\":?\"xxxxxx\"\n"?+
????"????????????}\n"?+
????"????????}\n"?+
????"????}\n"?+
????"}";
????HttpResponse?httpResponse=?HttpUtil.doPost(url,tokenBody,headerMap);
????//String?result?=?httpResponse.body();
????String?token=httpResponse.header("X-Subject-Token");
????return?token;
}
需要注意的是,獲取 token 接口入?yún)⒅械挠脩裘兔艽a,需要在「統(tǒng)一身份認(rèn)證」模塊中創(chuàng)建一個(gè)單獨(dú)的用戶。
創(chuàng)建的 Deploment 的代碼如下:
@GetMapping("/createDeploment")
public?String?createDeploment(){
????String?token=getToken();
????String?url="https://96284164-xxxx-11ec-a34d-0255ac1015f0.cce.cn-north-4.myhuaweicloud.com/apis/apps/v1/namespaces/default/deployments";
????Map?headerMap?=?new?HashMap<>(8);
????headerMap.put("Content-Type","application/json");
????headerMap.put("X-Auth-Token",token);
????headerMap.put("X-Cluster-ID","96284164-xxxx-11ec-a34d-0255ac1015f0");
????String?deploymentBody="{?\n"?+
????"?????\"apiVersion\":?\"apps/v1\",?\n"?+
????"?????\"kind\":?\"Deployment\",?\n"?+
????"?????\"metadata\":?{?\n"?+
????"?????????\"labels\":?{?\n"?+
????"?????????????\"app\":?\"deploy-test\"?\n"?+
????"?????????},?\n"?+
????"?????????\"name\":?\"deploy-test\"?\n"?+
????"?????},?\n"?+
????"?????\"spec\":?{?\n"?+
????"?????????\"replicas\":?1,?\n"?+
????"?????????\"selector\":?{?\n"?+
????"?????????????\"matchLabels\":?{?\n"?+
????"?????????????????\"app\":?\"deploy-test\"?\n"?+
????"?????????????}?\n"?+
????"?????????},?\n"?+
????"?????????\"template\":?{?\n"?+
????"?????????????\"metadata\":?{?\n"?+
????"?????????????????\"labels\":?{?\n"?+
????"?????????????????????\"app\":?\"deploy-test\"?\n"?+
????"?????????????????}?\n"?+
????"?????????????},?\n"?+
????"?????????????\"spec\":?{?\n"?+
????"?????????????????\"containers\":?[?\n"?+
????"?????????????????????{?\n"?+
????"?????????????????????????\"image\":?\"swr.cn-xxxxxx.myhuaweicloud.com/xxxxxx/deploy-test:v1.0\",?\n"?+
????"?????????????????????????\"imagePullPolicy\":?\"IfNotPresent\",?\n"?+
????"?????????????????????????\"name\":?\"deploy-test\"?\n"?+
????"?????????????????????}?\n"?+
????"?????????????????],?\n"?+
????"?????????????????\"imagePullSecrets\":?[{?\n"?+
????"?????????????????????\"name\":?\"default-secret\"?\n"?+
????"?????????????????}]?\n"?+
????"?????????????}?\n"?+
????"?????????}?\n"?+
????"?????}?\n"?+
????"?}";
????HttpResponse?httpResponse=?HttpUtil.doPost(url,deploymentBody,headerMap);
????String?result=httpResponse.body();
????return?result;
}
image:使用上面推送到華為云鏡像倉(cāng)庫(kù)中的鏡像名稱 接口的入?yún)⑹?json 格式,json 中的內(nèi)容,可以參考已創(chuàng)建的無(wú)狀態(tài)負(fù)載中 Yaml 配置的內(nèi)容,當(dāng)然建議還是深入學(xué)習(xí) k8s 的知識(shí),這些參數(shù)什么意思自然就清楚了
創(chuàng)建完 Deploment 后,還需要?jiǎng)?chuàng)建 Service 才能進(jìn)行訪問(wèn),下面是創(chuàng)建 Service 的代碼:
@GetMapping("/createService")
public?String?createService()?{
????String?token=getToken();
????String?url="https://96284164-xxxx-11ec-a34d-0255ac1015f0.cce.xxxxxx-4.myhuaweicloud.com/api/v1/namespaces/default/services";
????Map?headerMap?=?new?HashMap<>(8);
????headerMap.put("Content-Type","application/json");
????headerMap.put("X-Auth-Token",token);
????headerMap.put("X-Cluster-ID","96284164-xxxx-11ec-a34d-0255ac1015f0");
????String?serviceBody="{?\n"?+
????"?????\"kind\":\"Service\",?\n"?+
????"?????\"apiVersion\":\"v1\",?\n"?+
????"?????\"metadata\":{?\n"?+
????"????????\"name\":\"service-deploy-test\",?\n"?+
????"????????\"creationTimestamp\":null,?\n"?+
????"????????\"labels\":{?\n"?+
????"???????????\"app\":\"deploy-test\"?\n"?+
????"????????}?\n"?+
????"?????},?\n"?+
????"?????\"spec\":{?\n"?+
????"????????\"ports\":[{?\n"?+
????"???????????\"name\":\"http\",?\n"?+
????"???????????\"port\":8082,\n"?+
????"?????????\"protocol\":\"TCP\",??\n"?+
????"???????????\"targetPort\":8080?\n"?+
????"????????}],?\n"?+
????"????????\"selector\":{?\n"?+
????"????????\"app\":\"deploy-test\"?\n"?+
????"????????},?\n"?+
????"???????????????\"type\":\"ClusterIP\"\n"?+
????"????}\n"?+
????"?}";
????HttpResponse?httpResponse=?HttpUtil.doPost(url,serviceBody,headerMap);
????String?result=httpResponse.body();
????return?result;
}
name:service-deploy-test ,服務(wù)的名稱,名稱可以在界面中輸入指定,最終會(huì)拼成訪問(wèn)的地址; app:設(shè)置為 deploy-test ,這個(gè)名稱和 Deploment 的名稱要對(duì)應(yīng)上,否則就掛接不上 type:設(shè)置為 ClusterIP ,表示集群內(nèi)訪問(wèn),集群內(nèi)的容器之間可以訪問(wèn),如果想要外網(wǎng)訪問(wèn),需要設(shè)置為 NodePort ,如果使用了華為云的網(wǎng)關(guān)服務(wù),則需要設(shè)置為 DNAT port:8082 是訪問(wèn)時(shí)的端口 targetPort:8080 是 jar 包程序中監(jiān)聽的端口
依次進(jìn)行鏡像構(gòu)建、創(chuàng)建 Deploment 和 Service 后,在華為云的 cce 無(wú)狀態(tài)負(fù)載中就可以看到 deploy-test 了:

查看詳情的訪問(wèn)方式:

到這,依次調(diào)用三個(gè)接口就能進(jìn)行自定義 API 到華為云 cce 的部署。
上面的三個(gè)步驟是一個(gè)簡(jiǎn)單的發(fā)布部署的過(guò)程,場(chǎng)景很單一,僅僅是將一個(gè) WebAPI 發(fā)布到華為云、形式也很簡(jiǎn)單,只是寫了幾個(gè)簡(jiǎn)單的接口,那么在發(fā)布部署這個(gè)大的場(chǎng)景下,還會(huì)有下面一些情況:
部署環(huán)境可能是阿里云,也可能是自己的服務(wù)器 部署的程序可能是 WebAPI,也可能是后臺(tái)服務(wù)程序 如果用戶想要自己輸入訪問(wèn)的端口,還需要進(jìn)行端口的檢查 在團(tuán)隊(duì)內(nèi)部也有很多的部署的需求存在
通過(guò)上面的場(chǎng)景,可以將三個(gè)簡(jiǎn)單接口的發(fā)布流程演進(jìn)為一個(gè)發(fā)布部署平臺(tái),架構(gòu)圖如下:

1、將上面發(fā)布華為云 cce 的核心功能抽象到發(fā)布平臺(tái)中;
2、發(fā)布平臺(tái)和發(fā)布的使用方進(jìn)行解耦,通過(guò)消息隊(duì)列進(jìn)行連接,因?yàn)槭褂梅娇赡懿恢挂粋€(gè)地方,比如有 SaaS 平臺(tái)和內(nèi)部的運(yùn)維平臺(tái);
3、在發(fā)布平臺(tái)中提供服務(wù)器管理、執(zhí)行組件管理、檢查組件管理、部署管理等;
服務(wù)器管理:管理服務(wù)器的連接,給執(zhí)行組件使用 執(zhí)行組件管理:前面提到的構(gòu)建鏡像、創(chuàng)建 Deploment 、創(chuàng)建 Service 可以封裝成不同的執(zhí)行組件 檢查組件管理:對(duì)執(zhí)行組件中的一些步驟進(jìn)行檢查,比如端口的重復(fù)校驗(yàn) 部署管理:一個(gè)部署中可以包含多個(gè)步驟,每個(gè)步驟中包含執(zhí)行組件和檢查組件
這樣當(dāng)有更多的場(chǎng)景需要滿足的時(shí)候,只需要提供更多的執(zhí)行組件就可以,執(zhí)行組件可以在部署管理中進(jìn)行任意的組合,這也滿足了開放封閉原則。
更進(jìn)一步,可以對(duì)執(zhí)行組件和檢查組件抽象出一套標(biāo)準(zhǔn)的規(guī)范和接口,只要按照要求就能編寫出符合自己業(yè)務(wù)的執(zhí)行組件,并對(duì)接到發(fā)布平臺(tái)中,這樣就更靈活了。如果在企業(yè)內(nèi)部使用,不光是發(fā)布平臺(tái)的開發(fā)人員來(lái)進(jìn)行執(zhí)行組件的編寫,業(yè)務(wù)方的程序員也能根據(jù)規(guī)范編寫自己的執(zhí)行組件。
殊途同歸,想要軟件能滿足變化、足夠靈活,趨勢(shì)就是組件化。在零代碼平臺(tái)中,這種思想也無(wú)處不在,表單是由各種不同的組件(文本框、數(shù)字框等)構(gòu)成的、頁(yè)面也是由各種組件(列表、圖表等)構(gòu)成的、業(yè)務(wù)規(guī)則也是由各種組件(分支控制、循環(huán)控制、賦值等)構(gòu)成的、流程也是由各種組件(審批、消息等)構(gòu)成的,一切皆組件。
周六在微信視頻號(hào)看崔健的演唱會(huì),中間和竇文濤的訪談環(huán)節(jié)中,老崔說(shuō):“現(xiàn)在都講極少主義,但我認(rèn)為極多也是很重要的,是必須經(jīng)歷的過(guò)程,有了這種閱歷才能極少”,我覺(jué)得很有道理。
零代碼產(chǎn)品中就是將復(fù)雜的、極多的東西放在了背后,讓用戶能夠真正去感受那個(gè)極少,我們的目標(biāo)就是要讓產(chǎn)品既簡(jiǎn)單又強(qiáng)大。
下面是我們的一個(gè)零代碼的交流群,歡迎大家進(jìn)群交流。
