如何使用Kustomize管理Kubernetes配置
作为 Write for DOnations 计划的一部分,作者选择了 Diversity in Tech Fund 来接受捐赠。
介绍
将应用程序部署到 Kubernetes 有时会感觉很麻烦。 您部署一些 Pods,由 Deployment 支持,可访问性在 Service 中定义。 所有这些资源都需要 YAML 文件才能正确定义和配置。
除此之外,您的应用程序可能需要与数据库通信、管理 Web 内容或设置日志记录的详细程度。 此外,这些参数可能需要根据您要部署的环境而有所不同。 所有这些都可能导致 YAML 定义的代码库变得庞大,每个定义都有难以确定的一行或两行更改。
Kustomize 是一种开源配置管理工具,旨在帮助解决这些问题。 从 Kubernetes 1.14 开始,kubectl 完全支持 Kustomize 和 kustomization 文件。
在本指南中,您将构建一个小型 Web 应用程序,然后使用 Kustomize 来管理您的配置蔓延。 您将应用程序部署到具有不同配置的开发和生产环境中。 您还将使用 Kustomize 的基础和覆盖 对这些变量配置进行分层,以便您的代码更易于阅读,从而更易于维护。
先决条件
对于本教程,您将需要:
- 一个 Kubernetes 1.14+ 集群,您的连接配置设置为
kubectl
默认值。 要在 DigitalOcean 上创建 Kubernetes 集群,请阅读我们的 Kubernetes 快速入门 。 要连接到集群,请阅读 如何连接到 DigitalOcean Kubernetes 集群。 kubectl
安装在您的本地计算机上。 按照 this tutorial on getting started with Kubernetes: A kubectl Cheat Sheet 进行安装。
第 1 步——在没有 Kustomize 的情况下部署您的应用程序
在使用 Kustomize 部署您的应用程序之前,您将首先以更传统的方式部署它。 在这种情况下,您将部署 sammy-app
的开发版本——托管在 Nginx 上的静态 Web 应用程序。 您将 Web 内容作为数据存储在 ConfigMap 中,您将在 Deployment 中将其挂载到 Pod 上。 其中每一个都需要一个单独的 YAML 文件,您现在将创建该文件。
首先,为您的应用程序及其所有配置文件创建一个文件夹。 您将在此处运行本教程中的所有命令。
在您的主目录中创建一个新文件夹并在其中导航:
mkdir ~/sammy-app && cd ~/sammy-app
现在使用您喜欢的文本编辑器创建并打开一个名为 configmap.yml
的文件:
nano configmap.yml
添加以下内容:
~/sammy-app/configmap.yml
--- apiVersion: v1 kind: ConfigMap metadata: name: sammy-app namespace: default data: body: > <html> <style> body { background-color: #222; } p { font-family:"Courier New"; font-size:xx-large; color:#f22; text-align:center; } </style> <body> <p>DEVELOPMENT</p> </body> </html>
该规范创建了一个新的 ConfigMap 对象。 您将其命名为 sammy-app
并将一些 HTML 网页内容保存在 data:
中。
保存并关闭文件。
现在创建并打开另一个名为 deployment.yml
的文件:
nano deployment.yml
添加以下内容:
~/sammy-app/deployment.yml
--- apiVersion: apps/v1 kind: Deployment metadata: name: sammy-app namespace: default labels: app: sammy-app spec: replicas: 1 selector: matchLabels: app: sammy-app template: metadata: labels: app: sammy-app spec: containers: - name: server image: nginx:1.17 volumeMounts: - name: sammy-app mountPath: /usr/share/nginx/html ports: - containerPort: 80 protocol: TCP resources: requests: cpu: 100m memory: "128M" limits: cpu: 100m memory: "256M" env: - name: LOG_LEVEL value: "DEBUG" volumes: - name: sammy-app configMap: name: sammy-app items: - key: body path: index.html
该规范创建了一个新的部署对象。 您正在添加 sammy-app
的名称和标签,将副本数设置为 1
,并指定要使用 Nginx 1.17 版容器映像的对象。 您还将容器的端口设置为 80
,定义 CPU 和内存请求和限制,并将日志记录级别设置为 DEBUG
。
保存并关闭文件。
现在将这两个文件部署到您的 Kubernetes 集群。 要从标准输入创建多个对象,请将 cat 命令通过管道传输到 kubectl:
cat configmap.yml deployment.yml | kubectl apply -f -
稍等片刻,然后使用 kubectl
检查您的应用程序的状态:
kubectl get pods -l app=sammy-app
您最终会在 READY
列中看到一个运行您的应用程序的 Pod 和 1/1
容器:
OutputNAME READY STATUS RESTARTS AGE sammy-app-56bbd86cc9-chs75 1/1 Running 0 8s
您的 Pod 正在运行并由 Deployment 支持,但您仍然无法访问您的应用程序。 首先,您需要添加一个服务。
创建并打开名为 service.yml
的第三个 YAML 文件:
nano service.yml
添加以下内容:
~/sammy-app/service.yml
--- apiVersion: v1 kind: Service metadata: name: sammy-app labels: app: sammy-app spec: type: LoadBalancer ports: - name: sammy-app-http port: 80 protocol: TCP targetPort: 80 selector: app: sammy-app
该规范创建了一个名为 sammy-app
的新服务对象。 对于大多数云提供商,将 spec.type 设置为 LoadBalancer 将提供负载均衡器 。 例如,DigitalOcean 托管 Kubernetes (DOKS) 将提供 DigitalOcean LoadBalancer 以使您的应用程序可用于 Internet。 spec.ports
将针对任何带有 sammy-app
标签的 Pod 的 TCP
端口 80
。
保存并关闭文件。
现在将服务部署到您的 Kubernetes 集群:
kubectl apply -f service.yml
稍等片刻,然后使用 kubectl
检查您的应用程序的状态:
kubectl get services -w
最终,在 EXTERNAL-IP
列下会为您的服务显示一个公共 IP。 your_external_ip
的地方会出现一个唯一的IP:
OutputNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.245.0.1 <none> 443/TCP 7h26m sammy-app LoadBalancer 10.245.186.235 <pending> 80:30303/TCP 65s sammy-app LoadBalancer 10.245.186.235 your_external_ip 80:30303/TCP 2m29s
复制出现的 IP 地址并将其输入您的网络浏览器。 您将看到应用程序的 DEVELOPMENT
版本。
在您的终端上,输入 CTRL + C
以停止观看您的服务。
在这一步中,您将 sammy-app
的开发版本部署到 Kubernetes。 在第 2 步和第 3 步中,您将使用 Kustomize 重新部署 sammy-app
的开发版本,然后部署配置略有不同的生产版本。 使用这个新的工作流程,您将看到 Kustomize 管理配置更改和简化开发工作流程的能力。
第 2 步 — 使用 Kustomize 部署您的应用程序
在此步骤中,您将部署完全相同的应用程序,但采用 Kustomize 期望的形式,而不是默认的 Kubernetes 方式。
您的文件系统当前如下所示:
sammy-app/ ├── configmap.yml ├── deployment.yml └── service.yml
要使用 Kustomize 部署此应用程序,您需要添加一个文件 kustomization.yml
。 现在就这样做:
nano kustomization.yml
至少,此文件应指定使用 -k 选项运行 kubectl
时要管理的资源,这将指示 kubectl 处理 kustomization 文件 。
添加以下内容:
~/sammy-app/kustomization.yml
--- resources: - configmap.yml - deployment.yml - service.yml
保存并关闭文件。
现在,在再次部署之前,从步骤 1 中删除现有的 Kubernetes 资源:
kubectl delete deployment/sammy-app service/sammy-app configmap/sammy-app
并再次部署它们,但这次使用 Kustomize:
kubectl apply -k .
无需向 kubectl
提供 -f
选项来指导 Kubernetes 从文件创建资源,而是提供 -k
和目录(在本例中为 .
表示当前目录)。 这指示 kubectl
使用 Kustomize 并检查该目录的 kustomization.yml
。
这将创建所有三个资源:ConfigMap、Deployment 和 Service。 使用 get pods
命令检查您的部署:
kubectl get pods -l app=sammy-app
您将再次在 READY
列中看到一个正在运行您的应用程序的 Pod 和 1/1
容器。
现在重新运行 get services
命令。 您还将通过可公开访问的 EXTERNAL-IP
看到您的服务:
kubectl get services -l app=sammy-app
您现在已成功使用 Kustomize 来管理您的 Kubernetes 配置。 在下一步中,您将使用稍微不同的配置将 sammy-app
部署到生产环境。 您还将使用 Kustomize 来管理这些差异。
第 3 步 — 使用 Kustomize 管理应用程序差异
一旦您开始处理多种资源类型,Kubernetes 资源的配置文件就会真正开始蔓延,尤其是当环境之间存在微小差异时(例如,开发与生产)。 您可能有 deployment-development.yml
和 deployment-production.yml
而不仅仅是 deployment.yml
。 您的所有其他资源的情况也可能类似。
想象一下当一个新版本的 Nginx Docker 镜像发布并且你想开始使用它时会发生什么。 也许您在 deployment-development.yml
中测试了新版本并想继续,但是您忘记用新版本更新 deployment-production.yml
。 突然之间,您在开发中运行的 Nginx 版本与您在生产中运行的版本不同。 像这样的小配置错误会很快破坏您的应用程序。
Kustomize 可以大大简化这些管理问题。 请记住,您现在拥有一个包含 Kubernetes 配置文件和 kustomization.yml
的文件系统:
sammy-app/ ├── configmap.yml ├── deployment.yml ├── kustomization.yml └── service.yml
想象一下,您现在已准备好将 sammy-app
部署到生产环境。 您还决定您的应用程序的生产版本将在以下方面与其开发版本不同:
replicas
将从1
增加到3
。- 容器资源
requests
将从100m
CPU 和128M
内存增加到250m
CPU 和256M
内存。 - 容器资源
limits
将从100m
CPU 和256M
内存增加到1
CPU 和1G
内存。 LOG_LEVEL
环境变量将从DEBUG
更改为INFO
。- ConfigMap 数据将更改以显示略有不同的 Web 内容。
首先,创建一些新目录来以更特定于 Kustomize 的方式组织事物:
mkdir base
这将保存你的“默认”配置——你的 base。 在您的示例中,这是 sammy-app
的开发版本。
现在将 sammy-app/
中的当前配置移动到此目录中:
mv configmap.yml deployment.yml service.yml kustomization.yml base/
然后为您的生产配置创建一个新目录。 Kustomize 将此称为叠加层。 将叠加层视为基础之上的层——它们总是需要一个基础才能发挥作用:
mkdir -p overlays/production
创建另一个 kustomization.yml
文件来定义您的生产覆盖:
nano overlays/production/kustomization.yml
添加以下内容:
~/sammy-app/overlays/production/kustomization.yml
--- bases: - ../../base patchesStrategicMerge: - configmap.yml - deployment.yml
该文件将指定覆盖的 base
和 Kubernetes 将使用什么策略来修补资源 。 在此示例中,您将指定 strategic-merge-style 补丁 来更新 ConfigMap 和 Deployment 资源。
保存并关闭文件。
最后,将新的 deployment.yml
和 configmap.yml
文件添加到 overlays/production/
目录中。
首先新建deployment.yml
文件:
nano overlays/production/deployment.yml
将以下内容添加到您的文件中。 突出显示的部分表示您的开发配置的更改:
~/sammy-app/overlays/production/deployment.yml
--- apiVersion: apps/v1 kind: Deployment metadata: name: sammy-app namespace: default spec: replicas: 3 template: spec: containers: - name: server resources: requests: cpu: 250m memory: "256M" limits: cpu: 1 memory: "1G" env: - name: LOG_LEVEL value: "INFO"
注意这个新的 deployment.yml
的内容。 它仅包含 TypeMeta
字段,用于标识已更改的资源(在本例中为应用程序的部署),以及足够的剩余字段以进入嵌套结构以指定新字段值,例如,容器资源请求和限制。
保存并关闭文件。
现在为您的生产叠加创建一个新的 configmap.yml
:
nano /overlays/production/configmap.yml
添加以下内容:
~/sammy-app/overlays/production/configmap.yml
--- apiVersion: v1 kind: ConfigMap metadata: name: sammy-app namespace: default data: body: > <html> <style> body { background-color: #222; } p { font-family:"Courier New"; font-size:xx-large; color:#22f; text-align:center; } </style> <body> <p>PRODUCTION</p> </body> </html>
此处您已将文本更改为显示 PRODUCTION
而不是 DEVELOPMENT
。 请注意,您还将文本颜色从红色调 #f22
更改为蓝色调 #22f
。 考虑一下,如果您不使用 Kustomize 之类的配置管理工具,定位和跟踪这些微小的更改会有多困难。
您的目录结构现在如下所示:
sammy-app/ ├── base │ ├── configmap.yml │ ├── deployment.yml │ ├── kustomization.yml │ └── service.yml └── overlays └── production ├── configmap.yml ├── deployment.yml └── kustomization.yml
您已准备好使用基本配置进行部署。 首先,删除现有资源:
kubectl delete deployment/sammy-app service/sammy-app configmap/sammy-app
将您的基本配置部署到 Kubernetes:
kubectl apply -k base/
检查您的部署:
kubectl get pods,services -l app=sammy-app
您将看到预期的基本配置,在服务的 EXTERNAL-IP
上可以看到开发版本:
OutputNAME READY STATUS RESTARTS AGE pod/sammy-app-5668b6dc75-rwbtq 1/1 Running 0 21s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/sammy-app LoadBalancer 10.245.110.172 your_external_ip 80:31764/TCP 7m43s
现在部署您的生产配置:
kubectl apply -k overlays/production/
再次检查您的部署:
kubectl get pods,services -l app=sammy-app
您将看到预期的 production
配置,生产版本在服务的 EXTERNAL-IP
上可见:
OutputNAME READY STATUS RESTARTS AGE pod/sammy-app-86759677b4-h5ndw 1/1 Running 0 15s pod/sammy-app-86759677b4-t2dml 1/1 Running 0 17s pod/sammy-app-86759677b4-z56f8 1/1 Running 0 13s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/sammy-app LoadBalancer 10.245.110.172 your_external_ip 80:31764/TCP 8m59s
请注意,在生产配置中,总共有 3 个 Pod,而不是 1 个。 您可以查看部署资源以确认不太明显的更改也已生效:
kubectl get deployments -l app=sammy-app -o yaml
在浏览器中访问 your_external_ip
以查看您网站的生产版本。
您现在正在使用 Kustomize 来管理应用程序差异。 回想一下您最初的问题之一,如果您现在想更改 Nginx 映像版本,您只需要修改基础中的 deployment.yml
,并且使用该基础的叠加层也将通过 Kustomize 接收该更改. 这极大地简化了您的开发工作流程,提高了可读性,并降低了出错的可能性。
结论
在本教程中,您构建了一个小型 Web 应用程序并将其部署到 Kubernetes。 然后,您使用 Kustomize 来简化对不同环境的应用程序配置的管理。 您将一组几乎重复的 YAML 文件重新组织成一个分层模型。 这将减少错误,减少手动配置,并使您的工作更加可识别和可维护。
然而,这只是触及 Kustomize 提供的表面。 有【X10X】数十个官方示例【X41X】和大量【X61X】深度技术文档【X97X】,有兴趣了解更多可以探索。