如何使用k3OS和Argo進行自動化邊緣部署?

k3s中文社群發表於2020-07-30

本文轉自邊緣計算k3s社群

前 言

隨著Kubernetes生態系統的發展,新的技術正在被開發出來,以實現更廣泛的應用和用例。邊緣計算的發展推動了對其中一些技術的需求,以實現將Kubernetes部署到網路邊緣資源受限的基礎設施上。在這篇文章中,我們將向你介紹一種將k3OS部署到邊緣的方法。你可以使用這種方法將你的邊緣機自動註冊到Rancher例項中作為控制平面。我們還將討論自動部署到物理機的一些好處。

k3OS於2019年4月由業界應用最為廣泛的Kubernetes管理平臺建立者Rancher Labs(以下簡稱Rancher)推出,它是一個輕量的、專注於邊緣的Kubernetes作業系統,同時也是業界首個Kubernetes作業系統。它與K3s打包,使得應用程式能夠輕鬆地部署到資源受限的環境中,如部署在邊緣裝置上。

雖然k3OS仍處於起步階段,但它已經通過了實戰測試,並被用於各種生產環境中。為了充分掌握邊緣計算的全部優勢,你需要在你部署的基礎設施上儘可能地節省空間。

Argo簡介

Argo是雲原生計算基金會(CNCF)的一個專案,旨在減輕在容器原生環境中執行計算密集型工作負載的一些痛苦。子專案Argo workflow是一個開源的容器原生workflow引擎,用於協調Kubernetes中的並行job。它以Kubernetes自定義資源(CRD)的形式實現,本質上是Kubernetes API的擴充套件。

通過Argo workflow,我們可以定義workflow,其中的每一步都是一個容器,並將多步工作流建模為任務序列,或使用有向無環圖(DAG)捕獲任務之間的依賴關係。這在自動化部署和配置邊緣原生服務時非常有用。我們將在本次demo的後面看到Argo Workflows的許多方面將會發揮作用。

Step 1 設定一個demo環境

為了模擬一個工作邊緣站點,我們需要在本地虛擬機器上啟動k3OS,然後使用Argo工作流呼叫到遠端Rancher例項。在本節中,我們將:

  • 下載k3OS iso

  • 部署Rancher

  • 安裝Argo Workflows

設定本地VM(邊緣端)

安裝VirtualBox不在本次演示的範圍內,因此預設你已經安裝完成。然後,我們將其啟動並完成設定虛擬機器和附加k3OS iso的初始過程。完成之後,我們將啟動機器並看到介紹螢幕:

在這裡插入圖片描述

此時,我們將開啟一個terminal並新增k3OS VM到我們的config.yaml檔案。我們可以使用這個方便的幫忙指令碼:

# Pull k3OS credentials
get_vm() {
gsed -i '/127.0.0.1/d' ~/.ssh/known_hosts
scp -P 3022 rancher@127.0.0.1:/etc/rancher/k3s/k3s.yaml ~/.kube/current_k3os_vm.yaml
sed 's/6443/4443/g' ~/.kube/current_k3os_vm.yaml > ~/.kube/current_k3os_master.yaml
export KUBECONFIG=~/.kube/current_k3os_master.yaml
rm ~/.kube/current_k3os_vm.yaml
}

請注意:需要轉發3022和4443埠

我們成功拉取.kubeconfig檔案之後,我們應該準備好部署控制平面。

部署Rancher(雲端)

要部署Rancher到雲端環境,請執行以下步驟:

  1. Clone或下載該倉庫(https://github.com/rancher/quickstart)到本地資料夾

  2. 選擇一個雲提供商並導航到提供商的資料夾中

  3. 將terraform.tfvars.example複製或重新命名為terraform.tfvars並填入所有必要的變數

  4. 執行terraform init

  5. 執行terraform apply

當配置完成之後,Terraform將輸出連線到Rancher伺服器的URL。還會生成兩套Kubernetes配置:

Apply complete! Resources: 16 added, 0 changed, 0 destroyed.

Outputs:

rancher_node_ip = xx.xx.xx.xx
rancher_server_url = https://xx-xx-xx-xx.nip.io
workload_node_ip = yy.yy.yy.yy

kube_config_server.yaml包含了訪問支援Rancher server的RKE叢集的憑證, kube_config_workload.yaml包含了訪問配置工作負載叢集的憑證。

有關每個雲提供商的更多詳情,請參閱 repo 中各自資料夾中的文件。

Step 2 安裝Argo Workflow

安裝Argo CLI:

你可以從Argo release頁面下載最新的Argo CLI:

https://github.com/argoproj/argo/releases

安裝controller:

在這一步中,我們將安裝Argo Workflows,通過workflow CRD擴充套件Kubernetes API。這將允許我們將多個“job”依次鏈在一起。安裝Argo Workflows就像切換到k3OS叢集並執行一樣簡單:

kubectl create namespace argo
kubectl apply -n argo -f https://raw.githubusercontent.com/argoproj/argo/stable/manifests/install.yaml

請注意:在GKE上,你可能需要授予你的賬戶建立新叢集角色的能力。

kubectl create clusterrolebinding YOURNAME-cluster-admin-binding --clusterrole=cluster-admin --user=YOUREMAIL@gmail.com

Step 3 配置服務賬戶以執行workflows

角色、角色繫結以及ServiceAccount

為了讓Argo支援工件、輸出、訪問secret等功能,它需要使用Kubernetes API與Kubernetes資源進行通訊。為了做到這一點,Argo使用ServiceAccount來驗證自己與Kubernetes API的關係。你可以通過使用RoleBinding將一個Role繫結到ServiceAccount上,指定Argo使用的ServiceAccount是哪個Role(即哪個許可權)。

然後,在提交workflow時,指定Argo使用哪個ServiceAccount:

argo submit --serviceaccount <name>

當沒有提供ServiceAccount時,Argo將使用執行的名稱空間的預設ServiceAccount,預設情況下它的許可權幾乎總是不夠的。

授予管理員許可權

在本次demo中,我們將授予defaultServiceAccount管理員許可權(即我們將繫結adminRole到當前名稱空間的defaultServiceAccount中):

kubectl create rolebinding default-admin --clusterrole=admin --serviceaccount=argo:default -n argo

請注意:這將向命令執行的名稱空間中的default ServiceAccount授予管理許可權,因此你將只能在製作RoleBinding的名稱空間中執行workflows。

Step 4 執行workflow

從這裡,你可以通過CLI以多種方式提交Argo workflow:

argo submit -n argo --watch https://raw.githubusercontent.com/argoproj/argo/master/examples/hello-world.yaml
argo submit -n argo --watch https://raw.githubusercontent.com/argoproj/argo/master/examples/coinflip.yaml
argo submit -n argo --watch https://raw.githubusercontent.com/argoproj/argo/master/examples/loops-maps.yaml
argo list -n argo
argo get xxx-workflow-name-xxx -n argo
argo logs xxx-pod-name-xxx -n argo #from get command above

你也能使用kubectl直接建立Workflow,但是Argo CLI會提供諸如YAML驗證、workflow視覺化、引數傳遞、重試以及重新提交、暫停和恢復等額外的功能:

kubectl create -n argo -f https://raw.githubusercontent.com/argoproj/argo/master/examples/hello-world.yaml
kubectl get wf -n argo
kubectl get wf hello-world-xxx -n argo
kubectl get po -n argo --selector=workflows.argoproj.io/workflow=hello-world-xxx
kubectl logs hello-world-yyy -c main -n argo

所以,我們建立一個workflow.yaml檔案並把這裡的內容全部加進去:

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  name: cluster-up
spec:
  serviceAccountName: argo-serviceaccount
  entrypoint: main
  templates:
    - name: main
      steps:
        - - name: rancher-dance
            template: rancher-dance

    - name: rancher-dance
      inputs:
        artifacts:
          - name: kubectl
            path: /bin/kubectl
            mode: 0755
            http:
              url: https://storage.googleapis.com/kubernetes-release/release/v1.18.0/bin/linux/amd64/kubectl
      container:
        image: giantswarm/tiny-tools:3.10
        command:
          - /bin/sh
          - -c
          - |
            echo "Log in to Rancher"
            LOGIN_RESPONSE=$(curl -s "https://$RANCHER_URI/v3-public/localProviders/local?action=login" \
              -H 'content-type: application/json' \
              --data-binary '{"username":"'$RANCHER_USER'","password":"'$RANCHER_PASS'"}')

            LOGIN_TOKEN=$(echo $LOGIN_RESPONSE | jq -r .token)

            echo "Obtain Rancher API token"
            API_RESPONSE=$(curl -s "https://$RANCHER_URI/v3/token" \
              -H 'content-type: application/json' \
              -H "Authorization: Bearer $LOGIN_TOKEN" \
              --data-binary '{"type":"token","description":"automation"}')

            API_TOKEN=$(echo $API_RESPONSE | jq -r .token)

            echo "Configure server-url"
            RANCHER_SERVER_URL="https://$RANCHER_URI/latest/meta-data/public-ipv4"
            curl -s 'https://$RANCHER_URI/v3/settings/server-url' \
              -H 'content-type: application/json' -H "Authorization: Bearer $API_TOKEN" \
              -X PUT --data-binary '{"name":"server-url","value":"'$RANCHER_SERVER_URL'"}'

            echo "Create the cluster, or get the info on an existing cluster"
            CLUSTER_RESPONSE=$(curl -sf "https://$RANCHER_URI/v3/cluster" \
              -H 'content-type: application/json' -H "Authorization: Bearer $API_TOKEN" \
              --data-binary '{"type": "cluster",
                "name": "'$CLUSTER_NAME'",
                "enableClusterAlerting":true,
                "enableClusterMonitoring":false}'\
                || curl -s "https://$RANCHER_URI/v3/cluster?name=$CLUSTER_NAME" \
                -H 'content-type: application/json' \
                -H "Authorization: Bearer $API_TOKEN" \
                | jq ".data | .[]" )

            echo "Extract the cluster ID"
            CLUSTER_ID=$(echo $CLUSTER_RESPONSE | jq -r .id)

            echo "Generate the cluster registration token"
            CLUSTER_JSON=$(curl -s "https://$RANCHER_URI/v3/clusterregistrationtoken" \
              -H 'content-type: application/json' -H "Authorization: Bearer $API_TOKEN" \
              --data-binary '{"type":"clusterRegistrationToken","clusterId":"'$CLUSTER_ID'"}')

            echo "Extract the cluster registration token"
            CLUSTER_TOKEN=$(echo $CLUSTER_JSON | jq -r .token)

            echo "Notify Slack of import"
            curl -s "https://$RANCHER_URI/v3/notifiers" \
              -H 'content-type: application/json' \
              -H "Authorization: Bearer $API_TOKEN" \
              --data-binary  '{"clusterId":"'$CLUSTER_ID'",
                "name":"slack-alerter",
                "namespaceId":"",
                "pagerdutyConfig":null,
                "sendResolved":true,
                "slackConfig":{"url":"'$SLACK_WEBHOOK_URI'"},
                "smtpConfig":null,
                "webhookConfig":null,
                "wechatConfig":null}'

            echo "Retrieve and Apply Manifests"
            kubectl apply -f "https://$RANCHER_URI/v3/import/$CLUSTER_TOKEN.yaml"
        env:
          - name: RANCHER_URI
            value: "x.x.x.x.x.x"
          - name: CLUSTER_NAME
            valueFrom:
              configMapKeyRef:
                name: cluster-name
                key: CLUSTER_NAME
          - name: RANCHER_USER
            valueFrom:
              secretKeyRef:
                name: rancher-credentials
                key: RANCHER_USER
          - name: RANCHER_PASS
            valueFrom:
              secretKeyRef:
                name: rancher-credentials
                key: RANCHER_PASS
          - name: SLACK_WEBHOOK_URI
            value: https://hooks.slack.com/services/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

在一個較高的層次上,這個workflow本質上是將一個指令碼作為一個pod在我們的叢集中執行,並允許它使用某些變數。

  • 登入到Rancher API

  • cURL,一個Rancher API令牌,使用TinyTools

  • 將Rancher server的URL設定為一個變數。

  • 提取叢集ID

  • 檢索和應用manifest

接下來,我們要把workflow cd到目錄中,然後執行:

argo submit -n argo workflow.yaml

你可以看到workflow在你的叢集中配置一個名為cluster-up的pod,它將會與Rancher連線:

在這裡插入圖片描述

總結:為什麼要在邊緣自動執行任務

現在你已經瞭解瞭如何使用k3OS和Argo進行自動化邊緣部署,讓我們來討論一下為什麼這種型別的自動化如此重要。在為工業物聯網(IIOT)等業務啟動物理機器時,自動化這些任務是有益的,與機器互動的人是硬體技術人員,而不是雲工程師。

在邊緣,往往物理機器的配置是很費力的——但不應該一次只配置一臺。通過這種方法,技術人員可以簡單地插入類似USB的東西,它會啟動一個ISO,然後執行一個指令碼來啟動機器的配置,然後註冊到控制平面。

相關文章