作者选择了技术多样性基金来接受捐赠,作为Write for DOnations计划的一部分。
介绍
将应用程序部署到 Kubernetes 有时会感觉很麻烦。您部署了一些Pod,由Deployment支持,在Service 中定义了可访问性。所有这些资源都需要YAML文件才能正确定义和配置。
最重要的是,您的应用程序可能需要与数据库通信、管理 Web 内容或设置日志记录详细程度。此外,根据您要部署到的环境,这些参数可能需要有所不同。所有这些都可能导致 YAML 定义的庞大代码库,每个代码库都有难以确定的一行或两行更改。
Kustomize是一种开源配置管理工具,旨在帮助解决这些问题。从 Kubernetes 1.14 开始,kubectl
完全支持 Kustomize 和kustomization
files。
在本指南中,您将构建一个小型 Web 应用程序,然后使用 Kustomize 管理您的配置蔓延。您将应用程序部署到具有不同配置的开发和生产环境。您还将使用Kustomize 的基础和覆盖层对这些变量配置进行分层,以便您的代码更易于阅读,从而更易于维护。
先决条件
对于本教程,您将需要:
- Kubernetes 1.14+ 集群,将您的连接配置设置为
kubectl
默认值。要在 DigitalOcean 上创建 Kubernetes 集群,请阅读我们的Kubernetes 快速入门。要连接到集群,请阅读如何连接到 DigitalOcean Kubernetes 集群。 kubectl
安装在本地机器上。按照本教程开始使用 Kubernetes:kubectl
安装备忘单。
第 1 步 – 在没有 Kustomize 的情况下部署您的应用程序
在使用 Kustomize 部署您的应用程序之前,您将首先更传统地部署它。在这种情况下,您将部署一个开发版本——sammy-app
一个托管在Nginx上的静态 Web 应用程序。您将您的 Web 内容作为数据存储在ConfigMap 中,您将在部署中将其安装在 Pod 上。每一个都需要一个单独的 YAML 文件,您现在将创建该文件。
首先,为您的应用程序及其所有配置文件创建一个文件夹。您将在此处运行本教程中的所有命令。
在您的主目录中创建一个新文件夹并在其中导航:
- mkdir ~/sammy-app && cd ~/sammy-app
现在使用您喜欢的文本编辑器创建并打开一个名为 的文件configmap.yml
:
- nano 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
添加以下内容:
---
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
该规范创建了一个新的 Deployment 对象。您正在添加 的名称和标签sammy-app
,将副本数设置为1
,并指定对象以使用 Nginx 1.17 版容器映像。您还将容器的端口设置为80
,定义 cpu 和内存请求和限制,并将日志记录级别设置为DEBUG
。
保存并关闭文件。
现在将这两个文件部署到您的 Kubernetes 集群。要从 中创建多个对象stdin
,请将cat
命令通过管道传输到kubectl
:
- cat configmap.yml deployment.yml | kubectl apply -f -
稍等片刻,然后使用kubectl
来检查您的应用程序的状态:
- kubectl get pods -l app=sammy-app
您最终将1/1
在READY
列中看到一个运行着您的应用程序和容器的Pod :
OutputNAME READY STATUS RESTARTS AGE
sammy-app-56bbd86cc9-chs75 1/1 Running 0 8s
您的 Pod 正在运行并由 Deployment 提供支持,但您仍然无法访问您的应用程序。首先,您需要添加一个服务。
创建并打开名为 的第三个 YAML 文件service.yml
:
- nano 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 Managed Kubernetes (DOKS)将提供DigitalOcean LoadBalancer以使您的应用程序可用于 Internet。spec.ports
将为带有标签的任何 Pod定位TCP
端口。80
sammy-app
保存并关闭文件。
现在将服务部署到您的 Kubernetes 集群:
- kubectl apply -f service.yml
稍等片刻,然后使用kubectl
来检查您的应用程序的状态:
- kubectl get services -w
最终,您的服务的公共 IP 将出现在EXTERNAL-IP
列下。一个唯一的 IP 将出现在以下位置your_external_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 地址并将其输入到您的 Web 浏览器中。您将看到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
至少,此文件应指定kubectl
使用-k
选项kubectl
kustomization
运行时要管理的资源,该选项将直接处理文件。
添加以下内容:
---
resources:
- configmap.yml
- deployment.yml
- service.yml
保存并关闭文件。
现在,在再次部署之前,从步骤 1 中删除现有的 Kubernetes 资源:
- kubectl delete deployment/sammy-app service/sammy-app configmap/sammy-app
并再次部署它们,但这次使用 Kustomize:
- kubectl apply -k .
相反提供的-f
,以选择kubectl
直接Kubernetes从文件创建资源,您提供-k
和目录(在这种情况下,.
表示当前目录)。这指示kubectl
使用 Kustomize 并检查该目录的kustomization.yml
.
这将创建所有三个资源:ConfigMap、部署和服务。使用get pods
命令检查您的部署:
- kubectl get pods -l app=sammy-app
您将再次1/1
在READY
列中看到一个 Pod 正在运行您的应用程序和容器。
现在重新运行get services
命令。您还将看到您的服务具有可公开访问的EXTERNAL-IP
:
- kubectl get services -l app=sammy-app
您现在已成功使用 Kustomize 来管理您的 Kubernetes 配置。在下一步中,您将使用sammy-app
稍微不同的配置部署到生产环境。您还将使用 Kustomize 来管理这些差异。
第 3 步 — 使用 Kustomize 管理应用程序差异
一旦您开始处理多种资源类型,Kubernetes 资源的配置文件就会真正开始蔓延,尤其是当环境之间存在微小差异时(例如开发与生产)。您可能有一个deployment-development.yml
anddeployment-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
这将保存您的“默认”配置——您的基础. 在您的示例中,这是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
添加以下内容:
---
bases:
- ../../base
patchesStrategicMerge:
- configmap.yml
- deployment.yml
该文件将为base
覆盖指定 a以及Kubernetes 将使用什么策略来修补资源。在此示例中,您将指定一个战略合并样式补丁来更新 ConfigMap 和部署资源。
保存并关闭文件。
最后,将 newdeployment.yml
和configmap.yml
files添加到overlays/production/
目录中。
首先创建新deployment.yml
文件:
- nano 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
添加以下内容:
---
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 提供的表面。有几十个官方的例子和大量的深入的技术文档,探讨,如果你有兴趣学习更多。