如何使用 Kustomize 管理您的 Kubernetes 配置

作者选择了技术多样性基金来接受捐赠,作为Write for DOnations计划的一部分。

介绍

将应用程序部署到 Kubernetes 有时会感觉很麻烦。您部署了一些Pod,由Deployment支持,在Service 中定义了可访问性所有这些资源都需要YAML文件才能正确定义和配置。

最重要的是,您的应用程序可能需要与数据库通信、管理 Web 内容或设置日志记录详细程度。此外,根据您要部署到的环境,这些参数可能需要有所不同。所有这些都可能导致 YAML 定义的庞大代码库,每个代码库都有难以确定的一行或两行更改。

Kustomize是一种开源配置管理工具,旨在帮助解决这些问题。从 Kubernetes 1.14 开始,kubectl完全支持 Kustomize 和kustomizationfiles

在本指南中,您将构建一个小型 Web 应用程序,然后使用 Kustomize 管理您的配置蔓延。您将应用程序部署到具有不同配置的开发和生产环境。您还将使用Kustomize 的基础和覆盖层对这些变量配置进行分层,以便您的代码更易于阅读,从而更易于维护。

先决条件

对于本教程,您将需要:

第 1 步 – 在没有 Kustomize 的情况下部署您的应用程序

在使用 Kustomize 部署您的应用程序之前,您将首先更传统地部署它。在这种情况下,您将部署一个开发版本——sammy-app一个托管在Nginx上的静态 Web 应用程序您将您的 Web 内容作为数据存储在ConfigMap 中,您将在部署中将其安装在 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

该规范创建了一个新的 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/1READY列中看到一个运行着您的应用程序和容器的Pod

Output
NAME READY STATUS RESTARTS AGE sammy-app-56bbd86cc9-chs75 1/1 Running 0 8s

您的 Pod 正在运行并由 Deployment 提供支持,但您仍然无法访问您的应用程序。首先,您需要添加一个服务。

创建并打开名为 的第三个 YAML 文件service.yml

  • 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.typeLoadBalancer将提供负载均衡器例如,DigitalOcean Managed Kubernetes (DOKS)将提供DigitalOcean LoadBalancer以使您的应用程序可用于 Internet。spec.ports将为带有标签的任何 Pod定位TCP端口80sammy-app

保存并关闭文件。

现在将服务部署到您的 Kubernetes 集群:

  • kubectl apply -f service.yml

稍等片刻,然后使用kubectl来检查您的应用程序的状态:

  • kubectl get services -w

最终,您的服务的公共 IP 将出现在EXTERNAL-IP列下。一个唯一的 IP 将出现在以下位置your_external_ip

Output
NAME 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应用程序版本。

正在开发中的 sammy-app

在您的终端中,键入CTRL + C以停止观看您的服务。

在此步骤中,您部署了sammy-appKubernetes的开发版本在第 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选项kubectlkustomization运行时要管理的资源,该选项将直接处理文件

添加以下内容:

~/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 .

相反提供的-f,以选择kubectl直接Kubernetes从文件创建资源,您提供-k和目录(在这种情况下,.表示当前目录)。这指示kubectl使用 Kustomize 并检查该目录的kustomization.yml.

这将创建所有三个资源:ConfigMap、部署和服务。使用get pods命令检查您的部署:

  • kubectl get pods -l app=sammy-app

您将再次1/1READY列中看到一个 Pod 正在运行您的应用程序和容器

现在重新运行get services命令。您还将看到您的服务具有可公开访问的EXTERNAL-IP

  • kubectl get services -l app=sammy-app

您现在已成功使用 Kustomize 来管理您的 Kubernetes 配置。在下一步中,您将使用sammy-app稍微不同的配置部署到生产环境。您还将使用 Kustomize 来管理这些差异。

第 3 步 — 使用 Kustomize 管理应用程序差异

一旦您开始处理多种资源类型,Kubernetes 资源的配置文件就会真正开始蔓延,尤其是当环境之间存在微小差异时(例如开发与生产)。您可能有一个deployment-development.ymlanddeployment-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将增加13
  • 容器资源requests会从100mCPU 和128M内存增加到250mCPU 和256M内存。
  • 容器资源limits会从100mCPU 和256M内存增加到1CPU 和1G内存。
  • LOG_LEVEL环境变量将更改DEBUGINFO
  • 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

添加以下内容:

~/sammy-app/overlays/production/kustomization.yml
---
bases:
- ../../base
patchesStrategicMerge:
- configmap.yml
- deployment.yml

该文件将为base覆盖指定 a以及Kubernetes 将使用什么策略来修补资源在此示例中,您将指定一个战略合并样式补丁来更新 ConfigMap 和部署资源。

保存并关闭文件。

最后,将 newdeployment.ymlconfigmap.ymlfiles添加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

Output
NAME 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在服务上可以看到生产版本

Output
NAME 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在浏览器中访问以查看您网站的生产版本。

生产中的 sammy-app

您现在正在使用 Kustomize 来管理应用程序差异。回想一下您最初的问题之一,如果您现在想要更改 Nginx 映像版本,您只需要deployment.yml在基础中进行修改,使用该基础的叠加层也将通过 Kustomize 接收更改。这大大简化了您的开发工作流程,提高了可读性,并降低了出错的可能性。

结论

在本教程中,您构建了一个小型 Web 应用程序并将其部署到 Kubernetes。然后,您使用 Kustomize 简化了对不同环境的应用程序配置的管理。您将一组几乎重复的 YAML 文件重组为一个分层模型。这将减少错误,减少手动配置,并使您的工作更易于识别和维护。

然而,这仅仅触及了 Kustomize 提供的表面。几十个官方的例子和大量的深入的技术文档,探讨,如果你有兴趣学习更多。

觉得文章有用?

点个广告表达一下你的爱意吧 !😁