Kubernetes 中部署应用程序的最佳实践

Kubernetes 是一种用于容器编排和管理的开源平台,已成为当今最流行的容器编排工具之一。Kubernetes 使得部署、扩展和管理容器化应用程序变得更加容易和高效。在本文中,我们将讨论 Kubernetes 中部署应用程序的最佳实践,以帮助您在生产环境中部署 Kubernetes 应用程序。

前置要求

在进入最佳实践之前,我们需要了解一些 Kubernetes 中的概念和组件。以下是一些必需的前置知识:

  • Kubernetes 集群:由一组工作节点(工作负载的容器实例运行的计算机)和一个控制平面(管理和协调工作节点的组件)组成的一组主机。
  • Pod:Kubernetes 中最小的部署单元,它由一个或多个容器组成。
  • Deployment:管理 Pod 的声明性对象,确保 Pod 按照定义的方式运行,并且可以方便地进行升级和回滚。
  • Service:将应用程序暴露在集群内或者集群外,使得其他应用程序或者用户可以访问应用程序。
  • ConfigMap:一个 Kubernetes 对象,用于将应用程序配置从容器镜像中分离出来。

最佳实践

现在,我们来探讨一些 Kubernetes 中部署应用程序的最佳实践。

1. 使用声明式部署

在 Kubernetes 中,您可以以编程方式或者声明式方式进行部署。推荐的方法是使用声明式部署。

声明性部署的好处有:

  • 快速而精确的部署
  • 可重复性 — 将部署的“状态”保存在版本控制系统中,这样您就可以在需要时回滚
  • 易于理解 — 部署从 YAML 或 JSON 文件中完成,可以轻松阅读和理解。

以下是一个简单的声明式 YAML 文件示例。

----------- -------
----- ----------
---------
  ----- ----------
-----
  --------- -
  ---------
    ------------
      ---- ----------
  ---------
    ---------
      -------
        ---- ----------
    -----
      -----------
      - ----- ----------
        ------ ------------------------------------
        ------
        - -------------- ----
        --------
        - -------------
            ----- -----------------

在上面的示例中,我们定义了一个名为 sample-app 的 Deployment,它由三个 Pod 组成,并使用容器镜像 mydockerhubaccount/sample-app:latest 运行。此镜像将公开端口 8080,并从 ConfigMap 中读取应用程序配置。

2. 持久化数据

在 Kubernetes 中,Pod 中的容器是临时的,它们可以随时终止和重启。因此,如果应用程序具有需要持久化的数据,则应将这些数据存储在 Kubernetes 集群之外的存储中。

Kubernetes 支持各种类型的持久化存储,如 NFS、iSCSI、Ceph 等。您可以使用 PersistentVolumeClaim(PVC)来声明需要的存储卷,Kubernetes 将 PVC 匹配到存储卷中,并将其分配给 Pod。

以下是一个简单的 PVC 示例。

----------- --
----- ---------------------
---------
  ----- -------------
-----
  ------------
  - -------------
  ----------
    ---------
      -------- ---

在上例中,我们定义了一个名称为 my-data-pvc-1 的 PVC,请求 1GB 存储容量,读写访问权限为 ReadWriteOnce

将此 PVC 应用于 Deployment,示例如下所述。

----------- -------
----- ----------
---------
  ----- ----------
-----
  --------- -
  ---------
    ------------
      ---- ----------
  ---------
    ---------
      -------
        ---- ----------
    -----
      -----------
      - ----- ----------
        ------ ------------------------------------
        ------
        - -------------- ----
        -------------
        - ----- -----------
          ---------- -----
      --------
      - ----- -----------
        ----------------------
          ---------- -------------

使用以上示例,我们定义了一个名为 data-volume 的持久化数据卷,并将其应用于 sample-app 中。

3. 禁止使用 root 用户

在容器编排中,最佳实践之一是限制容器内的进程只能使用非特权用户。由于容器内的进程对整个宿主机具有完全控制权,若容器发生被入侵等安全问题,攻击者可以轻松地对主机上的进程进行恶意操作。

为了避免此类问题,建议通过设置显式的 USER 指令或开启 USER Namespaces,禁止使用 root 用户在容器中运行应用程序。

以下是一个 Dockerfile 示例,其中示例容器镜像使用的是 node

---- -----------
--- ------- ------------------- ------- -- ------
---- ------

在上述示例中,我们创建了一个名为 myuser 的非特权用户,并使用此用户运行应用程序。

4. 应用程序配置分离

将应用程序配置从容器镜像中分离出来是一种最佳部署实践。这是因为应用程序配置通常与镜像本身不同,例如数据库凭据等,并且应该由运行应用程序的 Kubernetes 集群的管理员管理。

可以将应用程序配置存储在 ConfigMap 中,并通过挂载 ConfigMap 到 Pod 中,向应用程序提供配置信息。

以下是一个 ConfigMap 示例。

----------- --
----- ---------
---------
  ----- -----------------
-----
  ------------ --------------
  ------------ ------
  ------------ ----------
  --------- ------

在上述示例中,我们定义了一个 ConfigMap,包含数据库的连接相关信息和应用程序使用的端口。

将 ConfigMap 应用于 Deployment,示例如下所述。

----------- -------
----- ----------
---------
  ----- ----------
-----
  --------- -
  ---------
    ------------
      ---- ----------
  ---------
    ---------
      -------
        ---- ----------
    -----
      -----------
      - ----- ----------
        ------ ------------------------------------
        ------
        - -------------- ----
        --------
        - -------------
            ----- -----------------

在上述示例中,我们将 sample-app Deployment 修改为从 ConfigMap 中读取配置。

5. 使用亲和性和反亲和性

亲和性和反亲和性是 Kubernetes 实现 Pod 弹性伸缩的强大工具。您可以使用它们来控制 Pod 如何调度在 Kubernetes 集群中的节点上,并确保相关的 Pod 能够完全利用一组节点的资源。

亲和性限制了在默认情况下不同 Deployment 的 Pod 不会调度到相同的节点上。反亲和性表达相同的想法,但是实现起来有所不同。使用反亲和规则时,您可以确保同一 Deployment 的 Pod 不会被调度到相同的节点上。

以下是一个示例,给予示例的 dbapp Deployment 的 Pods 分别定义了相同和不同的亲和特性。

----------- -------
----- ----------
---------
  ----- --
-----
  --------- -
  ---------
    ------------
      ---- --
  ---------
    ---------
      -------
        ---- --
    -----
      ---------
        ------------
          -----------------------------------------------
          - --------------
              -----------------
              - ---- ---
                --------- --
                -------
                - --
            ------------ ------------------------
      -----------
      - ----- --
        ------ ----------------------------
---
----------- -------
----- ----------
---------
  ----- ---
-----
  --------- -
  ---------
    ------------
      ---- ---
  ---------
    ---------
      -------
        ---- ---
    -----
      ---------
        ----------------
          -----------------------------------------------
          - --------------
              -----------------
              - ---- ---
                --------- --
                -------
                - ---
            ------------ ------------------------
      -----------
      - ----- ---
        ------ -----------------------------
        ------
        - -------------- ----
        --------
        - -------------
            ----- ----------

在上面的示例中,db Deployment 定义了 podAffinity,以确保在同一节点上只调度具有相同标签 app=db 或逻辑上相同的 Pod。相反,app Deployment 定义了 podAntiAffinity,以确保同一 Deployment 的 Pod 不会被调度到相同的节点上。

结论

本文介绍了 Kubernetes 中部署应用程序的一些最佳实践。我们建议您始终使用声明式部署、持久化存储、非特权用户、应用程序配置的分离以及亲和性和反亲和性。按照这些最佳实践来开发和维护 Kubernetes 应用程序,可以让您的应用程序更加灵活和高效。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/672afbaaddd3a70eb6d14be3