<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>CICD on 维克的博客</title><link>https://blogs.wuvikr.top/tags/cicd/</link><description>Recent content in CICD on 维克的博客</description><generator>Hugo</generator><language>en</language><lastBuildDate>Fri, 30 Oct 2026 15:59:39 +0800</lastBuildDate><atom:link href="https://blogs.wuvikr.top/tags/cicd/index.xml" rel="self" type="application/rss+xml"/><item><title>从零开始：生产级 GitLab CI 流水线搭建</title><link>https://blogs.wuvikr.top/posts/%E4%BB%8E%E9%9B%B6%E5%BC%80%E5%A7%8B%E7%94%9F%E4%BA%A7%E7%BA%A7gitlab-ci%E6%B5%81%E6%B0%B4%E7%BA%BF%E6%90%AD%E5%BB%BA/</link><pubDate>Fri, 30 Oct 2026 15:59:39 +0800</pubDate><guid>https://blogs.wuvikr.top/posts/%E4%BB%8E%E9%9B%B6%E5%BC%80%E5%A7%8B%E7%94%9F%E4%BA%A7%E7%BA%A7gitlab-ci%E6%B5%81%E6%B0%B4%E7%BA%BF%E6%90%AD%E5%BB%BA/</guid><description>&lt;p>本文以 Go 语言为案例，从「只做编译和测试」的最小流水线起步，逐步加上&lt;strong>构建镜像&lt;/strong>、&lt;strong>镜像漏洞扫描&lt;/strong>、&lt;strong>推送 Harbor&lt;/strong>，最终形成五阶段完整生产级 GitLab CI 流水线。&lt;/p>
&lt;p>下面是本文的实践路线：&lt;/p>
&lt;ol>
&lt;li>最小流水线，只做 &lt;code>build&lt;/code> 和 &lt;code>test&lt;/code> 阶段，让流水线先简单跑通。&lt;/li>
&lt;li>增加 &lt;code>build-image&lt;/code> 阶段，用 Kaniko 按 Dockerfile 构建镜像。&lt;/li>
&lt;li>增加 &lt;code>scan-image&lt;/code> 阶段，用 Trivy 扫描镜像，有高危漏洞直接退出。&lt;/li>
&lt;li>增加 &lt;code>push&lt;/code> 阶段，扫描通过后把镜像推送并打上标签。&lt;/li>
&lt;li>&lt;strong>汇总&lt;/strong>：给出完整五阶段配置与生产最佳实践。&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>为什么从头开始一点点增加步骤&lt;/strong>?&lt;/p>
&lt;p>直接给出五十行的完整配置的话，出了问题根本不知道是编译、测试、构建、扫描还是推送哪一个阶段的问题。先跑通最小闭环，每次增加一个阶段，有问题能立即验证，排查范围小，人也更有把握。&lt;/p>
&lt;p>日常编写构建生产级别的流水线也建议这样一步步验证。&lt;/p>
&lt;h1 id="1-最小流水线验证">1. 最小流水线验证&lt;/h1>
&lt;p>先只配置两个 job：&lt;/p>
&lt;ul>
&lt;li>&lt;code>build&lt;/code> 阶段：负责编译校验，确认代码能否正常打包、是否存在语法错误。&lt;/li>
&lt;li>&lt;code>test&lt;/code> 阶段：运行单元测试。&lt;/li>
&lt;/ul>
&lt;p>这两个 job 是整个 CI 的基础，也是触发最频繁、最需要优先跑稳的部分。&lt;/p>
&lt;h2 id="11-为什么先只做这两步">1.1 为什么先只做这两步&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>反馈最快&lt;/strong>：编译和单元测试在同一个代码环境中运行，几秒内就能拿到结果，不依赖镜像仓库或外部服务。&lt;/li>
&lt;li>&lt;strong>成本最低&lt;/strong>：不构建镜像、不推送，也不做扫描，任何分支的提交都可以安全触发，不会产生多余产物。&lt;/li>
&lt;li>&lt;strong>优先保障代码质量&lt;/strong>：如果编译或测试失败，就不应继续执行后续的构建、扫描和推送步骤。&lt;/li>
&lt;/ul>
&lt;h2 id="13-写配置文件">1.3 写配置文件&lt;/h2>
&lt;p>在项目根目录新建 &lt;code>.gitlab-ci.yml&lt;/code>，写入下面内容：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">stages&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">build&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">test&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">variables&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">GO_VERSION&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;1.26&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 国内须覆盖 GOPROXY，否则 go mod download 走 proxy.golang.org 会超时&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">GOPROXY&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;https://goproxy.cn,direct&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">GOSUMDB&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;sum.golang.google.cn&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 镜像仓库地址&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">HARBOR_REGISTRY&lt;/span>: &lt;span style="color:#ae81ff">example.harbor.com&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">IMAGE_NAME&lt;/span>: &lt;span style="color:#ae81ff">${HARBOR_REGISTRY}/devops/web-demo&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 缓存目录&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">GOMODCACHE&lt;/span>: &lt;span style="color:#ae81ff">$CI_PROJECT_DIR/.cache/go-mod&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">GOCACHE&lt;/span>: &lt;span style="color:#ae81ff">$CI_PROJECT_DIR/.cache/go-build&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># ============================================================================&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Stage 1: 服务构建&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># ============================================================================&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">build&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">stage&lt;/span>: &lt;span style="color:#ae81ff">build&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">image&lt;/span>: &lt;span style="color:#ae81ff">${HARBOR_REGISTRY}/devops/golang:1.26-trixie&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">variables&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">GOFLAGS&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;-mod=mod&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">cache&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">key&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">files&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">go.sum&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">paths&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">.cache/go-mod/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">.cache/go-build/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">untracked&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">before_script&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">mkdir -p ${GOMODCACHE} ${GOCACHE}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">script&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">go mod download&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">go build -o /dev/null ./... &lt;/span> &lt;span style="color:#75715e"># 只验证能否编译，不产出二进制&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">go vet ./...&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># ============================================================================&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Stage 2: 单元测试&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># ============================================================================&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">test&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">stage&lt;/span>: &lt;span style="color:#ae81ff">test&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">image&lt;/span>: &lt;span style="color:#ae81ff">${HARBOR_REGISTRY}/devops/golang:1.26-trixie&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">cache&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">key&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">files&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">go.sum&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">paths&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">.cache/go-mod/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">.cache/go-build/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">untracked&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">before_script&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">mkdir -p ${GOMODCACHE} ${GOCACHE}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">script&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">go mod download&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">go test -v -race -coverprofile=coverage.out ./...&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">artifacts&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">when&lt;/span>: &lt;span style="color:#ae81ff">always&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">expire_in&lt;/span>: &lt;span style="color:#ae81ff">1&lt;/span> &lt;span style="color:#ae81ff">week&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">reports&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">coverage_report&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">coverage_format&lt;/span>: &lt;span style="color:#ae81ff">cobertura&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">path&lt;/span>: &lt;span style="color:#ae81ff">coverage.out&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">paths&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">coverage.out&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>配置说明&lt;/strong>：&lt;/p></description></item><item><title>Kaniko 从入门到实践</title><link>https://blogs.wuvikr.top/posts/kaniko%E4%BB%8E%E5%85%A5%E9%97%A8%E5%88%B0%E5%AE%9E%E8%B7%B5/</link><pubDate>Sat, 24 Oct 2026 11:28:31 +0800</pubDate><guid>https://blogs.wuvikr.top/posts/kaniko%E4%BB%8E%E5%85%A5%E9%97%A8%E5%88%B0%E5%AE%9E%E8%B7%B5/</guid><description>&lt;h1 id="1-kaniko-是什么">1. Kaniko 是什么&lt;/h1>
&lt;p>&lt;strong>Kaniko&lt;/strong> 是一个由 Google 开源的，在&lt;strong>容器或 Kubernetes 集群内部&lt;/strong>，直接根据 Dockerfile 构建容器镜像的工具。&lt;/p>
&lt;p>它最核心的特点只有一个：&lt;strong>不依赖 Docker daemon（守护进程）&lt;/strong>，所有构建动作都在用户态（userspace）完成。这意味着你不需要在集群里跑一个 Docker 服务，也不需要挂载 &lt;code>/var/run/docker.sock&lt;/code>，就可以构建出标准镜像。&lt;/p>
&lt;h1 id="2-kaniko-解决了什么问题">2. Kaniko 解决了什么问题&lt;/h1>
&lt;p>在 Kaniko 出现之前，CI 里构建镜像的主流做法是 &lt;strong>Docker-in-Docker（DinD）&lt;/strong>。即在 CI Job 里再起一个 Docker 守护进程，用它去 build。这套方案在 Kubernetes 集群里有两个致命痛点：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>需要 privileged 特权模式&lt;/strong>：dind 服务容器要操控内核特性，必须给 Pod 开 &lt;code>privileged: true&lt;/code>。这是很严重的安全隐患——容器可能逃逸到宿主机，很多安全策略严格的集群直接禁止。&lt;/li>
&lt;li>&lt;strong>性能差&lt;/strong>：每个 Job 都额外拉起一个完整 Docker daemon，启动慢、占用高，多任务并发时更是灾难。&lt;/li>
&lt;/ol>
&lt;p>Kaniko 就是为了解决这个问题而生的：&lt;strong>不用特权、不用 daemon，在标准 K8s 集群里就能安全构建镜像。&lt;/strong>&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>问题&lt;/th>
&lt;th>DinD（旧方案）&lt;/th>
&lt;th>Kaniko&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>需要 privileged 特权&lt;/td>
&lt;td>✅ 必须&lt;/td>
&lt;td>❌ 不需要&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>依赖 Docker daemon&lt;/td>
&lt;td>✅ 必须&lt;/td>
&lt;td>❌ 完全不需要&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>挂载 docker.sock&lt;/td>
&lt;td>✅ 需要&lt;/td>
&lt;td>❌ 不需要&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>安全性&lt;/td>
&lt;td>有容器逃逸风险&lt;/td>
&lt;td>纯用户态，安全&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>性能开销&lt;/td>
&lt;td>每个 Job 起 daemon，慢&lt;/td>
&lt;td>轻量，快&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>Kaniko 的核心价值用一句话来说就是：&lt;strong>在不安全、不方便跑 Docker daemon 的环境（尤其是 K8s 集群）里，仍然能安全、快速地构建镜像。&lt;/strong>&lt;/p></description></item><item><title>GitLab CICD 入门指南</title><link>https://blogs.wuvikr.top/posts/gitlab-cicd-%E5%9F%BA%E7%A1%80%E5%85%A5%E9%97%A8/</link><pubDate>Thu, 22 Oct 2026 10:02:12 +0800</pubDate><guid>https://blogs.wuvikr.top/posts/gitlab-cicd-%E5%9F%BA%E7%A1%80%E5%85%A5%E9%97%A8/</guid><description>&lt;h1 id="1-简介">1. 简介&lt;/h1>
&lt;h2 id="11-gitlab-cicd-是什么">1.1 GitLab CI/CD 是什么？&lt;/h2>
&lt;p>GitLab CI/CD 可以理解为：GitLab 内置的持续集成 / 持续交付引擎。代码提交、合并请求、打标签或定时触发后，GitLab 会根据项目里的 &lt;code>.gitlab-ci.yml&lt;/code> 生成流水线，再交给 GitLab Runner 去执行构建、测试、扫描、打包、部署等任务。&lt;/p>
&lt;p>它的整体架构可以分成三层：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align: center">&lt;strong>层级&lt;/strong>&lt;/th>
&lt;th style="text-align: center">&lt;strong>组件&lt;/strong>&lt;/th>
&lt;th style="text-align: center">&lt;strong>作用&lt;/strong>&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align: center">控制层&lt;/td>
&lt;td style="text-align: center">GitLab Server&lt;/td>
&lt;td style="text-align: center">解析 &lt;code>.gitlab-ci.yml&lt;/code>，生成 Pipeline，分发 Job，展示结果&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: center">执行层&lt;/td>
&lt;td style="text-align: center">GitLab Runner&lt;/td>
&lt;td style="text-align: center">从 GitLab 拉取任务，执行脚本，回传日志和产物&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: center">环境层&lt;/td>
&lt;td style="text-align: center">Executor&lt;/td>
&lt;td style="text-align: center">决定 Job 跑在哪里，比如 Docker、Kubernetes、Shell、SSH 等&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>一个典型的 Gitlab CICD 执行链路如下所示：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-plaintext" data-lang="plaintext">&lt;span style="display:flex;">&lt;span>开发者 push 代码或创建 MR，触发流水线
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ↓
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>GitLab 读取仓库里的 .gitlab-ci.yml，生成 Pipeline 流水线作业
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ↓
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Runner 轮询到待执行的任务，领取 Job
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ↓
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Job 的 Tag 会和 Executor 的 Tag 进行匹配，匹配成功后，Executor 去执行 Job
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ↓
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>执行完成后，日志、制品、状态回传到 GitLab，在页面上可以查看结果
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="12-如何定义流水线">1.2 如何定义流水线？&lt;/h2>
&lt;p>一个流水线本质上由两个核心概念构成：&lt;/p></description></item><item><title>Gitlab 入门和生产部署实践</title><link>https://blogs.wuvikr.top/posts/gitlab%E5%85%A5%E9%97%A8%E5%92%8C%E7%94%9F%E4%BA%A7%E9%83%A8%E7%BD%B2%E5%AE%9E%E8%B7%B5/</link><pubDate>Mon, 12 Oct 2026 14:51:37 +0800</pubDate><guid>https://blogs.wuvikr.top/posts/gitlab%E5%85%A5%E9%97%A8%E5%92%8C%E7%94%9F%E4%BA%A7%E9%83%A8%E7%BD%B2%E5%AE%9E%E8%B7%B5/</guid><description>&lt;h1 id="1-什么是-gitlab">1. 什么是 GitLab&lt;/h1>
&lt;p>GitLab 是一款开源的 Git 代码托管平台，支持私有化部署，被众多企业用于搭建内部代码仓库。与 GitHub 主打开源协作不同，GitLab 更聚焦于代码托管和研发流程自动化，原生提供 CI/CD、代码评审、权限管控、镜像仓库、日志审计等能力。&lt;/p>
&lt;p>GitLab 主要分为两个版本：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>CE 社区版&lt;/strong>：免费开源，基本能满足 95% 中小企业的生产需求（本文案例）；&lt;/li>
&lt;li>&lt;strong>EE 企业版&lt;/strong>：付费使用，提供高可用架构、高级安全扫描、集群权限管控以及官方技术支持，比较适合大厂落地。&lt;/li>
&lt;/ul>
&lt;p>总之，对企业来说，GitLab 的核心价值主要体现在四个方面：&lt;strong>代码内网私有化存储、研发流程标准化、流水线自动化、操作可审计追溯&lt;/strong>。&lt;/p>
&lt;h1 id="2-三种部署方式选型">2. 三种部署方式（选型）&lt;/h1>
&lt;ol>
&lt;li>&lt;strong>Omnibus 包部署（生产首选）&lt;/strong>：官方推荐的标准生产部署方案，以一键安装包形式提供，支持主流 Linux 发行版。内置 PostgreSQL、Redis、Gitaly、Web、Sidekiq 等核心组件，部署路径清晰、运维成本较低、稳定性较高，是生产环境中最稳妥的选择。&lt;/li>
&lt;li>&lt;strong>K8s 混合部署（不推荐新人尝试）&lt;/strong>：面向大规模高并发场景时，官方推荐采用混合架构，将 Web、Sidekiq 等无状态组件部署在 Kubernetes 中，便于弹性扩缩；Gitaly、数据库、缓存等有状态服务则保留在虚拟机或独立节点上部署，以保证存储和数据的稳定性。不建议新手直接使用 Kubernetes 全组件部署 GitLab。有状态组件在容器环境中的存储管理、备份恢复和升级复杂度较高，生产风险较大。&lt;/li>
&lt;li>&lt;strong>Docker 单容器部署（仅测试用）&lt;/strong>：Docker 单容器部署启动快、上手简单，但在数据持久化、备份恢复、版本升级和高可用方面能力有限，仅适合本地测试、功能验证或演示环境，不建议用于生产。&lt;/li>
&lt;/ol>
&lt;h1 id="3-安装-gitlab">3. 安装 GitLab&lt;/h1>
&lt;p>&lt;a href="https://docs.gitlab.com/omnibus/installation/index.html">官方安装文档&lt;/a>&lt;/p>
&lt;h2 id="31-前置硬件系统要求">3.1 前置硬件&amp;amp;系统要求&lt;/h2>
&lt;ul>
&lt;li>仅支持 linux，最低配置：4核8G（10人以内小团队），生产推荐 8 核 16G 及以上；&lt;/li>
&lt;li>关闭 SELinux 或 AppArmor，否则可能影响服务正常运行；&lt;/li>
&lt;li>存储优先用 SSD；不建议用 NFS、EFS、Azure Files 这类网络文件系统放仓库数据；&lt;/li>
&lt;li>开放端口：80(http)、443(https)、22(ssh)。&lt;/li>
&lt;/ul>
&lt;h2 id="32-添加-apt-源安装">3.2 添加 apt 源安装&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 更新系统依赖&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo apt update &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> sudo apt upgrade -y
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 安装必备依赖&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo apt install -y curl openssh-server ca-certificates tzdata
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 添加 GitLab 官方 APT 源&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo curl --location &lt;span style="color:#e6db74">&amp;#34;https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh&amp;#34;&lt;/span> | sudo bash
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 安装 GitLab 社区版（默认启动初始化）&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo apt install gitlab-ce -y
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="33-离线包无网络环境使用">3.3 离线包（无网络环境使用）&lt;/h2>
&lt;p>&lt;a href="https://packages.gitlab.com/gitlab/gitlab-ce">官方离线包下载地址&lt;/a>&lt;/p></description></item><item><title>ArgoCD 入门和生产实践指南</title><link>https://blogs.wuvikr.top/posts/argocd%E5%85%A5%E9%97%A8%E5%92%8C%E7%94%9F%E4%BA%A7%E5%AE%9E%E8%B7%B5%E6%8C%87%E5%8D%97/</link><pubDate>Sat, 10 Oct 2026 09:33:28 +0800</pubDate><guid>https://blogs.wuvikr.top/posts/argocd%E5%85%A5%E9%97%A8%E5%92%8C%E7%94%9F%E4%BA%A7%E5%AE%9E%E8%B7%B5%E6%8C%87%E5%8D%97/</guid><description>&lt;h1 id="1-什么是-argocd">1. 什么是 ArgoCD&lt;/h1>
&lt;p>&lt;a href="https://argo-cd.readthedocs.io/en/stable/">ArgoCD&lt;/a> 是 CNCF 毕业级项目，面向 Kubernetes 的&lt;strong>声明式 GitOps 持续交付工具&lt;/strong>。&lt;/p>
&lt;p>GitOps 核心思想：&lt;strong>Git 仓库作为应用配置的唯一可信源&lt;/strong>。ArgoCD 持续监听 Git 仓库内定义的应用目标状态，对比集群内资源的实际运行状态，自动完成应用部署、版本更新与故障回滚。&lt;/p>
&lt;p>ArgoCD 原生支持多种配置编排方式：Helm Chart、Kustomize、Jsonnet、Ksonnet，以及原生 YAML/JSON Kubernetes 资源清单。&lt;/p>
&lt;h1 id="2-架构原理">2. 架构原理&lt;/h1>
&lt;p>ArgoCD 以 Kubernetes 控制器形态运行，持续对应用做状态巡检：&lt;/p>
&lt;ol>
&lt;li>拉取 Git 仓库中声明的&lt;strong>期望状态（Target State）&lt;/strong>&lt;/li>
&lt;li>采集集群内资源&lt;strong>实际运行状态（Live State）&lt;/strong>&lt;/li>
&lt;li>对比两者差异，不一致时标记为 &lt;code>OutOfSync&lt;/code>（不同步）&lt;/li>
&lt;li>可视化展示资源差异，支持&lt;strong>手动同步 / 自动同步&lt;/strong>，将集群状态收敛到 Git 定义的目标状态&lt;/li>
&lt;/ol>
&lt;p>Git 仓库中修改清单后，ArgoCD 会感知变更并同步至目标集群，实现“改 Git 即发布”。&lt;/p>
&lt;p>具体工作流程参见下面的图片：
&lt;img alt="argocd工作流程图" loading="lazy" src="https://blogs.wuvikr.top/posts/argocd%E5%85%A5%E9%97%A8%E5%92%8C%E7%94%9F%E4%BA%A7%E5%AE%9E%E8%B7%B5%E6%8C%87%E5%8D%97/argocd%E5%B7%A5%E4%BD%9C%E6%B5%81%E7%A8%8B%E7%A4%BA%E6%84%8F%E5%9B%BE.png">&lt;/p>
&lt;p>&lt;strong>核心组件&lt;/strong>:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align: center">组件&lt;/th>
&lt;th style="text-align: center">核心作用&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align: center">&lt;code>argocd-server&lt;/code>&lt;/td>
&lt;td style="text-align: center">ArgoCD API 服务，提供 REST API、Web UI，处理认证鉴权&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: center">&lt;code>argocd-repo-server&lt;/code>&lt;/td>
&lt;td style="text-align: center">Git 仓库管理服务，缓存仓库代码、渲染 Helm/Kustomize 生成K8s清单&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: center">&lt;code>argocd-application-controller&lt;/code>&lt;/td>
&lt;td style="text-align: center">应用控制器，持续做状态比对，执行同步、健康检查&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: center">&lt;code>argocd-applicationset-controller&lt;/code>&lt;/td>
&lt;td style="text-align: center">ApplicationSet控制器，批量、模板化管理多环境/多集群 Application&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: center">&lt;code>argocd-redis&lt;/code>&lt;/td>
&lt;td style="text-align: center">缓存组件，存储仓库缓存、应用状态信息&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: center">&lt;code>argocd-dex-server&lt;/code>&lt;/td>
&lt;td style="text-align: center">可选，Dex 身份代理，对接OIDC、LDAP等外部身份源&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: center">&lt;code>argocd-notifications-controller&lt;/code>&lt;/td>
&lt;td style="text-align: center">可选，通知控制器，同步状态变更推送至邮件、Slack、Webhook等&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h1 id="3-部署">3. 部署&lt;/h1>
&lt;p>部署前建议查阅&lt;a href="https://argo-cd.readthedocs.io/en/stable/operator-manual/installation/#supported-versions">官方版本兼容矩阵&lt;/a>，选择与K8s集群匹配的ArgoCD版本。&lt;/p></description></item></channel></rss>