Argo Workflows build demo

本例将演示如何使用 Argo workflows 来进行一次完整的 CI/CD

  1. 创建demo用的 react 项目,为了更贴近实际项目,这里使用的是一个私有库

在这个仓库中我们准备了一个简单的 react helloworld 项目

2. 创建 docker 权限用的 secrets

kubectl create secret docker-registry regcred --docker-server=https://index.docker.io/v1/ --docker-username=YOURNAME --docker-password=YOURPASSWORD --docker-email=YOUREMAIL@ADDRESS -n argo

3. 准备dockerhub仓库

libaibai/argobuilddemo

4. 创建 build.yaml 文件

参考 https://github.com/argoproj/argo-workflows/blob/master/examples/buildkit-template.yaml

为了方便测试,这里加入了 ttl 并且把官方文档上的 WorkflowTemplate 替换成了 Workflow

官方文档上使用的是 buildkit ,下面的例子中我使用的是 kaniko

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: buildkit-
  namespace: argo
spec:
  ttlStrategy:
    secondsAfterCompletion: 1800 # Time to live after workflow is completed, replaces ttlSecondsAfterFinished
    secondsAfterSuccess: 1800     # Time to live after workflow is successful
    secondsAfterFailure: 1800     # Time to live after workflow fails
  arguments:
    parameters:
      - name: repo
        value: https://username:password@github.com/zl86790/argo_build_demo_react.git
      - name: branch
        value: master
      - name: path
        value: helloworld
      - name: image
        value: libaibai/argobuilddemo:latest
  entrypoint: main
  volumeClaimTemplates:
    - metadata:
        name: work
      spec:
        accessModes: [ "ReadWriteOnce" ]
        # storageClassName: local-storage
        storageClassName: local-path
        resources:
          requests:
            storage: 1Gi
  templates:
    - name: main
      dag:
        tasks:
          - name: clone
            template: clone
            arguments:
              parameters:
                - name: repo
                  value: "{{workflow.parameters.repo}}"
                - name: branch
                  value: "{{workflow.parameters.branch}}"
          - name: install
            template: install
            arguments:
              parameters:
                - name: path
                  value: "{{workflow.parameters.path}}"
            depends: "clone"
          - name: build
            template: build
            arguments:
              parameters:
                - name: path
                  value: "{{workflow.parameters.path}}"
            depends: "install"
          - name: image
            template: image
            arguments:
              parameters:
                - name: path
                  value: "{{workflow.parameters.path}}"
                - name: image
                  value: "{{workflow.parameters.image}}"
            depends: "build"
    - name: clone
      inputs:
        parameters:
          - name: repo
          - name: branch
      container:
        volumeMounts:
          - mountPath: /work
            name: work
        image: alpine/git:v2.26.2
        workingDir: /work
        # Do a shallow clone, which is the fastest way to clone, by using the
        # --depth, --branch, and --single-branch options
        args:
          - clone
          - --depth
          - "1"
          - --branch
          - "{{inputs.parameters.branch}}"
          - --single-branch
          - "{{inputs.parameters.repo}}"
          - .
    - name: install
      inputs:
        parameters:
          - name: path
      container:
        image: node:14.17.3-alpine3.14
        volumeMounts:
          - mountPath: /work
            name: work
        workingDir: /work/{{inputs.parameters.path}}
        env:
          # Because this is not a Gomodule, we must turn modules off.
          - name: ENVTEST
            value: "helloworld"
        command:
          - npm
        args:
          - install
    - name: build
      inputs:
        parameters:
          - name: path
      container:
        image: node:14.17.3-alpine3.14
        volumeMounts:
          - mountPath: /work
            name: work
        workingDir: /work/{{inputs.parameters.path}}
        env:
          # Because this is not a Gomodule, we must turn modules off.
          - name: ENVTEST
            value: "helloworld"
        command:
          - npm
        args:
          - run
          - build
    - name: image
      inputs:
        parameters:
          - name: path
          - name: image
      # Mount the configuration so we can push the image.
      # This should create the /.docker/config.json file.
      volumes:
      - name: jenkins-docker-cfg
        projected:
          sources:
          - secret:
              name: regcred
              items:
                - key: .dockerconfigjson
                  path: .docker/config.json
      container:
        # image: debug-v0.19.0
        image: gcr.io/kaniko-project/executor@sha256:f652f28537fa76e8f4f9393de13a064f0206003c451ce2ad6e4359fd5a21acbc
        volumeMounts:
          - name: work
            mountPath: /work
          - name: jenkins-docker-cfg
            mountPath: /root
        workingDir: /work/{{inputs.parameters.path}}
        env:
          - name: envkey
            value: envvalue
        command:
          - /kaniko/executor
        args:
          - -f
          - /work/{{inputs.parameters.path}}/Dockerfile
          - -c
          - /work/{{inputs.parameters.path}}/
          - --destination={{inputs.parameters.image}}

此例子中使用的

storageClassName: local-path

是通过以下脚本创建的,但是只能使用在 测试环境中 参考 使用hostpath作为VolumeClaimsTemplate

当然如果真的没有办法使用NFS卷或者其他可共享的pv卷,可以考虑使用 nodeselector 将build pod固定在某个特殊的节点上

kubectl apply -f https://raw.githubusercontent.com/rancher/local-path-provisioner/master/deploy/local-path-storage.yaml
kubectl create -f https://raw.githubusercontent.com/rancher/local-path-provisioner/master/examples/pvc/pvc.yaml

使用的Dockerfile

FROM nginx:1.19
COPY build /usr/share/nginx/html

Send a Message