Argo workflow 案例練習和配置詳細解析

神奇二進位制發表於2022-02-20

引數化 - parameters

hello-world-parameters.yaml檔案解析

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: hello-world-parameters-
spec:

  entrypoint: whalesay    # 呼叫 whalesay 模板
  arguments:              # 傳遞給函式的引數
    parameters:           # 宣告引數
    - name: message       # Key
      value: hello world  # value

  templates:
  - name: whalesay  # whalesay 模板
    inputs:
      parameters:
      - name: message
    container:
      image: docker/whalesay
      command: [cowsay]
      args: ["{{inputs.parameters.message}}"]

提交此工作流時,可以指定實際引數值

[root@k8s-master01 argo]# argo submit -n argo arguments-parameters.yaml -p message="goodbye world"
[root@k8s-master01 argo]# argo logs -n argo hello-world-parameters-xxx

image-20220210101035695

自定義 Parameter 資料生產端和消費端

output 作為生產端資訊輸出給 input 作為資訊消費端,以parameter引數的方式。

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: output-parameter-
spec:
  entrypoint: output-parameter
  templates:
  - name: output-parameter
    steps:
    # 產生引數
    - - name: generate-parameter
        template: nginx
    # 消費引數
    - - name: consume-parameter
        template: print-message
        arguments:
          parameters:
          - name: message
            value: "{{steps.generate-parameter.outputs.parameters.nginx-index}}"
  # 生產模板 nginx
  - name: nginx
    container:
      image: nginx:latest
      # 輸出 logs,不影響實際的消費資訊
      command: [sh, -c]
      args: ["sleep 1; cat /usr/share/nginx/html/index.html"]
    # 輸出生產資訊
    outputs:
      parameters:
      - name: nginx-index
      # 檢查 path 檔案是否存在,如果不存在,則輸出 "Foobar"
        valueFrom:
          default: "Foobar"
          # 輸出檔案內容,作為 print-message 的輸入內容
          path: /usr/share/nginx/html/index.html
  # 消費模板 print-message
  - name: print-message
    inputs:
      parameters:
      - name: message
    container:
      image: alpine:latest
      # 輸出 outputs 過來的資訊
      command: [echo]
      args: ["{{inputs.parameters.message}}"]

生產端日誌

image-20220212133158906

消費端日誌

image-20220211170647031

steps 型別工作流

hello-hello-hello.yaml檔案解析

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: steps-          # Workflow 的名稱字首
spec:
  entrypoint: hello-hello-hello # 表示第一個執行的模板名稱,讓工作流知道從哪個模板開始執行,類似於 main 函式

  # 該templates中有兩個模板,分別是:hello-hello-hello和whalesay
  templates:
  - name: hello-hello-hello     # 第一個模板 hello-hello-hello 
    steps:                      # template 的型別是 steps
    # 一個 template 有多種型別,分別為:container、script、dag、steps、resource、suspend
    - - name: hello1            # 在 steps 型別中,[--] 表示順序執行,[-] 表示並行執行
        template: whalesay      # 引用 whalesay 模板
        arguments:              # 傳遞給函式的引數
          parameters:           # 宣告引數
          - name: message       # Key
            value: "hello1"     # value
    - - name: hello2a           # [--] 順序執行
        template: whalesay
        arguments:
          parameters:
          - name: message
            value: "hello2a"
      - name: hello2b           # [-] 表示跟上一步並行執行
        template: whalesay
        arguments:
          parameters:
          - name: message
            value: "hello2b"

  - name: whalesay   # 第二個模板 whalesay 
    inputs:          # input、output 實現資料互動
      parameters:
      - name: message
    container:
      image: docker/whalesay  # 映象名稱
      command: [cowsay]       # 執行命令
      args: ["{{inputs.parameters.message}}"]  # 引數引用

上面的工作流規範列印了三種不同的“hello”。hello-hello-hello模板由三個步驟組成。名為hello1的第一步將按順序執行,而名為hello2a和hello2b的後面兩個步驟將並行執行。使用argo CLI命令,我們可以圖形化地顯示這個工作流規範的執行歷史,它顯示了名為hello2a和hello2b的步驟彼此並行執行。

image-20220211094155895

DAG工作流

作為指定步驟序列的另一種方法,您可以通過指定每個任務的依賴關係來將工作流定義為有向無環圖(DAG)。對於複雜的工作流,這可以更容易維護,並且在執行任務時允許最大程度的並行性。

在下面的工作流中,步驟A首先執行,因為它沒有依賴項。一旦A完成,步驟B和步驟C將並行執行。最後,一旦BC完成,步驟D就可以執行了。

dag-diamond.yaml檔案解析

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: dag-diamond-
spec:
  entrypoint: diamond
  # 分別有 echo 和 diamond 兩個模板
  templates:
  - name: echo
    inputs:
      parameters:     # 宣告引數
      - name: message
    container:
      image: alpine:3.7
      command: [echo, "{{inputs.parameters.message}}"]
  # 入口點模板
  - name: diamond
    # DAG宣告
    dag:
      tasks:
      - name: A
        template: echo
        arguments:
          parameters: [{name: message, value: A}]
      - name: B
        # 任務B依賴於任務A
        dependencies: [A]
        template: echo
        arguments:
          parameters: [{name: message, value: B}]
      - name: C
        dependencies: [A]
        template: echo
        arguments:
          parameters: [{name: message, value: C}]
      - name: D
        # 任務D同時依賴於任務B、C
        dependencies: [B, C]
        template: echo
        arguments:
          parameters: [{name: message, value: D}]

image-20220211101622960

Artifacts 工作流

通過 input/output 以及 artifacts 實現 Job 之間資料傳遞。

在工作流中,某些步驟產生或者消費構件,是很常見的需求。通常,前一環節的輸出構件,用作下一環節的輸入構件。

下面的例子包含兩個Step,前一個步驟產生構件供後一個消費。

artifact-passing.yaml檔案解析

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: artifact-passing-
spec:
  entrypoint: artifact-example
  templates:
  - name: artifact-example
    steps:
    # 產生構件
    - - name: generate-artifact
        template: whalesay
    # 消費構件
    - - name: consume-artifact
        template: print-message
        arguments:
          artifacts:
          # 繫結構件名message到generate-artifact,輸出製品庫 hello-art 內容
          - name: message
            from: "{{steps.generate-artifact.outputs.artifacts.hello-art}}"
 
  # 此模板產生構件
  - name: whalesay
    container:
      image: docker/whalesay:latest
      command: [sh, -c]
      args: ["cowsay hello world | tee /tmp/hello_world.txt"] 
    # 輸出構件宣告
    outputs:
      artifacts:
      - name: hello-art            # 生成製品共享 hello-art
        path: /tmp/hello_world.txt # 把這個檔案打包後上傳到製品庫中
 
  # 此模板消費構件
  - name: print-message
    # 輸入構件宣告
    inputs:
      artifacts:
      - name: message
        path: /tmp/message
    container:
      image: alpine:latest
      command: [sh, -c]
      args: ["cat /tmp/message"]

生產資訊

image-20220211100015508

消費資訊

image-20220211100049730

Scripts & Results

很多情況下,我們僅僅希望 Template 來執行一個指令碼:

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: scripts-bash-
spec:
  entrypoint: bash-script-example
  templates:
  - name: bash-script-example
    steps:
    - - name: generate
        # 呼叫其中一個模板,分別有 gen-random-int-bash、python、javascript
        template: gen-random-int-python
    - - name: print
        template: print-message
        arguments:
          parameters:
          - name: message
            # 引用 result 此特殊的輸出引數
            value: "{{steps.generate.outputs.result}}"
 
  - name: gen-random-int-bash
    # 在 script 關鍵字的 source 標籤中,可以編寫指令碼
    # script 還導致執行指令碼時的標準輸出,儲存為名為 result 的特殊輸出引數
    script:
      image: debian:9.4
      command: [bash]
      # Shell 指令碼隨機生成一個數值
      source: |
        cat /dev/urandom | od -N2 -An -i | awk -v f=1 -v r=100 '{printf "%i\n", f + r * $1 / 65536}'
 
  - name: gen-random-int-python
    script:
      image: python:alpine3.6
      command: [python]
      # Python 指令碼隨機生成數值
      source: |
        import random
        i = random.randint(1, 100)
        print(i)
 
  - name: gen-random-int-javascript
    script:
      image: node:9.1-alpine
      command: [node]
      # JS 指令碼隨機生成數值
      source: |
        var rand = Math.floor(Math.random() * 100);
        console.log(rand);

  # 輸出隨機數模板 print-message
  - name: print-message
    inputs:
      parameters:
      - name: message
    container:
      image: alpine:latest
      command: [sh, -c]
      args: ["echo result was: {{inputs.parameters.message}}"]

generate 模板呼叫 gen-random-int-python 任務隨機生成個50數值,print 模板利用result特殊引數呼叫輸出,如圖所示。

image-20220212211251941

image-20220212211302761

退出處理器工作流

Exit handler是一種必然會在工作流結尾執行的模板,不論工作流執行成功與否。它的運用場景包括:

  • 工作流執行後清理
  • 傳送工作流狀態的通知(例如,電子郵件/Slack)
  • 將成功/失敗狀態傳遞為 Webhook 結果(例如GitHub Build Result)
  • 重新提交工作流 或 提交另外一個工作流
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: exit-handlers-
spec:
  entrypoint: intentional-fail
  # 在工作流的末尾呼叫退出處理程式模板
  onExit: exit-handler
  templates:
  # 工作流主模板
  - name: intentional-fail
    container:
      image: alpine:latest
      command: [sh, -c]
      # exit 1 表示工作流異常退出,exit 0 表示工作流成功退出
      args: ["echo intentional failure; exit 1"]
 
  # 退出處理器模板
  # 主模板完成後,工作流狀態可以通過全域性變數{{workflow.status}}獲取,其值是Succeeded, Failed, Error之一
  - name: exit-handler
    steps:
    # 無論工作流是否成功,都會呼叫 send-email 模板
    - - name: notify
        template: send-email
      # 如果工作流等於 Succeeded,才會呼叫 celebrate 模板
      - name: celebrate
        template: celebrate
        when: "{{workflow.status}} == Succeeded"
      # 如果工作流不等於 Succeeded,則會呼叫 cry 模板
      - name: cry
        template: cry
        when: "{{workflow.status}} != Succeeded"
  # send-email 模板資訊
  - name: send-email
    container:
      image: alpine:latest
      command: [sh, -c]
      # 輸出工作流名稱和工作流狀態
      args: ["echo send e-mail: {{workflow.name}} {{workflow.status}}"]
  # celebrate 模板資訊
  - name: celebrate
    container:
      image: alpine:latest
      command: [sh, -c]
      args: ["echo hooray!"]
  # cry 模板資訊
  - name: cry
    container:
      image: alpine:latest
      command: [sh, -c]
      args: ["echo boohoo!"]

接下來分別演示工作流成功和不成功所執行的任務,只需要更改exit 0/1狀態碼即可。

演示工作流不成功:

image-20220212224403703

image-20220212224519835

image-20220212224454586

演示工作流成功:

image-20220212224552604

image-20220212224610458

image-20220212224626056

簡單的將官方案例進行實踐和配置詳細解析,歡迎有研究Argo的大佬們一起交流交流,多多指教!

相關文章