了解如何使用用于切换目录的一个基本但必不可少的 Linux 命令。Linux 中的 cd 命令用于更改目录。cd 实际上是“ 更改目录 change directories ”的缩写。这是你必须了解的 基本 Linux 命令之一。使用 cd 命令非常简单：cd path_to_directory 不可能比这更简单了，对吧。然而，你应该理解它的路径部分，以便轻松地浏览 文件系统 而不会感到困惑。这是绝对路径和相对路径的快速回顾：如果你需要更多细节，我建议你阅读这篇文章：Linux 上的绝对路径和相对路径有什么不同让我们看一些使用 cd 命令的示例。使用绝对路径更改目录从视觉上看会更容易理解。看下图。我当前的位置是我的主目录（/home/abhishek），我必须进入 scripts 目录中的 python 目录。假设我想使用绝对路径。python 目录的绝对路径是 /home/abhishek/scripts/python。cd /home/abhishek/scripts/python 使用相对路径更改目录让我们举同样的例子，但这次我将采用相对路径。我的主目录到 python 目录的相对路径是 scripts/python。让我们用这个：cd scripts/python 进入上级目录到目前为止，你一直在进入下级。如果你必须进入上级目录怎么办？假设你位于 /home/abhishek/scripts/python 中，并且必须将目录添加到 scripts？使用绝对路径始终是一种选择，但它相当冗长。相反，你可以使用特殊的目录符号 ..。双点 （..）表示父目录或上一级目录。单点（.）表示当前目录。cd .. 这是一个例子：你可以使用 .. 在 Linux 文件系统层次结构中向上移动路径。假设我在上图中的 python 目录中，想要进入 code 目录。这是我能做的：cd ../../code 进入主目录如果你在所有这些目录切换中感到迷失并想回到主目录，有很多简单的快捷方式。事实上，最简单的就是使用不带任何选项的 cd 命令。cd 这将使你从文件系统上的任何位置返回主目录。或者，你可以使用 ~ 符号，表示主目录。cd ~ 进入根目录尽管你不会像前一个那样经常使用它，但了解一下仍然有好处。如果你想返回文件系统开始的根目录，请使用以下命令：cd / 这里不涉及“魔法”。当放在路径开头使用时，/ 表示根。不要将它与路径分隔符混淆。切换回上一级目录这是一个救命稻草，或者我应该说是“省时稻草”。当你深入目录结构，然后转到另一个目录，然后你觉得需要返回到以前的位置时，此快捷方式会有所帮助。cd - 还不清楚吗？ 让我举个例子。我位于 /etc/apt/sources.list.d。从这里，进入 /home/abhishek/scripts/python 来处理我的代码。然后我意识到我必须再次检查 /etc/apt/sources.list.d 目录中的某些内容。通常的方法是这样做，这让我再次输入所有路径：但聪明的方法是使用这个：看吧，无需再次输入冗长的路径。如期工作！?️ 练习时间如果你想练习 cd 命令，这里有一些练习供你使用。打开终端并进入 /var/log 目录。检查目录内容。你看到了什么？现在，进入 /var 目录。这是一个上级目录。从这里返回你的主目录。这些内容足以让你熟悉 cd 命令。以下是你应该了解的其他一些重要命令。每个 Ubuntu 用户都应该知道的 31 条 Linux 命令如果你有疑问或建议，请告诉我。（题图：MJ/6fbaa345-651a-4cb9-a752-130eda922790）via: https://itsfoss.com/cd-command/作者：Abhishek Prakash 选题：lkxed 译者：geekpi 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
对齐部署镜像和描述符是很困难的，但是某些策略可以使整个过程更高效。在软件架构中，当两个组件之间有某些概念性或技术上的差异时会出现 阻抗失配 impedance mismatch 。这个术语其实是从电子工程中借用的，表示电路中输入和输出的电子阻抗必须要匹配。在软件开发中，存储在镜像仓库中的镜像与存储在源码控制管理系统（LCTT 译注：SCM，Source Code Management）中它的 部署描述符 deployment descriptor 之间存在阻抗失配。你如何确定存储在 SCM 中的部署描述符表示的是正确的镜像？两个仓库追踪数据的方式并不一致，因此将一个镜像（在镜像仓库中独立存储的不可修改的二进制）和它的部署描述符（Git 中以文本文件形式存储的一系列修改记录）相匹配并不那么直观。注意：本文假定读者已经熟悉以下概念： 源码控制管理 Source Control Management （SCM）系统和分支Docker 或符合 OCI 标准的镜像和容器 容器编排系统 Container Orchestration Platforms （COP），如 Kubernetes 持续集成/持续交付 Continuous Integration/Continuous Delivery （CI/CD） 软件开发生命周期 Software development lifecycle （SDLC）环境阻抗失配：SCM 与镜像仓库为了更好地理解阻抗失配在什么场景下会成为问题，请考虑任意项目中的软件开发生命周期环境（SDLC），如开发、测试或发布环境。测试环境不会有阻抗失配。现在使用 CI/CD 的最佳实践中开发分支的最新提交都会对应开发环境中的最新部署。因此，一个典型的、成功的 CI/CD 开发流程如下：向 SCM 的开发分支提交新的修改新提交触发一次镜像构建新生成的镜像被推送到镜像仓库，标记为开发中镜像被部署到容器编排系统（COP）中的开发环境，该镜像的部署描述符也更新为从 SCM 拉取的最新描述符。换句话说，开发环境中最新的镜像永远与最新的部署描述符匹配。回滚到前一个构建的版本也不是问题，因为 SCM 也会跟着回滚。最终，随着开发流程继续推进，需要进行更多正式的测试，因此某个镜像 —— 镜像对应着 SCM 中的某次提交 —— 被推到测试环境。如果是一次成功的构建，那么不会有大问题，因为从开发环境推过来的镜像应该会与开发分支的最新提交相对应。开发环境的最新部署被允许入库，触发入库过程最新部署的镜像被标记为测试中镜像在测试环境中被拉取和部署，（该镜像）对应从 SCM 拉取的最新部署描述符到目前为止,一切都没有问题，对吗？如果出现下面的场景，会有什么问题？场景 A：镜像被推到下游环境，如 用户验收测试 user acceptance testing （UAT），或者是生产环境。场景 B：测试环境中发现了一个破坏性的 bug，镜像需要回滚到某个确定正常的版本。在任一场景中，开发过程并没有停止，即开发分支上游有了一次或多次新的提交，而这意味着最新的部署描述符已经发生了变化，最新的镜像与之前部署在测试环境中的镜像不一致。对部署描述符的修改可能会也可能不会对之前版本的镜像起作用，但是它们一定是不可信任的。如果它们有了变化，那么它们就一定与目前为止你测试过的想要部署的镜像的部署描述符不一致。问题的关键是：如果部署的镜像不是镜像库中的最新版本，你怎么确定与部署的镜像相对应的是 SCM 中的哪个部署描述符？ 一言以蔽之，无法确定。两个库直接有阻抗失配。如果要详细阐述下，那么是有方法可以解决的，但是你需要做很多工作，这部分内容就是文章接下来的主题了。请注意，下面的方案并不是解决问题的唯一办法，但是已经投入到生产环境并已经对很多项目起了作用，而且已经被构建并部署到生产环境中运行了超过一年。二进制与部署描述符源码通常被构建成一个 Docker 镜像或符合 OCI 标准的镜像，该镜像通常被部署到一个容器编排平台（COP）上，如 Kubernetes。部署到 COP 需要部署描述符来定义镜像被如何部署以及作为容器运行，如 Kubernetes 部署 或 CronJobs。这是因为在镜像和它的部署描述符之间有本质差异，在这里可以看到阻抗失配。在这次讨论中，我们认为镜像是存储在镜像仓库中不可修改的二进制。对源码的任何修改都不会修改镜像，而是用另一个新的镜像去替换它。相比之下，部署描述符是文本文件，因而可以被认为是源码且可修改。如果遵循最佳实践，那么部署描述符是被存储在 SCM，所有修改都会提交，而这很容易回溯。解决阻抗失配建议的解决方案的第一部分，就是提供一个能匹配镜像仓库中的镜像与对保存部署描述符的 SCM 做的代码提交的方法。最直接的解决方案是用源提交的哈希值标记镜像。这个方法可以区分不同版本的镜像、容易分辨，并且提供足够的信息来查找正确的部署描述符，以便镜像更好地部署到 COP。再回顾下上面的场景：场景 A 镜像被推到下游环境： 当镜像被从测试环境推到 UAT 环境时，我们可以从镜像的标签中知道应该从 SCM 的哪一次源码提交拉取部署描述符。场景 B 当一个镜像需要在某一环节中回滚：无论我们选择回滚到那个镜像版本，我们都可以知道从 SCM 的哪一次源码提交拉取正确的部署描述符。在每一种情景中，无论在某个镜像被部署到测试环境后开发分支有多少次提交和构建，对于每一次升级的镜像，我们都可以找到它当初部署时对应的部署描述符。然而，这并不是阻抗失配的完整解决方案。再考虑两个场景：场景 C 在负载测试环境中，会尝试对不同的部署描述符进行多次部署，以此来验证某一次构建的表现。场景 D 一个镜像被推送到下游环境，在该环境中部署描述符有一个错误。在上面的所有场景中，我们都需要修改部署描述符，但是目前为止我们只有一个源码提交哈希。请记住，最佳实践要求我们所有对源码的修改都要先提交到 SCM。某次提交的哈希本身是无法修改的，因此我们需要一个比仅仅追踪原来的源码提交哈希更好地解决方案。解决方案是基于原来的源码提交哈希新建一个分支。我们把这个分支称为部署分支。每当一个镜像被推到下游测试或发布环境时，你应该基于前一个 SDLC 环境的部署分支的最新提交创建一个新的部署分支。这样同一个镜像可以重复多次部署到不同的 SDLC 环境，并在后面每个环境中可以感知前面发现的改动或对镜像做的修改。注意： 在某个环境中做的修改是如何影响下一个环境的，是用可以共享数据的工具（如 Helm Charts）还是手动剪切、粘贴到其他目录，都不在本文讨论的范围内。因此，当一个镜像被从一个 SDLC 环境中推到下一环境时：创建一个部署分支如果镜像是从开发环境中推过来的，那么部署分支就基于构建这个镜像的源码提交哈希创建否则，部署分支基于当前部署分支的最新提交创建镜像被部署到下一个 SDLC 环境，使用的部署描述符是该环境中新创建的部署分支的部署描述符图 1：部署分支树部署分支下游环境的第一个部署分支，只有一次提交下游环境的第二个部署分支，只有一次提交有了部署分支这个解决方案，再回顾下上面的场景 C 和场景 D：场景 C 修改已经部署到下游 SDLC 环境中的镜像的部署描述符场景 D 修复某个 SDLC 环境中部署描述符的错误两个场景中，工作流如下：把对部署描述符做的修改提交到 SLDC 环境和镜像对应的部署分支通过部署分支最新提交对应的部署描述符把镜像重新部署到 SLDC 环境这样，部署分支彻底解决了（存储着代表一次独一无二的构建的单一的、不可修改的镜像的）镜像仓库与（存储着对应一个或多个 SDLC 环境的可修改的部署描述符的）SCM 仓库之间的阻抗失配。实践中的思考这看起来像是行得通的解决方案，但同时它也为开发者和运维人员带来了新的实践中的问题，比如：A. 为了更好地管理部署分支，部署描述符作为资源应该保存在哪里，是否要与构建镜像的源码保存在同一个 SCM 仓库？到目前为止，我们都在避免谈论应该把部署描述符放在哪个仓库里。在还没有太多细节需要处理时，我们推荐把所有 SDLC 环境的部署描述符与镜像源码放在同一个 SCM 仓库。当部署分支创建后，镜像的源码可以作为方便找到部署的容器中运行的镜像的引用来使用。上面提到过，可以通过镜像的标签来关联镜像与原始的源码提交。在一个单独的仓库中查找某次提交的源码的引用，会给开发者带来更大的困难（即便借助工具），这就是没有必要把所有资源都分开存储的原因。B. 应该在部署分支上修改构建镜像的源码吗？简答：不应该。详细阐述：不应该，因为永远不要在部署分支上构建镜像，它们是在开发分支上构建的。修改部署分支上定义一个镜像的源码会破坏被部署的镜像的构建记录，而且这些修改并不会对镜像的功能生效。在对比两个部署分支的版本时这也会成为问题。这可能会导致两个版本的功能差异有错误的测试结果（这是使用部署分支的一个很小的额外好处）。C. 为什么使用镜像 标签 tag ？ 标记 label 不可以吗？通过 标签 tag 可以在仓库中很容易地查找镜像，可读性也很好。在一组镜像中读取和查找 标记 label 的值需要拉取所有镜像的 清单文件 manifest ，而这会增加复杂度、降低性能。而且，考虑到历史记录的追踪和不同版本的查找，对不同版本的镜像添加 标签 tag 也很有必要，因此使用源码提交哈希是保证唯一性，以及保存能即时生效的有用信息的最简单的解决方案。D. 创建部署分支的最佳实践是怎样的？DevOps 最重要的三个原则：自动化、自动化、自动化。依赖资源来持续地强迫遵循最佳实践，充其量只是碰运气，因此在实现镜像的升级、回滚等 CI/CD 流水线时，把自动化部署分支写到脚本里。E. 对部署分支的命名规范有建议吗？<部署分支标识>-<环境>-<源码提交哈希>部署分支标识： 所有部署分支范围内唯一的字符串；如 “deployment” 或 “deploy”环境： 部署分支适用的 SDLC 环境；如 “qa”（测试环境）、 “stg”（预生产环境）、 或 “prod”（生产环境）源码提交哈希： 源码提交哈希中包含原来构建被部署的镜像的源码，开发者可以通过它很容易地查找到创建镜像的原始提交，同时也能保证分支名唯一。例如， deployment-qa-asdf78s 表示推到 QA 环境的部署分支， deployment-stg-asdf78s 表示推到 STG 环境的部署分支。F. 你怎么识别环境中运行的哪个镜像版本？我们的建议是把最新的部署分支提交哈希和源码提交哈希添加到 标记 中。开发者和运维人员可以通过这两个独一无二的标识符查找到部署的所有东西及其来源。在诸如执行回滚或前滚操作时，使用那些不同版本的部署的选择器也能清理资源碎片。G. 什么时候应该把部署分支的修改合并回开发分支？这完全取决于开发团队。如果你修改的目的是为了做负载测试，只是想验证什么情况会让程序崩溃，那么这些修改不应该被合并回开发分支。另一方面，如果你发现和修复了一个错误，或者对下游环境的部署做了调整，那么就应该把部署分支的修改合并回开发分支。H. 有现成的部署分支示例让我们试水吗？el-CICD 已经在生产上使用这个策略持续一年半应用到超过一百个项目了，覆盖所有的 SDLC 环境，包括管理生产环境的部署。如果你可以访问 OKD、Red Hat OpenShift lab cluster 或 Red Hat CodeReady Containers，你可以下载el-CICD 的最新版本，参照 教程 来学习部署分支是何时以怎样的方式创建和使用的。结语通过实践上面的例子可以帮助你更好的理解开发过程中阻抗失配相关的问题。对齐镜像和部署描述符是成功管理部署的关键部分。via: https://opensource.com/article/21/8/impedance-mismatch-cicd作者：Evan "Hippy" Slatis 选题：lujun9972 译者：lxbwolf 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
GitHub Actions 是一项为快速建立持续集成和交付（CI/CD）工作流程而提供的服务。这些工作流程在被称为“ 运行器 runner ”的主机上运行。GitHub 提供的 托管运行器 的操作系统的选择是有限的（Windows Server、Ubuntu、MacOS）。另一个选择是使用 自托管 的运行器，这让仓库管理员对运行器有更多控制。自托管的运行程序是专门为某个存储库或组织服务的。下面的文章介绍了使用 Fedora CoreOS 配置自托管运行程序的步骤。入门Fedora CoreOS 是一个精简的操作系统，旨在便于大规模的部署和维护。该操作系统会自动更新，并默认提供运行容器所需的工具。由于这些原因，Fedora CoreOS 是运行 CI/CD 工作流程的一个极佳选择。配置和配备 Fedora CoreOS 机器的第一步是生成一个 Ignition 文件。Butane 允许你使用更友好的格式（YAML）生成 Ignition 文件。配置一个 Fedora CoreOS 运行器要在 Fedora CoreOS 上执行 GitHub Actions，托管主机需要用于注册和运行该运行器的二进制文件和脚本。从 Actions 运行器项目 下载二进制文件和脚本，并部署在 /usr/local/sbin/actions-runner 下。version: "1.3.0" variant: fcos storage: directories: - path: /usr/local/sbin/actions-runner mode: 0755 user: name: core group: name: core files: - path: /usr/local/sbin/actions-runner/actions-runner-linux.tar.gz overwrite: true contents: source: https://github.com/actions/runner/releases/download/v2.278.0/actions-runner-linux-x64-2.278.0.tar.gz mode: 0755 user: name: core group: name: core 注册和删除令牌为一个项目配置运行器需要一个“ 令牌 token ”。这可以防止在没有正确权限的情况下从项目中注册或删除自托管的运行器。GitHub 提供的令牌有一个小时的过期时间。如果运行器在这个时间之后重新启动，它将需要一个新的注册令牌。该令牌可能出问题，特别是在 Fedora CoreOS 自动更新时。更新过程希望托管主机在收到新数据后至少每隔几周重启一次。幸运的是，可以使用 GitHub REST API 来获取这些令牌，并在托管主机每次重启时自动配置运行器。下面的 manage-runner.sh 脚本使用 API 来获取令牌，删除任何已经配置好的运行器，并用新的令牌注册运行器。#!/bin/bash # Handles the Github Action runner configuration. # Remove and Registration token expires after 1 hour, if we want our runner # to work after a reboot (auto update) we need to refresh the tokens. # First remove the runner with a fresh remove token REMOVE_TOKEN=$(curl -u ${GITHUB_USER}:${GITHUB_TOKEN} -X POST -H "Accept: application/vnd.github.v3+json" https://api.github.com/repos/${GITHUB_USER}/${GITHUB_REPO}/actions/runners/remove-token | jq -r '.token') /usr/local/sbin/actions-runner/config.sh remove --token ${REMOVE_TOKEN} # Then register the runner with a fresh registration token REGISTRATION_TOKEN=$(curl -u ${GITHUB_USER}:${GITHUB_TOKEN} -X POST -H "Accept: application/vnd.github.v3+json" https://api.github.com/repos/${GITHUB_USER}/${GITHUB_REPO}/actions/runners/registration-token | jq -r '.token') /usr/local/sbin/actions-runner/config.sh --url https://github.com/cverna/fcos-actions-runner --token ${REGISTRATION_TOKEN} --labels fcos --unattended 上面的脚本使用了一些环境变量，包含 GitHub 用户名和用于验证 REST API 请求的 个人访问令牌 Personal Access Token 。个人访问令牌需要存储库权限，以便成功检索运行器的注册和移除令牌。该令牌是安全敏感信息，所以最好将其存储在一个具有更严格权限的不同文件中。在这个例子中，这个文件是 actions-runner。GITHUB_USER=<user> GITHUB_REPO=<repo> GITHUB_TOKEN=<personal_access_token> 以下是创建这两个文件 manage-runner.sh 和 actions-runner 的 Butane 片段。- path: /usr/local/sbin/actions-runner/manage-runner.sh contents: local: manage-runner.sh mode: 0755 user: name: core group: name: core - path: /etc/actions-runner contents: local: actions-runner mode: 0700 user: name: core group: name: core 在 Fedora CoreOS 上运行 Actions最后，创建用于配置和启动运行器的 systemd 服务。在 Butane 配置文件中定义这些服务。systemd: units: - name: github-runner-configure.service enabled: true contents: | [Unit] Description=Configure the github action runner for a repository After=network-online.target boot-complete.target Requires=boot-complete.target [Service] EnvironmentFile=/etc/actions-runner Type=oneshot RemainAfterExit=yes User=core WorkingDirectory=/usr/local/sbin/actions-runner ExecStartPre=tar xvf actions-runner-linux.tar.gz --no-same-owner ExecStart=/usr/local/sbin/actions-runner/manage-runner.sh [Install] WantedBy=multi-user.target - name: github-runner.service enabled: true contents: | [Unit] Description=Run the github action runner After=github-runner-configure.service [Service] WorkingDirectory=/usr/local/sbin/actions-runner User=core ExecStart=/usr/local/sbin/actions-runner/run.sh [Install] WantedBy=multi-user.target 这将创建两个服务：github-runner-configure.service（在主机启动完成后运行一次）和 github-runner.service（运行 Actions 运行器二进制文件并等待新的 CI/CD 作业）。现在 Butane 配置已经完成，从中生成一个 Ignition 文件并配备一个 Fedora CoreOS Actions 运行器。$ podman run -i --rm -v $PWD:/code:z --workdir /code quay.io/coreos/butane:release --pretty --strict --files-dir /code config.yaml -o config.ignition 一旦 Ignition 文件生成，它就可以用来在 支持 Fedora CoreOS 的平台上配备一个运行器。配置一个 Action 来使用一个自托管的运行器下面的测试 Action 工作流程将测试 FCOS 的自托管的运行器。在你的 git 存储库中创建以下文件 .github/workflows/main.yml。# This is a basic workflow to help you get started with Actions name: CI # Controls when the action will run. on: # Triggers the workflow on push or pull request events but only for the main branch push: branches: [ main ] pull_request: branches: [ main ] # Allows you to run this workflow manually from the Actions tab workflow_dispatch: # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: # This workflow contains a single job called "build" build: # The type of runner that the job will run on runs-on: fcos # Steps represent a sequence of tasks that will be executed as part of the job steps: # Runs a single command using the runners shell - name: Run a one-line script run: podman run --rm fedora-minimal:34 echo Hello World ! 请注意，runs-on 的配置被设置为使用标签为 fcos 的运行器。本文介绍的代码可以在 这里 中找到。via: https://fedoramagazine.org/run-github-actions-on-fedora-coreos/作者：Clément Verna 选题：lujun9972 译者：wxy 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
你如何定义持续集成/持续部署管道取决于你组织的要求。 持续集成 continuous integration / 持续部署 continuous deployment （CI/CD）管道是每个 DevOps 计划的基础。 CI/CD 管道打破了传统的开发孤岛，使开发和运营团队能够在整个软件开发生命周期中进行协作。更好的是，转向 DevOps 和 CI/CD 管道可以帮助你的组织以更高的速度更安全地 交付软件。拆解 CI/CD 管道CI/CD 管道有很多定义，所以我总是建议组织定义自己的 CI/CD 管道版本和其他 DevOps 概念，而不是使用其他人的。开源 CI/CD 工具为你提供构建满足组织要求的 CI/CD 管道的自由和选择。形成 CI/CD 管道的阶段是将不同的任务子集分组为 管道阶段。典型的管道阶段包括：构建：开发人员编译应用程序代码。测试：质量保证（QA）团队使用自动化测试工具和策略测试应用程序代码。发布：开发团队将应用程序代码交付到代码库。部署：DevOps 团队将应用程序代码分阶段投入生产。安全性和合规性：QA 团队根据项目要求验证构建。这是组织部署容器扫描工具的阶段，这些工具根据 常见漏洞和暴露 Common Vulnerabilities and Exposures （CVE）检查容器镜像的质量。这些是 CI/CD 管道的标准阶段，但一些组织调整 CI/CD 管道模型以满足他们的要求。例如，为医疗保健市场构建应用程序的组织，具有严格的合规性标准，可以在整个工具链中分发测试、验证和合规性门槛。其他示例可能是依赖于具有开源软件（OSS）的复杂软件供应链的组织。商业组件可能会设立一个门槛，开发团队成员可以在其中为 OSS 包生成 软件物料清单 software bill of materials （SBOM），或者外部商业软件供应商必须将 SBOM 作为其合同可交付成果的一部分进行交付。CI/CD 管道的障碍实施 CI/CD 管道会改变团队的流程和文化。尽管许多开发人员愿意接受某些任务和测试的自动化，但人员可能成为采用 CI/CD 的障碍。从瀑布式流程转向 CI/CD 可能会动摇某些组织中基本的和隐含的权力结构。由于 CI/CD 管道提高了软件交付速度，旧手动流程的“守门人”可能会受到这种变化的威胁。整合机会随着你在文化、流程和工具中达到更高的 DevOps 成熟度水平，包含 CI/CD 工具链的工具的开源根源为一些激动人心的集成创造了机会。分析公司 Forrester 在 2020 年预测， 即时学习 just-in-time learning 将加入 CI/CD 管道。如果你考虑一下，会发现这是有道理的。在当前远程工作的时代，甚至对于新员工的远程入职，这更有意义。例如，组织可以将文档 wiki 与内部流程文档集成到其管道中。更雄心勃勃的组织可以将学习管理系统（LMS）（例如 Moodle）集成到其 CI/CD 管道中。它可以使用 LMS 发布有关新 DevOps 工具链功能的简短视频，开发人员在加入时或在整个管道中更新工具时需要学习这些功能。一些组织正在将群聊和其他协作工具直接集成到他们的 CI/CD 管道中。聊天平台提供警报并支持团队之间的协作和沟通。将 Mattermost、Rocket.Chat 或其他 企业聊天 平台集成到你的 CI/CD 管道中需要预先规划和分析，以确保管道用户不会被警报淹没。另一个需要探索的集成机会是将分析和高级报告构建到你的 CI/CD 管道中。这有助于你利用通过管道传输的数据。总结CI/CD 管道是 DevOps 的基础。开源使其能够适应并灵活地满足你在 DevOps 之旅中实施的运营变更所产生的新需求。我希望看到对统一 DevOps 平台趋势的开源响应，在这种趋势中，组织寻求端到端的 CI/CD 解决方案。这种解决方案的要素就在那里。毕竟，GitLab 和 GitHub 将他们的平台追溯到开源根源。最后，不要忘记每一个成功的 CI/CD 工具链背后的教育和外展。记录你的工具链和相关流程将改善开发人员入职和持续的 DevOps 团队培训。你和你的组织如何定义你的 CI/CD 工具链？请在评论中分享你的反馈。via: https://opensource.com/article/21/6/what-cicd-pipeline作者：Will Kelly 选题：lujun9972 译者：baddate 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
统一的持续集成与持续交付的流水线的构想是一种梦想吗？当我加入 WorkSafeBC 负责云端运维和工程流程优化的云端运维团队时，我和大家分享了我的梦想，那就是一个工具化的流水线，每一个产品都可以持续集成和持续交付。根据 Lukas Klose 的说法， 流程 flow （在软件工程的语境内）是“软件系统以稳定和可预测的速度创造价值的状态”。我认为这是最大的挑战和机遇之一，特别是在复杂的新兴解决方案领域。我力求通过一种持续、高效和优质的解决方案，提供一种持续交付模式，并且能够构建正确的事物让我们的用户感到满意。想办法把我们的系统分解成更小的碎片，这些碎片本身是有价值的，使团队能够渐进式地交付价值。这需要业务和工程部门改变思维方式。持续集成和持续交付的（CI/CD）流水线CI/CD 流水线是一种 DevOps 实践，用于更频繁、一致、可靠的地交付代码变更。它可以帮助敏捷开发团队提高部署频率，减少变更准备时间、变更失败率和关键绩效指标（KPI）的平均恢复时间，从而提高质量并且实现更快的交付。唯一的先决条件就是坚实的开发流程、对质量的心态和对需求从构想到废弃的责任心，以及一个全面的流水线（如下图所示）。它简化了工程流程和产品，以稳定基础架构环境；优化工作流程；并创建一致的、可重复的、自动化的任务。正如 Dave Snowden 的 Cynefin Sensemaking 模型所说的那样，这样就允许我们将复杂不可解决的任务变成了复杂可解决的任务，降低了维护成本，提高了质量和可靠性。精简流程的一部分是将 浪费实践类型 wasteful practice types Muri（过载）、Mura（变异）和 Muda（浪费）的浪费降低最低。Muri（过载）：避免过度工程化，避免与商业价值不相关的功能以及过多的文档。Mura（变异）：改善审批和验证流程（比如，安全签批）；推动 左移提前 shift-left 策略以推行单元测试、安全漏洞扫描与代码质量检查；并改进风险评定。Muda（浪费）：避免技术债、错误或前期的详细文档等浪费。看起来 80％ 的重点都集中在提供一种可以集成和协作的工程产品上，这些系统可以采用一个创意和计划、开发、测试和监控你的解决方案。然而，一个成功的转型和工程系统是由 5％ 的产品、15％ 的过程和 80％ 的开发人员组成的。我们可以使用的产品有很多。比如，Azure DevOps 为持续集成（CI）、持续交付（CD）和可扩展性提供了丰富支持，并与 Stryker、SonarQube、WhiteSource、Jenkins 和 Octopus 等开源集成和商用成品（COTS）软件即服务（SaaS）进行集成。对于工程师来说，关注产品总是一种诱惑，但请记住，它们只是我们旅程的 5%。最大的挑战是打破数十年的规则、规定和已经步入舒适区的流程：“我们一直都是这样做的；为什么需要改变呢？”开发和运维人员之间的摩擦导致了各种支离破碎的、重复的、不间断的集成和交付流水线。开发人员希望能访问所有东西，以便持续迭代，让用户使用起来和持续地快速发布。运维人员希望将所有东西锁起来，保护业务、用户和品质。这些矛盾在不经意间导致了很难做到一种自动化的流程，进而导致发布周期晚于预期。让我们使用最近的一次白板讨论中的片段来探索流水线。想要支持流水线的变化是一项困难并且花费巨大的工作；版本和可追溯性的不一致使得这个问题变得更加复杂，因此不断精简开发流程和流水线是一项挑战。我主张一些原则使得每个产品都能使用通用流水线：使一切可自动化的东西都自动化一次构建保持持续集成和持续交付保持持续精简和改进保持一个构建的定义保持一个发布流水线的定义尽早、频繁地扫描漏洞，并且尽快失败尽早、频繁地进行测试，并且尽快失败保持已发布版本的可追踪和监控但是，如果我要打破这些，最重要的原则就是保持简单。如果你不能说明流水线化的原因（是什么、为什么）和过程（如何），你或许是不了解自己的软件过程的。我们大多数人想要的不是最好的、超现代的和具有革命意义的流水线 —— 我们仅仅是需要一个功能强大的、有价值的和能促进工程的流水线。首先需要解决的是那 80% —— 文化、人员和他们的心态。请你的 CI/CD 骑士们穿上闪亮的盔甲，在他们的盾牌上贴上 TLA（ 两个/三个字母的缩写 two/three-lettered acronym ）符号，加入到实践和经验工程的力量中来。统一流水线让我们逐步完成我们的白板会议实践。每个应用使用一套构建定义来定义一个 CI/CD 流水线，用来触发拉取请求的预合并验证与持续集成的构建。生成一个带有调试信息的发布的构建，并且将其上传到 符号服务器。这使开发人员可以在本地和远程生产环境进行调试，而在不用考虑需要加载哪个构建和符号，符号服务器为我们施展了这样的魔法。在构建过程中进行尽可能多的验证（左移提前），这允许开发新特性的团队可以尽快失败，不断的提高整体的产品质量，并在拉取请求中为代码审核人员提供宝贵证据。你喜欢有大量提交的拉取请求吗？还是一个带有少数提交和提供了漏洞检查、测试覆盖率、代码质量检查和 Stryker 突变残余等支持的拉取请求？就我个人而言，我投后者的票。不要使用构建转换来生成多个特定环境的构建。通过一个构建实现发布时转换、标记化和 XML/JSON 的值替换。换句话说，右移滞后具体环境的配置。安全存储发布配置数据，并且根据数据的信任度和敏感度，让开发和运维都能使用。使用开源的密钥管理工具、Azure 密钥保险库、AWS 密钥管理服务或者其他产品，记住你的工具箱中有很多方便的工具。使用用户组而不是用户，将审批人管理从跨多个流水线的多个阶段移动到简单的组成员。创建一条流水线并且对赋予特定的交付阶段的权限，而不是重复流水线让团队进入他们感兴趣的地方。最后，但并非最不重要的是，拥抱拉取请求，以帮助提高对代码仓库的洞察力和透明度，增进整体质量、协作，并将预验证构建发布到选定的环境，比如，开发环境。这是整个白板更正式的视图。所以，你对 CI/CD 流水线有什么想法和经验？我的通过一条流水线来管理它们的这个梦想是空想吗？via: https://opensource.com/article/19/7/cicd-pipeline-rule-them-all作者：Willy-Peter Schaub 选题：lujun9972 译者：chunibyo-wly 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
cd 命令可能是任何 Linux 用户学习的前 10 个命令之一，但这并不是在 Linux 文件系统中导航的唯一方法，这里还有其他一些方法。无论你是在文件系统中四处查看、寻找文件还是尝试进入重要目录，Linux 都可以提供很多帮助。在本文中，我们将介绍一些技巧，使你可以在文件系统中移动，查找和使用所需的命令也更加轻松。添加到 $PATH确保你不必花费大量时间在 Linux 系统上查找命令的最简单、最有用的方法之一就是在 $PATH 变量中添加适当的目录。但是，添加到 $PATH 变量中的目录顺序非常重要。它们确定系统在目录中查找要运行命令的目录顺序–在找到第一个匹配项时停止。例如，你可能希望将家目录放在第一个，这样，如果你创建的脚本与其他可执行文件有相同的名称，那么只要输入该脚本的名称，它便会运行。要将家目录添加到 $PATH 变量中，可以执行以下操作：$ export PATH=~:$PATH~ 字符代表家目录。如果将脚本保存在 bin 目录中，下面的会有效：$ export PATH=~/bin:$PATH然后，你可以运行位于家目录中的脚本，如下所示：$ myscript Good morning, you just ran /home/myacct/bin/myscript重要提示：上面显示的命令会添加到你的搜索路径中，因为 $PATH（当前路径）被包含在内。它们不会覆盖它。你的搜索路径应该在你的 .bashrc 文件中配置，任何你打算永久化的更改也应该添加到那里。使用符号链接符号链接提供了一种简单而明显的方式来记录可能经常需要使用的目录的位置。例如，如果你管理网站的内容，那么可能需要通过创建如下链接来使你的帐户“记住”网页文件的位置：ln -s /var/www/html www参数的顺序很重要。第一个（/var/www/html）是目标，第二个是你创建的链接的名称。如果你当前不在家目录中，那么以下命令将执行相同的操作：ln -s /var/www/html ~/www设置好之后，你可以使用 cd www 进入 /var/www/html。使用 shoptshopt 命令还提供了一种让移动到其他目录更加容易的方法。当你使用 shopt 的 autocd 选项时，只需输入名称即可转到目录。例如：$ shopt -s autocd $ www cd -- www /home/myacct/www $ pwd -P /var/www/html $ ~/bin cd -- /home/myacct/bin $ pwd /home/myacct/bin在上面的第一组命令中，启用了 shopt 命令的 autocd 选项。输入 www，就会调用 cd www 命令。由于此符号链接是在上面的 ln 命令示例之一中创建的，因此将我们移至 /var/www/html。 pwd -P 命令显示实际位置。在第二组中，键入 ~/bin 会调用 cd 进入在用户家目录的 bin 目录。请注意，当你输入的是命令时，autocd 行为将不会生效，即使它也是目录的名称。shopt 是 bash 内置命令，它有很多选项。这只是意味着你不必在要进入每个目录的名称之前输入 cd。要查看 shopt 的其他选项，只需输入 shopt。使用 $CDPATH可能进入特定目录的最有用技巧之一，就是将你希望能够轻松进入的路径添加到 $CDPATH 中。这将创建一个目录列表，只需输入完整路径名的一部分即可进入。一方面，这可能有点棘手。你的 $CDPATH 需要包含要移动到的目录的父目录，而不是目录本身。例如，假设你希望仅通过输入 cd html 就可以移至 /var/www/html 目录，并仅使用 cd 和简单目录名即可移至 /var/log 中的子目录。在这种情况下，此 $CDPATH 就可以起作用：$ CDPATH=.:/var/log:/var/www你将看到：$ cd journal /var/log/journal $ cd html /var/www/html当你输入的不是完整路径时，$CDPATH 就会生效。它向下查看其目录列表，以查看指定的目录是否存在于其中一个目录中。找到匹配项后，它将带你到那里。在 $CDPATH 开头保持 . 意味着你可以进入本地目录，而不必在 $CDPATH 中定义它们。$ export CDPATH=".:$CDPATH" $ Videos cd -- Videos /home/myacct/Videos在 Linux 文件系统键切换并不难，但是如果你使用一些方便的技巧轻松地到达各个位置，那你可以节省一些大脑细胞。via: https://www.networkworld.com/article/3533421/tricks-for-getting-around-your-linux-file-system.html作者：Sandra Henry-Stocker 选题：lujun9972 译者：geekpi 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
本文是一篇简单指南：介绍一些顶级的开源的持续集成、持续交付和持续部署（CI/CD）工具。虽然持续集成、持续交付和持续部署（CI/CD）在开发者社区里已经存在很多年，一些机构在其运维部门也有实施经验，但大多数公司并没有做这样的尝试。对于很多机构来说，让运维团队能够像他们的开发同行一样熟练操作 CI/CD 工具，已经变得十分必要了。无论是基础设施、第三方应用还是内部开发的应用，都可以开展 CI/CD 实践。尽管你会发现有很多不同的工具，但它们都有着相似的设计模型。而且可能最重要的一点是：通过带领你的公司进行这些实践，会让你在公司内部变得举足轻重，成为他人学习的榜样。一些机构在自己的基础设施上已有多年的 CI/CD 实践经验，常用的工具包括 Ansible、Chef 或者 Puppet。另一些工具，比如 Test Kitchen，允许在最终要部署应用的基础设施上运行测试。事实上，如果使用更高级的配置方法，你甚至可以将应用部署到有真实负载的仿真“生产环境”上，来运行应用级别的测试。然而，单单是能够测试基础设施就是一项了不起的成就了。配置管理工具 Terraform 可以通过 Test Kitchen 来快速创建更短暂和冥等的的基础设施配置，这比它的前辈要强不少。再加上 Linux 容器和 Kubernetes，在数小时内，你就可以创建一套类似于生产环境的配置参数和系统资源，来测试整个基础设施和其上部署的应用，这在以前可能需要花费几个月的时间。而且，删除和再次创建整个测试环境也非常容易。当然，作为初学者，你也可以把网络配置和 DDL（ 数据定义语言 data definition language ）文件加入版本控制，然后开始尝试一些简单的 CI/CD 流程。虽然只能帮你检查一下语义语法或某些最佳实践，但实际上大多数开发的管道都是这样起步的。只要你把脚手架搭起来，建造就容易得多了。而一旦起步，你就会发现各种管道的使用场景。举个例子，我经常会在公司内部写新闻简报，我使用 MJML 制作邮件模板，然后把它加入版本控制。我一般会维护一个 web 版本，但是一些同事喜欢 PDF 版，于是我创建了一个管道。每当我写好一篇新闻稿，就在 Gitlab 上提交一个合并请求。这样做会自动创建一个 index.html 文件，生成这篇新闻稿的 HTML 和 PDF 版链接。HTML 和 PDF 文件也会在该管道里同时生成。除非有人来检查确认，这些文件不会被直接发布出去。使用 GitLab Pages 发布这个网站后，我就可以下载一份 HTML 版，用来发送新闻简报。未来，我会修改这个流程，当合并请求成功或者在某个审核步骤后，自动发出对应的新闻稿。这些处理逻辑并不复杂，但的确为我节省了不少时间。实际上这些工具最核心的用途就是替你节省时间。关键是要在抽象层创建出工具，这样稍加修改就可以处理不同的问题。值得留意的是，我创建的这套流程几乎不需要任何代码，除了一些轻量级的 HTML 模板，一些把 HTML 文件转换成 PDF 的 nodejs 代码，还有一些生成索引页面的 nodejs 代码。这其中一些东西可能看起来有点复杂，但其中大部分都源自我使用的不同工具的教学文档。而且很多开发人员也会乐意跟你合作，因为他们在完工时会发现这些东西也挺有用。上面我提供的那些代码链接是给 DevOps KC（LCTT 译注：一个地方性 DevOps 组织） 发送新闻简报用的，其中大部分用来创建网站的代码来自我在内部新闻简报项目上所作的工作。下面列出的大多数工具都可以提供这种类型的交互，但是有些工具提供的模型略有不同。这一领域新兴的模型是用声明式的方法例如 YAML 来描述一个管道，其中的每个阶段都是短暂而幂等的。许多系统还会创建有向无环图（DAG），来确保管道上不同的阶段排序的正确性。这些阶段一般运行在 Linux 容器里，和普通的容器并没有区别。有一些工具，比如 Spinnaker，只关注部署组件，而且提供一些其他工具没有的操作特性。Jenkins 则通常把管道配置存成 XML 格式，大部分交互都可以在图形界面里完成，但最新的方案是使用领域专用语言（DSL）（如 Groovy）。并且，Jenkins 的任务（job）通常运行在各个节点里，这些节点上会装一个专门的 Java 代理，还有一堆混杂的插件和预装组件。Jenkins 在自己的工具里引入了管道的概念，但使用起来却并不轻松，甚至包含一些禁区。最近，Jenkins 的创始人决定带领社区向新的方向前进，希望能为这个项目注入新的活力，把 CI/CD 真正推广开（LCTT 译注：详见后面的 Jenkins 章节)。我认为其中最有意思的想法是构建一个云原生 Jenkins，能把 Kubernetes 集群转变成 Jenkins CI/CD 平台。当你更多地了解这些工具并把实践带入你的公司和运维部门，你很快就会有追随者，因为你有办法提升自己和别人的工作效率。我们都有多年积累下来的技术债要解决，如果你能给同事们提供足够的时间来处理这些积压的工作，他们该会有多感激呢？不止如此，你的客户也会开始看到应用变得越来越稳定，管理层会把你看作得力干将，你也会在下次谈薪资待遇或参加面试时更有底气。让我们开始深入了解这些工具吧，我们将对每个工具做简短的介绍，并分享一些有用的链接。GitLab CI项目主页源代码许可证：MITGitLab 可以说是 CI/CD 领域里新登场的玩家，但它却在权威调研机构 Forrester 的 CI 集成工具的调查报告中位列第一。在一个高水平、竞争充分的领域里，这是个了不起的成就。是什么让 GitLab CI 这么成功呢？它使用 YAML 文件来描述整个管道。另有一个功能叫做 Auto DevOps，可以为较简单的项目用多种内置的测试单元自动生成管道。这套系统使用 Herokuish buildpacks 来判断语言的种类以及如何构建应用。有些语言也可以管理数据库，它真正改变了构建新应用程序和从开发的开始将它们部署到生产环境的过程。它原生集成于 Kubernetes，可以根据不同的方案将你的应用自动部署到 Kubernetes 集群，比如灰度发布、蓝绿部署等。除了它的持续集成功能，GitLab 还提供了许多补充特性，比如：将 Prometheus 和你的应用一同部署，以提供操作监控功能；通过 GitLab 提供的 Issues、Epics 和 Milestones 功能来实现项目评估和管理；管道中集成了安全检测功能，多个项目的检测结果会聚合显示；你可以通过 GitLab 提供的网页版 IDE 在线编辑代码，还可以快速查看管道的预览或执行状态。GoCD项目主页源代码许可证：Apache 2.0GoCD 是由老牌软件公司 Thoughtworks 出品，这已经足够证明它的能力和效率。对我而言，GoCD 最具亮点的特性是它的价值流视图（VSM）。实际上，一个管道的输出可以变成下一个管道的输入，从而把管道串联起来。这样做有助于提高不同开发团队在整个开发流程中的独立性。比如在引入 CI/CD 系统时，有些成立较久的机构希望保持他们各个团队相互隔离，这时候 VSM 就很有用了：让每个人都使用相同的工具就很容易在 VSM 中发现工作流程上的瓶颈，然后可以按图索骥调整团队或者想办法提高工作效率。为公司的每个产品配置 VSM 是非常有价值的；GoCD 可以使用 JSON 或 YAML 格式存储配置，还能以可视化的方式展示数据等待时间，这让一个机构能有效减少学习它的成本。刚开始使用 GoCD 创建你自己的流程时，建议使用人工审核的方式。让每个团队也采用人工审核，这样你就可以开始收集数据并且找到可能的瓶颈点。Travis CI项目主页源代码许可证：MIT我使用的第一个软件既服务（SaaS）类型的 CI 系统就是 Travis CI，体验很不错。管道配置以源码形式用 YAML 保存，它与 GitHub 等工具无缝整合。我印象中管道从来没有失效过，因为 Travis CI 的在线率很高。除了 SaaS 版之外，你也可以使用自行部署的版本。我还没有自行部署过，它的组件非常多，要全部安装的话，工作量就有点吓人了。我猜更简单的办法是把它部署到 Kubernetes 上，Travis CI 提供了 Helm charts，这些 charts 目前不包含所有要部署的组件，但我相信以后会越来越丰富的。如果你不想处理这些细枝末节的问题，还有一个企业版可以试试。假如你在开发一个开源项目，你就能免费使用 SaaS 版的 Travis CI，享受顶尖团队提供的优质服务！这样能省去很多麻烦，你可以在一个相对通用的平台上（如 GitHub）研发开源项目，而不用找服务器来运行任何东西。Jenkins项目主页源代码许可证：MITJenkins 在 CI/CD 界绝对是元老级的存在，也是事实上的标准。我强烈建议你读一读这篇文章：“Jenkins: Shifting Gears”，作者 Kohsuke 是 Jenkins 的创始人兼 CloudBees 公司 CTO。这篇文章契合了我在过去十年里对 Jenkins 及其社区的感受。他在文中阐述了一些这几年呼声很高的需求，我很乐意看到 CloudBees 引领这场变革。长期以来，Jenkins 对于非开发人员来说有点难以接受，并且一直是其管理员的重担。还好，这些问题正是他们想要着手解决的。Jenkins 配置既代码（JCasC）应该可以帮助管理员解决困扰了他们多年的配置复杂性问题。与其他 CI/CD 系统类似，只需要修改一个简单的 YAML 文件就可以完成 Jenkins 主节点的配置工作。Jenkins Evergreen 的出现让配置工作变得更加轻松，它提供了很多预设的使用场景，你只管套用就可以了。这些发行版会比官方的标准版本 Jenkins 更容易维护和升级。Jenkins 2 引入了两种原生的管道功能，我在 LISA（LCTT 译注：一个系统架构和运维大会） 2017 年的研讨会上已经讨论过了。这两种功能都没有 YAML 简便，但在处理复杂任务时它们很好用。Jenkins X 是 Jenkins 的一个全新变种，用来实现云端原生 Jenkins（至少在用户看来是这样）。它会使用 JCasC 及 Evergreen，并且和 Kubernetes 整合的更加紧密。对于 Jenkins 来说这是个令人激动的时刻，我很乐意看到它在这一领域的创新，并且继续发挥领袖作用。Concourse CI项目主页源代码许可证：Apache 2.0我第一次知道 Concourse 是通过 Pivotal Labs 的伙计们介绍的，当时它处于早期 beta 版本，而且那时候也很少有类似的工具。这套系统是基于微服务构建的，每个任务运行在一个容器里。它独有的一个优良特性是能够在你本地系统上运行任务，体现你本地的改动。这意味着你完全可以在本地开发（假设你已经连接到了 Concourse 的服务器），像在真实的管道构建流程一样从你本地构建项目。而且，你可以在修改过代码后从本地直接重新运行构建，来检验你的改动结果。Concourse 还有一个简单的扩展系统，它依赖于“资源”这一基础概念。基本上，你想给管道添加的每个新功能都可以用一个 Docker 镜像实现，并作为一个新的资源类型包含在你的配置中。这样可以保证每个功能都被封装在一个不可变的独立工件中，方便对其单独修改和升级，改变其中一个时不会影响其他构建。Spinnaker项目主页源代码许可证：Apache 2.0Spinnaker 出自 Netflix，它更关注持续部署而非持续集成。它可以与其他工具整合，比如 Travis 和 Jenkins，来启动测试和部署流程。它也能与 Prometheus、Datadog 这样的监控工具集成，参考它们提供的指标来决定如何部署。例如，在 金丝雀发布 canary deployment 里，我们可以根据收集到的相关监控指标来做出判断：最近的这次发布是否导致了服务降级，应该立刻回滚；还是说看起来一切 OK，应该继续执行部署。谈到持续部署，一些另类但却至关重要的问题往往被忽略掉了，说出来可能有点让人困惑：Spinnaker 可以帮助持续部署不那么“持续”。在整个应用部署流程期间，如果发生了重大问题，它可以让流程停止执行，以阻止可能发生的部署错误。但它也可以在最关键的时刻让人工审核强制通过，发布新版本上线，使整体收益最大化。实际上，CI/CD 的主要目的就是在商业模式需要调整时，能够让待更新的代码立即得到部署。Screwdriver项目主页源代码许可证：BSDScrewdriver 是个简单而又强大的软件。它采用微服务架构，依赖像 Nomad、Kubernetes 和 Docker 这样的工具作为执行引擎。官方有一篇很不错的部署教学文档，介绍了如何将它部署到 AWS 和 Kubernetes 上，但如果正在开发中的 Helm chart 也完成的话，就更完美了。Screwdriver 也使用 YAML 来描述它的管道，并且有很多合理的默认值，这样可以有效减少各个管道重复的配置项。用配置文件可以组织起高级的工作流，来描述各个任务间复杂的依赖关系。例如，一项任务可以在另一个任务开始前或结束后运行；各个任务可以并行也可以串行执行；更赞的是你可以预先定义一项任务，只在特定的拉取请求时被触发，而且与之有依赖关系的任务并不会被执行，这能让你的管道具有一定的隔离性：什么时候被构造的工件应该被部署到生产环境，什么时候应该被审核。以上只是我对这些 CI/CD 工具的简单介绍，它们还有许多很酷的特性等待你深入探索。而且它们都是开源软件，可以自由使用，去部署一下看看吧，究竟哪个才是最适合你的那个。via: https://opensource.com/article/18/12/cicd-tools-sysadmins作者：Dan Barker 选题：lujun9972 译者：jdh8383 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
了解自动化，使用 Git 存储库以及参数化 Jenkins 管道。本文涵盖了三个关键主题：自动化 CI/CD 配置、使用 Git 存储库处理常见的 CI/CD 工件、参数化 Jenkins 管道。术语首先，我们定义一些术语。CI/CD 是允许团队快速自动化测试、打包、部署其应用程序的实践。它通常通过利用名为 Jenkins 的服务器来实现，该服务器充当 CI/CD 协调器。Jenkins 侦听特定输入（通常是代码签入后的 Git 挂钩），并在触发时启动一个管道。 管道 pipeline 由开发和/或运营团队编写的代码组成，这些代码指导 Jenkins 在 CI/CD 过程中采取哪些操作。这个流水线通常类似于“构建我的代码，然后测试我的代码，如果这些测试通过，则把我的应用程序部署到下一个最高环境（通常是开发、测试或生产环境）”。组织通常具有更复杂的管道，并入了诸如工件存储库和代码分析器之类的工具，这里提供了一个高级示例。现在我们了解了关键术语，让我们深入研究一些最佳实践。1、自动化是关键要在 PaaS 上运行 CI/CD，需要在集群上配置适当的基础设施。在这个例子中，我将使用 OpenShift。“Hello, World” 的实现很容易实现。简单地运行 oc new-app jenkins-<persistent/ephemeral>，然后，你就有了一个已经就绪的运行中的 Jenkins 服务器了。然而，在企业中的使用要复杂得多。除了 Jenkins 服务器之外，管理员通常还需要部署代码分析工具（如 SonarQube）和工件库（如 Nexus）。然后，它们必须创建管道来执行 CI/CD 和 Jenkins 从服务器，以减少主服务器的负载。这些实体中的大多数都由 OpenShift 资源支持，需要创建这些资源来部署所需的 CI/CD 基础设施。最后，部署 CI/CD 组件所需要的手动步骤可能是需要重复进行的，而且你可能不想成为执行那些重复步骤的人。为了确保结果能够像以前一样快速、无错误和准确地产生，应该在创建基础设施的方式中结合自动化方法。这可以是一个 Ansible 剧本、一个 Bash 脚本，或者任何您希望自动化 CI/CD 基础设施部署的其它方式。我已经使用 Ansible 和 OpenShift-Applier 角色来自动化我的实现。您可能会发现这些工具很有价值，或者您可能会发现其他一些对您和组织更有效的工具。无论哪种方式，您都将发现自动化显著地减少了重新创建 CI/CD 组件所需的工作量。配置 Jenkins 主服务器除了一般的“自动化”之外，我想单独介绍一下 Jenkins 主服务器，并讨论管理员如何利用 OpenShift 来自动化配置 Jenkins。来自 Red Hat Container Catalog 的 Jenkins 镜像已经安装了 OpenShift-Sync plugin。在 该视频 中，我们将讨论如何使用这个插件来创建 Jenkins 管道和从设备。要创建 Jenkins 管道，请创建一个类似于下面的 OpenShift BuildConfig：apiVersion: v1 kind: BuildConfig ... spec: source: git: ref: master uri: <repository-uri> ... strategy: jenkinsPipelineStrategy: jenkinsfilePath: Jenkinsfile type: JenkinsPipelineOpenShift-Sync 插件将注意到已经创建了带有 jenkinsPipelineStrategy 策略的 BuildConfig，并将其转换为 Jenkins 管道，从 Git 源指定的 Jenkinsfile 中提取。也可以使用内联 Jenkinsfile，而不是从 Git 存储库中提取。有关更多信息，请参阅文档。要创建 Jenkins 从站，请创建一个 OpenShift ImageStream，它从以下定义开始：apiVersion: v1 kind: ImageStream metadata: annotations: slave-label: jenkins-slave labels: role: jenkins-slave ...注意在这个 ImageStream 中定义的元数据。OpenShift-Sync 插件将把带有标签 role: jenkins-slave 的任何 ImageStream 转换为 Jenkins 从站。Jenkins 从站将以 slave-label 注释中的值命名。ImageStreams 对于简单的 Jenkins 从属配置工作得很好，但是一些团队会发现有必要配置一些细节详情，比如资源限制、准备就绪和活动性探测，以及实例上限。这就是 ConfigMap 发挥作用的地方：apiVersion: v1 kind: ConfigMap metadata: labels: role: jenkins-slave ... data: template1: |- <Kubernetes pod template>注意，仍然需要角色：jenkins-slave 标签来将 ConfigMap 转换为 Jenkins 从站。Kubernetes pod 模板由一长段 XML 组成，它将根据组织的喜好配置每个细节。要查看此 XML，以及有关将 ImageStreams 和 ConfigMaps 转换为 Jenkins 从站的更多信息，请参阅文档。请注意上面所示的三个示例，其中没有一个操作需要管理员对 Jenkins 控制台进行手动更改。通过使用 OpenShift 资源，可以简单的自动化方式配置 Jenkins。2、分享就是关爱第二个最佳实践是维护一个公共 CI/CD 工件的 Git 存储库。主要思想是防止团队重新发明轮子。假设您的团队需要执行到 OpenShift 环境的蓝/绿部署，作为管道 CD 阶段的一部分。负责编写管道的团队成员可能不是 OpenShift 专家，也不可能具有从头开始编写此功能的能力。幸运的是，有人已经编写了一个将此功能合并到一个公共 CI/CD 存储库中的函数，因此您的团队可以使用该函数而不是花时间编写一个函数。为了更进一步，您的组织可能决定维护整个管道。您可能会发现团队正在编写具有相似功能的管道。对于那些团队来说，使用来自公共存储库的参数化管道要比从头开始编写自己的管道更有效。3、少即是多正如我在前一节中提到的，第三个也是最后一个最佳实践是参数化您的 CI/CD 管道。参数化将防止过多的管道，使您的 CI/CD 系统更容易维护。假设我有多个区域可以部署应用程序。如果没有参数化，我需要为每个区域设置单独的管道。要参数化一个作为 OpenShift 构建配置编写的管道，请将 env 节添加到配置：... spec: ... strategy: jenkinsPipelineStrategy: env: - name: REGION value: US-West jenkinsfilePath: Jenkinsfile type: JenkinsPipeline使用此配置，我可以传递 REGION 参数给管道以将我的应用程序部署到指定区域。这有一个视频提供了一个更实质性的情况，其中参数化是必须的。一些组织决定把他们的 CI/CD 管道分割成单独的 CI 和 CD 管道，通常是因为在部署之前有一些审批过程。假设我有四个镜像和三个不同的环境要部署。如果没有参数化，我需要 12 个 CD 管道来允许所有部署可能性。这会很快失去控制。为了使 CD 流水线的维护更容易，组织会发现将镜像和环境参数化以便允许一个流水线执行多个流水线的工作会更好。总结企业级的 CI/CD 往往比许多组织预期的更加复杂。幸运的是，对于 Jenkins，有很多方法可以无缝地提供设置的自动化。维护一个公共 CI/CD 工件的 Git 存储库也会减轻工作量，因为团队可以从维护的依赖项中提取而不是从头开始编写自己的依赖项。最后，CI/CD 管道的参数化将减少必须维护的管道的数量。如果您找到了其他不可或缺的做法，请在评论中分享。via: https://opensource.com/article/18/11/best-practices-cicd作者：Austin Dewey 选题：lujun9972 译者：ChiZelin 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
未来的开发工作需要非常精通 CI/CD 流程。在 2017 年启动后，OpenDev 大会现在已是一个年度活动。在去年 9 月的首届活动上，会议的重点是边缘计算。今年的活动，于 5 月 22 - 23 日举行，会议的重点是持续集成和持续发布 (CI/CD)，并与 OpenStack 峰会一起在温哥华举行。基于我在 OpenStack 项目的 CI/CD 系统的技术背景和我近期进入容器下的 CI/CD 方面的经验，我被邀请加入 OpenDev CI/CD 计划委员会。今天我经常借助很多开源技术，例如 Jenkins、GitLab、Spinnaker 和 Artifactory 来讨论 CI/CD 流程。这次活动对我来说是很激动人心的，因为我们将在这个活动中融合两个开源基础设施理念。首先，我们将讨论可以被任何组织使用的 CI/CD 工具。为此目的，在 讲演 中，我们将听到关于开源 CI/CD 工具的使用讲演，一场来自 Boris Renski 的关于 Spinnaker 的讲演，和一场来自 Jim Blair 的关于 Zuul 的讲演。同时，讲演会涉及关于开源技术的偏好的高级别话题，特别是那种跨社区的和本身就是开源项目的。从Fatih Degirmenci 和 Daniel Farrel 那里，我们将听到关于在不同社区分享持续发布实践经历，接着 Benjamin Mako Hill 会为我们带来一场关于为什么自由软件需要自由工具的分享。在分享 CI/CD 相对新颖的特性后，接下来的活动是对话、研讨会和协作讨论的混合组合。当从人们所提交的讲座和研讨会中进行选择，并提出协作讨论主题时，我们希望确保有一个多样灵活的日程表，这样任何参与者都能在 CI/CD 活动进程中发现有趣的东西。这些讲座会是标准的会议风格，选择涵盖关键主题，如制定 CI/CD 流程，在实践 DevOps 时提升安全性，以及更具体的解决方案，如基于容器关于 Kubernetes 的 Aptomi 和在 ETSI NFV 环境下 CI/CD。这些会话的大部分将会是作为给新接触 CI/CD 或这些特定技术的参与者关于这些话题和理念的简介。交互式的研讨会会持续相对比较长的时间，参与者将会在思想上得到特定的体验。这些研讨会包括 “在持续集成任务中的异常检测”、“如何安装 Zuul 和配置第一个任务”，和“Spinnake 101：快速可靠的软件发布”。（注意这些研讨会空间是有限的，所以设立了一个 RSVP 系统。你们将会在会议的链接里找到一个 RSVP 的按钮。)可能最让我最兴奋的是协作讨论，这些协作讨论占据了一半以上的活动安排。协作讨论的主题由计划委员会选取。计划委员会根据我们在社区里所看到来选取对应的主题。这是“鱼缸”风格式的会议，通常是几个人聚在一个房间里围绕着 CI/CD 讨论某一个主题。这次会议风格的理念是来自于开发者峰会，最初是由 Ubuntu 社区提出，接着 OpenStack 社区也在活动上采纳。这些协作讨论的主题包含不同的会议，这些会议是关于 CI/CD 基础，可以鼓励跨社区协作的提升举措，在组织里推行 CI/CD 文化，和为什么开源 CI/CD 工具如此重要。采用共享文档来做会议笔记，以确保尽可能的在会议的过程中分享知识。在讨论过程中，提出行动项目也是很常见的，因此社区成员可以推动和所涉及的主题相关的倡议。活动将以联合总结会议结束。联合总结会议将总结来自协同讨论的关键点和为即将在这个领域工作的参与者指出可选的职业范围。可以在 OpenStack 峰会注册页 上注册参加活动。或者可以在温哥华唯一指定售票的会议中心购买活动的入场券，价格是 $199。更多关于票和全部的活动安排见官网 OpenDev 网站。我希望你们能够加入我们，并在温哥华渡过令人激动的两天，并且在这两天的活动中学习，协作和在 CI/CD 取得进展。via: https://opensource.com/article/18/5/opendev作者：Elizabeth K.Joseph 选题：lujun9972 译者：jamelouis 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
在软件开发中经常会提到 持续集成 Continuous Integration （CI）和 持续交付 Continuous Delivery （CD）这几个术语。但它们真正的意思是什么呢？在谈论软件开发时，经常会提到 持续集成 Continuous Integration （CI）和 持续交付 Continuous Delivery （CD）这几个术语。但它们真正的意思是什么呢？在本文中，我将解释这些和相关术语背后的含义和意义，例如 持续测试 Continuous Testing 和 持续部署 Continuous Deployment 。概览工厂里的装配线以快速、自动化、可重复的方式从原材料生产出消费品。同样，软件交付管道以快速、自动化和可重复的方式从源代码生成发布版本。如何完成这项工作的总体设计称为“持续交付”（CD）。启动装配线的过程称为“持续集成”（CI）。确保质量的过程称为“持续测试”，将最终产品提供给用户的过程称为“持续部署”。一些专家让这一切简单、顺畅、高效地运行，这些人被称为 运维开发 DevOps 践行者。“持续”是什么意思？“持续”用于描述遵循我在此提到的许多不同流程实践。这并不意味着“一直在运行”，而是“随时可运行”。在软件开发领域，它还包括几个核心概念/最佳实践。这些是：频繁发布：持续实践背后的目标是能够频繁地交付高质量的软件。此处的交付频率是可变的，可由开发团队或公司定义。对于某些产品，一季度、一个月、一周或一天交付一次可能已经足够频繁了。对于另一些来说，一天可能需要多次交付也是可行的。所谓持续也有“偶尔、按需”的方面。最终目标是相同的：在可重复、可靠的过程中为最终用户提供高质量的软件更新。通常，这可以通过很少甚至无需用户的交互或掌握的知识来完成（想想设备更新）。自动化流程：实现此频率的关键是用自动化流程来处理软件生产中的方方面面。这包括构建、测试、分析、版本控制，以及在某些情况下的部署。可重复：如果我们使用的自动化流程在给定相同输入的情况下始终具有相同的行为，则这个过程应该是可重复的。也就是说，如果我们把某个历史版本的代码作为输入，我们应该得到对应相同的可交付产出。这也假设我们有相同版本的外部依赖项（即我们不创建该版本代码使用的其它交付物）。理想情况下，这也意味着可以对管道中的流程进行版本控制和重建（请参阅稍后的 DevOps 讨论）。快速迭代：“快速”在这里是个相对术语，但无论软件更新/发布的频率如何，预期的持续过程都会以高效的方式将源代码转换为交付物。自动化负责大部分工作，但自动化处理的过程可能仍然很慢。例如，对于每天需要多次发布候选版更新的产品来说，一轮 集成测试 integrated testing 下来耗时就要大半天可能就太慢了。什么是“持续交付管道”？将源代码转换为可发布产品的多个不同的 任务 task 和 作业 job 通常串联成一个软件“管道”，一个自动流程成功完成后会启动管道中的下一个流程。这些管道有许多不同的叫法，例如持续交付管道、部署管道和软件开发管道。大体上讲，程序管理者在管道执行时管理管道各部分的定义、运行、监控和报告。持续交付管道是如何工作的？软件交付管道的实际实现可以有很大不同。有许多程序可用在管道中，用于源代码跟踪、构建、测试、指标采集，版本管理等各个方面。但整体工作流程通常是相同的。单个业务流程/工作流应用程序管理整个管道，每个流程作为独立的作业运行或由该应用程序进行阶段管理。通常，在业务流程中，这些独立作业是以应用程序可理解并可作为工作流程管理的语法和结构定义的。这些作业被用于一个或多个功能（构建、测试、部署等）。每个作业可能使用不同的技术或多种技术。关键是作业是自动化的、高效的，并且可重复的。如果作业成功，则工作流管理器将触发管道中的下一个作业。如果作业失败，工作流管理器会向开发人员、测试人员和其他人发出警报，以便他们尽快纠正问题。这个过程是自动化的，所以比手动运行一组过程可更快地找到错误。这种快速排错称为 快速失败 fail fast ，并且在抵达管道端点方面同样有价值。“快速失败”是什么意思？管道的工作之一就是快速处理变更。另一个是监视创建发布的不同任务/作业。由于编译失败或测试未通过的代码可以阻止管道继续运行，因此快速通知用户此类情况非常重要。快速失败指的是在管道流程中尽快发现问题并快速通知用户的方式，这样可以及时修正问题并重新提交代码以便使管道再次运行。通常在管道流程中可通过查看历史记录来确定是谁做了那次修改并通知此人及其团队。所有持续交付管道都应该被自动化吗？管道的几乎所有部分都是应该自动化的。对于某些部分，有一些人为干预/互动的地方可能是有意义的。一个例子可能是 用户验收测试 user-acceptance testing （让最终用户试用软件并确保它能达到他们想要/期望的水平）。另一种情况可能是部署到生产环境时用户希望拥有更多的人为控制。当然，如果代码不正确或不能运行，则需要人工干预。有了对“持续”含义理解的背景，让我们看看不同类型的持续流程以及它们在软件管道上下文中的含义。什么是“持续集成”？持续集成（CI）是在源代码变更后自动检测、拉取、构建和（在大多数情况下）进行单元测试的过程。持续集成是启动管道的环节（尽管某些预验证 —— 通常称为 上线前检查 pre-flight checks —— 有时会被归在持续集成之前）。持续集成的目标是快速确保开发人员新提交的变更是好的，并且适合在代码库中进一步使用。持续集成是如何工作的？持续集成的基本思想是让一个自动化过程监测一个或多个源代码仓库是否有变更。当变更被推送到仓库时，它会监测到更改、下载副本、构建并运行任何相关的单元测试。持续集成如何监测变更？目前，监测程序通常是像 Jenkins 这样的应用程序，它还协调管道中运行的所有（或大多数）进程，监视变更是其功能之一。监测程序可以以几种不同方式监测变更。这些包括：轮询：监测程序反复询问代码管理系统，“代码仓库里有什么我感兴趣的新东西吗？”当代码管理系统有新的变更时，监测程序会“唤醒”并完成其工作以获取新代码并构建/测试它。定期：监测程序配置为定期启动构建，无论源码是否有变更。理想情况下，如果没有变更，则不会构建任何新内容，因此这不会增加额外的成本。推送：这与用于代码管理系统检查的监测程序相反。在这种情况下，代码管理系统被配置为提交变更到仓库时将“推送”一个通知到监测程序。最常见的是，这可以以 webhook 的形式完成 —— 在新代码被推送时一个 挂勾 hook 的程序通过互联网向监测程序发送通知。为此，监测程序必须具有可以通过网络接收 webhook 信息的开放端口。什么是“预检查”（又称“上线前检查”）？在将代码引入仓库并触发持续集成之前，可以进行其它验证。这遵循了最佳实践，例如 测试构建 test build 和 代码审查 code review 。它们通常在代码引入管道之前构建到开发过程中。但是一些管道也可能将它们作为其监控流程或工作流的一部分。例如，一个名为 Gerrit 的工具允许在开发人员推送代码之后但在允许进入（Git 远程）仓库之前进行正式的代码审查、验证和测试构建。Gerrit 位于开发人员的工作区和 Git 远程仓库之间。它会“接收”来自开发人员的推送，并且可以执行通过/失败验证以确保它们在被允许进入仓库之前的检查是通过的。这可以包括检测新变更并启动构建测试（CI 的一种形式）。它还允许开发者在那时进行正式的代码审查。这种方式有一种额外的可信度评估机制，即当变更的代码被合并到代码库中时不会破坏任何内容。什么是“单元测试”？单元测试（也称为“提交测试”），是由开发人员编写的小型的专项测试，以确保新代码独立工作。“独立”这里意味着不依赖或调用其它不可直接访问的代码，也不依赖外部数据源或其它模块。如果运行代码需要这样的依赖关系，那么这些资源可以用 模拟 mock 来表示。模拟是指使用看起来像资源的 代码存根 code stub ，可以返回值，但不实现任何功能。在大多数组织中，开发人员负责创建单元测试以证明其代码正确。事实上，一种称为 测试驱动开发 test-driven develop （TDD）的模型要求将首先设计单元测试作为清楚地验证代码功能的基础。因为这样的代码可以更改速度快且改动量大，所以它们也必须执行很快。由于这与持续集成工作流有关，因此开发人员在本地工作环境中编写或更新代码，并通单元测试来确保新开发的功能或方法正确。通常，这些测试采用断言形式，即函数或方法的给定输入集产生给定的输出集。它们通常进行测试以确保正确标记和处理出错条件。有很多单元测试框架都很有用，例如用于 Java 开发的 JUnit。什么是“持续测试”？持续测试是指在代码通过持续交付管道时运行扩展范围的自动化测试的实践。单元测试通常与构建过程集成，作为持续集成阶段的一部分，并专注于和其它与之交互的代码隔离的测试。除此之外，可以有或者应该有各种形式的测试。这些可包括：集成测试 验证组件和服务组合在一起是否正常。功能测试 验证产品中执行功能的结果是否符合预期。验收测试 根据可接受的标准验证产品的某些特征。如性能、可伸缩性、抗压能力和容量。所有这些可能不存在于自动化的管道中，并且一些不同类型的测试分类界限也不是很清晰。但是，在交付管道中持续测试的目标始终是相同的：通过持续的测试级别证明代码的质量可以在正在进行的发布中使用。在持续集成快速的原则基础上，第二个目标是快速发现问题并提醒开发团队。这通常被称为快速失败。除了测试之外，还可以对管道中的代码进行哪些其它类型的验证？除了测试是否通过之外，还有一些应用程序可以告诉我们测试用例执行（覆盖）的源代码行数。这是一个可以衡量代码量指标的例子。这个指标称为 代码覆盖率 code-coverage ，可以通过工具（例如用于 Java 的 JaCoCo）进行统计。还有很多其它类型的指标统计，例如代码行数、复杂度以及代码结构对比分析等。诸如 SonarQube 之类的工具可以检查源代码并计算这些指标。此外，用户还可以为他们可接受的“合格”范围的指标设置阈值。然后可以在管道中针对这些阈值设置一个检查，如果结果不在可接受范围内，则流程终端上。SonarQube 等应用程序具有很高的可配置性，可以设置仅检查团队感兴趣的内容。什么是“持续交付”？持续交付（CD）通常是指整个流程链（管道），它自动监测源代码变更并通过构建、测试、打包和相关操作运行它们以生成可部署的版本，基本上没有任何人为干预。持续交付在软件开发过程中的目标是自动化、效率、可靠性、可重复性和质量保障（通过持续测试）。持续交付包含持续集成（自动检测源代码变更、执行构建过程、运行单元测试以验证变更），持续测试（对代码运行各种测试以保障代码质量），和（可选）持续部署（通过管道发布版本自动提供给用户）。如何在管道中识别/跟踪多个版本？版本控制是持续交付和管道的关键概念。持续意味着能够经常集成新代码并提供更新版本。但这并不意味着每个人都想要“最新、最好的”。对于想要开发或测试已知的稳定版本的内部团队来说尤其如此。因此，管道创建并轻松存储和访问的这些版本化对象非常重要。在管道中从源代码创建的对象通常可以称为 工件 artifact 。工件在构建时应该有应用于它们的版本。将版本号分配给工件的推荐策略称为 语义化版本控制 semantic versioning 。（这也适用于从外部源引入的依赖工件的版本。）语义版本号有三个部分： 主要版本 major 、 次要版本 minor 和 补丁版本 patch 。（例如，1.4.3 反映了主要版本 1，次要版本 4 和补丁版本 3。）这个想法是，其中一个部分的更改表示工件中的更新级别。主要版本仅针对不兼容的 API 更改而递增。当以 向后兼容 backward-compatible 的方式添加功能时，次要版本会增加。当进行向后兼容的版本 bug 修复时，补丁版本会增加。这些是建议的指导方针，但只要团队在整个组织内以一致且易于理解的方式这样做，团队就可以自由地改变这种方法。例如，每次为发布完成构建时增加的数字可以放在补丁字段中。如何“分销”工件？团队可以为工件分配 分销 promotion 级别以指示适用于测试、生产等环境或用途。有很多方法。可以用 Jenkins 或 Artifactory 等应用程序进行分销。或者一个简单的方案可以在版本号字符串的末尾添加标签。例如，-snapshot 可以指示用于构建工件的代码的最新版本（快照）。可以使用各种分销策略或工具将工件“提升”到其它级别，例如 -milestone 或 -production，作为工件稳定性和完备性版本的标记。如何存储和访问多个工件版本？从源代码构建的版本化工件可以通过管理 工件仓库 artifact repository 的应用程序进行存储。工件仓库就像构建工件的版本控制工具一样。像 Artifactory 或 Nexus 这类应用可以接受版本化工件，存储和跟踪它们，并提供检索的方法。管道用户可以指定他们想要使用的版本，并在这些版本中使用管道。什么是“持续部署”？持续部署（CD）是指能够自动提供持续交付管道中发布版本给最终用户使用的想法。根据用户的安装方式，可能是在云环境中自动部署、app 升级（如手机上的应用程序）、更新网站或只更新可用版本列表。这里的一个重点是，仅仅因为可以进行持续部署并不意味着始终部署来自管道的每组可交付成果。它实际上指，通过管道每套可交付成果都被证明是“可部署的”。这在很大程度上是由持续测试的连续级别完成的（参见本文中的持续测试部分）。管道构建的发布成果是否被部署可以通过人工决策，或利用在完全部署之前“试用”发布的各种方法来进行控制。在完全部署到所有用户之前，有哪些方法可以测试部署？由于必须回滚/撤消对所有用户的部署可能是一种代价高昂的情况（无论是技术上还是用户的感知），已经有许多技术允许“尝试”部署新功能并在发现问题时轻松“撤消”它们。这些包括：蓝/绿测试/部署在这种部署软件的方法中，维护了两个相同的主机环境 —— 一个“蓝色” 和一个“绿色”。（颜色并不重要，仅作为标识。）对应来说，其中一个是“生产环境”，另一个是“预发布环境”。在这些实例的前面是调度系统，它们充当产品或应用程序的客户“网关”。通过将调度系统指向蓝色或绿色实例，可以将客户流量引流到期望的部署环境。通过这种方式，切换指向哪个部署实例（蓝色或绿色）对用户来说是快速，简单和透明的。当新版本准备好进行测试时，可以将其部署到非生产环境中。在经过测试和批准后，可以更改调度系统设置以将传入的线上流量指向它（因此它将成为新的生产站点）。现在，曾作为生产环境实例可供下一次候选发布使用。同理，如果在最新部署中发现问题并且之前的生产实例仍然可用，则简单的更改可以将客户流量引流回到之前的生产实例 —— 有效地将问题实例“下线”并且回滚到以前的版本。然后有问题的新实例可以在其它区域中修复。金丝雀测试/部署在某些情况下，通过蓝/绿发布切换整个部署可能不可行或不是期望的那样。另一种方法是为 金丝雀 canary 测试/部署。在这种模型中，一部分客户流量被重新引流到新的版本部署中。例如，新版本的搜索服务可以与当前服务的生产版本一起部署。然后，可以将 10％ 的搜索查询引流到新版本，以在生产环境中对其进行测试。如果服务那些流量的新版本没问题，那么可能会有更多的流量会被逐渐引流过去。如果仍然没有问题出现，那么随着时间的推移，可以对新版本增量部署，直到 100％ 的流量都调度到新版本。这有效地“更替”了以前版本的服务，并让新版本对所有客户生效。功能开关对于可能需要轻松关掉的新功能（如果发现问题），开发人员可以添加 功能开关 feature toggles 。这是代码中的 if-then 软件功能开关，仅在设置数据值时才激活新代码。此数据值可以是全局可访问的位置，部署的应用程序将检查该位置是否应执行新代码。如果设置了数据值，则执行代码；如果没有，则不执行。这为开发人员提供了一个远程“终止开关”，以便在部署到生产环境后发现问题时关闭新功能。暗箱发布在 暗箱发布 dark launch 中，代码被逐步测试/部署到生产环境中，但是用户不会看到更改（因此名称中有 暗箱 dark 一词）。例如，在生产版本中，网页查询的某些部分可能会重定向到查询新数据源的服务。开发人员可收集此信息进行分析，而不会将有关接口，事务或结果的任何信息暴露给用户。这个想法是想获取候选版本在生产环境负载下如何执行的真实信息，而不会影响用户或改变他们的经验。随着时间的推移，可以调度更多负载，直到遇到问题或认为新功能已准备好供所有人使用。实际上功能开关标志可用于这种暗箱发布机制。什么是“运维开发”？ 运维开发 DevOps 是关于如何使开发和运维团队更容易合作开发和发布软件的一系列想法和推荐的实践。从历史上看，开发团队研发了产品，但没有像客户那样以常规、可重复的方式安装/部署它们。在整个周期中，这组安装/部署任务（以及其它支持任务）留给运维团队负责。这经常导致很多混乱和问题，因为运维团队在后期才开始介入，并且必须在短时间内完成他们的工作。同样，开发团队经常处于不利地位 —— 因为他们没有充分测试产品的安装/部署功能，他们可能会对该过程中出现的问题感到惊讶。这往往导致开发和运维团队之间严重脱节和缺乏合作。DevOps 理念主张是贯穿整个开发周期的开发和运维综合协作的工作方式，就像持续交付那样。持续交付如何与运维开发相交？持续交付管道是几个 DevOps 理念的实现。产品开发的后期阶段（如打包和部署）始终可以在管道的每次运行中完成，而不是等待产品开发周期中的特定时间。同样，从开发到部署过程中，开发和运维都可以清楚地看到事情何时起作用，何时不起作用。要使持续交付管道循环成功，不仅要通过与开发相关的流程，还要通过与运维相关的流程。说得更远一些，DevOps 建议实现管道的基础架构也会被视为代码。也就是说，它应该自动配置、可跟踪、易于修改，并在管道发生变化时触发新一轮运行。这可以通过将管道实现为代码来完成。什么是“管道即代码”？ 管道即代码 pipeline-as-code 是通过编写代码创建管道作业/任务的通用术语，就像开发人员编写代码一样。它的目标是将管道实现表示为代码，以便它可以与代码一起存储、评审、跟踪，如果出现问题并且必须终止管道，则可以轻松地重建。有几个工具允许这样做，如 Jenkins 2。DevOps 如何影响生产软件的基础设施？传统意义上，管道中使用的各个硬件系统都有配套的软件（操作系统、应用程序、开发工具等）。在极端情况下，每个系统都是手工设置来定制的。这意味着当系统出现问题或需要更新时，这通常也是一项自定义任务。这种方法违背了持续交付的基本理念，即具有易于重现和可跟踪的环境。多年来，很多应用被开发用于标准化交付（安装和配置）系统。同样， 虚拟机 virtual machine 被开发为模拟在其它计算机之上运行的计算机程序。这些 VM 要有管理程序才能在底层主机系统上运行，并且它们需要自己的操作系统副本才能运行。后来有了 容器 container 。容器虽然在概念上与 VM 类似，但工作方式不同。它们只需使用一些现有的操作系统结构来划分隔离空间，而不需要运行单独的程序和操作系统的副本。因此，它们的行为类似于 VM 以提供隔离但不需要过多的开销。VM 和容器是根据配置定义创建的，因此可以轻易地销毁和重建，而不会影响运行它们的主机系统。这允许运行管道的系统也可重建。此外，对于容器，我们可以跟踪其构建定义文件的更改 —— 就像对源代码一样。因此，如果遇到 VM 或容器中的问题，我们可以更容易、更快速地销毁和重建它们，而不是在当前环境尝试调试和修复。这也意味着对管道代码的任何更改都可以触发管道新一轮运行（通过 CI），就像对代码的更改一样。这是 DevOps 关于基础架构的核心理念之一。via: https://opensource.com/article/18/8/what-cicd作者：Brent Laster 选题：lujun9972 译者：pityonline 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出