mirror of
https://github.com/LCTT/TranslateProject.git
synced 2024-12-26 21:30:55 +08:00
Merge pull request #24963 from lxbwolf/42-20210824-Solve-the-repository-impedance-mismatch-in-CI/CD
TSL
This commit is contained in:
commit
08e41fe802
@ -1,207 +0,0 @@
|
||||
[#]: subject: "Solve the repository impedance mismatch in CI/CD"
|
||||
[#]: via: "https://opensource.com/article/21/8/impedance-mismatch-cicd"
|
||||
[#]: author: "Evan "Hippy" Slatis https://opensource.com/users/hippyod"
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: "lxbwolf"
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
Solve the repository impedance mismatch in CI/CD
|
||||
======
|
||||
Aligning deployment images and descriptors can be difficult, but here
|
||||
are few strategies to streamline the process.
|
||||
![Tips and gears turning][1]
|
||||
|
||||
An _impedance mismatch_ in software architecture happens when there's a set of conceptual and technical difficulties between two components. It's actually a term borrowed from electrical engineering, where the impedance of electrical input and output must match for the circuit to work.
|
||||
|
||||
In software development, an impedance mismatch exists between images stored in an image repository and its deployment descriptors stored in the SCM. How do you know whether the deployment descriptors stored in the SCM are actually meant for the image in question? The two repositories don't track the data they hold the same way, so matching an image (an immutable binary stored individually in an image repository) to its specific deployment descriptors (text files stored as a series of changes in Git) isn't straightforward.
|
||||
|
||||
**NOTE**: This article assumes at least a passing familiarity with the following concepts:
|
||||
|
||||
* Source Control Management (SCM) systems and branching
|
||||
* Docker/OCI-compliant images and containers
|
||||
* Container Orchestration Platforms (COP) such as Kubernetes
|
||||
* Continuous Integration/Continuous Delivery (CI/CD)
|
||||
* Software development lifecycle (SDLC) environments
|
||||
|
||||
|
||||
|
||||
### Impedance mismatch: SCM and image repositories
|
||||
|
||||
To fully understand where this becomes a problem, consider a set of basic Software Development LifeCycle (SDLC) environments typically used in any given project; for example, dev, test, and prod (or release) environments.
|
||||
|
||||
The dev environment does not suffer from an impedance mismatch. Best practices, which today include using CI/CD, dictate that the latest commit to your development branch should reflect what's deployed in the development environment. So, given a typical, successful CI/CD development workflow:
|
||||
|
||||
1. A commit is made to the development branch in the SCM
|
||||
2. The commit triggers an image build
|
||||
3. The new, distinct image is pushed to the image repository and tagged as being in dev
|
||||
4. The image is deployed to the dev environment in a Container Orchestration Platform (COP) with the latest deployment descriptors pulled from the SCM
|
||||
|
||||
|
||||
|
||||
In other words, the latest image is always matched to the latest deployment descriptors in the development environment. Rolling back to a previous build isn't an issue, either, because that implies rolling back the SCM, too.
|
||||
|
||||
Eventually, though, development progresses to the point where more formal testing needs to occur, so an image—which implicitly relates to a specific commit in the SCM—is promoted to a test environment. Again, assuming a successful build, this isn't much of a problem because the image promoted from development should reflect the latest in the development branch:
|
||||
|
||||
1. The latest deployment to development is approved for promotion, and the promotion process is triggered
|
||||
2. The latest development image tagged as being in test
|
||||
3. The image is pulled and deployed to the test environment using the latest deployment descriptors pulled from the SCM
|
||||
|
||||
|
||||
|
||||
So far, so good, right? But what happens in either of the following scenarios?
|
||||
|
||||
**Scenario A**. The image is promoted to the next downstream environment, e.g., user acceptance testing (UAT) or even a production environment.
|
||||
|
||||
**Scenario B**. A breaking bug is discovered in the test environment, and the image needs to be rolled back to a known good image.
|
||||
|
||||
In either scenario, it's not as if development has stopped, which means one or more commits to the development branch may have occurred, which in turn means it's possible the latest deployment descriptors have changed, and the latest image isn't the same as what was previously deployed in test. Changes to the deployment descriptors may or may not apply to older versions of an image, but they certainly can't be trusted. If they have changed, they certainly aren't the same deployment descriptors you've been testing with up to now with the image you want to deploy.
|
||||
|
||||
And that's the crux of the problem: I**f the image being deployed isn't the latest from the image repository, how do you identify which deployment descriptors in the SCM apply specifically to the image being deployed?** The short answer is, you can't. The two repositories have an impedance mismatch. The longer answer is that you can, but you have to work for it, which will be the subject of the rest of this article. Note that the following isn't necessarily the only solution to this problem, but it has been put into production and proven to work for dozens of projects that, in turn, have been built and deployed in production for more than a year now.
|
||||
|
||||
### Binaries and deployment descriptors
|
||||
|
||||
A common artifact produced from building source code is a Docker or OCI-compliant image, and that image will typically be deployed to a Container Orchestration Platform (COP) such as Kubernetes. Deploying to a COP requires deployment descriptors defining how the image is to be deployed and run as a container, e.g., [Kubernetes Deployments][2] or [CronJobs][3]. It is because of the fundamental difference between what an image is and its deployment descriptors where the impedance mismatch manifests itself. For this discussion, think of images as immutable binaries stored in an image repository. Any change in the source code does not change the image but rather replaces it with a distinct, new image.
|
||||
|
||||
By contrast, deployment descriptors are text files and thus can be considered source code and mutable. If best practices are being followed, then the deployment descriptors are stored in SCM, and all changes are committed there first to be properly tracked.
|
||||
|
||||
### Solving the impedance mismatch
|
||||
|
||||
The first part of the proposed solution is to ensure that a method exists of matching the image in the image repository to the source commit in the SCM, which holds the deployment descriptors. The most straightforward solution is to tag the image with its source commit hash. This will keep different versions of the image separate, easily identifiable, and provide enough information to find the correct deployment descriptors so that the image can be properly deployed in the COP.
|
||||
|
||||
Reviewing the scenarios above again:
|
||||
|
||||
**Scenario A**. _Promoting an image from one downstream environment to the next_: When the image is promoted from test to UAT, the image's tag tells us from which source commit in the SCM to pull the deployment descriptors.
|
||||
|
||||
**Scenario B**. _When an image needs to be rolled back in a downstream environment_: Whichever image we choose to roll back to will also tell us from which source commit in the SCM to pull the correct deployment descriptors.
|
||||
|
||||
In each case, it doesn't matter how many development branch commits and builds have taken place since a particular image has been deployed in test since every image that's been promoted can find the exact deployment descriptors it was originally deployed with.
|
||||
|
||||
This isn't a complete solution to the impedance mismatch, however. Consider two additional scenarios:
|
||||
|
||||
**Scenario C**. In a load testing environment, different deployment descriptors are tried at various times to see how a particular build performs.
|
||||
|
||||
**Scenario D**. An image is promoted to a downstream environment, and there's an error in the deployment descriptors for that environment.
|
||||
|
||||
In each of these scenarios, changes need to be made to the deployment descriptors, but right now all we have is a source commit hash. Remember that best practices require all source code changes to be committed back to SCM first. The commit at that hash is immutable by itself, so a better solution than just tracking the initial source commit hash is clearly needed.
|
||||
|
||||
The solution here is a new branch created at the original source commit hash. This will be dubbed a **Deployment Branch**. Every time an image is promoted to a downstream test or release environment, you should create a new Deployment Branch **from the head of the previous SDLC environment's Deployment Branch**.
|
||||
|
||||
This will allow the same image to be deployed differently and repeatedly within each SDLC environment and also pick up any changes discovered or applied for that image in each subsequent environment.
|
||||
|
||||
**NOTE:** How changes applied in one environment's deployment descriptors are applied to the next, whether by tools that enable sharing values such as Helm Charts or by manually cutting and pasting across directories, is beyond the scope of this article.
|
||||
|
||||
So, when an image is promoted from one SDLC environment to the next:
|
||||
|
||||
1. A Deployment Branch is created
|
||||
1. If the image is being promoted from the dev environment, the branch is created from the source commit hash that built the image
|
||||
2. Otherwise, _the Deployment Branch is created from the head of the current Deployment Branch_
|
||||
2. The image is deployed into the next SDLC environment using the deployment descriptors from the newly created Deployment Branch for that environment
|
||||
|
||||
|
||||
|
||||
![deployment branching tree][4]
|
||||
|
||||
Figure 1: Deployment branches
|
||||
|
||||
1. Development branch
|
||||
2. First downstream environment's Deployment Branch with a single commit
|
||||
3. Second downstream environment's Deployment Branch with a single commit
|
||||
|
||||
|
||||
|
||||
Revisiting Scenarios C and D from above with Deployment Branches as a solution:
|
||||
|
||||
**Scenario C**. Change the deployment descriptors for an image deployed to a downstream SDLC environment
|
||||
|
||||
**Scenario D**. Fix an error in the deployment descriptors for a particular SDLC environment
|
||||
|
||||
In each scenario, the workflow is as follows:
|
||||
|
||||
1. Commit the changes to the deployment descriptors to the Deployment Branch for the SLDC environment and image
|
||||
2. Redeploy the image into the SLDC environment using the deployment descriptors at the head of the Deployment Branch
|
||||
|
||||
|
||||
|
||||
Thus, Deployment Branches fully resolve the impedance mismatch between image repositories storing a single, immutable image representing a unique build and SCM repositories storing mutable deployment descriptors for one more downstream SDLC environments.
|
||||
|
||||
### Practical considerations
|
||||
|
||||
While this seems like a workable solution, it also opens up several new practical questions for developers and operations resources alike, such as:
|
||||
|
||||
A. Where should deployment descriptors be kept as source to best facilitate Deployment Branch management, i.e., in the same or a different SCM repository than the source that built the image?
|
||||
|
||||
Up until now, we've avoided speaking about which repository the deployment descriptors should reside. Without going into too much detail, we recommend putting the deployment descriptors for all SDLC environments into the same SCM repository as the image source. As Deployment Branches are created, the source for the images will follow and act as an easy-to-find reference for what is actually running in the container being deployed.
|
||||
|
||||
As mentioned above, images will be associated with the original source commit via their tag. Finding the reference for the source at a particular commit in a separate repository would add a level of difficulty to developers, even with tooling, which is unnecessary by keeping everything in a single repository.
|
||||
|
||||
B. Should the source code that built the image be modified on a Deployment Branch?
|
||||
|
||||
Short answer: **NEVER**.
|
||||
|
||||
Longer answer: No, because images should never be built from Deployment Branches. They're built from development branches. Changing the source that defines an image in a Deployment Branch will destroy the record of what built the image being deployed and doesn't actually modify the functionality of the image. This could also become an issue when comparing two Deployment Branches from different versions. It might give a false positive for differences in functionality between them (a small but additional benefit to using Deployment Branches).
|
||||
|
||||
C. Why an image tag? Couldn't image labels be used?
|
||||
|
||||
Tags are easily readable and searchable for images stored in a repository. Reading and searching for labels with a particular value over a group of images requires pulling the manifest for each image, which adds complexity and reduces performance. Also, tagging images for different versions is still necessary for historical record and finding different versions, so using the source commit hash is the easiest solution that guarantees uniqueness while also containing instantly useful information.
|
||||
|
||||
D. What is the most practical way to create Deployment Branches?
|
||||
|
||||
The first three rules of DevOps are _automate_, _automate_, _automate_.
|
||||
|
||||
Relying on resources to enforce best practices uniformly is hit and miss at best, so when implementing a CI/CD pipeline for image promotion, rollback, etc., incorporate automated Deployment Branching into the script.
|
||||
|
||||
E. Any suggestions for a naming convention for Deployment Branches?
|
||||
|
||||
<_**deployment-branch-identifier**_>-<_**env**_>-<_**src-commit-hash**_>
|
||||
|
||||
* _**deployment-branch-identifier:**_ A unique string used by every Deployment Branch to identify it as a Deployment Branch; e.g. 'deployment' or 'deploy'
|
||||
* _**env:**_ The SDLC environment the Deployment Branch pertains to; e.g. 'qa', 'stg', or' prod' for the test, staging, and production environments, respectively
|
||||
* _**src-commit-hash:**_ The source code commit hash that holds the original code that built the image being deployed, which allows developers to easily find the original commit that created the image while ensuring the branch name is unique
|
||||
|
||||
|
||||
|
||||
For example, _**deployment-qa-asdf78s**_ or _**deployment-stg-asdf78s**_ for Deployment Branches promoted to the QA and STG environments, respectively.
|
||||
|
||||
F. How do you tell which version of the image is running in the environment?
|
||||
|
||||
Our suggestion is to [label][5] all your deployment resources with the latest Deployment Branch commit hash and the source commit hash. These two unique identifiers will allow developers and operations personnel to find everything that was deployed and from where. It also makes cleanup of resources trivial using those selectors on deployments of different versions, e.g., on rollback or roll forward operations.
|
||||
|
||||
G. When is it appropriate to merge changes from Deployment Branches back into the development branch?
|
||||
|
||||
It's completely up to the development team on what makes sense.
|
||||
|
||||
If you're making changes for load testing purposes just to see what will break your application, for example, then those changes may not be the best thing to merge back into the development branch. On the other hand, if you find and fix an error or tune a deployment in a downstream environment, merging the Deployment Branch changes back into the development branch makes sense.
|
||||
|
||||
H. Is there a working example of Deployment Branching to test with first?
|
||||
|
||||
[el-CICD][6] has been successfully using this strategy for a year and a half in production for more than a hundred projects across all SDLC downstream environments, including managing deployments to production. If you have access to an [OKD][7], Red Hat OpenShift lab cluster, or [Red Hat CodeReady Containers][8], you can download the [latest el-CICD version][9] and run through the [tutorial][10] to see how and when Deployment Branches are created and used.
|
||||
|
||||
### Wrap up
|
||||
|
||||
Using the working example above would be a good exercise to help you better understand the issues surrounding impedance mismatches in development processes. Maintaining alignment between images and deployment descriptors is a critical part of successfully managing deployments.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/8/impedance-mismatch-cicd
|
||||
|
||||
作者:[Evan "Hippy" Slatis][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/hippyod
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/gears_devops_learn_troubleshooting_lightbulb_tips_520.png?itok=HcN38NOk (Tips and gears turning)
|
||||
[2]: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/
|
||||
[3]: https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/
|
||||
[4]: https://opensource.com/sites/default/files/picture1.png
|
||||
[5]: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/
|
||||
[6]: https://github.com/elcicd
|
||||
[7]: https://www.okd.io/
|
||||
[8]: https://cloud.redhat.com/openshift/create/local
|
||||
[9]: https://github.com/elcicd/el-CICD-RELEASES
|
||||
[10]: https://github.com/elcicd/el-CICD-docs/blob/master/tutorial.md
|
@ -0,0 +1,206 @@
|
||||
[#]: subject: "Solve the repository impedance mismatch in CI/CD"
|
||||
[#]: via: "https://opensource.com/article/21/8/impedance-mismatch-cicd"
|
||||
[#]: author: "Evan "Hippy" Slatis https://opensource.com/users/hippyod"
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: "lxbwolf"
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
解决 CI/CD 中的仓库阻抗失配
|
||||
======
|
||||
对齐部署镜像和描述符是很困难的,但是某些策略可以使整个过程更高效。
|
||||
![Tips and gears turning][1]
|
||||
|
||||
在软件架构中,当两个组件之间有某些概念性或技术上的差异时会出现_阻抗失配_。这个术语其实是从电子工程中借用的,表示正常环路中输入和输出的电子阻抗必须要匹配。
|
||||
|
||||
在软件开发中,存储在镜像仓库中的镜像与存储在源码控制管理系统(译者注:SCM,Source Code Management)中它的部署描述符之间存在阻抗失配。你如何确定存储在 SCM 中的部署描述符表示的是正确的镜像?两个仓库追踪数据的方式并不一致,因此匹配镜像(在镜像仓库中独立存储的不可修改的二进制)和它的部署描述符(Git 中以文本文件形式存储的一系列修改记录)并不那么直观。
|
||||
|
||||
**注意**:本文假定读者已经熟悉以下概念:
|
||||
|
||||
* 源码控制管理(SCM)系统和分支
|
||||
* docker/符合 OCI 标准的镜像和容器
|
||||
* <ruby>容器编排系统<rt>Container Orchestration Platforms</rt></ruby>(COP),如 Kubernetes
|
||||
* <ruby>持续集成/持续交付<rt>Continuous Integration/Continuous Delivery</rt></ruby>(CI/CD)
|
||||
* <ruby>软件开发生命周期<rt>Software development lifecycle</rt></ruby>(SDLC)环境
|
||||
|
||||
|
||||
|
||||
### 阻抗失配:SCM 与镜像仓库
|
||||
|
||||
为了更好地理解阻抗失配在什么场景下会成为问题,请考虑任意项目中的软件开发生命周期环境(SDLC),如开发、测试或发布环境。
|
||||
|
||||
测试环境不会有阻抗失配。现在使用 CI/CD 的最佳实践中开发分支的最新提交都会对应开发环境中的最新部署。因此,一个典型的、成功的 CI/CD 开发流程如下:
|
||||
|
||||
1. 向 SCM 的开发分支提交新的修改
|
||||
2. 新提交触发一次镜像构建
|
||||
3. 新生成的镜像被推送到镜像仓库,标记为开发中
|
||||
4. 镜像被部署到容器编排系统中的开发环境,该镜像的部署描述符也更新为从 SCM 拉取的最新描述符。
|
||||
|
||||
|
||||
|
||||
换句话说,开发环境中最新的镜像永远与最新的部署描述符匹配。回滚到前一个构建的版本也不是问题,因为 SCM 也会跟着回滚。
|
||||
|
||||
最终,随着开发流程继续推进,需要进行更多正式的测试,因此某个镜像 —— 镜像对应着 SCM 中的某次提交 —— 被推到测试环境。如果是一次成功的构建,那么不会有大问题,因为从开发环境推过来的镜像应该会与开发分支的最新提交相对应。
|
||||
|
||||
1. 开发环境的最新部署被允许入库,触发入库过程
|
||||
2. 最新部署的镜像被标记为测试中
|
||||
3. 镜像在测试环境中被拉取和部署,(该镜像)对应从 SCM 拉取的最新部署描述符
|
||||
|
||||
|
||||
|
||||
到目前为止,一切都没有问题,对吗?如果出现下面的场景,会有什么问题?
|
||||
|
||||
**场景 A**. 镜像被推到下游环境,如<ruby>用户验收测试<rt>user acceptance testing </rt></ruby>(UAT),或者是生产环境。
|
||||
|
||||
**场景 B**. 测试环境中发现了一个破坏性的 bug,镜像需要回滚到某个确定正常的版本。
|
||||
|
||||
在任一场景中,开发过程并没有停止,即开发分支上游新的提交,而这意味着最新的部署描述符已经发生了变化,最新的镜像与之前部署在测试环境中的镜像不一致。对部署描述符的修改可能会也可能不会对之前版本的镜像起作用,但是它们一定是不可信任的。如果它们有了变化,那么它们就一定与目前为止你测试过的想要部署的镜像的部署描述符不一致。
|
||||
|
||||
问题的关键是:**如果部署的镜像不是镜像库中的最新版本,你怎么确定与部署的镜像相对应的是 SCM 中的哪个部署描述符?**一言以蔽之,无法确定。两个库直接有阻抗失配。如果要详细阐述下,那么是有方法可以解决的,但是你需要做很多工作,这部分内容就是文章接下来的主题了。请注意,下面的方案并不是解决问题的唯一办法,但是已经投入到生产环境并已经对很多项目起了作用,而且已经被构建并部署到生产环境中运行了超过一年。
|
||||
|
||||
### 二进制与部署描述符
|
||||
|
||||
源码通常被构建成一个 docker 镜像或符合 OCI 标准的镜像,该镜像通常被部署到一个容器编排平台(COP)上,如Kubernetes。部署到 COP 需要部署描述符定义镜像被如何部署以及作为容器运行,如 [Kubernetes 部署][2] 或 [CronJobs][3]。这是因为在镜像和它的部署描述符之间有本质差异,在这里可以看到阻抗失配。在这次讨论中,我们认为镜像是存储在镜像仓库中不可修改的二进制。对源码的任何修改都不会修改镜像,而是用另一个新的镜像去替换它。
|
||||
|
||||
相比之下,部署描述符是文本文件,因而可以被认为是源码且可修改。如果遵循最佳实践,那么部署描述符是被存储在 SCM,所有修改都会提交,而这很容易回溯。
|
||||
|
||||
### 解决阻抗失配
|
||||
|
||||
建议的解决方案的第一部分,就是提供一个能匹配镜像仓库中的镜像与对保存部署描述符的 SCM 做的代码提交的方法。最直接的解决方案就是对镜像打上源码提交哈希的标签。这个方法可以使不同版本的镜像相互独立、容易分辨,并且在查找正确的部署描述符时可以提供足够的信息,以便镜像更好地部署到 COP。
|
||||
|
||||
再回顾下上面的场景:
|
||||
|
||||
**场景 A**. _镜像被推到下游环境_: 当镜像被从测试环境推到 UAT 环境时,我们可以从标签中知道应该从 SCM 的哪一次源码提交拉取部署描述符。
|
||||
|
||||
**场景 B**. _当一个镜像需要在某一环节中回滚_:无论我们选择回滚到那个镜像版本,我们都可以知道从 SCM 的哪一次源码提交拉取部署描述符
|
||||
|
||||
在每个案例中,无论在某个镜像被部署到测试环境后开发分支有多少次提交和构建,对于每一次升级的镜像,我们都可以找到它当初部署时对应的部署描述符。
|
||||
|
||||
然而,这并不是阻抗失配的完整解决方案。再考虑两个场景:
|
||||
|
||||
**场景 C**. 在负载测试环境中,会尝试对不同的部署描述符进行多次部署,以此来验证某一次构建的表现。
|
||||
|
||||
**场景 D**. 一个镜像被推送到下游环境,在该环境中部署描述符有一个错误。
|
||||
|
||||
在上面的所有场景中,我们都需要修改部署描述符,但是目前为止我们只有一个源码提交哈希。请记住,最佳实践要求我们所有对源码的修改都要先提交到 SCM。某次提交的哈希本身是无法修改的,因此我们需要一个比仅仅追踪原来的源码提交哈希更好地解决方案。
|
||||
|
||||
解决方案是基于原来的源码提交哈希新建一个分支。我们把这个分支称为**部署分支**。每当一个镜像被推到下游测试或发布环境时,你应该**基于前一个 SDLC 环境的部署分支的最新提交**创建一个新的部署分支。
|
||||
|
||||
这样同一个镜像可以重复多次部署到不同的 SDLC 环境,在后面每个环境中可以感知前面发现的改动或对镜像做的修改。
|
||||
|
||||
**注意:**在某个环境中做的修改是如何影响下一个环境的,是用可以共享数据的工具(如 Helm Charts)还是手动剪切、粘贴到其他目录,都不在本文讨论的范围内。
|
||||
|
||||
因此,当一个镜像被从一个 SDLC 环境中推到下一环境时:
|
||||
|
||||
1. 创建一个部署分支
|
||||
1. 如果镜像是从开发环境中推过来的,那么部署分支就基于构建这个镜像的源码提交哈希创建
|
||||
2. 否则,_部署分支基于当前部署分支的最新提交创建_
|
||||
2. 镜像被部署到下一个 SDLC 环境,使用的部署描述符是该环境中新创建的部署分支的部署描述符
|
||||
|
||||
|
||||
|
||||
![deployment branching tree][4]
|
||||
|
||||
图 1:部署分支
|
||||
|
||||
1. 部署分支
|
||||
2. 下游环境的第一个部署分支,只有一次提交
|
||||
3. 下游环境的第二个部署分支,只有一次提交
|
||||
|
||||
|
||||
|
||||
有了部署分支这个解决方案,再回顾下上面的场景 C 和场景 D:
|
||||
|
||||
**场景 C**. 修改已经部署到下游 SDLC 环境中的镜像的部署描述符
|
||||
|
||||
**场景 D**. 修复某个 SDLC 环境中部署描述符的错误
|
||||
|
||||
两个场景中,工作流如下:
|
||||
|
||||
1. 把对部署描述符做的修改提交到 SLDC 环境和镜像对应的部署分支
|
||||
2. 通过部署分支最新提交对应的部署描述符把镜像重新部署到 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. 你怎么识别环境中运行的哪个镜像版本?
|
||||
|
||||
我们的建议是把最新的部署分支提交哈希和源码提交哈希添加到 [label][5] 中。开发者和运维人员可以通过这两个独一无二的标识符查找的部署的所有东西及其来源。在诸如执行回滚或前滚操作时,使用那些不同版本的部署的选择器也能清理资源碎片。
|
||||
|
||||
G. 什么时候应该把部署分支的修改合并回开发分支?
|
||||
|
||||
这完全取决于开发团队。
|
||||
|
||||
如果你修改的目的是为了做负载测试,只是想验证什么情况会让程序崩溃,那么这些修改不应该被合并回开发分支。另一方面,如果你发现和修复了一个错误,或者对下游环境的部署做了调整,那么久应该把部署分支的修改合并回开发分支。
|
||||
|
||||
H. 有现成的部署分支示例让我们试水吗?
|
||||
|
||||
[el-CICD][6] 已经在生产上使用这个策略持续一年半应用到超过一百个项目了,覆盖所有的 SDLC 环境,包括管理生产环境的部署。如果你可以访问 [OKD][7]、Red Hat OpenShift lab cluster 或 [Red Hat CodeReady Containers][8],你可以下载[el-CICD 的最新版本][9],参照[教程][10]来学习部署分支是何时以怎样的方式创建和使用的。
|
||||
|
||||
### 结语
|
||||
|
||||
通过实践上面的例子可以帮助你更好的理解开发过程中阻抗失配相关的问题。对齐镜像和部署描述符是成功管理部署的关键部分。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/8/impedance-mismatch-cicd
|
||||
|
||||
作者:[Evan "Hippy" Slatis][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[lxbwolf](https://github.com/lxbwolf)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/hippyod
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/gears_devops_learn_troubleshooting_lightbulb_tips_520.png?itok=HcN38NOk "Tips and gears turning"
|
||||
[2]: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/
|
||||
[3]: https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/
|
||||
[4]: https://opensource.com/sites/default/files/picture1.png
|
||||
[5]: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/
|
||||
[6]: https://github.com/elcicd
|
||||
[7]: https://www.okd.io/
|
||||
[8]: https://cloud.redhat.com/openshift/create/local
|
||||
[9]: https://github.com/elcicd/el-CICD-RELEASES
|
||||
[10]: https://github.com/elcicd/el-CICD-docs/blob/master/tutorial.md
|
Loading…
Reference in New Issue
Block a user