十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Kubernetes StatefulSet 与 Deployment 对比实战:从 YAML 到有状态应用的部署选型

Kubernetes StatefulSet 与 Deployment 对比实战:从 YAML 到有状态应用的部署选型 Kubernetes StatefulSet 与 Deployment 对比实战从 YAML 到有状态应用的部署选型【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine导读本文以 Kubernetes 中两种最常用的工作负载资源为切入点系统对比 Deployment 与 StatefulSet 在副本管理、存储、扩缩容与更新策略上的本质差异并结合本仓库refine 文档站点中真实存在的 Helm/Deployment 配置以及一套完整的 MySQL 有状态应用实战 YAML帮助你在实际项目中做出正确的资源选型何时用 Deployment 管理无状态应用何时用 StatefulSet 承载数据库等有状态应用以及部署过程中可能遇到哪些典型错误。读完本文你将能够独立编写、应用并验证这两类资源的 YAML 清单。为什么需要区分 Deployment 与 StatefulSetKubernetes 为部署和管理容器化应用提供了强大的能力而 Deployment 与 StatefulSet 是其中最重要的两个工作负载控制器。二者都在扮演管理应用副本的关键角色却服务于截然不同的需求与场景Deployment面向无状态stateless应用。此类应用的每个实例本质上完全相同、可互相替换例如 Web 服务器、API 后端。StatefulSet面向有状态stateful应用。此类应用要求稳定的、唯一的网络标识与持久化存储例如数据库、消息队列。理解这两类资源的差异是决定什么时候、用什么方式部署的核心前提。下面分别深入讲解。什么是 DeploymentDeployment 用于创建并管理应用副本它能够无缝地更新应用并在出问题时快速回滚。应用借助 Deployment 可以获得高可用并且很容易进行水平扩缩容与负载均衡。Deployment 的核心特性按需扩缩容Demand-based scaling可根据负载自动或手动增加、减少运行中的实例数量。滚动发布与回滚Rollout and Rollback在不停机的情况下平滑发布新版本或回退到之前的版本。自愈Auto-healing当某个 Pod 失败或被删除时Deployment 会自动替换它以维持期望状态desired state。更新策略Update Strategy可以选择同时更新所有副本也可以采用滚动更新逐步替换以最小化对服务的扰动。一个 Deployment 配置示例下面是一个最简单的 Deployment 配置。它定义了一个管理 3 个 nginx 应用副本的 DeploymentapiVersion: apps/v1 kind: Deployment metadata: name: proxy-deployment spec: replicas: 3 selector: matchLabels: app: proxy template: metadata: labels: app: proxy spec: containers: - name: nginx image: nginx:1.14.2 ports: - containerPort: 80逐字段解读这个 YAMLapiVersion指定所使用的 Kubernetes API 版本此处为apps/v1。kind声明资源类型为Deployment。metadata为 Deployment 提供名称和标签用于标识该对象。spec.replicas期望的副本数量这里是 3。selector通过matchLabels选择该 Deployment 管理的 Pod。template描述 Pod 副本应如何构建包括容器镜像与端口。仓库中的真实 Deploymentrefine 文档站点的 Helm 模板本仓库中 documentation/k8s/refine-documentation/templates/deployment.yaml 就是一个生产形态的 Deployment 模板它展示了上述概念在真实项目中的落地方式replicas由values.yaml中的replicaCount注入默认 1并且在启用自动扩缩容autoscaling.enabled时不再显式声明副本数而是交给 HPA 接管见 documentation/k8s/refine-documentation/templates/hpa.yaml。容器定义了 HTTP 端口、livenessProbe与readinessProbe探针这是无状态 Deployment 的标准健康检查配置。镜像地址与拉取策略image.pullPolicy通过 documentation/k8s/refine-documentation/values.yaml 配置默认仓库为ghcr.io/refinedev/refine/refine-documentation。支持nodeSelector、affinity、tolerations等调度约束均为 Deployment 模板中的可选字段。这说明对 Web 前端、API 等无状态服务Deployment 是默认且推荐的工作负载类型配合 HPA 即可实现按 CPU/内存利用率的自动伸缩。什么是 StatefulSet设想一个电商应用场景你需要维护购物车与会话session的状态就必须有某种方式持久化数据和状态。此时 StatefulSet 登场——它确保每个 Pod 的身份与数据在重启和重新调度之后依然保留。如果把无状态应用比作健忘的实例那么 StatefulSet 则像记事的实例即使被调度到集群中的其他节点它依然记得自己的数据状态。StatefulSet 的核心特性稳定、唯一的网络标识Stable, Unique Network IdentifiersStatefulSet 中每个 Pod 都会获得唯一且稳定的主机名与网络标识确保网络与存储访问的一致性和可识别性。这一点对数据库这类有状态应用至关重要。持久化存储管理Persistent Storage ManagementStatefulSet 管理一组 Pod 的部署与扩缩容同时维护与每个 Pod 关联的持久化存储。即使 Pod 被重新调度到不同节点它仍然保留自己的存储从而保证数据持久性。有序、优雅的部署与扩缩容Ordered, Graceful Deployment and ScalingStatefulSet 中的 Pod 严格按照序号ordinal index依次创建、更新和删除。这保证了受控的扩缩容与滚动更新维护了对有状态应用至关重要的顺序与完整性。一个 StatefulSet 配置示例apiVersion: apps/v1 kind: StatefulSet metadata: name: scheduling-statefulset spec: serviceName: scheduling-service replicas: 3 selector: matchLabels: app: scheduling-app template: metadata: labels: app: scheduling-app spec: containers: - name: scheduling-container image: scheduling-image volumeClaimTemplates: - metadata: name: scheduling-storage spec: accessModes: [ ReadWriteOnce ] resources: requests: storage: 2Gi在这个示例中我们定义了一个名为scheduling-statefulset、拥有 3 个副本的 StatefulSet。请注意serviceName是维持每个 Pod 网络身份的关键字段它必须指向一个 Headless ServiceclusterIP: None的 ServiceStatefulSet 借助它生成形如pod-name.service-name.namespace.svc.cluster.local的稳定 DNS 名称。volumeClaimTemplates是 StatefulSet 区别于 Deployment 的重要机制它为集合中的每个 Pod自动创建属于自己的 PersistentVolumeClaimPVC从而实现一个 Pod 一份独立存储。实战一部署一个有状态应用MySQL前置条件你已经成功创建了一个 Kubernetes 集群。创建 YAML 文件下面通过 YAML 创建一个 StatefulSet运行一个典型的有状态应用——MySQL 数据库。我们将使用 MySQL 的公共镜像apiVersion: apps/v1 kind: StatefulSet metadata: name: mysql-statefulset spec: serviceName: mysql replicas: 1 selector: matchLabels: app: mysql template: metadata: labels: app: mysql spec: containers: - name: mysql image: mysql:5.7 env: - name: MYSQL_ROOT_PASSWORD value: YOUR_PASSWORD ports: - containerPort: 3306 volumeMounts: - name: mysql-persistent-storage mountPath: /var/lib/mysql volumeClaimTemplates: - metadata: name: mysql-persistent-storage spec: accessModes: [ReadWriteOnce] resources: requests: storage: 1Gi专家提示请密切关注该 YAML 正常运行所需的环境变量。以 MySQL 为例必须在 YAML 中提供 MySQL 的 root 主密码即上面 YAML 中YOUR_PASSWORD所引用的值。此外两个关键设计值得说明volumeMounts将名为mysql-persistent-storage的卷挂载到容器内/var/lib/mysql——这是 MySQL 的数据目录数据落盘后即可跨重启保留。volumeClaimTemplates会为 Pod 动态创建 PVCaccessModes: [ReadWriteOnce]表示该卷仅支持单节点读写单副本数据库的标准选择storage: 1Gi声明了容量请求。应用 StatefulSet YAML执行kubectl apply命令将清单提交到集群kubectl apply -f mysql.yaml验证 StatefulSet 是否正常运行用kubectl get statefulsets检查 StatefulSet 是否已创建kubectl get statefulsets还可以查看与该 StatefulSet 关联的 Pod。使用按标签过滤的命令kubectl get pods -l label-keylabel-value例如本文中的标签是appmysqlkubectl get pods -l appmysql从输出中可以看到该 StatefulSet 下正在运行的 Pod。扩缩容与更新镜像扩缩容 StatefulSet 使用kubectl scale命令格式为kubectl scale statefulsets [statefulset-name] --replicas[new-replica-count]。更新 StatefulSet 中使用的容器镜像即发布应用新版本使用kubectl set image命令格式为kubectl set image statefulset [statefulset-name] [container-name][new-image-name]。使用 StatefulSet 时可能遇到的典型错误StatefulSet 对状态敏感而 Deployment 是无状态的因此创建 StatefulSet 时更容易遇到错误。以下是一些只在创建 StatefulSet 时才会出现的问题PVC 冲突Persistent Volume Claim Conflicts当指定的 PVC 不可用或已被另一个 StatefulSet / Pod 占用时报错。Headless Service 缺失Headless Service Requirement由于缺少 StatefulSet 网络身份所需的 Headless Service 而报错。Pod 命名问题Pod Naming IssueStatefulSet 的 Pod 名称格式statefulset-name-ordinal与 Kubernetes 命名规范冲突时报错。更新策略配置错误Update Strategy Misconfiguration更新策略配置不当导致的错误——与默认支持滚动更新的 Deployment 不同StatefulSet 对更新顺序与策略有更严格的约束。有状态 Pod 调度失败Stateful Pod Scheduling Failure由于持久化存储的亲和性affinity约束导致 Pod 无法调度这在无状态 Deployment 中并不常见。实战二部署一个无状态应用hello-app前置条件你已经成功创建了一个 Kubernetes 集群。创建 YAML 文件apiVersion: apps/v1 kind: Deployment metadata: name: stateless-app1 namespace: default spec: replicas: 3 selector: matchLabels: app: stateless-app1 template: metadata: labels: app: stateless-app1 spec: containers: - name: hello-app-1 image: gcr.io/google-samples/hello-app:2.0 resources: requests: cpu: 500m memory: 2Gi limits: cpu: 500m memory: 2Gi逐段解读这份 YAMLAPI 版本与类型API Version and KindapiVersion和kind字段指定了资源对应的 API 版本与资源类型此处kind为Deployment。元数据Metadata包含 Deployment 的name和namespace如果未指定namespace默认为default。规格Spec定义 Deployment 的期望状态replicas期望的 Pod 数量。selector通过matchLabels指定 Deployment 如何找到它所管理的 Pod。template定义要创建的 Pod包含用于标签的metadata部分以及描述容器配置的spec部分。容器规格Container Specs包含容器name、所用image以及resources块——它定义了容器的 CPU 与内存requests请求量和limits上限。应用无状态 YAML执行kubectl apply -f stateless-app1.yaml验证 Deployment 是否正常运行使用kubectl rollout status检查 Deployment 是否发布成功kubectl rollout status deployment/stateless-app1从输出可以看到 deployment 成功滚动发布。若想确认该 Deployment 当前正在运行的 Pod 数量使用kubectl get pods -l app[deployment-label]即可——上述示例会显示 3 个 Pod副本在运行。Deployment 与 StatefulSet 对比一览表下表汇总了 Kubernetes 世界中这两个重要工作负载的核心差异帮助你快速选型对比维度DeploymentStatefulSet主要用途Primary Use-Case管理无状态应用。管理有状态应用。适用场景When to Use- 需要扩缩容无状态应用时- 每个实例可互相替换的应用- 需要稳定、唯一网络标识的场景- 需要持久化存储的应用副本管理Replica Management每个 Pod 名称包含一个随机哈希值。每个 Pod 被分配一个唯一的序号ordinal index只要 Pod 存在该序号就保持不变。存储Storage通常使用临时ephemeral存储可以使用持久卷但不由 Deployment 生命周期统一管理。支持稳定存储通过 Persistent Volume 与每个 Pod 的序号关联。扩缩容行为Scaling Behavior扩缩容副本时不考虑顺序与状态。按可预测的顺序扩缩容Pod 按序号依次创建和删除。更新策略Update Strategy支持 Rolling Update滚动更新与 Recreate 两种策略。主要使用滚动更新且按 Pod 序号的逆序进行。故障转移行为Failover Behavior节点故障时Pod 被重新调度不关心原始状态。重新调度后仍保持相同的网络身份这对某些数据密集应用至关重要。Pod 名称保持Pod Name PreservationPod 被替换时名称会改变。Pod 被重新调度时名称保持不变粘性身份sticky identity。使用案例Use Case Examples- Web 服务器- 无状态后端服务- 数据库如 MySQL、PostgreSQL- 任何对数据一致性与顺序敏感的系统前置条件Pre-Requisites了解 Kubernetes 对象的基础知识。理解持久化存储以及用于稳定网络标识的 Headless Service。从对比到选型结合仓库实际案例回到本仓库本身可以观察到一个有趣的对照refine 文档站点这类内容型 Web 应用完全无状态其 Helm Chart 使用 Deployment Service HPA 的组合见 documentation/k8s/refine-documentation/templates/deployment.yaml、documentation/k8s/refine-documentation/templates/service.yaml 与 documentation/k8s/refine-documentation/templates/hpa.yaml任意副本被替换都不会影响数据与身份——这正是 Deployment 的典型画像。而一旦某个业务模块需要落盘数据例如电商的购物车、会话或 PostgreSQL、MySQL 这类数据库就必须切换到 StatefulSet借助volumeClaimTemplates与 Headless Service 获得逐 Pod 的持久卷与稳定网络身份。仓库中 documentation/blog/2024-01-22-k8s-postgres.md在 K8s 中部署 PostgreSQL、documentation/blog/2023-12-25-kubectl-scale.mdkubectl scale 详解与 documentation/blog/2023-11-20-kubeclt-delete-pod.md删除 Pod 的行为差异可作为深入阅读材料帮助你把本文的选型原则应用到更多真实场景。总结Kubernetes 的 Deployment 与 StatefulSet 服务于应用管理的不同需求。Deployment 适合无状态应用提供了自动扩缩容、便捷更新和高可用等能力在需要快速伸缩、频繁发布变更的场景中表现出色StatefulSet 则为有状态应用而生确保稳定的网络标识与持久化存储是数据库等对数据持久性和顺序敏感的系统的必备选择。选择 Deployment 还是 StatefulSet最终取决于你的应用是否需要状态如果数据可随时重建、实例可互相替换选择 Deployment如果应用依赖持久数据、要求稳定的身份与启动顺序则应选择 StatefulSet。希望本文的 YAML 示例、对比表与常见错误清单能帮助你在下一次 Kubernetes 部署中做出清晰、正确的决策。【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表