如何使用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 的基础和覆盖 对这些变量配置进行分层,以便您的代码更易于阅读,从而更易于维护。

先决条件

对于本教程,您将需要:

第 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.ymldeployment-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

该文件将指定覆盖的 baseKubernetes 将使用什么策略来修补资源 。 在此示例中,您将指定 strategic-merge-style 补丁 来更新 ConfigMap 和 Deployment 资源。

保存并关闭文件。

最后,将新的 deployment.ymlconfigmap.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】,有兴趣了解更多可以探索。