<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <title>Git - Tag - 学习随记</title>
    <link>https://www.ronald.wang/tags/git/</link>
    <description>Git - Tag - 学习随记</description>
    <generator>Hugo -- gohugo.io</generator><language>zh-cn</language><lastBuildDate>Fri, 14 Oct 2022 11:47:10 &#43;0800</lastBuildDate><atom:link href="https://www.ronald.wang/tags/git/" rel="self" type="application/rss+xml" /><item>
  <title>GitLab &#43; Jenkins &#43; Harbor 工具链快速落地指南</title>
  <link>https://www.ronald.wang/posts/devops/devops1/</link>
  <pubDate>Fri, 14 Oct 2022 11:47:10 &#43;0800</pubDate>
  <author>Ronald</author>
  <guid>https://www.ronald.wang/posts/devops/devops1/</guid>
  <description><![CDATA[<h2 id="一今天想干啥">一、今天想干啥？</h2>
<p>今天我们来聊聊如何快速落地“GitLab + Jenkins + Harbor 工具链”。</p>
<p>请注意这里的关键词：<strong>快速</strong>（有多快呢？我希望这个时间是5分钟。）</p>
<p>我知道你想要一条<strong>闪闪亮</strong>的工具链来支撑你的应用 CICD 流程，你想要“最佳实践”，你想要既<strong>灵活</strong>又<strong>简单</strong>还<strong>易维护</strong>，你有一肚子的既要，又要，还要……</p>
<p>行，今天我就给你一个“既有，又有，还有”的《GitLab + Jenkins + Harbor 落地方案》。</p>
<h2 id="二今天干点啥">二、今天干点啥？</h2>
<p>今天我们要搭建一条怎样的工具链呢？且看效果图：</p>
<!-- raw HTML omitted -->
<ol>
<li>首先我们需要完成 GitLab、Jenkins 和 Harbor 三个工具的部署；</li>
<li>接着我们需要在 GitLab 上创建一个代码库，并且在 Jenkins 上创建相应的流水线，这个流程最好也自动化（确实可以自动化）；</li>
<li>然后适当地配置这三个工具，实现如下 CI 流程：
<ol>
<li>当用户推送代码到 GitLab，也就是 GitLab 上相应代码库产生 push 或者 merge 事件的时候，这个事件能够自动触发 Jenkins 上的流水线执行；</li>
<li>Jenkins 上流水线执行的结果能够回显到 GitLab；</li>
<li>Jenkins 上完成了编译、构建等等流程后，最终制品是一个容器镜像，这个镜像可以被推送到 Harbor 上。</li>
</ol>
</li>
</ol>
<h2 id="三今天怎么干">三、今天怎么干？</h2>
<p>我准备使用云原生的方式来部署这三个工具，原因不赘述。</p>
<p>当然我也知道多数情况下你并不需要考虑 GitLab 如何部署，因为95% 的概率你们公司已经有可用的 GitLab 了，或者你们考虑使用 SaaS 版的 GitLab。外加 Kubernetes 上部署 GitLab 的复杂度不低，运维成本高，所以，GitLab 的“高可用部署”不是本文重点，我们把重点放在如何部署和配置好 Jenkins + Harbor，然后对接 GitLab，走通一个 CI 流程。</p>
<p>综上，今天我准备 sale 的部署模式是：</p>
<ul>
<li>GitLab：Docker</li>
<li>Jenkins：Helm(Kubernetes)</li>
<li>Harbor：Helm(Kubernetes)</li>
</ul>
<h3 id="31常规打法">3.1、常规打法</h3>
<p>如果按照常理出牌，这时候我们应该是翻阅三个工具的官网，学习部署流程和配置步骤，然后总结最佳实践，一步步试错，一步步改进……</p>
<p>听起来就复杂。</p>
<p>这个流程不应该让所有人都重头体验一遍，被折磨一遍。假如有人已经研究了一遍这些工具的部署模式，并且将这个流程代码化，做一个工具出来，并且开源免费，让大家“开箱即用”，那该多好！</p>
<h3 id="32不走寻常路">3.2、不走寻常路</h3>
<p>没错，你已经猜到了，我不打算按常理出牌，我要找一个能够管理 DevOps 工具链的工具！</p>
<p>有这种工具？还真有！</p>
<p><a href="https://github.com/devstream-io/devstream"target="_blank" rel="external nofollow noopener noreferrer">DevStream</a> 就干这事。DevStream 是啥？一句话：一个 DevOps 工具链管理器。</p>
<p>我们看下 DevStream 如何完成这三个工具的落地：</p>
<p><figure><a class="lightgallery" href="resources/3208bf242fca400f82aad696bbb863e1.svg" data-thumbnail="resources/3208bf242fca400f82aad696bbb863e1.svg" data-sub-html="<h2>./gitlab-jenkins-harbor-dtm.png</h2><p>GitLab&#43;Jenkins&#43;Harbor with DevStream</p>">
    
  </a><figcaption class="image-caption">./gitlab-jenkins-harbor-dtm.png</figcaption>
  </figure></p>
<p>DevStream 官网里有这么一个图。所以，这个花里胡哨的 <strong>DevStream 做了啥？</strong></p>
<p>从上面的流程图，结合官方文档和源码，大致我可以猜到它的工作流和原理：</p>
<ol>
<li>DevStream 首先将 GitLab、Jenkins、Harbor 等工具的部署流程代码化，通过插件的形式支持这些工具的安装部署；</li>
<li>工具部署完成后，DevStream 会从 SCM（GitHub 或者 GitLab 都可以）下载一个项目脚手架模板，模板源码在<a href="https://github.com/devstream-io/dtm-repo-scaffolding-java-springboot"target="_blank" rel="external nofollow noopener noreferrer">这里</a>；这个模板支持高度自定义，本质就是将一些需要自定义的内容抽离成变量，供用户自由渲染，然后批量生产项目脚手架；</li>
<li>接着 DevStream 根据用户给定的配置文件渲染模板库，然后将其上传到 SCM（GitHub 或者 GitLab 都可以）；</li>
<li>然后 DevStream 会配置 Jenkins，安装一些必要的插件等，用户支持最终的 Pipeline 顺利执行；</li>
<li>DevStream 期望 Pipeline 配置通过 Jenkinsfile 来定义，这个 Jenkinsfile 也是通过模板的方式保存，可以灵活渲染。比如官网示例中 Jenkinsfile 模板保存在<a href="https://github.com/devstream-io/dtm-jenkins-pipeline-example"target="_blank" rel="external nofollow noopener noreferrer">这里</a>；DevStream 执行的时候会下载这个 Jenkinsfile 模板（当然，这个模板也支持自定义，支持放到 GitLab 或者其他任何 web 服务器上），下载后渲染用户自定义变量，然后将其写入刚才创建的项目脚手架对应的代码库里；</li>
<li>接着 DevStream 就可以调用 Jenkins api，完成 Pipeline 创建了。没错，创建 Pipeline 的时候，需要的 Jenkinsfile、项目地址等信息都有了，所以这里的 Pipeline 配置很轻量；</li>
<li>最后 DevStream 还需要调用 GitLab api 完成 webhook 的创建，这样 SCM（GitHub 或者 GitLab）上的事件（push、merge 等）才能顺利通知到 Jenkins，从而触发 Pipeline 执行。</li>
</ol>
<p>到这里 DevStream 基本就打完收工了，这时候如果你往这个代码库里的主分支 push 了一个 commit，GitLab 就会直接触发 Jenkins 上流水线运行；进而 Jenkins 上的流水线执行状态也会直接回显到 GitLab 上；当然，Jenkins 里构建的产物，比如 Docker container image(s) 也会被 push 到 Harbor（每错，这个过程是定义在 Jenkinsfile 里的，你可以灵活修改；同时 Harbor 也不一定非得是 Harbor，你可以直接改成其他镜像仓库的地址，从而让 Jenkins 对接到云厂商提供的镜像仓库服务里也完全 OK）。</p>
<h2 id="四开干吧">四、开干吧！</h2>
<p>考虑到插件的依赖顺序，外加 Jenkins、GitLab、Harbor 等工具的部署属于&quot;基础设施&quot;，几乎只需要执行一次， 而 Repo Scaffolding 和 Jenkins Pipeline 的创建属于&quot;配置&quot;过程，可能要执行多次（比如不断新增 Repo 和 Pipeline 等）， 所以我们分2步来完成这条工具链的搭建过程。</p>
<h3 id="41工具链部署">4.1、工具链部署</h3>
<p>先下载一个 DevStream 的 CLI，参考<a href="https://docs.devstream.io/en/latest/best-practices/air-gapped-deployment.zh/#11-dtm"target="_blank" rel="external nofollow noopener noreferrer">这个文档</a>。有了 dtm 之后，我们就该着手准备配置文件了（下面配置保存到 config.yaml 里）：</p>
<pre tabindex="0"><code>---  varFile:  &#34;&#34;  # If not empty, use the specified external variables config file  toolFile:  &#34;&#34;  # If not empty, use the specified external tools config file  pluginDir:  &#34;&#34;  # 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:  &#34;rc&#34;  - name:  jenkins   instanceID:  default   dependsOn:  [  ]   options:   repo:   name:  jenkins   url:  https://charts.jenkins.io   chart:   chartPath:  &#34;&#34;   chartName:  jenkins/jenkins   namespace:  jenkins   wait:  true   timeout:  5m   upgradeCRDs:  true   valuesYaml:  |  serviceAccount: create: true name: jenkins controller: adminUser: &#34;admin&#34; adminPassword: &#34;changeme&#34; 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 &#34;GitHub Pull Request Builder&#34; plugin, see https://plugins.jenkins.io/ghprb/ for more details - ghprb # install &#34;OWASP Markup Formatter&#34; 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&#39;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: &#34;&#34; accessMode: ReadWriteOnce size: 5Gi jobservice: storageClass: &#34;&#34; accessMode: ReadWriteOnce size: 1Gi database: storageClass: &#34;&#34; accessMode: ReadWriteOnce size: 1Gi redis: storageClass: &#34;&#34; accessMode: ReadWriteOnce size: 1Gi 
</code></pre><p>这里的配置项并不难看懂，推荐大伙执行后面的命令前先仔细看一遍这个配置文件，按需调整。比如里面配置了几个工具的域名啥的，这些都可以改。</p>
<p>然后就可以开始初始化了（主要是插件下载）：</p>
<pre tabindex="0"><code>dtm init -f config.yaml 
</code></pre><p>然后执行 apply 开始部署：</p>
<pre tabindex="0"><code>dtm apply -f config.yaml -y 
</code></pre><p>这时候你会看到和谐的日志：</p>
<pre tabindex="0"><code>2022-10-08 09:43:13 ℹ [INFO]  Apply started.
2022-10-08 09:43:13 ℹ [INFO]  Using dir &lt;/root/.devstream/plugins&gt; 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&#39;t exist in the state, will be created. 2022-10-08 09:43:13 ℹ [INFO]  Tool (jenkins/default) found in config but doesn&#39;t exist in the state, will be created.
2022-10-08 09:43:13 ℹ [INFO]  Tool (harbor/default) found in config but doesn&#39;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) -&gt; 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 &lt;gitlab&gt; 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=&#39;{{json .Mounts}}&#39; 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 -&gt; docker exec -it gitlab grep &#39;Password:&#39; /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) -&gt; 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) -&gt; 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. 
</code></pre><p>假如日志不够和谐，那就，那就，，，debug 吧。</p>
<h3 id="42网络配置">4.2、网络配置</h3>
<p>前面 GitLab + Jenkins + Harbor 三个工具的配置文件里我们都设置了域名，如果是 kubeadm 直接部署的 k8s 集群，你可以直接将这些域名与 IP 的映射关系配置到 DNS 服务器里。</p>
<p>如果没有 DNS 服务器，你也可以直接将域名与 IP 的映射关系配置到 <code>/etc/hosts</code> 以及 <code>CoreDNS</code> 的 ConfigMap <code>kube-system/coredns</code> 里让域名生效。比如：</p>
<ol>
<li>
<p>修改 <code>/etc/hosts</code> 文件，添加这条记录（记得替换成你自己的 IP）：</p>
<pre tabindex="0"><code>44.33.22.11 gitlab.example.com jenkins.example.com harbor.example.com 
</code></pre></li>
<li>
<p>修改 <code>CoreDNS</code> 的配置，在 ConfigMap <code>kube-system/coredns</code> 中添加静态解析记录：</p>
<ol>
<li>执行命令：<code>kubectl edit cm coredns -n kube-system</code>；</li>
<li>在 hosts(第20行左右) 部分添加和 /etc/hosts 一样的记录。</li>
</ol>
</li>
</ol>
<p>这样 Jenkins 才能通过域名访问到 GitLab。</p>
<h3 id="43验证工具链部署结果">4.3、验证工具链部署结果</h3>
<p>来，看下新部署的 GitLab、Jenkins、Harbor 是不是都能访问到。</p>
<h4 id="431gitlab">4.3.1、GitLab</h4>
<p>不出意外的话，你可以在自己的 PC 里配置 <code>44.33.22.11 gitlab.example.com</code> 静态域名解析记录，然后在浏览器里通过 <code>http://gitlab.example.com:30080</code> 访问到 GitLab：</p>
<p><figure><a class="lightgallery" href="resources/3208bf242fca400f82aad696bbb863e1.svg" data-thumbnail="resources/3208bf242fca400f82aad696bbb863e1.svg" data-sub-html="<h2>./gitlab-login.png</h2><p>GitLab login</p>">
    
  </a><figcaption class="image-caption">./gitlab-login.png</figcaption>
  </figure></p>
<p>然后通过执行如下命令，你就能获得 GitLab 的初始 root 密码了：</p>
<pre tabindex="0"><code>docker exec gitlab cat /etc/gitlab/initial_root_password | grep Password: 
</code></pre><p>拿到 root 密码后，你可以尝试用 root/YOUR_PASSWORD 来登录 GitLab。因为后面我们需要用到 GitLab 的 token，所以这时候可以顺手创建一个 token：</p>
<p><figure><a class="lightgallery" href="resources/3208bf242fca400f82aad696bbb863e1.svg" data-thumbnail="resources/3208bf242fca400f82aad696bbb863e1.svg" data-sub-html="<h2>./gitlab-token.png</h2><p>GitLab token</p>">
    
  </a><figcaption class="image-caption">./gitlab-token.png</figcaption>
  </figure></p>
<h4 id="432jenkins">4.3.2、Jenkins</h4>
<p>在浏览器里通过 <code>http://jenkins.example.com:32000</code> 就可以访问到 Jenkins 了：</p>
<p><figure><a class="lightgallery" href="resources/3208bf242fca400f82aad696bbb863e1.svg" data-thumbnail="resources/3208bf242fca400f82aad696bbb863e1.svg" data-sub-html="<h2>./jenkins-login.png</h2><p>Jenkins login</p>">
    
  </a><figcaption class="image-caption">./jenkins-login.png</figcaption>
  </figure></p>
<p>Jenkins 的 admin 用户初始登录密码是 <code>changeme</code>，如果你仔细看了前面 dtm 使用的配置文件，可以发现这是在配置文件里指定的。我们尝试用 <code>admin/changeme</code> 登录 Jenkins 检查功能是否正常，不过这时不需要在 Jenkins 上进行任何额外的操作。</p>
<p><figure><a class="lightgallery" href="resources/3208bf242fca400f82aad696bbb863e1.svg" data-thumbnail="resources/3208bf242fca400f82aad696bbb863e1.svg" data-sub-html="<h2>./jenkins-dashboard.png</h2><p>Jenkins dashboard</p>">
    
  </a><figcaption class="image-caption">./jenkins-dashboard.png</figcaption>
  </figure></p>
<h4 id="433harbor">4.3.3、Harbor</h4>
<p>我们可以通过 <code>docker login harbor.example.com:80</code> 命令来尝试登录 Harbor，也可以直接通过 <code>http://harbor.example.com:30180</code> 访问 Dashboard：</p>
<p><figure><a class="lightgallery" href="resources/3208bf242fca400f82aad696bbb863e1.svg" data-thumbnail="resources/3208bf242fca400f82aad696bbb863e1.svg" data-sub-html="<h2>./harbor-login.png</h2><p>Harbor login</p>">
    
  </a><figcaption class="image-caption">./harbor-login.png</figcaption>
  </figure></p>
<p>Harbor 的 admin 用户初始登录密码是 <code>Harbor12345</code>，我们尝试用 <code>admin/Harbor12345</code> 登录 Harbor：</p>
<p><figure><a class="lightgallery" href="resources/3208bf242fca400f82aad696bbb863e1.svg" data-thumbnail="resources/3208bf242fca400f82aad696bbb863e1.svg" data-sub-html="<h2>./harbor-dashboard.png</h2><p>Harbor dashboard</p>">
    
  </a><figcaption class="image-caption">./harbor-dashboard.png</figcaption>
  </figure></p>
<h3 id="44流水线配置">4.4、流水线配置</h3>
<p>工具有了，下一步就是配置流水线了，咱继续准备第二个配置文件（config-pipeline.yaml）：</p>
<pre tabindex="0"><code>---  varFile:  &#34;&#34;  # If not empty, use the specified external variables config file  toolFile:  &#34;&#34;  # If not empty, use the specified external tools config file  pluginDir:  &#34;&#34;  # 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 
</code></pre><p>同样我建议你仔细看一下这个配置文件，里面的一些访问地址，比如 IP 和域名啥的，按需调整。</p>
<p>前面我们添加了一个 GitLab 的 token，这个 token 需要被设置到环境变量里：</p>
<pre tabindex="0"><code>export GITLAB_TOKEN=YOUR_GITLAB_TOKEN 
</code></pre><p>同时我们需要将 Harbor 密码配置到环境变量里，如果你的 Harbor 没有去修改密码，这时候默认密码应该是 Harbor12345：</p>
<pre tabindex="0"><code>export IMAGE_REPO_PASSWORD=Harbor12345 
</code></pre><p>接着就是熟悉的 init 和 apply 命令了：</p>
<pre tabindex="0"><code>dtm init -f config-pipeline.yaml
dtm apply -f config-pipeline.yaml -y 
</code></pre><p>结果日志依旧应该和谐：</p>
<pre tabindex="0"><code>2022-10-08 13:19:27 ℹ [INFO]  Apply started.
2022-10-08 13:19:27 ℹ [INFO]  Using dir &lt;/root/.devstream/plugins&gt; 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&#39;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) -&gt; 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. 
</code></pre><h3 id="45验证流水线配置结果">4.5、验证流水线配置结果</h3>
<p>我们上 GitLab 看下 dtm 准备的 Java Spring Boot 项目脚手架：</p>
<p><figure><a class="lightgallery" href="resources/3208bf242fca400f82aad696bbb863e1.svg" data-thumbnail="resources/3208bf242fca400f82aad696bbb863e1.svg" data-sub-html="<h2>./repo-scaffolding.png</h2><p>Repo scaffolding</p>">
    
  </a><figcaption class="image-caption">./repo-scaffolding.png</figcaption>
  </figure></p>
<p>接着登录 Jenkins，可以看到 dtm 创建的 Pipeline：</p>
<p><figure><a class="lightgallery" href="resources/3208bf242fca400f82aad696bbb863e1.svg" data-thumbnail="resources/3208bf242fca400f82aad696bbb863e1.svg" data-sub-html="<h2>./jenkins-pipeline.png</h2><p>Jenkins Pipeline</p>">
    
  </a><figcaption class="image-caption">./jenkins-pipeline.png</figcaption>
  </figure></p>
<p>Pipeline 成功执行完成后：</p>
<p><figure><a class="lightgallery" href="resources/3208bf242fca400f82aad696bbb863e1.svg" data-thumbnail="resources/3208bf242fca400f82aad696bbb863e1.svg" data-sub-html="<h2>./pipeline-success.png</h2><p>Pipeline Success</p>">
    
  </a><figcaption class="image-caption">./pipeline-success.png</figcaption>
  </figure></p>
<p>再回到 GitLab 看下回显的状态：</p>
<p><figure><a class="lightgallery" href="resources/3208bf242fca400f82aad696bbb863e1.svg" data-thumbnail="resources/3208bf242fca400f82aad696bbb863e1.svg" data-sub-html="<h2>./gitlab-status.png</h2><p>GitLab Status</p>">
    
  </a><figcaption class="image-caption">./gitlab-status.png</figcaption>
  </figure></p>
<p>歌舞升平，一片祥和！</p>
<h2 id="五总结">五、总结</h2>
<p>此处应该有个总结，但是到饭点了。</p>
<p>不总结了吧。</p>
<p>就留一个问题：<strong>DevStream 部署 DevOps 工具链是不是最佳实践？</strong></p>
<p>也许是，也许不是。不过我相信 DevStream 会逐步汇集业内最佳实践，最终变成一个标准。</p>
<p>再留个问题：<strong>DevStream 足够成熟稳定了不？</strong></p>
<p>应该不够。不过 DevStream 在逐渐走向成熟。如果大家愿意使用 DevStream，多提 bug，甚至参与社区开发，DevStream 就会更快走向成熟稳定。</p>
<hr>
<blockquote>
<p>参考：</p>
<ul>
<li><a href="https://github.com/devstream-io/devstream"target="_blank" rel="external nofollow noopener noreferrer">DevStream 项目仓库</a></li>
<li><a href="https://docs.devstream.io/en/latest/best-practices/gitlab-jenkins-harbor.zh/"target="_blank" rel="external nofollow noopener noreferrer">DevStream 文档：本地部署 GitLab + Jenkins + Harbor 工具链</a></li>
<li><a href="https://docs.devstream.io/en/latest/best-practices/air-gapped-deployment.zh/"target="_blank" rel="external nofollow noopener noreferrer">DevStream 文档：离线部署</a></li>
</ul>
</blockquote>
<p><a href="https://blog.devstream.io/tags/devops/"target="_blank" rel="external nofollow noopener noreferrer">devops</a>, <a href="https://blog.devstream.io/tags/gitlab/"target="_blank" rel="external nofollow noopener noreferrer">gitlab</a>, <a href="https://blog.devstream.io/tags/jenkins/"target="_blank" rel="external nofollow noopener noreferrer">jenkins</a>, <a href="https://blog.devstream.io/tags/harbor/"target="_blank" rel="external nofollow noopener noreferrer">harbor</a>, <a href="https://blog.devstream.io/tags/cicd/"target="_blank" rel="external nofollow noopener noreferrer">cicd</a>, <a href="https://blog.devstream.io/tags/%E4%B8%AD%E6%96%87%E6%96%87%E7%AB%A0/"target="_blank" rel="external nofollow noopener noreferrer">中文文章</a>, <a href="https://blog.devstream.io/tags/%E5%BC%80%E6%BA%90/"target="_blank" rel="external nofollow noopener noreferrer">开源</a></p>
<p>Back | <a href="https://blog.devstream.io/"target="_blank" rel="external nofollow noopener noreferrer">Home</a></p>
<p><a href="https://blog.devstream.io/posts/v090-release/" title="DevStream v0.9.0 Release"target="_blank" rel="external nofollow noopener noreferrer">DevStream v0.9.0 Release</a> <a href="https://blog.devstream.io/posts/10-devops-tools-for-startups/" title="10 Best DevOps Tools for Start-ups"target="_blank" rel="external nofollow noopener noreferrer">10 Best DevOps Tools for Start-ups</a></p>
<p>Merico Inc. and the DevStream Contributors</p>
<p>2022</p>]]></description>
</item>
</channel>
</rss>
