droneのpipelineの原理とコードの分析

16170 ワード

最近のプロジェクトでは、以前のCICDの経験に基づいてjenkins pipelineとdroneのpipelineが候補に入る作業タスクフロー(task pipeline)を実現する必要がある.
droneはgoに基づくcicdソリューションでgithubには1.6万+starがあり,jenkinsとの違いを簡単に比較し,droneのpipeline原理を重点的に紹介し,コードを簡単に解析した.
Jenkinsとdrone
ひかくこうもく
jenkins
drone
pipeline定義
jenkinsfileの作成
プロセスymlの作成
運転モード
1つのpodで実行
ステップごとに対応するcontainerを急上昇させ、volumeをマウントすることでデータ共有を実現
実行環境
K 8 Sを含む物理マシンまたはコンテナ環境
dockerコンテナ環境
開発言語
java
golang
drone pipelineの利点は比較的軽量級で、yml定義も比較的簡潔で明確で、機能によって容器を区分し、taskの多重化を容易に実現することができるが、jenkinsは完全に1つのミラーにパッケージされ、jenkinsの1つのミラーの体積が2 Gを超えるなど、1つのミラーの体積が大きすぎる.
droneのpipelineは、https://github.com/cncd/pipeline実現したのは,ここでその原理を簡単に分析することである.
drone pipelineのコンパイルと実行
一つのプログラムの原理を理解するには、まず入出力から話します.
先にインストール:
go get -u github.com/cncd/pipeline
go install github.com/cncd/pipeline/pipec

そしてテスト
cd $GOPATH/github.com/cncd/pipeline/samples/sample_1
# ll
total 28
drwxr-xr-x  2 root root 4096 Jan 22 11:44 ./
drwxr-xr-x 13 root root 4096 Jan 22 11:02 ../
-rw-r--r--  1 root root  549 Jan 22 11:02 .env
-rw-r--r--  1 root root 6804 Jan 22 16:30 pipeline.json
-rw-r--r--  1 root root  229 Jan 22 11:02 pipeline.yml
-rw-r--r--  1 root root  138 Jan 22 11:02 README.md

  • pipeline.yml定義ファイル
  • pipeline.jsonコンパイル後のプロファイル
  • .Env環境変数
  • まず、pipeline.yml定義を参照してください.
    workspace:
      base: /go
      path: src/github.com/drone/envsubst
    
    clone:
      git:
        image: plugins/git
        depth: 50
    
    pipeline:
      build:
        image: golang:1.7
        commands:
          - go get -t ./...
          - go build
          - go test -v

    上のymlは次のように定義されています.
  • ワーキングディレクトリワークスペース
  • 初期化作業、git clone倉庫、倉庫住所は.Envで定義されている
  • そしてpipelineを定義し、
  • pipelineの下にstep配列があり、ここにはbuild
  • が1つしかありません.
  • golang:1.7ミラー
  • を使用
  • 構築コマンドcommands配列で
  • を定義する
    pipec compile compileプロファイルから:
    # pipec compile
    Successfully compiled pipeline.yml to pipeline.json

    コンパイルされたpipeline.jsonの表示
    {
      "pipeline": [
        {
          "name": "pipeline_clone_0",
          "alias": "git",
          "steps": [
            {
              "name": "pipeline_clone_0",
              "alias": "git",
              "image": "plugins/git:latest",
              "working_dir": "/go/src/github.com/drone/envsubst",
              "environment": {
                "CI": "drone",
                "CI_BUILD_CREATED": "1486119586",
                "CI_BUILD_EVENT": "push",
                "CI_BUILD_NUMBER": "6",
                "CI_BUILD_STARTED": "1486119585",
                "CI_COMMIT_AUTHOR": "bradrydzewski",
                "CI_COMMIT_AUTHOR_NAME": "bradrydzewski",
                "CI_COMMIT_BRANCH": "master",
                "CI_COMMIT_MESSAGE": "added a few more test cases for escaping behavior",
                "CI_COMMIT_REF": "refs/heads/master",
                "CI_COMMIT_SHA": "d0876d3176965f9552a611cbd56e24a9264355e6",
                "CI_REMOTE_URL": "https://github.com/drone/envsubst.git",
                "CI_REPO": "drone/envsubst",
                "CI_REPO_LINK": "https://github.com/drone/envsubst",
                "CI_REPO_NAME": "drone/envsubst",
                "CI_REPO_REMOTE": "https://github.com/drone/envsubst.git",
                "CI_SYSTEM": "pipec",
                "CI_SYSTEM_ARCH": "linux/amd64",
                "CI_SYSTEM_LINK": "https://github.com/cncd/pipec",
                "CI_SYSTEM_NAME": "pipec",
                "CI_WORKSPACE": "/go/src/github.com/drone/envsubst",
                "DRONE": "true",
                "DRONE_ARCH": "linux/amd64",
                "DRONE_BRANCH": "master",
                "DRONE_BUILD_CREATED": "1486119586",
                "DRONE_BUILD_EVENT": "push",
                "DRONE_BUILD_LINK": "https://github.com/cncd/pipec/drone/envsubst/6",
                "DRONE_BUILD_NUMBER": "6",
                "DRONE_BUILD_STARTED": "1486119585",
                "DRONE_COMMIT": "d0876d3176965f9552a611cbd56e24a9264355e6",
                "DRONE_COMMIT_AUTHOR": "bradrydzewski",
                "DRONE_COMMIT_BRANCH": "master",
                "DRONE_COMMIT_MESSAGE": "added a few more test cases for escaping behavior",
                "DRONE_COMMIT_REF": "refs/heads/master",
                "DRONE_COMMIT_SHA": "d0876d3176965f9552a611cbd56e24a9264355e6",
                "DRONE_JOB_STARTED": "1486119585",
                "DRONE_REMOTE_URL": "https://github.com/drone/envsubst.git",
                "DRONE_REPO": "drone/envsubst",
                "DRONE_REPO_LINK": "https://github.com/drone/envsubst",
                "DRONE_REPO_NAME": "envsubst",
                "DRONE_REPO_OWNER": "drone",
                "DRONE_REPO_SCM": "git",
                "DRONE_WORKSPACE": "/go/src/github.com/drone/envsubst",
                "PLUGIN_DEPTH": "50"
              },
              "volumes": [
                "pipeline_default:/go"
              ],
              "networks": [
                {
                  "name": "pipeline_default",
                  "aliases": [
                    "git"
                  ]
                }
              ],
              "on_success": true,
              "auth_config": {}
            }
          ]
        },
        {
          "name": "pipeline_stage_0",
          "alias": "build",
          "steps": [
            {
              "name": "pipeline_step_0",
              "alias": "build",
              "image": "golang:1.7",
              "working_dir": "/go/src/github.com/drone/envsubst",
              "environment": {
                "CI": "drone",
                "CI_BUILD_CREATED": "1486119586",
                "CI_BUILD_EVENT": "push",
                "CI_BUILD_NUMBER": "6",
                "CI_BUILD_STARTED": "1486119585",
                "CI_COMMIT_AUTHOR": "bradrydzewski",
                "CI_COMMIT_AUTHOR_NAME": "bradrydzewski",
                "CI_COMMIT_BRANCH": "master",
                "CI_COMMIT_MESSAGE": "added a few more test cases for escaping behavior",
                "CI_COMMIT_REF": "refs/heads/master",
                "CI_COMMIT_SHA": "d0876d3176965f9552a611cbd56e24a9264355e6",
                "CI_REMOTE_URL": "https://github.com/drone/envsubst.git",
                "CI_REPO": "drone/envsubst",
                "CI_REPO_LINK": "https://github.com/drone/envsubst",
                "CI_REPO_NAME": "drone/envsubst",
                "CI_REPO_REMOTE": "https://github.com/drone/envsubst.git",
                "CI_SCRIPT": "CmlmIFsgLW4gIiRDSV9ORVRSQ19NQUNISU5FIiBdOyB0aGVuCmNhdCA8PEVPRiA+ICRIT01FLy5uZXRyYwptYWNoaW5lICRDSV9ORVRSQ19NQUNISU5FCmxvZ2luICRDSV9ORVRSQ19VU0VSTkFNRQpwYXNzd29yZCAkQ0lfTkVUUkNfUEFTU1dPUkQKRU9GCmNobW9kIDA2MDAgJEhPTUUvLm5ldHJjCmZpCnVuc2V0IENJX05FVFJDX1VTRVJOQU1FCnVuc2V0IENJX05FVFJDX1BBU1NXT1JECnVuc2V0IENJX1NDUklQVAp1bnNldCBEUk9ORV9ORVRSQ19VU0VSTkFNRQp1bnNldCBEUk9ORV9ORVRSQ19QQVNTV09SRAoKZWNobyArICJnbyBnZXQgLXQgLi8uLi4iCmdvIGdldCAtdCAuLy4uLgoKZWNobyArICJnbyBidWlsZCIKZ28gYnVpbGQKCmVjaG8gKyAiZ28gdGVzdCAtdiIKZ28gdGVzdCAtdgoK",
                "CI_SYSTEM": "pipec",
                "CI_SYSTEM_ARCH": "linux/amd64",
                "CI_SYSTEM_LINK": "https://github.com/cncd/pipec",
                "CI_SYSTEM_NAME": "pipec",
                "CI_WORKSPACE": "/go/src/github.com/drone/envsubst",
                "DRONE": "true",
                "DRONE_ARCH": "linux/amd64",
                "DRONE_BRANCH": "master",
                "DRONE_BUILD_CREATED": "1486119586",
                "DRONE_BUILD_EVENT": "push",
                "DRONE_BUILD_LINK": "https://github.com/cncd/pipec/drone/envsubst/6",
                "DRONE_BUILD_NUMBER": "6",
                "DRONE_BUILD_STARTED": "1486119585",
                "DRONE_COMMIT": "d0876d3176965f9552a611cbd56e24a9264355e6",
                "DRONE_COMMIT_AUTHOR": "bradrydzewski",
                "DRONE_COMMIT_BRANCH": "master",
                "DRONE_COMMIT_MESSAGE": "added a few more test cases for escaping behavior",
                "DRONE_COMMIT_REF": "refs/heads/master",
                "DRONE_COMMIT_SHA": "d0876d3176965f9552a611cbd56e24a9264355e6",
                "DRONE_JOB_STARTED": "1486119585",
                "DRONE_REMOTE_URL": "https://github.com/drone/envsubst.git",
                "DRONE_REPO": "drone/envsubst",
                "DRONE_REPO_LINK": "https://github.com/drone/envsubst",
                "DRONE_REPO_NAME": "envsubst",
                "DRONE_REPO_OWNER": "drone",
                "DRONE_REPO_SCM": "git",
                "DRONE_WORKSPACE": "/go/src/github.com/drone/envsubst",
                "HOME": "/root",
                "SHELL": "/bin/sh"
              },
              "entrypoint": [
                "/bin/sh",
                "-c"
              ],
              "command": [
                "echo $CI_SCRIPT | base64 -d | /bin/sh -e"
              ],
              "volumes": [
                "pipeline_default:/go"
              ],
              "networks": [
                {
                  "name": "pipeline_default",
                  "aliases": [
                    "build"
                  ]
                }
              ],
              "on_success": true,
              "auth_config": {}
            }
          ]
        }
      ],
      "networks": [
        {
          "name": "pipeline_default",
          "driver": "bridge"
        }
      ],
      "volumes": [
        {
          "name": "pipeline_default",
          "driver": "local"
        }
      ],
      "secrets": null
    }

    単純な解析構造:
  • pipelineは、実行されるステージを定義し、各ステージには1つ以上のstep
  • がある.
  • networks、volumes、secretsは、それぞれネットワーク、ストレージ、secretsを定義します.
  • networkによりcontainer相互接続
  • を実現
  • volumesによるデータ共有
  • pipec execによって実行されます.
    # pipec exec
    proc "pipeline_clone_0" started
    + git init
    Initialized empty Git repository in /go/src/github.com/drone/envsubst/.git/
    + git remote add origin https://github.com/drone/envsubst.git
    + git fetch --no-tags --depth=50 origin +refs/heads/master:
    From https://github.com/drone/envsubst
     * branch            master     -> FETCH_HEAD
     * [new branch]      master     -> origin/master
    + git reset --hard -q d0876d3176965f9552a611cbd56e24a9264355e6
    + git submodule update --init --recursive
    proc "pipeline_clone_0" exited with status 0
    proc "pipeline_step_0" started
    + go get -t ./...
    + go build
    + go test -v
    === RUN   TestExpand
    --- PASS: TestExpand (0.00s)
    === RUN   TestFuzz
    --- PASS: TestFuzz (0.01s)
    === RUN   Test_len
    --- PASS: Test_len (0.00s)
    === RUN   Test_lower
    --- PASS: Test_lower (0.00s)
    === RUN   Test_lowerFirst
    --- PASS: Test_lowerFirst (0.00s)
    === RUN   Test_upper
    --- PASS: Test_upper (0.00s)
    === RUN   Test_upperFirst
    --- PASS: Test_upperFirst (0.00s)
    === RUN   Test_default
    --- PASS: Test_default (0.00s)
    PASS
    ok      github.com/drone/envsubst   0.009s
    proc "pipeline_step_0" exited with status 0

    pipeline原理分析
    コンパイルプロセス
    イメージ的に理解できる.env+pipeline.yml --> pipeline.json
    コンパイルプロセスは複雑ではありません.主にpipelineを解析します.ymlはConfigです.
    Config struct {
            Cache     libcompose.Stringorslice
            Platform  string
            Branches  Constraint
            Workspace Workspace
            Clone     Containers
            Pipeline  Containers
            Services  Containers
            Networks  Networks
            Volumes   Volumes
            Labels    libcompose.SliceorMap
        }

    次にjson対応configに変換します.
    Config struct {
            Stages   []*Stage   `json:"pipeline"` // pipeline stages
            Networks []*Network `json:"networks"` // network definitions
            Volumes  []*Volume  `json:"volumes"`  // volume definitions
            Secrets  []*Secret  `json:"secrets"`  // secret definitions
        }

    この部分の主なコードはpipeline/frontendにあります
    プロセスの実行
    主にpipeline/backendの実行プロセスに注目します.
    まず、読み出しプロファイルがbackendである.Config
    config, err := pipeline.Parse(reader)
        if err != nil {
            return err
        }

    次に実行環境を作成し、現在のコードはdockerのみ使用可能であり、k 8 sは空のコードである.
    var engine backend.Engine
        if c.Bool("kubernetes") {
            engine = kubernetes.New(
                c.String("kubernetes-namepsace"),
                c.String("kubernetes-endpoint"),
                c.String("kubernetes-token"),
            )
        } else {
            engine, err = docker.NewEnv()
            if err != nil {
                return err
            }
        }

    次に実行を開始
        ctx, cancel := context.WithTimeout(context.Background(), c.Duration("timeout"))
        defer cancel()
        ctx = interrupt.WithContext(ctx)
    
        return pipeline.New(config,
            pipeline.WithContext(ctx),
            pipeline.WithLogger(defaultLogger),
            pipeline.WithTracer(defaultTracer),
            pipeline.WithEngine(engine),
        ).Run()

    ここでpipeline.NEWはRuntimeオブジェクトを作成しました.
    type Runtime struct {
        err     error  //     
        spec    *backend.Config  //     
        engine  backend.Engine  // docker engine
        started int64 //     
    
        ctx    context.Context
        tracer Tracer
        logger Logger
    }

    ここでEngineは、コンテナのinterfaceを操作し、現在はdockerのみ使用できます.
    // Engine defines a container orchestration backend and is used
    // to create and manage container resources.
    type Engine interface {
        // Setup the pipeline environment.
        Setup(context.Context, *Config) error
        // Start the pipeline step.
        Exec(context.Context, *Step) error
        // Kill the pipeline step.
        Kill(context.Context, *Step) error
        // Wait for the pipeline step to complete and returns
        // the completion results.
        Wait(context.Context, *Step) (*State, error)
        // Tail the pipeline step logs.
        Tail(context.Context, *Step) (io.ReadCloser, error)
        // Destroy the pipeline environment.
        Destroy(context.Context, *Config) error
    }

    注目Run:
    // Run starts the runtime and waits for it to complete.
    func (r *Runtime) Run() error {
        
        //     ,    docker env
        defer func() {
            r.engine.Destroy(r.ctx, r.spec)
        }()
        
        //    docker engine
        r.started = time.Now().Unix()
        if err := r.engine.Setup(r.ctx, r.spec); err != nil {
            return err
        }
       
       //     stage
        for _, stage := range r.spec.Stages {
            select {
            case 

    ポイントはerrgroupを使用することです.Groupはスレッド方式でstepを実行します.
    
    //     steps
    func (r *Runtime) execAll(procs []*backend.Step) 

    作者:Jadepeng出典:jqpengの技術手帳--http://www.cnblogs.com/xiaoqiあなたの支持はブロガーに対する最大の励ましであり、真剣に読んでくれてありがとう.本文の著作権は作者の所有に帰して、転載を歓迎して、しかし作者の同意を得ずに必ずこの声明を保留しなければならなくて、しかも文章のページの明らかな位置で原文の接続を与えて、さもなくば法律の責任を追及する権利を保留します.
    転載先:https://www.cnblogs.com/xiaoqi/p/drone-pipeline.html