<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          GitLab + Jenkins + Harbor 工具鏈快速落地指南

          共 14437字,需瀏覽 29分鐘

           ·

          2022-10-15 12:54

          一、今天想干啥?

          今天我們來(lái)聊聊如何快速落地“GitLab + Jenkins + Harbor 工具鏈”。

          請(qǐng)注意這里的關(guān)鍵詞:快速(有多快呢?我希望這個(gè)時(shí)間是5分鐘。)

          我知道你想要一條閃閃亮的工具鏈來(lái)支撐你的應(yīng)用 CICD 流程,你想要“最佳實(shí)踐”,你想要既靈活簡(jiǎn)單易維護(hù),你有一肚子的既要,又要,還要……

          行,今天我就給你一個(gè)“既有,又有,還有”的《GitLab + Jenkins + Harbor 落地方案》。

          二、今天干點(diǎn)啥?

          今天我們要搭建一條怎樣的工具鏈呢?且看效果圖:

          GitLab + Jenkins + Harbor Toolchain Workflow
          1. 首先我們需要完成 GitLab、Jenkins 和 Harbor 三個(gè)工具的部署;
          2. 接著我們需要在 GitLab 上創(chuàng)建一個(gè)代碼庫(kù),并且在 Jenkins 上創(chuàng)建相應(yīng)的流水線,這個(gè)流程最好也自動(dòng)化(確實(shí)可以自動(dòng)化);
          3. 然后適當(dāng)?shù)嘏渲眠@三個(gè)工具,實(shí)現(xiàn)如下 CI 流程:
            1. 當(dāng)用戶推送代碼到 GitLab,也就是 GitLab 上相應(yīng)代碼庫(kù)產(chǎn)生 push 或者 merge 事件的時(shí)候,這個(gè)事件能夠自動(dòng)觸發(fā) Jenkins 上的流水線執(zhí)行;
            2. Jenkins 上流水線執(zhí)行的結(jié)果能夠回顯到 GitLab;
            3. Jenkins 上完成了編譯、構(gòu)建等等流程后,最終制品是一個(gè)容器鏡像,這個(gè)鏡像可以被推送到 Harbor 上。

          三、今天怎么干?

          我準(zhǔn)備使用云原生的方式來(lái)部署這三個(gè)工具,原因不贅述。

          當(dāng)然我也知道多數(shù)情況下你并不需要考慮 GitLab 如何部署,因?yàn)?5% 的概率你們公司已經(jīng)有可用的 GitLab 了,或者你們考慮使用 SaaS 版的 GitLab。外加 Kubernetes 上部署 GitLab 的復(fù)雜度不低,運(yùn)維成本高,所以,GitLab 的“高可用部署”不是本文重點(diǎn),我們把重點(diǎn)放在如何部署和配置好 Jenkins + Harbor,然后對(duì)接 GitLab,走通一個(gè) CI 流程。

          綜上,今天我準(zhǔn)備 sale 的部署模式是:

          • GitLab:Docker
          • Jenkins:Helm(Kubernetes)
          • Harbor:Helm(Kubernetes)

          3.1、常規(guī)打法

          如果按照常理出牌,這時(shí)候我們應(yīng)該是翻閱三個(gè)工具的官網(wǎng),學(xué)習(xí)部署流程和配置步驟,然后總結(jié)最佳實(shí)踐,一步步試錯(cuò),一步步改進(jìn)……

          聽(tīng)起來(lái)就復(fù)雜。

          這個(gè)流程不應(yīng)該讓所有人都重頭體驗(yàn)一遍,被折磨一遍。假如有人已經(jīng)研究了一遍這些工具的部署模式,并且將這個(gè)流程代碼化,做一個(gè)工具出來(lái),并且開(kāi)源免費(fèi),讓大家“開(kāi)箱即用”,那該多好!

          3.2、不走尋常路

          沒(méi)錯(cuò),你已經(jīng)猜到了,我不打算按常理出牌,我要找一個(gè)能夠管理 DevOps 工具鏈的工具!

          有這種工具?還真有!

          DevStream[1] 就干這事。DevStream 是啥?一句話:一個(gè) DevOps 工具鏈管理器。

          我們看下 DevStream 如何完成這三個(gè)工具的落地:

          GitLab+Jenkins+Harbor with DevStream

          DevStream 官網(wǎng)里有這么一個(gè)圖。所以,這個(gè)花里胡哨的 DevStream 做了啥?

          從上面的流程圖,結(jié)合官方文檔和源碼,大致我可以猜到它的工作流和原理:

          1. DevStream 首先將 GitLab、Jenkins、Harbor 等工具的部署流程代碼化,通過(guò)插件的形式支持這些工具的安裝部署;
          2. 工具部署完成后,DevStream 會(huì)從 SCM(GitHub 或者 GitLab 都可以)下載一個(gè)項(xiàng)目腳手架模板,模板源碼在這里[2];這個(gè)模板支持高度自定義,本質(zhì)就是將一些需要自定義的內(nèi)容抽離成變量,供用戶自由渲染,然后批量生產(chǎn)項(xiàng)目腳手架;
          3. 接著 DevStream 根據(jù)用戶給定的配置文件渲染模板庫(kù),然后將其上傳到 SCM(GitHub 或者 GitLab 都可以);
          4. 然后 DevStream 會(huì)配置 Jenkins,安裝一些必要的插件等,用戶支持最終的 Pipeline 順利執(zhí)行;
          5. DevStream 期望 Pipeline 配置通過(guò) Jenkinsfile 來(lái)定義,這個(gè) Jenkinsfile 也是通過(guò)模板的方式保存,可以靈活渲染。比如官網(wǎng)示例中 Jenkinsfile 模板保存在這里[3];DevStream 執(zhí)行的時(shí)候會(huì)下載這個(gè) Jenkinsfile 模板(當(dāng)然,這個(gè)模板也支持自定義,支持放到 GitLab 或者其他任何 web 服務(wù)器上),下載后渲染用戶自定義變量,然后將其寫(xiě)入剛才創(chuàng)建的項(xiàng)目腳手架對(duì)應(yīng)的代碼庫(kù)里;
          6. 接著 DevStream 就可以調(diào)用 Jenkins api,完成 Pipeline 創(chuàng)建了。沒(méi)錯(cuò),創(chuàng)建 Pipeline 的時(shí)候,需要的 Jenkinsfile、項(xiàng)目地址等信息都有了,所以這里的 Pipeline 配置很輕量;
          7. 最后 DevStream 還需要調(diào)用 GitLab api 完成 webhook 的創(chuàng)建,這樣 SCM(GitHub 或者 GitLab)上的事件(push、merge 等)才能順利通知到 Jenkins,從而觸發(fā) Pipeline 執(zhí)行。

          到這里 DevStream 基本就打完收工了,這時(shí)候如果你往這個(gè)代碼庫(kù)里的主分支 push 了一個(gè) commit,GitLab 就會(huì)直接觸發(fā) Jenkins 上流水線運(yùn)行;進(jìn)而 Jenkins 上的流水線執(zhí)行狀態(tài)也會(huì)直接回顯到 GitLab 上;當(dāng)然,Jenkins 里構(gòu)建的產(chǎn)物,比如 Docker container image(s) 也會(huì)被 push 到 Harbor(每錯(cuò),這個(gè)過(guò)程是定義在 Jenkinsfile 里的,你可以靈活修改;同時(shí) Harbor 也不一定非得是 Harbor,你可以直接改成其他鏡像倉(cāng)庫(kù)的地址,從而讓 Jenkins 對(duì)接到云廠商提供的鏡像倉(cāng)庫(kù)服務(wù)里也完全 OK)。

          四、開(kāi)干吧!

          考慮到插件的依賴順序,外加 Jenkins、GitLab、Harbor 等工具的部署屬于"基礎(chǔ)設(shè)施",幾乎只需要執(zhí)行一次, 而 Repo Scaffolding 和 Jenkins Pipeline 的創(chuàng)建屬于"配置"過(guò)程,可能要執(zhí)行多次(比如不斷新增 Repo 和 Pipeline 等), 所以我們分2步來(lái)完成這條工具鏈的搭建過(guò)程。

          4.1、工具鏈部署

          先下載一個(gè) DevStream 的 CLI,參考這個(gè)文檔[4]。有了 dtm 之后,我們就該著手準(zhǔn)備配置文件了(下面配置保存到 config.yaml 里):

          ---
          varFile: "" # If not empty, use the specified external variables config file
          toolFile: "" # If not empty, use the specified external tools config file
          pluginDir: "" # If empty, use the default value: ~/.devstream/plugins, or use -d flag to specify a directory
          state: # state config, backend can be local, s3 or k8s
          backend: local
          options:
          stateFile: devstream-1.state
          ---
          tools:
          - name: gitlab-ce-docker
          instanceID: default
          dependsOn: [ ]
          options:
          hostname: gitlab.example.com
          gitlabHome: /srv/gitlab
          sshPort: 30022
          httpPort: 30080
          httpsPort: 30443
          rmDataAfterDelete: false
          imageTag: "rc"
          - name: jenkins
          instanceID: default
          dependsOn: [ ]
          options:
          repo:
          name: jenkins
          url: https://charts.jenkins.io
          chart:
          chartPath: ""
          chartName: jenkins/jenkins
          namespace: jenkins
          wait: true
          timeout: 5m
          upgradeCRDs: true
          valuesYaml: |
          serviceAccount:
          create: true
          name: jenkins
          controller:
          adminUser: "admin"
          adminPassword: "changeme"
          ingress:
          enabled: true
          hostName: jenkins.example.com
          installPlugins:
          - kubernetes:3600.v144b_cd192ca_a_
          - workflow-aggregator:581.v0c46fa_697ffd
          - git:4.11.3
          - configuration-as-code:1512.vb_79d418d5fc8
          additionalPlugins:
          # install "GitHub Pull Request Builder" plugin, see https://plugins.jenkins.io/ghprb/ for more details
          - ghprb
          # install "OWASP Markup Formatter" plugin, see https://plugins.jenkins.io/antisamy-markup-formatter/ for more details
          - antisamy-markup-formatter
          # Enable HTML parsing using OWASP Markup Formatter Plugin (antisamy-markup-formatter), useful with ghprb plugin.
          enableRawHtmlMarkupFormatter: true
          # Jenkins Configuraction as Code, refer to https://plugins.jenkins.io/configuration-as-code/ for more details
          # notice: All configuration files that are discovered MUST be supplementary. They cannot overwrite each other's configuration values. This creates a conflict and raises a ConfiguratorException.
          JCasC:
          defaultConfig: true
          - name: harbor
          instanceID: default
          dependsOn: [ ]
          options:
          chart:
          valuesYaml: |
          externalURL: http://harbor.example.com
          expose:
          type: ingress
          tls:
          enabled: false
          ingress:
          hosts:
          core: harbor.example.com
          chartmuseum:
          enabled: false
          notary:
          enabled: false
          trivy:
          enabled: false
          persistence:
          persistentVolumeClaim:
          registry:
          storageClass: ""
          accessMode: ReadWriteOnce
          size: 5Gi
          jobservice:
          storageClass: ""
          accessMode: ReadWriteOnce
          size: 1Gi
          database:
          storageClass: ""
          accessMode: ReadWriteOnce
          size: 1Gi
          redis:
          storageClass: ""
          accessMode: ReadWriteOnce
          size: 1Gi

          這里的配置項(xiàng)并不難看懂,推薦大伙執(zhí)行后面的命令前先仔細(xì)看一遍這個(gè)配置文件,按需調(diào)整。比如里面配置了幾個(gè)工具的域名啥的,這些都可以改。

          然后就可以開(kāi)始初始化了(主要是插件下載):

          dtm init -f config.yaml

          然后執(zhí)行 apply 開(kāi)始部署:

          dtm apply -f config.yaml -y

          這時(shí)候你會(huì)看到和諧的日志:

          2022-10-08 09:43:13 ? [INFO]  Apply started.
          2022-10-08 09:43:13 ? [INFO] Using dir </root/.devstream/plugins> to store plugins.
          2022-10-08 09:43:13 ? [INFO] Using local backend. State file: devstream-1.state.
          2022-10-08 09:43:13 ? [INFO] Tool (gitlab-ce-docker/default) found in config but doesn't exist in the state, will be created.
          2022-10-08 09:43:13 ? [INFO] Tool (jenkins/default) found in config but doesn'
          t exist in the state, will be created.
          2022-10-08 09:43:13 ? [INFO] Tool (harbor/default) found in config but doesn't exist in the state, will be created.
          2022-10-08 09:43:13 ? [INFO] Start executing the plan.
          2022-10-08 09:43:13 ? [INFO] Changes count: 3.
          2022-10-08 09:43:13 ? [INFO] -------------------- [ Processing progress: 1/3. ] --------------------
          2022-10-08 09:43:13 ? [INFO] Processing: (gitlab-ce-docker/default) -> Create ...
          2022-10-08 09:43:13 ? [INFO] Cmd: docker image ls gitlab/gitlab-ce:rc -q.
          2022-10-08 09:43:13 ? [INFO] Running container as the name <gitlab>
          2022-10-08 09:43:13 ? [INFO] Cmd: docker run --detach --hostname gitlab.example.com --publish 30022:22 --publish 30080:80 --publish 30443:443 --name gitlab --restart always --volume /srv/gitlab/config:/etc/gitlab --volume /srv/gitlab/data:/var/opt/gitlab --volume /srv/gitlab/logs:/var/log/gitlab gitlab/gitlab-ce:rc.
          Stdout: 53e30ad85faf7e9d6d18764450bb8458db46b388b690b7c8b7a7cc6d0deb283a
          2022-10-08 09:43:14 ? [INFO] Cmd: docker inspect --format='
          {{json .Mounts}}' gitlab.
          2022-10-08 09:43:14 ? [INFO] GitLab access URL: http://gitlab.example.com:30080
          2022-10-08 09:43:14 ? [INFO] GitLab initial root password: execute the command -> docker exec -it gitlab grep '
          Password:' /etc/gitlab/initial_root_password
          2022-10-08 09:43:14 ? [SUCCESS] Tool (gitlab-ce-docker/default) Create done.
          2022-10-08 09:43:14 ? [INFO] -------------------- [ Processing progress: 2/3. ] --------------------
          2022-10-08 09:43:14 ? [INFO] Processing: (jenkins/default) -> Create ...
          2022-10-08 09:43:15 ? [INFO] Creating or updating helm chart ...
          2022/10/08 09:43:16 creating 13 resource(s)
          2022/10/08 09:43:16 beginning wait for 13 resources with timeout of 5m0s
          2022/10/08 09:43:16 StatefulSet is not ready: jenkins/jenkins. 0 out of 1 expected pods are ready
          ...
          2022/10/08 09:44:18 StatefulSet is not ready: jenkins/jenkins. 0 out of 1 expected pods are ready
          2022/10/08 09:44:20 release installed successfully: jenkins/jenkins-4.1.17
          2022-10-08 09:44:20 ? [SUCCESS] Tool (jenkins/default) Create done.
          2022-10-08 09:44:20 ? [INFO] -------------------- [ Processing progress: 3/3. ] --------------------
          2022-10-08 09:44:20 ? [INFO] Processing: (harbor/default) -> Create ...
          2022-10-08 09:44:21 ? [INFO] Creating or updating helm chart ...
          2022/10/08 09:44:23 creating 28 resource(s)
          2022/10/08 09:44:23 beginning wait for 28 resources with timeout of 10m0s
          2022/10/08 09:44:24 Deployment is not ready: harbor/harbor-core. 0 out of 1 expected pods are ready
          ...
          2022/10/08 09:46:16 Deployment is not ready: harbor/harbor-jobservice. 0 out of 1 expected pods are ready
          2022/10/08 09:46:18 release installed successfully: harbor/harbor-1.10.0
          2022-10-08 09:46:19 ? [SUCCESS] Tool (harbor/default) Create done.
          2022-10-08 09:46:19 ? [INFO] -------------------- [ Processing done. ] --------------------
          2022-10-08 09:46:19 ? [SUCCESS] All plugins applied successfully.
          2022-10-08 09:46:19 ? [SUCCESS] Apply finished.

          假如日志不夠和諧,那就,那就,,,debug 吧。

          4.2、網(wǎng)絡(luò)配置

          前面 GitLab + Jenkins + Harbor 三個(gè)工具的配置文件里我們都設(shè)置了域名,如果是 kubeadm 直接部署的 k8s 集群,你可以直接將這些域名與 IP 的映射關(guān)系配置到 DNS 服務(wù)器里。

          如果沒(méi)有 DNS 服務(wù)器,你也可以直接將域名與 IP 的映射關(guān)系配置到 /etc/hosts 以及 CoreDNS 的 ConfigMap kube-system/coredns 里讓域名生效。比如:

          1. 修改 /etc/hosts 文件,添加這條記錄(記得替換成你自己的 IP):

            44.33.22.11 gitlab.example.com jenkins.example.com harbor.example.com
          2. 修改 CoreDNS 的配置,在 ConfigMap kube-system/coredns 中添加靜態(tài)解析記錄:

            1. 執(zhí)行命令:kubectl edit cm coredns -n kube-system
            2. 在 hosts(第20行左右) 部分添加和 /etc/hosts 一樣的記錄。

          這樣 Jenkins 才能通過(guò)域名訪問(wèn)到 GitLab。

          4.3、驗(yàn)證工具鏈部署結(jié)果

          來(lái),看下新部署的 GitLab、Jenkins、Harbor 是不是都能訪問(wèn)到。

          4.3.1、GitLab

          不出意外的話,你可以在自己的 PC 里配置 44.33.22.11 gitlab.example.com 靜態(tài)域名解析記錄,然后在瀏覽器里通過(guò) http://gitlab.example.com:30080 訪問(wèn)到 GitLab:

          GitLab login

          然后通過(guò)執(zhí)行如下命令,你就能獲得 GitLab 的初始 root 密碼了:

          docker exec gitlab cat /etc/gitlab/initial_root_password | grep Password:

          拿到 root 密碼后,你可以嘗試用 root/YOUR_PASSWORD 來(lái)登錄 GitLab。因?yàn)楹竺嫖覀冃枰玫?GitLab 的 token,所以這時(shí)候可以順手創(chuàng)建一個(gè) token:

          GitLab token

          4.3.2、Jenkins

          在瀏覽器里通過(guò) http://jenkins.example.com:32000 就可以訪問(wèn)到 Jenkins 了:

          Jenkins login

          Jenkins 的 admin 用戶初始登錄密碼是 changeme,如果你仔細(xì)看了前面 dtm 使用的配置文件,可以發(fā)現(xiàn)這是在配置文件里指定的。我們嘗試用 admin/changeme 登錄 Jenkins 檢查功能是否正常,不過(guò)這時(shí)不需要在 Jenkins 上進(jìn)行任何額外的操作。

          Jenkins dashboard

          4.3.3、Harbor

          我們可以通過(guò) docker login harbor.example.com:80 命令來(lái)嘗試登錄 Harbor,也可以直接通過(guò) http://harbor.example.com:30180 訪問(wèn) Dashboard:

          Harbor login

          Harbor 的 admin 用戶初始登錄密碼是 Harbor12345,我們嘗試用 admin/Harbor12345 登錄 Harbor:

          Harbor dashboard

          4.4、流水線配置

          工具有了,下一步就是配置流水線了,咱繼續(xù)準(zhǔn)備第二個(gè)配置文件(config-pipeline.yaml):

          ---
          varFile: "" # If not empty, use the specified external variables config file
          toolFile: "" # If not empty, use the specified external tools config file
          pluginDir: "" # If empty, use the default value: ~/.devstream/plugins, or use -d flag to specify a directory
          state: # state config, backend can be local, s3 or k8s
          backend: local
          options:
          stateFile: devstream-2.state
          ---
          tools:
          - name: repo-scaffolding
          instanceID: springboot
          dependsOn: [ ]
          options:
          destinationRepo:
          owner: root
          repo: spring-demo
          branch: master
          repoType: gitlab
          baseURL: http://gitlab.example.com:30080
          sourceRepo:
          owner: devstream-io
          repo: dtm-repo-scaffolding-java-springboot
          repoType: github
          - name: jenkins-pipeline
          instanceID: default
          dependsOn: [repo-scaffolding.springboot]
          options:
          jenkins:
          url: http://44.33.22.11:32000
          user: admin
          enableRestart: true
          scm:
          cloneURL: http://gitlab.example.com:30080/root/spring-demo
          branch: master
          pipeline:
          jobName: test-job
          jenkinsfilePath: https://raw.githubusercontent.com/devstream-io/dtm-jenkins-pipeline-example/main/springboot/Jenkinsfile
          imageRepo:
          url: http://harbor.example.com:80
          user: admin

          同樣我建議你仔細(xì)看一下這個(gè)配置文件,里面的一些訪問(wèn)地址,比如 IP 和域名啥的,按需調(diào)整。

          前面我們添加了一個(gè) GitLab 的 token,這個(gè) token 需要被設(shè)置到環(huán)境變量里:

          export GITLAB_TOKEN=YOUR_GITLAB_TOKEN

          同時(shí)我們需要將 Harbor 密碼配置到環(huán)境變量里,如果你的 Harbor 沒(méi)有去修改密碼,這時(shí)候默認(rèn)密碼應(yīng)該是 Harbor12345:

          export IMAGE_REPO_PASSWORD=Harbor12345

          接著就是熟悉的 init 和 apply 命令了:

          dtm init -f config-pipeline.yaml
          dtm apply -f config-pipeline.yaml -y

          結(jié)果日志依舊應(yīng)該和諧:

          2022-10-08 13:19:27 ? [INFO]  Apply started.
          2022-10-08 13:19:27 ? [INFO] Using dir </root/.devstream/plugins> to store plugins.
          2022-10-08 13:19:28 ? [INFO] Using local backend. State file: devstream-2.state.
          2022-10-08 13:19:28 ? [INFO] Tool (jenkins-pipeline/default) found in config but doesn't exist in the state, will be created.
          2022-10-08 13:19:28 ? [INFO] Start executing the plan.
          2022-10-08 13:19:28 ? [INFO] Changes count: 1.
          2022-10-08 13:19:28 ? [INFO] -------------------- [ Processing progress: 1/1. ] --------------------
          2022-10-08 13:19:28 ? [INFO] Processing: (jenkins-pipeline/default) -> Create ...
          2022-10-08 13:19:28 ? [INFO] Secret jenkins/docker-config has been created.
          2022-10-08 13:19:32 ? [SUCCESS] Tool (jenkins-pipeline/default) Create done.
          2022-10-08 13:19:32 ? [INFO] -------------------- [ Processing done. ] --------------------
          2022-10-08 13:19:32 ? [SUCCESS] All plugins applied successfully.
          2022-10-08 13:19:32 ? [SUCCESS] Apply finished.

          4.5、驗(yàn)證流水線配置結(jié)果

          我們上 GitLab 看下 dtm 準(zhǔn)備的 Java Spring Boot 項(xiàng)目腳手架:

          Repo scaffolding

          接著登錄 Jenkins,可以看到 dtm 創(chuàng)建的 Pipeline:

          Jenkins Pipeline

          Pipeline 成功執(zhí)行完成后:

          Pipeline Success

          再回到 GitLab 看下回顯的狀態(tài):

          GitLab Status

          歌舞升平,一片祥和!

          五、總結(jié)

          此處應(yīng)該有個(gè)總結(jié),但是到飯點(diǎn)了。

          不總結(jié)了吧。

          就留一個(gè)問(wèn)題:DevStream 部署 DevOps 工具鏈?zhǔn)遣皇亲罴褜?shí)踐?

          也許是,也許不是。不過(guò)我相信 DevStream 會(huì)逐步匯集業(yè)內(nèi)最佳實(shí)踐,最終變成一個(gè)標(biāo)準(zhǔn)。

          再留個(gè)問(wèn)題:DevStream 足夠成熟穩(wěn)定了不?

          應(yīng)該不夠。不過(guò) DevStream 在逐漸走向成熟。如果大家愿意使用 DevStream,多提 bug,甚至參與社區(qū)開(kāi)發(fā),DevStream 就會(huì)更快走向成熟穩(wěn)定。


          參考:

          • DevStream 項(xiàng)目倉(cāng)庫(kù)[5]
          • DevStream 文檔:本地部署 GitLab + Jenkins + Harbor 工具鏈[6]
          • DevStream 文檔:離線部署[7]

          結(jié)束。催吃飯了。

          本文外鏈

          [1]

          DevStream: https://github.com/devstream-io/devstream

          [2]

          這里: https://github.com/devstream-io/dtm-repo-scaffolding-java-springboot

          [3]

          這里: https://github.com/devstream-io/dtm-jenkins-pipeline-example

          [4]

          這個(gè)文檔: https://docs.devstream.io/en/latest/best-practices/air-gapped-deployment.zh/#11-dtm

          [5]

          DevStream 項(xiàng)目倉(cāng)庫(kù): https://github.com/devstream-io/devstream

          [6]

          DevStream 文檔:本地部署 GitLab + Jenkins + Harbor 工具鏈: https://docs.devstream.io/en/latest/best-practices/gitlab-jenkins-harbor.zh/

          [7]

          DevStream 文檔:離線部署: https://docs.devstream.io/en/latest/best-practices/air-gapped-deployment.zh/

          瀏覽 43
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  伊人久操 | 好逼综合| AV2014天堂 | 韩国三级黄| 色婷亚州五月天 |