vlambda博客
学习文章列表

读书笔记《hands-on-docker-for-microservices-with-python》使用GitOps原则

Using GitOps Principles

在了解如何配置 Kubernetes 集群之后,我们将学习如何使用 GitOps 实践而不是应用手动命令和文件来进行配置。 GitOps 意味着使用 Git 存储库管理集群配置,以存储和跟踪包含配置的 YAML 文件。我们将看到如何使用 Flux 将 GitHub 存储库与集群链接,以便定期更新。

这种方法允许我们以确定的方式存储配置,在代码中描述对基础设施的更改。正如我们将在 第 9 章管理工作流程

本章将涵盖以下主题:

  • Understanding the description of GitOps
  • Setting up Flux to control the Kubernetes cluster
  • Configuring GitHub
  • Making a Kubernetes cluster change through GitHub
  • Working in production

在本章结束时,您将了解如何将 Kubernetes 配置存储在 Git 存储库中,并自动应用合并到主分支中的任何更改。

Technical requirements

Understanding the description of GitOps

操作中的一个大传统问题是确保不同的服务器保持正确的配置。当您拥有一组服务器时,部署服务并对其进行正确配置并不是一项简单的任务。

For this chapter, we will use configuration as a way of describing a service and all the required configuration to run it in production. This includes the particular version of the service, but also things such as the underlying infrastructure (OS version, number of servers, and so on) or packages and configuration of the dependent services (load balancers, third-party libraries, and so on).

Configuration management will, therefore, be the way to make changes to that.

随着基础设施的发展,在所有服务器中保持配置正常是一项挑战。最常见的更改是部署新版本的服务,但还有其他可能性。例如,有一个新的服务器需要添加到负载均衡器中,为 NGINX 进行新的配置调整以修复安全漏洞,或者为服务启用一个新的环境变量以启用某个功能。

初始阶段是手动配置,但一段时间后就很难做到。

Managing configuration

手动配置意味着团队中的某个人跟踪少量服务器,当需要更改时,在每台服务器上单独记录并进行所需的更改。

这种操作方式是工作密集型的,并且在多台服务器上容易出错,因为它们很容易出现分歧。

所以,一段时间后,可以通过一些脚本使用 Fabric (http://www .fabfile.org/) Capistrano (https://capistranorb.com/ )<跨度>。基本模型是将配置和新代码推送到服务器并执行一些自动化任务,最后重新启动服务。通常,这是直接通过团队的计算机手动完成的。

代码和配置通常存在于 Git 上,但手动过程可以更改它,因为它是分离的。如果您以这种方式工作,请确保仅部署存储在源代码管理下的文件。

服务器维护的某些元素,如操作系统升级或更新库,可能仍需要手动完成。

下图显示了如何从进行配置更改的团队成员的计算机推送代码:

读书笔记《hands-on-docker-for-microservices-with-python》使用GitOps原则

在这个阶段,可以手动添加新的基础设施或r 使用诸如Terraform (https://www.terraform.io/) 与云服务交互。

更复杂的替代方法是使用 Puppet (https://puppet.com/) 或 Chef (https://www.chef.io/)。它们使用客户端-服务器架构。它们允许我们使用自己的声明性语言来描述服务器的状态,当服务器中的状态发生变化时,所有客户端都将更新以遵循定义。服务器将报告任何问题或偏差,并将集中配置定义。

下图总结了这个过程:

读书笔记《hands-on-docker-for-microservices-with-python》使用GitOps原则

在某些情况下,这些工具可能能够在云服务中分配资源;例如,在 AWS 中添加一个新的 EC2 实例。

A configuration management tool also helps in monitoring and performs a number of remediation tasks. For example, it can restart services that should be running, or retry if there has been a problem changing the configuration.

It also scales better for a higher number of servers.

所有这些策略都需要专门的工具,并且通常由特定的运营团队处理。这使得需要在他们之间进行协调以进行配置更新的开发人员无法获得配置。

这种工作分工产生了一些摩擦,随着时间的推移,DevOps 运动提出了其他方式来构建这项工作。

Understanding DevOps

划分工作的传统方式是创建一个控制基础设施和部署的运营团队,以及一个创建服务的开发团队。

这种方法的问题在于,开发人员通常不会真正了解他们的代码在生产中是如何工作的,同时,操作也不会确切地知道部署包含什么。 这可能会导致我不知道它是什么/我不知道它在哪里的情况,两者之间有一个鸿沟团队。 DevOps 最终被创建为填补这一空白的方法。

A typical problem is one where a service frequently fails in production and is detected by operations, which performs remediation tactics (for example, restarting the service).

However, the development team doesn't know exactly what makes it fail and they have other pressing priorities, so they won't fix the problem.

Over time, this may compromise the stability of the system.

DevOps 是一组改进运维端和开发端协作的技术。它旨在通过让开发人员了解整个操作方面来实现快速部署,并通过尽可能使用自动化来简化操作。

它的核心是授权团队允许他们控制自己的基础设施和部署,加快部署速度并了解基础设施,以帮助及早发现问题。团队应该自主部署和支持基础设施。

要启用 DevOps 实践,您需要一些工具来以可控的方式控制不同的操作。 GitOps 是一个有趣的选择,尤其是如果您使用 Kubernetes。

Defining GitOps

GitOps 的想法很简单——我们使用 Git 来描述我们的基础设施和配置管理。对已定义分支的任何更改都会触发相关更改。

如果你能够通过代码定义整个系统,Git 会给你很多优势:

  • Any change to either infrastructure or configuration management is versioned. They are explicit and can be rolled back if they have problems. Changes between versions can be observed through diffs, which is a normal Git operation.
  • A Git repo can act as a backup that can enable recovery from scratch if there's a catastrophic failure in the underlying hardware.
  • It is the most common source control tool. Everyone in the company likely knows how it works and can use it. It also easily integrates with existing workflows, like reviews.

GitOps 概念由 Weaveworks 在一篇博文(https:// /www.weave.works/blog/gitops-operations-by-pull-request)。从那时起,它在公司中被越来越多地使用。

虽然 GitOps 可以应用于其他类型的部署(而且确实如此),但它与 Kubernetes 有很好的协同作用,这实际上是 Weaveworks 博客文章中的描述。

一个 Kubernetes 集群可以使用 YAML 文件完全配置,它几乎封装了系统的整个定义。正如我们在上一章中看到的,这可能包括负载均衡器等元素的定义。 Kubernetes 集群外部的元素,例如外部 DNS,不包含在 YAML 文件中,很少更改。

The servers and infrastructure can be automated with other tools, like Terraform, or with the automated procedures described in Chapter 7, Configuring and Securing the Production System.

For pragmatic reasons, it is entirely feasible that some infrastructure operations are manual. For example, upgrading the Kubernetes version of an EKS cluster is an operation that can be done through the AWS console, and it is rare enough that it is fine to do so manually.

It is also fine to have these kinds of operations remain manual, since automating them probably won't pay dividends.

正如我们在 第 6 章使用 Kubernetes 进行本地开发中看到的,Kubernetes YAML 文件包含可以通过 kubectl apply -f <file> 命令应用的元素定义。 Kubernetes 非常灵活,因为单个文件可以包含多个元素或单个元素。

将所有 YAML 文件分组到一个目录结构下并将它们置于 Git 控制之下是应用更改的一种非常明确的方式。这就是我们的运作方式。

此操作并不复杂,但我们将使用 Wea​​veworks 创建的现有工具,名为 Flux。

Setting up Flux to control the Kubernetes cluster

Flux(https://github.com/fluxcd/flux)是一个工具,可以确保Kubernetes 集群匹配存储在 Git 存储库中的文件。

它作为另一个部署部署在 Kubernetes 集群中。它每 5 分钟运行一次,并检查 Git 存储库和 Docker 注册表。然后,它应用任何更改。这有助于访问 Git 存储库,因为无需在 CI 系统内创建任何推送机制。

我们将看到如何在 Kubernetes 中启动从 GitHub 存储库中提取的 Flux 容器。

Starting the system

为简单起见,我们将使用本地 Kubernetes。我们将使用 第 6 章使用 Kubernetes 进行本地开发中描述的图像,所以请务必运行以下命令:

$ cd Chapter06
$ cd frontend
$ docker-compose build server
...
Successfully tagged thoughts_frontend:latest
$ cd ..
$ cd thoughts_backend/
$ docker-compose build server db
...
Successfully tagged thoughts_frontend:latest
$ cd ..
$ cd users_backend
$ docker-compose build server db
...
Successfully tagged users_server:latest

基本的 Kubernetes 配置存储在示例文件夹中 (https://github.com/PacktPublishing/Hands-On-Docker-for-Microservices-with-Python/tree/master/Chapter08/example) 子目录。

您可以使用以下命令部署整个系统:

$ cd Chapter08/example
$ kubectl apply -f namespace.yaml
namespace/example created
$ kubectl apply -f . --recursive
deployment.apps/frontend created
ingress.extensions/frontend-ingress created
service/frontend-service created
namespace/example unchanged
deployment.apps/thoughts-backend created
ingress.extensions/thoughts-backend-ingress created
service/thoughts-service created
deployment.apps/users-backend created
ingress.extensions/users-backend-ingress created
service/users-service created

这将创建整个系统。

Apply the namespace.yaml file to avoid not being able to deploy elements as the namespace is not present, but you can run the kubectl apply -f . --recursive command twice.

如果您检查系统,它现在应该已部署,如运行 kubectl get pods 命令所示:

$ kubectl get pods -n example
NAME                   READY STATUS  RESTARTS AGE
frontend-j75fp         1/1   Running 0        4m
frontend-n85fk         1/1   Running 0        4m
frontend-nqndl         1/1   Running 0        4m
frontend-xnljj         1/1   Running 0        4m
thoughts-backend-f7tq7 2/2   Running 0        4m
users-backend-7wzts    2/2   Running 0        4m

请注意,frontend 有四个副本。我们将在本章中更改 pod 的数量,作为如何更改部署的示例。

现在,删除部署以从头开始:

$ kubectl delete namespace example
namespace "example" deleted

有关此设置的更多详细信息,请查看 在本地部署完整系统 部分中的 第 6 章使用 Kubernetes 进行本地开发

Configuring Flux

我们将准备一个 Flux 系统,它将帮助我们跟踪 我们的 Git 配置。 我们根据这个 repo (https://github .com/fluxcd/flux/tree/master/deploy),它位于 Chapter08/flux 子目录中。

主文件是 flux-deployment.yaml。其中大部分是注释样板文件,但请查看要从中提取的 repo 的定义:

# Replace the following URL to change the Git repository used by Flux.
- [email protected]:PacktPublishing/Hands-On-Docker-for-Microservices-with-Python.git
- --git-branch=master
# Include this if you want to restrict the manifests considered by flux
# to those under the following relative paths in the git repository
- --git-path=Chapter08/example

这些行告诉 Flux 要使用的 repo、分支和任何路径。如果路径被注释,它可能是你的情况,它使用整个回购。在下一节中,我们将需要更改 repo 以使用您自己的。

请注意,我们使用 flux 命名空间来部署所有这些元素。如果它更适合您,您可以重用您的主名称空间或使用默认名称空间。

要使用 Flux,请创建命名空间,然后应用完整的 flux 目录:

$ kubectl apply -f flux/namespace.yaml
namespace/flux created
$ kubectl apply -f flux/
serviceaccount/flux created
clusterrole.rbac.authorization.k8s.io/flux created
clusterrolebinding.rbac.authorization.k8s.io/flux created
deployment.apps/flux created
secret/flux-git-deploy created
deployment.apps/memcached created
service/memcached created
namespace/flux unchanged

使用以下代码,您可以检查一切是否按预期运行:

$ kubectl get pods -n flux
NAME                       READY STATUS  RESTARTS AGE
flux-75fff6bbf7-bfnq6      1/1   Running 0        34s
memcached-84f9f4d566-jv6gp 1/1   Running 0        34s

但是,为了能够从 Git 存储库进行部署,我们需要对其进行配置。

Configuring GitHub

虽然我们可以配置任何 Git 存储库,但通常我们将使用 GitHub 来设置它。我们需要设置一个有效的密钥来访问 Git 存储库。

最简单的方法是让 Flux 生成自己的密钥,并将其添加到 GitHub 存储库。但要做到这一点,我们需要创建自己的 GitHub 存储库。

Forking the GitHub repo

配置 repo 的第一步是分叉它。让我们看一下以下步骤以获取更多详细信息:

  1. Go to the page of the GitHub repo for the code (https://github.com/PacktPublishing/Hands-On-Docker-for-Microservices-with-Python/) and click in Fork on the top-right corner to generate your own copy.
  2. Once you have your own copy, it will have a URL similar to the following:
https://github.com/<YOUR GITHUB USER>/Hands-On-Docker-for-Microservices-with-Python/
  1. Now, you need to replace it in the Chapter08/flux/flux-deployment.yaml file for the --git-url parameter.
  2. Once you change it, reapply the Flux configuration with the following command:
$ kubectl apply -f flux/flux-deployment.yaml
deployment.apps/flux changed

现在,Flux 正在您完全控制下跟踪您自己的 repo,您​​可以对其进行更改。首先,我们需要允许 Flux 访问 GitHub repo,这可以通过部署密钥来实现。

Adding a deploy key

为了让 Flux 能够访问 GitHub,我们需要将其密钥添加为有效的部署密钥。使用fluxctl,很容易得到当前的ssh key;只需运行以下命令:

$ fluxctl identity --k8s-fwd-ns flux
ssh-rsa <secret key>

有了这些信息,转到 设置 | Deploy keys 部分在你的 fork GitHub 项目上。 用描述性名称填写标题,Key 部分使用您之前获得的密钥, 然后选择 添加键

读书笔记《hands-on-docker-for-microservices-with-python》使用GitOps原则

请务必选中 允许写入访问 复选框。现在,Flux 将能够联系 GitHub。

下一步是同步 GitHub 和集群上的状态。

Syncing Flux

我们可以与 Flux 同步,因此在集群中应用 GitHub 中的描述,使用以下命令:

$ fluxctl sync --k8s-fwd-ns flux
Synchronizing with [email protected]:<repo>.git
Revision of master to apply is daf1b12
Waiting for daf1b12 to be applied ...
Done.
Macbook Pro:Chapter08 $ kubectl get pods -n example
NAME                   READY STATUS  RESTARTS AGE
frontend-8srpc         1/1   Running 0        24s
frontend-cfrvk         1/1   Running 0        24s
frontend-kk4hj         1/1   Running 0        24s
frontend-vq4vf         1/1   Running 0        24s
thoughts-backend-zz8jw 2/2   Running 0        24s
users-backend-jrvcr    2/2   Running 0        24s

同步需要一点时间,并且您可能会收到一条错误消息,指出它正在克隆 repo:

$ fluxctl sync --k8s-fwd-ns flux
Error: git repository [email protected]:<repo>.git is not ready to sync (status: cloned)
Run 'fluxctl sync --help' for usage

等待几分钟,然后重试:

$ fluxctl sync --k8s-fwd-ns flux
Synchronizing with [email protected]:<repo>.git
Revision of master to apply is daf1b12
Waiting for daf1b12 to be applied ...
Done.
$

您的 Flux 部署以及本地 Kubernetes 集群现在与 Git 中的配置同步,并且会随着任何更改进行更新。

Making a Kubernetes cluster change through GitHub

您的本地 Kubernetes 集群将通过 Flux 更新以反映 Git 存储库中的更改。 Git 中的任何更改都会在几分钟后传播到集群。

让我们通过更新前端部署中的 pod 数量的测试来看看这一点:

  1. Change the Chapter08/example/frontend/deployment.yaml file in your forked repo as described here:
---
apiVersion: apps/v1
kind: Deployment
metadata:
    name: frontend
    labels:
        app: frontend
    namespace: example
spec:
    replicas: 2

这会将副本的数量从 4 更改为 2

  1. Commit the change into the master branch and push into the GitHub repo.
  2. Monitor the cluster with the following command:
$ kubectl get pods -n example -w

几分钟后,您将看到前端 pod 的数量将如何减少。您可以通过手动同步 Flux 来加快速度。

  1. Revert the change and see how they'll be added.
Flux won't delete elements to avoid problems. This means that removing a file of a deployment or service won't eliminate it from the repo. To do so, you need to remove it manually.

You can disable pods controlled by a deployment by setting the number of replicas to zero.

恭喜!您现在拥有一个由 GitHub 存储库控制的集群。

让我们看一下如何在生产环境中有效地使用这种方法的一些想法。

Working in production

GitOps 主要针对生产环境,它比我们在本章中使用的示例本地集群更大更复杂。在本节中,我们将描述如何利用 Git 的优势来提高部署和更改的清晰度,以及如何确保我们在源代码控制下构建不同的文件以避免混淆。

Creating structure

构建 YAML 文件对于大型部署至关重要。从技术上讲,您可以将所有内容合并到一个文件中,但这并不是处理文件增长的最佳方式。 Kubernetes 提供了很大的灵活性,因此请尝试找到适合您的结构。

一个简单的方法是通过命名空间创建子目录,然后通过微服务创建子目录。这就是我们在此示例中构建它的方式。这种结构将相关元素保持在一起,并为接触微服务的任何人提供了清晰的路径。如果部署只影响一个微服务(正如我们在 第 1 章中讨论的那样) , Making the Move – Design, Plan, and Execute,在 Parallel deployment and development speed 部分),这会将更改保留在同一子目录中。

但不要局限于这种结构。如果它对你有意义,你可以尝试不同的东西;例如,按元素进行划分,即一个目录下的所有部署,另一个目录下的所有服务,等等。不要害怕尝试和移动元素,为您的项目寻找最佳结构。

所有这些文件都在 GitHub 中的源代码控制下,这使我们能够利用它们的功能来发挥我们的优势。

Using GitHub features

鉴于任何与主分支的合并都会触发集群中的更改,因此应该在上线之前对其进行审查。

您可以通过要求在合并之前需要批准的拉取请求来做到这一点。批准可以来自专门跟踪集群的 Ops 团队,也可以来自微服务的所有者;例如,团队负责人或经理。

You can enforce code owners natively in GitHub. This means that a change in a particular file or directory requires some user or team to approve it. Check the GitHub documentation for more info ( https://help.github.com/en/articles/about-code-owners).

单个 GitHub 存储库还可以跟踪多个环境,例如,运行测试的暂存环境和可供客户使用的生产环境。您可以按分支或子目录来划分它们。

但是 GitHub 功能并不是唯一可用的,常规的 Git 标签非常通用,允许我们定义要部署的特定容器。

Working with tags

在此示例中,我们使用了图像的 latest 标记。这使用最近构建的容器,每次构建图像​​时都可以更改。对于生产,我们应该使用链接到不可变容器的特定标签,正如我们在 Chapter 3 中讨论的,< em>使用 Docker 构建、运行和测试您的服务,在使用远程注册表部分和第 4 章创建管道和工作流,在 从 Travis CI 推送 Docker 映像 部分。

这意味着替换以下行:

spec:
  containers:
  - name: frontend-service
    image: thoughts_frontend:latest

我们将它们替换为以下内容:

spec:
  containers:
  - name: frontend-service
    image: <registry>/thoughts_frontend:v1.5

这就是能够以受控方式更新图像的亮点。您将使用管道(如 第 4 章中所述,创建管道和工作流) 构建并推送标记的图像到远程注册表,然后您可以控制在集群中部署哪个特定版本。

In some cases, it may be needed to stop the syncing. Flux works with the concept of workloads, which are updateable elements, in the same way as deployments.

You can stop the automatic updating of them or control how they are updated. Refer to the documentation for more information: https://github.com/fluxcd/flux/blob/master/docs/using/fluxctl.md#workloads.

使这个版本在 Git 控制下使开发人员可以轻松地恢复或返回到以前的版本。

要遵循持续集成原则,请尝试进行小的更改并快速应用它们。 Git 将帮助您恢复错误的更改,但小的增量更改很容易测试并降低破坏系统的风险。

大多数操作都是简单的更改——要么更改要部署的映像版本,要么调整参数,例如副本数量或环境变量。

Summary

我们在本章开始时回顾了最常见的不同类型的配置管理策略,以及它们如何随着项目的发展而被应用。我们讨论了 DevOps 方法如何让团队掌握他们的部署并帮助填补开发和运营之间的传统差距。

我们看到了名为 GitOps 的最新方法如​​何与 Kubernetes 集群很好地配合,因为配置被严格描述为一组文件。我们体验了使用 Git 跟踪配置的优势。

我们介绍了 Flux,这是一个部署在集群内部并从 Git 存储库分支中提取更改的工具。我们展示了一个示例配置,将其部署在我们的本地 Kubernetes 集群中,并将 GitHub 配置为能够使用它。这使得任何推送到我们在 GitHub 中的 Git 分支都可以反映在本地集群中。

我们以一些在生产环境中工作的策略结束了这一章。我们着眼于确保 Kubernetes YAML 文件结构正确,利用 GitHub 功能,并学习了如何发布和回滚标记的图像

在下一章中,我们将描述集群的整个开发周期的过程,从引入新功能到将其部署到生产环境中。我们将描述在实时系统中工作时的一些有用策略,以便部署的代码能够顺利运行并具有高质量。

Questions

  1. What is the difference between using a script to push new code to servers and using a configuration management tool such as Puppet?
  2. What is the core idea behind DevOps?
  3. What are the advantages of using GitOps?
  4. Can GitOps only be used in a Kubernetes cluster?
  5. Where is the Flux deployment located?
  6. What do you need to configure in GitHub in order to allow Flux to access it?
  7. For working in production environments, which features does GitHub provide that can help ensure control over deployments?

Further reading