当前位置:网站首页>Argo workflows - getting started with kubernetes' workflow engine

Argo workflows - getting started with kubernetes' workflow engine

2022-06-27 03:48:00 Learn programming notes

Argo Workflows Kubernetes Workflow engine of

 picture

 picture

What is? Argo Workflows?

Argo Workflows It's an open source project , by Kubernetes Provide container-native Workflow , It is mainly through Kubernetes CRD Realized .

The characteristics are as follows :

  • Each step of the workflow is a container
  • Modeling a multi-step workflow as a series of tasks , Or use a directed acyclic graph (DAG) Describe the dependencies between tasks
  • It can easily run computing intensive jobs for machine learning or data processing in a short time
  • stay Kubernetes Up operation CI/CD Pipeline, No need for complex software configuration

install

Installing the controller end

Argo Wordflows The installation of is very simple , Directly use the following command to install .

kubectl create ns argo
kubectl apply -n argo -f https://raw.githubusercontent.com/argoproj/argo-workflows/stable/manifests/quick-start-postgres.yaml

After installation , Will generate the following 4 individual pod.

# kubectl get po -n argo
NAME                                   READY   STATUS      RESTARTS   AGE
argo-server-574ddc66b-62rjc            1/1     Running     4          4h25m
minio                                  1/1     Running     0          4h25m
postgres-56fd897cf4-k8fwd              1/1     Running     0          4h25m
workflow-controller-77658c77cc-p25ll   1/1     Running     4          4h25m

among :

  • argo-server yes argo Server side
  • mino It is a warehouse for products
  • postgres It's the database
  • workflow-controller It is a process controller

Then configure a server Terminal ingress, Can access UI, The configuration list is as follows ( What I use here is traefik):

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: argo-ui
  namespace: argo
spec:
  entryPoints:
  - web
  routes:
  - match: Host(`argowork-test.coolops.cn`)
    kind: Rule
    services:
    - name: argo-server
      port: 2746

UI The interface is as follows : picture

Configure one more minio Of ingress, The configuration list is as follows :

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: minio
  namespace: argo
spec:
  entryPoints:
  - web
  routes:
  - match: Host(`minio-test.coolops.cn`)
    kind: Rule
    services:
    - name: minio
      port: 9000

UI The interface is as follows ( The default username password is :admin:password): picture

install Client End

Argo Workflows Provide Argo CLI, The installation method is also very simple , as follows :Linux System :

# Download the binary
curl -sLO https://github.com/argoproj/argo/releases/download/v3.0.0-rc4/argo-linux-amd64.gz

# Unzip
gunzip argo-linux-amd64.gz

# Make binary executable
chmod +x argo-linux-amd64

# Move binary to path
mv ./argo-linux-amd64 /usr/local/bin/argo

After installation , Use the following command to verify that the installation was successful .

# argo version
argo: v3.0.0-rc4
  BuildDate: 2021-03-02T21:42:55Z
  GitCommit: ae5587e97dad0e4806f7a230672b998fe140a767
  GitTreeState: clean
  GitTag: v3.0.0-rc4
  GoVersion: go1.13
  Compiler: gc
  Platform: linux/amd64

The main commands are :

list       List workflows 
logs       View the workflow log 
submit     Create workflow 
watch      Monitor workflow in real time 
get        Reality details 
delete     Delete workflow 
stop       Stop workflow 

More commands can be used argo --help To view the .

Then you can use a simple hello world Of WorkFlow, as follows :

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: hello-world-
  namespace: zxl-test
  labels:
    workflows.argoproj.io/archive-strategy: "false"
spec:
  entrypoint: whalesay
  templates:
  - name: whalesay
    container:
      #image: docker/whalesay:latest
      image: 192.168.113.80:10000/zxl-test/whalesay
      command: [cowsay]
      args: ["hello world"]
  - name: gen-random-int
    script:
      #image: python:alpine3.6
      image: 192.168.113.80:10000/zxl-test/python:alpine3.6
      command: [python]
      source: | import random i = random.randint(1, 100) print(i)

Use the following command to create and observe workflow.

$ argo submit -n argo helloworld.yaml --watch

Then you can see the following output .

Name:                hello-world-9pw7v
Namespace:           argo
ServiceAccount:      default
Status:              Succeeded
Conditions:          
 Completed           True
Created:             Mon Mar 08 14:51:35 +0800 (10 seconds ago)
Started:             Mon Mar 08 14:51:35 +0800 (10 seconds ago)
Finished:            Mon Mar 08 14:51:45 +0800 (now)
Duration:            10 seconds
Progress:            1/1
ResourcesDuration:   4s*(1 cpu),4s*(100Mi memory)

STEP                  TEMPLATE  PODNAME            DURATION  MESSAGE
  hello-world-9pw7v  whalesay  hello-world-9pw7v  5s

You can also use argo list To see the status , as follows :

# argo list -n argo
NAME                STATUS      AGE   DURATION   PRIORITY
hello-world-9pw7v   Succeeded   1m    10s        0

Use argo logs To view specific logs , as follows :

# argo logs -n argo hello-world-9pw7v
hello-world-9pw7v:  _____________ 
hello-world-9pw7v: < hello world >
hello-world-9pw7v:  ------------- 
hello-world-9pw7v:     \
hello-world-9pw7v:      \
hello-world-9pw7v:       \     
hello-world-9pw7v:                     ##        .            
hello-world-9pw7v:               ## ## ##       ==            
hello-world-9pw7v:            ## ## ## ##      ===            
hello-world-9pw7v:        /""""""""""""""""___/ ===        
hello-world-9pw7v:   ~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ /  ===- ~~~   
hello-world-9pw7v:        \______ o          __/            
hello-world-9pw7v:         \    \        __/             
hello-world-9pw7v:           \____\______/   

The core concept

Workflow

Workflow yes Argo The most important resource in the world , It mainly has two important functions :

  • It defines the workflow to execute
  • It stores the state of the workflow

The workflow to execute is defined in Workflow.spec Field , It mainly includes templates and entrypoint, as follows :

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: hello-world-  # Workflow Configuration name for 
spec:
  entrypoint: whalesay        #  analysis whalesay templates
  templates:
  - name: whalesay            #  Definition whalesay templates, and entrypoint bring into correspondence with 
    container:                #  Define a container , Output "helloworld"
      image: docker/whalesay
      command: [cowsay]
      args: ["hello world"]   

Templates

templates It's a list structure , There are two main categories :

  • Define specific workflows
  • Call other templates to provide parallel control

Define specific workflows

Define specific workflows 4 Species category , as follows :

  • Container
  • Script
  • Resource
  • Suspend
Container

container Is the most commonly used template type , It will schedule a container, Its formwork specification and K8S The specification of the container is the same , as follows :

  - name: whalesay            
    container:                
      image: docker/whalesay
      command: [cowsay]
      args: ["hello world"]   
Script

Script yes Container Another wrapper implementation of , How it is defined and Container identical , Just added source Fields are used to customize scripts , as follows :

  - name: gen-random-int
    script:
      image: python:alpine3.6
      command: [python]
      source: | import random i = random.randint(1, 100) print(i)

The output of the script will be automatically exported to... According to the calling method { {tasks.<NAME>.outputs.result}} or { {steps.<NAME>.outputs.result}} in .

Resource

Resource Mainly used directly in K8S Perform cluster resource operations on the cluster , Sure get, create, apply, delete, replace, patch Cluster resources . Create one in the cluster as follows ConfigMap Type resources :

  - name: k8s-owner-reference
    resource:
      action: create
      manifest: | apiVersion: v1 kind: ConfigMap metadata: generateName: owned-eg- data: some: value
Suspend

Suspend Mainly used to pause , You can pause for a while , It can also be restored manually , Command to use argo resume Resume . The definition format is as follows :

  - name: delay
    suspend:
      duration: "20s"

Call other templates to provide parallel control

There are also two categories for invoking other templates :

  • Steps
  • Dag
Steps

Steps It mainly defines tasks by defining a series of steps , Its structure is "list of lists", The external list will be executed sequentially , The internal list will be executed in parallel . as follows :

  - name: hello-hello-hello
    steps:
    - - name: step1
        template: prepare-data
    - - name: step2a
        template: run-data-first-half
      - name: step2b
        template: run-data-second-half

among step1 and step2a It's sequential execution , and step2a and step2b It's parallel execution .

You can also use When To make conditional judgments . as follows :

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: coinflip-
spec:
  entrypoint: coinflip
  templates:
  - name: coinflip
    steps:
    - - name: flip-coin
        template: flip-coin
    - - name: heads
        template: heads
        when: "{
   {steps.flip-coin.outputs.result}} == heads"
      - name: tails
        template: tails
        when: "{
   {steps.flip-coin.outputs.result}} == tails"

  - name: flip-coin
    script:
      image: python:alpine3.6
      command: [python]
      source: |
        import random
        result = "heads" if random.randint(0,1) == 0 else "tails"
        print(result)

  - name: heads
    container:
      image: alpine:3.6
      command: [sh, -c]
      args: ["echo \"it was heads\""]

  - name: tails
    container:
      image: alpine:3.6
      command: [sh, -c]
      args: ["echo \"it was tails\""]

Submit this Workflow, The implementation effect is as follows : picture

Besides using When Make condition judgment , It can also be operated circularly , The sample code is as follows :

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: loops-
spec:
  entrypoint: loop-example
  templates:
  - name: loop-example
    steps:
    - - name: print-message
        template: whalesay
        arguments:
          parameters:
          - name: message
            value: "{
   {item}}"
        withItems:
        - hello world
        - goodbye world

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

Submit Workflow, The output is as follows : picture

Dag

Dag It is mainly used to define task dependencies , You can set other tasks that must be completed before starting a specific task , Tasks without any dependencies will be executed immediately . as follows :

  - name: diamond
    dag:
      tasks:
      - name: A
        template: echo
      - name: B
        dependencies: [A]
        template: echo
      - name: C
        dependencies: [A]
        template: echo
      - name: D
        dependencies: [B, C]
        template: echo

among A Will be executed immediately ,B and C Will depend on A,D rely on B and C.

Then run an example to see the effect , Examples are as follows :

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: dag-diamond-
spec:
  entrypoint: diamond
  templates:
  - name: diamond
    dag:
      tasks:
      - name: A
        template: echo
        arguments:
          parameters: [{name: message, value: A}]
      - name: B
        dependencies: [A]
        template: echo
        arguments:
          parameters: [{name: message, value: B}]
      - name: C
        dependencies: [A]
        template: echo
        arguments:
          parameters: [{name: message, value: C}]
      - name: D
        dependencies: [B, C]
        template: echo
        arguments:
          parameters: [{name: message, value: D}]

  - name: echo
    inputs:
      parameters:
      - name: message
    container:
      image: alpine:3.7
      command: [echo, "{
   {inputs.parameters.message}}"]

Submit workflow.

argo submit -n argo dag.yam --watch

 picture image.png

Variables

stay argo Of Workflow Variables are allowed in , as follows :

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: hello-world-parameters-
spec:
  entrypoint: whalesay
  arguments:
    parameters:
      - name: message
        value: hello world
  templates:
    - name: whalesay
      inputs:
        parameters:
          - name: message
      container:
        image: docker/whalesay
        command: [ cowsay ]
        args: [ "{
   {inputs.parameters.message}}" ] 

First, in the spec Field definition arguments, Defining variables message, Its value is hello world, And then in templates Field needs to be defined first inputs Field , be used for templates Input parameters of , And then use "{ {}}" Formal reference variable .

Variables can also perform some function operations , There are mainly :

  • filter: Filter
  • asInt: Convert to Int
  • asFloat: Convert to Float
  • string: Convert to String
  • toJson: Convert to Json

Example :

filter([1, 2], { # > 1})
asInt(inputs.parameters["my-int-param"])
asFloat(inputs.parameters["my-float-param"])
string(1)
toJson([1, 2])

More syntax can be accessed https://github.com/antonmedv/expr/blob/master/docs/Language-Definition.md To study .

Product warehouse

In the installation argo When , Already installed mino As a product warehouse , So how to use it ?

Let's look at an official example , as follows :

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:
          - name: message
            from: "{
   {steps.generate-artifact.outputs.artifacts.hello-art}}"

  - name: whalesay
    container:
      image: docker/whalesay:latest
      command: [sh, -c]
      args: ["sleep 1; cowsay hello world | tee /tmp/hello_world.txt"]
    outputs:
      artifacts:
      - name: 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"]

There are two steps :

  • Generate artifact first
  • Then get the product

Submit Workflow, The operation results are as follows : picture

And then in minio You can see the generated artifacts in , The product has been compressed , as follows : picture

WorkflowTemplate

WorkflowTemplate yes Workflow The template of , It can be downloaded from WorkflowTemplate Internal or cluster Workflow and WorkflowTemplate Quote them .

WorkflowTemplate and template The difference between :

  • template It's just Workflow in templates Next task , When we define a Workflow when , At least one... Needs to be defined template
  • WorkflowTemplate Is resident in the cluster Workflow The definition of , It is Workflow The definition of , Because it contains templates , It can be downloaded from WorkflowTemplate Internal or cluster Workflow and WorkflowTemplate Quote them .

stay 2.7 After version ,WorkflowTemplate The definition and Workflow It's the same definition as , We can simply kind:Workflow Change to kind:WorkflowTemplate. such as :

apiVersion: argoproj.io/v1alpha1
kind: WorkflowTemplate
metadata:
  name: workflow-template-1
spec:
  entrypoint: whalesay-template
  arguments:
    parameters:
      - name: message
        value: hello world
  templates:
    - name: whalesay-template
      inputs:
        parameters:
          - name: message
      container:
        image: docker/whalesay
        command: [cowsay]
        args: ["{
   {inputs.parameters.message}}"]

establish WorkflowTemplate, as follows

argo template create workflowtemplate.yaml

And then in Workflow I quote , as follows :

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: workflow-template-hello-world-
spec:
  entrypoint: whalesay
  templates:
  - name: whalesay
    steps:                              #  Reference template must be in steps/dag/template Next 
      - - name: call-whalesay-template
          templateRef:                  #  Apply template fields 
            name: workflow-template-1   # WorkflowTemplate name 
            template: whalesay-template #  Concrete template name 
          arguments:                    #  Parameters 
            parameters:
            - name: message
              value: "hello world"

ClusterWorkflowTemplate

ClusterWorkflowTemplate Create a cluster wide WorkflowTemplate, other workflow You can quote it .

Define a ClusterWorkflow.

apiVersion: argoproj.io/v1alpha1
kind: ClusterWorkflowTemplate
metadata:
  name: cluster-workflow-template-whalesay-template
spec:
  templates:
  - name: whalesay-template
    inputs:
      parameters:
      - name: message
    container:
      image: docker/whalesay
      command: [cowsay]
      args: ["{
   {inputs.parameters.message}}"]

And then in workflow Use in templateRef To quote it , as follows :

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: workflow-template-hello-world-
spec:
  entrypoint: whalesay
  templates:
  - name: whalesay
    steps:          
      - - name: call-whalesay-template
          templateRef:                  # Reference template 
            name: cluster-workflow-template-whalesay-template   # ClusterWorkflow name 
            template: whalesay-template #  Specific template name 
            clusterScope: true          #  Said is ClusterWorkflow
          arguments:                    #   Parameters 
            parameters:
            - name: message
              value: "hello world"

practice

The above roughly describes argo Basic theoretical knowledge , More theoretical knowledge can be learned on the official website .

The following will use a simple CI/CD practice , To learn how to use argo workflow How to do .

CI/CD The whole process is very simple , namely : Pull code -> compile -> Build a mirror image -> Upload the image -> Deploy .

Define a WorkflowTemplate, as follows :

apiVersion: argoproj.io/v1alpha1
kind: WorkflowTemplate
metadata:
  annotations:
    workflows.argoproj.io/description: |
      Checkout out from Git, build and deploy application.
    workflows.argoproj.io/maintainer: '@joker'
    workflows.argoproj.io/tags: java, git
    workflows.argoproj.io/version: '>= 2.9.0'
  name: devops-java 
spec:
  entrypoint: main
  arguments:
    parameters:
      - name: repo
        value: gitlab-test.coolops.cn/root/springboot-helloworld.git
      - name: branch
        value: master
      - name: image
        value: registry.cn-hangzhou.aliyuncs.com/rookieops/myapp:202103101613
      - name: cache-image
        value: registry.cn-hangzhou.aliyuncs.com/rookieops/myapp
      - name: dockerfile
        value: Dockerfile
      - name: devops-cd-repo
        value: gitlab-test.coolops.cn/root/devops-cd.git
      - name: gitlabUsername
        value: devops
      - name: gitlabPassword
        value: devops123456
  templates:
    - name: main
      steps:
        - - name: Checkout
            template: Checkout
        - - name: Build
            template: Build
        - - name: BuildImage
            template: BuildImage
        - - name: Deploy
            template: Deploy
    #  Pull the code 
    - name: Checkout
      script:
        image: registry.cn-hangzhou.aliyuncs.com/rookieops/maven:3.5.0-alpine
        workingDir: /work
        command:
        - sh
        source: |
          git clone --branch {
   {workflow.parameters.branch}} http://{
   {workflow.parameters.gitlabUsername}}:{
   {workflow.parameters.gitlabPassword}}@{
   {workflow.parameters.repo}} .
        volumeMounts:
          - mountPath: /work
            name: work
    #  Compile the package   
    - name: Build
      script:
        image: registry.cn-hangzhou.aliyuncs.com/rookieops/maven:3.5.0-alpine
        workingDir: /work
        command:
        - sh
        source: mvn -B clean package -Dmaven.test.skip=true -Dautoconfig.skip
        volumeMounts:
          - mountPath: /work
            name: work
    #  Build a mirror image   
    - name: BuildImage
      volumes:
      - name: docker-config
        secret:
          secretName: docker-config
      container:
        image: registry.cn-hangzhou.aliyuncs.com/rookieops/kaniko-executor:v1.5.0
        workingDir: /work
        args:
          - --context=.
          - --dockerfile={
   {workflow.parameters.dockerfile}}
          - --destination={
   {workflow.parameters.image}}
          - --skip-tls-verify
          - --reproducible
          - --cache=true
          - --cache-repo={
   {workflow.parameters.cache-image}}
        volumeMounts:
          - mountPath: /work
            name: work
          - name: docker-config
            mountPath: /kaniko/.docker/
    #  Deploy   
    - name: Deploy
      script:
        image: registry.cn-hangzhou.aliyuncs.com/rookieops/kustomize:v3.8.1
        workingDir: /work
        command:
        - sh
        source: |
           git remote set-url origin http://{
   {workflow.parameters.gitlabUsername}}:{
   {workflow.parameters.gitlabPassword}}@{
   {workflow.parameters.devops-cd-repo}}
           git config --global user.name "Administrator"
           git config --global user.email "[email protected]"
           git clone http://{
   {workflow.parameters.gitlabUsername}}:{
   {workflow.parameters.gitlabPassword}}@{
   {workflow.parameters.devops-cd-repo}} /work/devops-cd
           cd /work/devops-cd
           git pull
           cd /work/devops-cd/devops-simple-java
           kustomize edit set image {
   {workflow.parameters.image}}
           git commit -am 'image update'
           git push origin master
        volumeMounts:
          - mountPath: /work
            name: work
  volumeClaimTemplates:
    - name: work
      metadata:
        name: work
      spec:
        storageClassName: nfs-client-storageclass
        accessModes: [ "ReadWriteOnce" ]
        resources:
          requests:
            storage: 1Gi 

explain :

1、 Use kaniko To create images , No mounting docker.sock, however push When you mirror, you need to config.json, So first you need to create a secret, as follows :

kubectl create secret generic docker-config --from-file=.docker/config.json -n argo

2、 Get ready storageClass, Of course not , Use it directly empty, However, these cache files can be persisted , It can speed up the construction of ( I didn't do it ).

3、 establish WorkflowTemplate, The order is as follows :

argo template create -n argo devops-java.yaml

After creation , Can be in UI The newly created... Is displayed in the interface WorkflowTemplate, as follows : picture

4、 establish Workflow, You can create... Manually , as follows :

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: workflow-template-devops-java-
spec:
  workflowTemplateRef:
    name: devops-java

You can also directly UI Click create in the interface , I'm here directly UI Click create in the interface . Select the one you just created WorkflowTemplate, Click Create , as follows : picture Then it will generate a Workflow, as follows : picture Click in , You can see each specific step , as follows  picture Click on each specific step , You can look at the log , as follows : picture You can also see... In the command line interface Workflow The results of the implementation of , as follows : picture This is the end of the first use , It will be gradually optimized in the later stage .

Reference documents

  • https://github.com/argoproj/argo-workflows/releases
  • https://argoproj.github.io/argo-workflows
  • https://github.com/antonmedv/expr/blob/master/docs/Language-Definition.md
  • https://github.com/argoproj/argo-workflows/tree/master/examples
原网站

版权声明
本文为[Learn programming notes]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/178/202206270336330858.html