阿里雲K8s+Istio+Knative搭建Serverless平臺

https://yq.aliyun.com/articles/743865javascript


前言

本文以一個Nodejs前端開發者角度出發,從零基於阿里雲平臺能力搭建一個彈性的Serverless平臺的記錄。但願對也想了解這個產品總體的小夥伴們有必定幫助。html

官方文檔:https://help.aliyun.com/document_detail/121509.html
控制檯:https://cs.console.aliyun.com/
前端

爲何是Knative

項目主頁:https://knative.dev/
項目倉庫:https://github.com/knative
java

總結爲下面兩張以前我分享的PPTnode

  • knative 定位:
    enter image description here
  • knative 三大組件:
    enter image description here

前置依賴

  • 建立一個k8s集羣,且集羣中Worker節點的數量大於等於3個。
  • 部署 Istio。

下圖可知它們之間的關係:
enter image description here
git

部署k8s集羣

文檔:https://help.aliyun.com/document_detail/86488.html
Kubernetes 是流行的開源容器編排技術,按照如下步驟快速建立一個k8s集羣
github

  1. 選擇標準託管k8s
  2. 建立專有網絡和虛擬交換機, 不然沒法選擇購買實例規格
  3. 選擇worker實例規格,由於是體驗平臺,故我選擇了3臺最小規格支持Pod的實例, 這是最低要求。由於是託管k8s集羣,故不須要選擇master
    enter image description here
  4. 建立和選擇 密鑰對,後面在本機電腦操做遠端服務的認證
  5. 公網訪問:使用 EIP 暴露 API Server 記得選擇上集羣建立好不能修改, 否則沒法在本機電腦上經過http url 訪問服務
  6. 選擇上日誌服務
  7. 保障帳戶餘額不低於100
  8. 其餘默認配置

點擊建立k8s集羣,全部檢查項經過後,約10 分鐘建立成功全部資源
enter image description here
算法

部署Istio

文檔:https://help.aliyun.com/document_detail/89805.html
Istio爲解決微服務的分佈式應用架構在運維、調試、和安全管理等維度存在的問題,可經過部署Istio建立微服務網絡,並提供負載均衡、服務間認證以及監控等能力,同時Istio不須要修改服務便可實現以上功能
經過下面步驟快速在上面的k8s中部署istio

docker

  1. 選擇對應集羣部署istio
    enter image description here
  2. 若是要實現 Tracing 分佈式追蹤服務,勾選開啓
  3. 在鏈路追蹤服務,打開Region對應信息查看token, 複製與集羣region一直的內網接入http url 到istio配置中
  4. 其餘默認配置,點擊部署,很快相應服務部署成功再k8s集羣上
    enter image description here

部署Knative

文檔:https://help.aliyun.com/document_detail/121509.html
在控制檯左側,找到Knative(公測),選擇組件管理,點擊右上方一鍵部署,部署咱們前面講到的Knative 三大組件
express

  • Tekton 組件 (原build 組件不在推薦) - v0.9.2
  • Serving 組件 - v0.11.0
  • Eventing 組件 - v0.11.0
    enter image description here

檢查未經過,須要開啓 istio-ingressgateway,解決:
在控制檯> 服務網格 > istio管理, 點右側更新
將以下,光標高亮 gateways enabled 默認false 修改成 true, 點擊更新後,
enter image description here


再次部署kantive組件,很快便可部署成功
enter image description here

部署服務

下載Knative 官方服務demo 工程

git clone https://github.com/knative/docs

# nodejs demo 服務
cd docs/serving/samples/hello-world/helloworld-nodejs

查看修復成,你想要的服務

const express = require('express');
const app = express();

app.get('/', (req, res) => {
  console.log('Hello world received a request.');

  const target = process.env.TARGET || 'World';

 // 我添加了輸出,能夠查看流量訪問的不一樣服務版本
  const kRevision = process.env.K_REVISION || '';  
  res.send(`Hello ${target} (revision: ${kRevision}) \n`);
});

const port = process.env.PORT || 8080;
app.listen(port, () => {
  console.log('Hello world listening on port', port);
});

鏡像構建與發佈

# 目前 Docker 官方維護了一個公共倉庫Docker Hub 咱們將本身構建的鏡像發佈上去
# https://hub.docker.com/
# 進行鏡像構建, 其中859652049替換成你的帳號名
docker build -t 859652049/helloworld-nodejs .
# 推送鏡像到公共倉庫Docker Hub
docker push 859652049/helloworld-nodejs

控制檯可視化部署

  1. 回到控制面板 > Knative > 服務管理 > 選擇k8s集羣命名空間default, 建立服務
  2. 支持根據模板快速建立 和 可視化編輯建立。
  3. 咱們選擇可視化建立
  4. 鏡像名稱輸入:docker.io/859652049/helloworld-nodejs (也能夠用你上面本身建立的鏡像)
  5. 配置環境變量 TARGET: NodeX 1 (服務代碼裏用到這個環境變量)
  6. 其餘默認配置,能夠自由配置

    • 最大併發不控制
    • 彈性實例最小0, 最大100
    • CPU 0.25Core, 內存 125M
    • 不掛載額外存儲數據卷

enter image description here

服務部署成功
enter image description here

訪問服務,其中下面的ip 和 host 對應,上圖中默認域名和訪問網關ip

curl -H "HOST: nodejs.default.example.com" http://47.111.223.97

或者經過綁定公網ip 到默認域名上

# 推薦工具SwitchHosts https://github.com/oldj/SwitchHosts/blob/master/README_cn.md
47.111.223.97 nodejs.default.example.com

兩種方式,接口數據返回成功
enter image description here
enter image description here

Kubectl命令行部署

文檔:https://help.aliyun.com/document_detail/86494.html

  1. 安裝 kubectl 客戶端,根據文檔, 我這邊mac 經過docker 客戶端 Preferences 設置中 enable kubernetes 後安裝了。
  2. 配置登陸憑據
  3. 集羣列表,點擊集羣名,選擇KubeConfig(公網訪問)頁籤,並單擊複製,將內容複製到本地計算機的 $HOME/.kube/config
    enter image description here
  4. 執行 kubectl get revisions 查看部署服務的版本,以下能夠看到咱們上面經過控制檯可視化部署的服務nodejs, 一個版本nodejs-dn5vh
    enter image description here

5.經過kubectl 部署新的一個版本

仍是咱們以前使用的 helloworld-nodejs 工程, 將配置文件service.yaml

apiVersion: serving.knative.dev/v1alpha1
kind: Service
metadata:
  name: nodejs # 服務名
  namespace: default  # 服務部署的命名空間
spec:
  template:
    metadata:
      name: nodejs-dn5vh-v2
    spec:
      containers:
      - image: docker.io/859652049/helloworld-nodejs
        env:
        - name: TARGET
          value: "NodeX 2" # 環境變量更新爲2
  traffic:  # 設置流量分配到不一樣服務版本, 也可經過以下圖可視化修改配置
    - tag: current
      revisionName: nodejs-dn5vh # 修改成自動可視化自動生成的版本號
      percent: 50 # 50% 流量版本1
    - tag: candidate
      revisionName: nodejs-dn5vh-v2  # 與當前版本號一致
      percent: 50  # 50% 流量版本2
    - tag: latest
      latestRevision: true
      percent: 0
  1. 部署服務
kubectl --namespace default apply -f ./service.yaml
  1. 屢次訪問服務,流量按比例導入到2個版本
    enter image description here

enter image description here
enter image description here

自定義域名

在Knative Serving route 路由中默認使用 example.com 做爲默認域名,route 徹底定義的域名格式默認爲:
{service}.{namespace}.{default-domain} ,如:nodejs.default.example.com

域名A記錄到網關

  1. 首先你要有個阿里雲備案過的域名,不然最後訪問會顯示須要接入備案
  2. 將域名 A記錄 指向本身的公網網關地址,如上:47.111.223.97
    這個有個注意點,由於服務部署的命名空間和服務名 都會不斷變化,或者有多個。故A記錄時候使用泛域名綁定

好比 dev.lianxuify.com 這個子域名是我用來開發測試的
dev.lianxuify.com
nodejs.default.dev.lianxuify.com
nodejs-1.default.dev.lianxuify.com


  1. 修改默認域名example.com 爲 dev.lianxuify.com

經過控制檯配置

菜單 Knative > 組件管理 > 點擊核心組件Serving 詳情 > 自定義域名模板 > 點擊查看yaml

apiVersion: v1
data:
  _example: |
    ################################
    #                              #
    #    EXAMPLE CONFIGURATION     #
    #                              #
    ################################

    # This block is not actually functional configuration
    # ....
    example.org: |
      selector:
        app: nonprofit

    # Routes having domain suffix of 'svc.cluster.local' will not be exposed
    # through Ingress. You can define your own label selector to assign that
    # ...
    svc.cluster.local: |
      selector:
        app: secret
  # 以上都是註釋
  dev.lianxuify.com: '' # 自定義域名,僅須要添加該行,前面添加兩個空格,與頂部_example對齊
kind: ConfigMap
metadata:
  creationTimestamp: '2020-02-05T15:21:13Z'
  labels:
    serving.knative.dev/release: v0.11.0
  name: config-domain
  namespace: knative-serving
  resourceVersion: '83466654'
  selfLink: /api/v1/namespaces/knative-serving/configmaps/config-domain
  uid: 257133b2-482b-11ea-9d30-8e59b18ed506

yaml語法 基本語法 http://www.ruanyifeng.com/blog/2016/07/yaml.html
yaml轉換爲json: http://www.bejson.com/validators/yaml/

  • 大小寫敏感
  • 使用縮進表示層級關係,幾個空格不重要
  • 縮進時不容許使用Tab鍵,只容許使用空格 已驗證
  • 縮進的空格數目不重要,只要相同層級的元素左側對齊便可
  • #表示註釋
  • | 保留換行符 字符串

經過 kubectl 配置

kubectl edit cm config-domain --namespace knative-serving
# 同上添加一行,保存即生效

# 驗證生效
kubectl get route
# NAME     URL                                       READY   REASON
# nodejs   http://nodejs.default.dev.lianxuify.com   True

enter image description here

路由轉發

當咱們有多個服務使用相同的域名,經過請求的Path不一樣,將流量轉發到不一樣服務中

坑:knative 官方demo 工程,不支持路徑訪問,只處理根路徑訪問。 由於這個一直接口返回失敗,覺得配置搭建問題。

const express = require('express');
const app = express();
// 修改/ 爲 *
// app.get('/', (req, res) => {
app.get('*', (req, res) => {
  // ...
});

//
  1. 修改代碼路由爲*,從新構建鏡像,發佈鏡像 (docker.io/859652049/helloworld-nodejs:latest 已經修改過)
  2. 從新部署服務, 按照上面可視化、或者 kubectl 方式從新部署兩個服務 nodejs、nodejs2

enter image description here

  1. 選擇 Knative > 服務管理 > 點擊服務名 > 選擇路由轉發 > 點擊配置
    enter image description here
  2. 配置保存後當即生效,訪問符合預期

    • dev.lianxuify.com/nodejs 到服務1 nodejs
    • dev.lianxuify.com/nodejs 到服務2 nodejs2

enter image description here
enter image description here

彈性驗證與配置

kubectl get pods -w  // 查看運行的容器組,sidecar+業務服務

以下所示,當沒有流量後 pod 自動會刪除,流量進來會彈性擴展
enter image description here

流量根據以下配置進行擴縮容,可根據業務場景要求配置
Knative > 組件管理 > 點擊Serving組件詳情> 點擊擴縮容配置
enter image description here
這些參數是服務彈性算法的關鍵配置,須要結合業務配置出最佳實踐,鼠標hover小綠點有詳細說明。


日誌監控

在Knative 上對分佈式的日誌,監控接入這裏沒有進行深度探索。文檔總體看下來,流程與常規服務接入沒區別,開通對應產品進行接入便可。
如下是建立集羣默認建立的部分日誌和監控
enter image description here
enter image description here


回滾

在Knative 上對發佈進行回滾,沒有進行深度探索。大體理解以下

  • 回滾歷史版本,經過流量配置修改,將流量切到老版本
  • 對應同版本回滾,找到以下回滾面板
    enter image description here

CICD

持續集成持續交付這塊,還在探索中。看到 GitHub 事件源add-on 組件,經過github 倉庫的鉤子事件能觸發到
Knative平臺去構建鏡像、部署服務。另外一種方式本身監聽gitlab 鉤子事件,構建推送鏡像,調用平臺OpenAPI接口 (如上圖有個觸發從新部署的接口)或者 本身的部署平臺調用kubectl 命令行工具部署

總結

以上咱們利用阿里雲K8s+Istio+Knative 搭建Serverless平臺

  • 部署了k8s集羣
  • 部署了Istio
  • 部署了Knative 三大組件
  • 部署了業務服務,驗證了彈性擴縮容
  • 自定義了域名 + 路由轉發 到不一樣服務
  • 不停服藍綠部署、按流量灰度發佈, 同個服務多個版本

該平臺提供可視化配置 + 以及其yaml配置文件,對一個新手認識、使用這個生態能力有很好的幫助。
整套方案對應傳統服務遷移到Serverless平臺上靈活性、友好性較高,將來大有可爲。但目前開發者工具相關還不是這麼豐富,平臺在公測中,總體使用成本和門檻相對阿里雲函數計算更高些。由於最低集羣3臺worker要求,一直佔用, 我目前是體驗,選擇了低配置,大概是4元多一個小時 (不知道能不能更低)

這裏還有篇我對阿里雲函數計算總體調研的文章: https://yq.aliyun.com/articles/743665但願兩篇文章對你們總體上認識兩款產品,以及搭建serverless有幫助。若有理解有誤,歡迎指出,共同成長。其間感謝阿里雲 @元毅 的幫助與解答。

相關文章
相關標籤/搜索