`
lykops
  • 浏览: 86290 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
文章分类
社区版块
存档分类
最新评论

StatefulSet: Kubernetes 中对有状态应用的运行和伸缩

 
阅读更多

在最新发布的 Kubernetes 1.5 我们将过去的 PetSet 功能升级到了 Beta 版本,并重新命名为StatefulSet。除了依照社区民意改了名字之外,这一 API 对象并没有太大变化,不过我们在向集合里部署 Pod 的过程中加入了“每索引最多一个”的语义。有了顺序部署、顺序终结、唯一网络名称以及持久稳定的存储,我们认为,对于大量的有状态容器化负载,我们已经具备了一定的支持能力。我们并不是宣称这一功能已经完全完成,但是我们相信他已经处于一个可用状态,并且我们会在推动其正式发布的过程中保持其兼容性。

StatefulSet 的采用时机

在 Kubernetes 中,Deployment 和 ReplicaSets 都是运行无状态应用的有效手段。但这两种方式对于有状态应用来说就不太合适了。StatefulSet 的目的就是给为数众多的有状态负载提供正确的控制器支持。然而需要注意的是,不一定所有的有存储应用都是适合移植到 Kubernetes 上的,在移植存储层和编排框架之前,需要回答以下几个问题。

应用是否可以使用远程存储?

目前,我们推荐用远程存储来使用 StatefulSets,就要对因为网络造成的存储性能损失有一个准备:即使是专门优化的实例,也无法同本地加载的 SSD 相提并论。你的云中的网络存储,能够满足 SLA 要求么?如果答案是肯定的,那么利用 StatefulSet 运行这些应用,就能够获得自动化的优势。如果应用所在的 Node 发生故障,包含应用的 Pod 会调度到其他 Node 上,在这之后会重新加载他的网络存储以及其中的数据。

这些应用是否有伸缩需求?

用 StatefulSet 运行应用会带来什么好处呢?你的整个组织是否只需要一个应用实例?对该应用的伸缩是否会引起问题?如果你只需要较少的应用实例数量,这些实例能够满足组织现有的需要,而且可以预见的是,应用的负载不会很快增长,那么你的本地应用可能无需移植。

然而,如果你的系统是微服务所构成的生态系统,就会比较频繁的交付新服务,如果更近一步,服务是有状态的,那么 Kubernetes 的自动化和健壮性特性会对你的系统有很大帮助。如果你已经在使用 Kubernetes 来管理你的无状态服务,你可能会想要在同一个体系中管理你的有状态应用。

预期性能增长的重要性?

Kubernetes 还不支持网络或存储在 Pod 之间的隔离。如果你的应用不巧和嘈杂的邻居共享同一个节点,会导致你的 QPS 下降。解决方式是把 Pod 调度为该 Node 的唯一租户(独占服务器),或者使用互斥规则来隔离会争用网络和磁盘的 Pod,但是这就意味着用户必须鉴别和处置(竞争)热点。

如果榨干有状态应用的最大 QPS 不是你的首要目标,而且你愿意也有能力处理竞争问题,似的有状态应用能够达到 SLA 需要,又如果对服务的移植、伸缩和重新调度是你的主要需求,Kubernetes 和 StatefulSet 可能就是解决问题的好方案了。

你的应用是否需要特定的硬件或者实例类型

如果你的有状态应用在高端硬件或高规格实例上运行,而其他应用在通用硬件或者低规格实例上运行,你可能不想部署一个异构的集群。如果可以把所有应用都部署到统一实例规格的实例上,那么你就能够从 Kubernetes 获得动态资源调度和健壮性的好处。

实践环节 – ZooKeeper

有两个原因让 [ZooKeeper] 成为 StatefulSet 的好例子。首先,StatefulSet 在其中演示了运行分布式、强一致性存储的应用的能力;其次,ZooKeeper 也是 Apache Hadoop 和 Apache Kafka 在 Kubernetes 上运行的前置条件。在 Kubernetes 文档中有一个 深度教程 说明了在 Kubernetes 集群上部署 ZooKeeper Ensemble 的过程,这里会简要描述一下其中的关键特性。

创建 ZooKeeper 的 Ensemble

创建 Ensemble 很容易,只要用 kubectl create 来根据定义来创建对象就可以了。

$ kubectl create -f https://raw.githubusercontent.com/kubernetes/kubernetes.github.io/master/docs/tutorials/stateful-application/zookeeper.yaml
service "zk-headless" created
configmap "zk-config" created
poddisruptionbudget "zk-budget" created
statefulset "zk" created

接下来 StatefulSet 控制器开始顺序创建各个 Pod,在创建后续 Pod 之前,首先要等前面的 Pod 运行成功并进入到就绪状态。

$ kubectl get -w -l app=zk
NAME      READY     STATUS    RESTARTS   AGE
zk-0      0/1       Pending   0          0s
zk-0      0/1       Pending   0         0s
zk-0      0/1       Pending   0         7s
zk-0      0/1       ContainerCreating   0         7s
zk-0      0/1       Running   0         38s
zk-0      1/1       Running   0         58s
zk-1      0/1       Pending   0         1s
zk-1      0/1       Pending   0         1s
zk-1      0/1       ContainerCreating   0         1s
zk-1      0/1       Running   0         33s
zk-1      1/1       Running   0         51s
zk-2      0/1       Pending   0         0s
zk-2      0/1       Pending   0         0s
zk-2      0/1       ContainerCreating   0         0s
zk-2      0/1       Running   0         25s
zk-2      1/1       Running   0         40s

检查一下 StatefulSet 中每个 Pod 的主机名称,你会发现 Pod 的主机名也包含了 Pod 的顺序:

$ for i in 0 1 2; do kubectl exec zk-$i -- hostname; done
zk-0
zk-1
zk-2

ZooKeeper 在一个名为 “myid” 的文件中保存了每个服务器的唯一标识符。这个标识符只是自然数。在 Ensemble 的服务器中,”myid” 文件中保存的数字就是 Pod 主机名中的顺序号加一。

$ for i in 0 1 2; do echo "myid zk-$i";kubectl exec zk-$i -- cat /var/lib/zookeeper/data/myid; done
myid zk-0
1
myid zk-1
2
myid zk-2
3

基于主机名,每个 Pod 都有独立的网络地址,这个网域由 zk-headless 这一 Headless 服务所控制。

$  for i in 0 1 2; do kubectl exec zk-$i -- hostname -f; done
zk-0.zk-headless.default.svc.cluster.local
zk-1.zk-headless.default.svc.cluster.local
zk-2.zk-headless.default.svc.cluster.local

Pod 具有了唯一的序号和网络地址,就可以用来在 ZooKeeper 的配置文件中设置 Ensemble 成员了。

kubectl exec zk-0 -- cat /opt/zookeeper/conf/zoo.cfg
clientPort=2181
dataDir=/var/lib/zookeeper/data
dataLogDir=/var/lib/zookeeper/log
tickTime=2000
initLimit=10
syncLimit=2000
maxClientCnxns=60
minSessionTimeout= 4000
maxSessionTimeout= 40000
autopurge.snapRetainCount=3
autopurge.purgeInteval=1
server.1=zk-0.zk-headless.default.svc.cluster.local:2888:3888
server.2=zk-1.zk-headless.default.svc.cluster.local:2888:3888
server.3=zk-2.zk-headless.default.svc.cluster.local:2888:3888

StatefulSet 让用户可以用稳定、可重复的方式来部署 ZooKeeper。不会创建具有重复 ID 的服务器,服务器之间可以通过稳定的网络地址互相通信,因为 Ensemble 具有稳定的成员关系,因此 Leader 选拔和写入复制能力也得到了保障。

检查 Ensemble 工作状况的最简单方式就是向一台服务器写入一个值,然后从另一台服务器中读取。可以利用 ZooKeeper 自带的 “zkCli.sh” 脚本来创建包含数据的 ZNode。

$  kubectl exec zk-0 zkCli.sh create /hello world
...

WATCHER::

WatchedEvent state:SyncConnected type:None path:null
Created /hello

使用同一脚本,可以从 Ensemble 另外一台服务器中读取数据。

$  kubectl exec zk-1 zkCli.sh get /hello 
...

WATCHER::

WatchedEvent state:SyncConnected type:None path:null
world
...

可以用删除 zk StatefulSet 的方式停掉 Ensemble。

$  kubectl delete statefulset zk
statefulset "zk" deleted

级联删除会销毁 StatefulSet 中的每个 Pod,并且按照创建顺序的反序来执行,只有在成功终结后面一个之后,才会继续下一个删除操作。

$  kubectl get pods -w -l app=zk
NAME      READY     STATUS    RESTARTS   AGE
zk-0      1/1       Running   0          14m
zk-1      1/1       Running   0          13m
zk-2      1/1       Running   0          12m
NAME      READY     STATUS        RESTARTS   AGE
zk-2      1/1       Terminating   0          12m
zk-1      1/1       Terminating   0         13m
zk-0      1/1       Terminating   0         14m
zk-2      0/1       Terminating   0         13m
zk-2      0/1       Terminating   0         13m
zk-2      0/1       Terminating   0         13m
zk-1      0/1       Terminating   0         14m
zk-1      0/1       Terminating   0         14m
zk-1      0/1       Terminating   0         14m
zk-0      0/1       Terminating   0         15m
zk-0      0/1       Terminating   0         15m
zk-0      0/1       Terminating   0         15m

可以使用 kubectl apply 命令来重建 zk StatefulSet,并重新部署 Ensemble。

$  kubectl apply -f http://k8s.io/docs/tutorials/stateful-application/zookeeper.yaml
service "zk-headless" configured
configmap "zk-config" configured
statefulset "zk" created

如果使用 “zkCli.sh” 脚本来尝试获取删除 StatefulSet 之前写入的数据,会发现数据依然存在。

$  kubectl exec zk-2 zkCli.sh get /hello 
...

WATCHER::

WatchedEvent state:SyncConnected type:None path:null
world
...

及时所有的 Pod 都被销毁,他们一旦被重新调度,StatefulSet 也能保证 Ensemble 能够选拔新的 Leader 并继续提供服务。

Node 故障的容错

ZooKeeper 会在 Ensmble 的服务器中复制他的状态机,用于应对 Node 故障。缺省情况下 Kubernetes 调度器可以在同一个 Node 上部署属于 zk StatefulSet 的多个 Pod,假设 zk-0 和 zk-1 两个 Pod 被部署在同一个 Node 上,如果这一 Node 出现故障,ZooKeepers Ensemble 会因为数量不足造成无法提交写入,ZooKeeper 会出现服务中断,直到 Pod 被重新调度。

在集群中,建议为关键进程预留更多资源,这样就能保证故障情况发生的时候能够迅速重新调度 Pod,缩短故障时间。

如果这样无法 SLA 规定的停机时间,那么就应该使用 PodAntiAffinity( Pod 互斥性)注解。用来创建 Ensemble 的定义文件中就包含了这样的注解,他会要求 Kubernetes 调度器不要把 zk StatefulSet 中的多个 Pod 部署在同一 Node 上。

计划内维护的容错

用于创建 ZooKeeper Ensemble 的描述文件还创建了一个 PodDistruptionBudget( Pod 中断预算 )对象:zk-budget。zk-budget 用于指示 Kubernetes, 这一服务能够容忍的中断 Pod (不健康 Pod)的上限。

{
  "podAntiAffinity": {
    "requiredDuringSchedulingRequiredDuringExecution": [
      {
        "labelSelector": {
          "matchExpressions": [
            {
              "key": "app",
              "operator": "In",
              "values": [
                "zk-headless"
              ]
            }
          ]
        },
        "topologyKey": "kubernetes.io/hostname"
      }
    ]
  }
}
$ kubectl get poddisruptionbudget zk-budget
NAME        MIN-AVAILABLE   ALLOWED-DISRUPTIONS   AGE
zk-budget   2               1                     2h

zk-budget 定义,至少要有两个处于可用状态的成员才能保障 Ensemble 的健康。如果在离线之前对 Node 进行 Drain 操作,如果这一操作过程中终止的 Pod 会违反预算,Drain 操作就会失败。如果使用 kubectl drain,来对 Node 进行 cordon 操作并驱逐所有其中运行的 Node,PodDistruption 让你可以确认这一操作不会中断有状态应用的服务。

更进一步

因为 Kubernetes 的开发工作目标是可用,我们希望获得更多来自用户的设想。如果你想要帮我们处理问题,可以看看 GitHub 上关于 statful 的 Issues。然而为了 API 的易于理解,我们并不准备实现所有的功能请求。我们会优先实现一些能够对所有有状态应用产生改善的功能,例如滚动更新支持、Node 升级的集成、使用高速的本地存储等。StatefulSet 的目的在于支持尽可能多而不是全部的有状态应用。基于这些考虑,我们会避免依赖隐藏特性或者技术的方式来充实 StatefulSet。每个人都可以开发一个想 StatefulSets 的控制器。我们称之为 “making it forkable”。明年,我们希望更多的流行的有状态应用能够有自己的社区支持的独立控制器或 “操作器”。我们已经听说了 etcd、Redis 和 ZooKeeper 的自定义控制器的开发工作。我们期待更多类似案例不断涌现。

ETCD 和 Prometheus 的 Operator 来自 CoreOS,演示了一种超出 StatefulSet 能力的自动化和集成能力。另一方面,使用 Deployment 和 StatefulSet 这样的通用控制器能够用同一种对象管理大量有状态应用。Kubernetes 用户有了运行有状态应用的能力,而且可以自行在两种方式之中进行选择。


转自https://www.kubernetes.org.cn/1130.html


分享到:
评论

相关推荐

    20 深入理解StatefulSet(三):有状态应用实践.pdf

    根据提供的文件信息,我们可以了解到关于Kubernetes中StatefulSet和有状态应用部署的详细知识。本篇文章将深入探讨如何使用StatefulSet部署一个具有代表性的有状态应用——MySQL集群,并将通过实践案例来解释其工作...

    Kubernetes之应用部署调度策略测试用例

    对于有状态的应用,测试用例应确保多个副本间的数据一致性,如StatefulSet的持久卷挂载和网络配置。 综上所述,Kubernetes应用部署调度策略的测试用例设计需要全面覆盖资源管理、亲和性、选择器、优先级、QoS、...

    kubernetes中文文档

    - **状态保存**: 学习如何使用 StatefulSet 来管理有状态的服务,确保数据的持久性和一致性。 - **自定义资源定义**: 如何使用 CRD 扩展 Kubernetes API,并创建自定义资源类型。 #### 1.4 Kubernetes 集群 这一...

    Kubernetes Part2

    Deployment用于无状态服务的滚动更新,StatefulSet用于有状态应用,保证每个实例的持久标识和顺序,而DaemonSet确保至少一个副本在每个节点上运行。 2. **服务发现与负载均衡**: Kubernetes Service是抽象层,它...

    k8s.zip kubernetes分享

    - **StatefulSet**:用于管理有状态应用,如数据库,保证了Pod的持久标识和有序部署。 3. **网络与存储**:Kubernetes提供了网络和存储的抽象,让应用可以跨节点通信和存储数据: - **Ingress**:定义了外部访问...

    csk:Kubernetes的容器服务

    - **StatefulSet**: 用于管理有状态应用,如数据库,确保每个实例都有唯一的身份、持久的存储和有序的生命周期。 **2. Kubernetes的功能** - **自动扩展与调度**: 根据设定的规则,Kubernetes可以自动扩展应用...

    k8s-config:Kubernetes配置清单

    Kubernetes中的资源对象是系统中可操作的实体,例如Deployment用于定义应用的副本集,Service定义了如何访问应用,Pod是运行容器的基本单位,ReplicaSet确保特定数量的Pod副本始终运行,而StatefulSet则用于需要稳定...

    kubernetes培训PPT

    其基本单元包括Pod(应用实例)、Service(服务发现和负载均衡)、Deployment(定义应用的期望状态)以及ReplicaSet(保证一定数量的Pod副本运行)。 2. **Pod**:Pod是Kubernetes中最小的部署单位,它可以包含一个...

    Kubernetes有状态集群服务部署与管理.rar

    本资料聚焦于Kubernetes中的有状态服务部署与管理,这对于运行需要持久化数据或依赖特定初始化顺序的应用至关重要。 一、有状态服务的概念 在Kubernetes中,服务分为两种类型:无状态服务(Stateless Services)和...

    Kubernetes基础及集群搭建.rar

    在IT行业中,Kubernetes(简称K8s)已经成为容器编排领域的主流标准,它使得部署、管理和扩展微服务应用变得更加高效。"Kubernetes基础及集群搭建"这一主题涵盖了理解Kubernetes核心概念、安装与配置Kubernetes集群...

    kubernetes-handbook-jimmysong-v1.3

    - **迁移传统应用到Kubernetes**:例如使用Hadoop YARN作为有状态应用的迁移案例。 ### 集群管理与维护 - **在CentOS上部署Kubernetes集群**:涉及创建TLS证书和秘钥、配置kubeconfig文件、安装kubectl命令行工具、...

    kubernetes-dev-docs:Kubernetes源码解析和实践-源码解析

    它的设计目标是让应用程序在物理或虚拟节点上运行,并通过声明式配置实现对服务的高可用性、可伸缩性和自愈能力。 源码解析部分将涉及以下几个关键领域: 1. **API Server**: Kubernetes的核心组件,作为控制平面...

    kubernetes-series:kubernetes系列代码

    工作负载如Deployment、StatefulSet和DaemonSet定义了应用的实例数量和状态。Service是内部负载均衡器,为Pod提供稳定的服务发现和访问。存储卷允许持久化数据,而网络策略确保容器间的通信安全和有序。 在标签中...

    kubernetes经典实例.zip

    7. **StatefulSet**:用于管理有状态应用的Pod集合,如数据库、消息队列等,它为每个Pod提供了唯一的网络标识和持久化的存储。 在Java开发环境中,Kubernetes可以帮助我们实现以下目标: - **弹性伸缩**:根据应用...

    kubernetes

    Kubernetes还提供了多种资源对象,如Namespace用于隔离资源,Service作为微服务间的抽象,Deployment用于声明性更新Pod和ReplicaSets,Secret用于管理敏感数据,StatefulSet用于部署和扩展有状态应用,DaemonSet确保...

    Kubernetes指南(Kubernetes Handbook)

    - **StatefulSet**: 管理有状态应用的Pod,保证其标识、存储和网络的一致性。 **部署与配置** Kubernetes 提供多种部署方式,如 kubeadm、kops、Kubespray 等,以及对不同云平台的支持,如 Azure、LinuxKit、...

    Kubernetes架构权威指南.pdf

    - **StatefulSet**:为有状态的应用程序提供声明式的部署和管理。 - **Volume**:Pod中的持久化存储卷。 #### 四、部署配置 - **部署指南**:介绍了如何使用`kubectl`工具进行Kubernetes集群的安装和配置,包括:...

    kubernetes部署mysql高可用

    2. **StatefulSet**: 用于管理有状态应用的控制器,如MySQL,确保Pod的持久性、有序性和唯一标识。 3. **Service**: 提供对Pod的稳定网络访问,可以是负载均衡器或头部服务。 4. **PersistentVolume (PV) 和 ...

    kubernetes-learning.zip

    - **StatefulSet**:处理有状态应用,提供持久化的存储和稳定的网络标识。 2. **Kubernetes 工作流程** - **调度**:Kubernetes 调度器根据资源需求和策略选择合适的节点来运行 Pod。 - **启动**:kubelet 服务...

    mongodb高可用所需yaml

    2. **StatefulSet**:在Kubernetes中,MongoDB作为有状态的应用,适合使用StatefulSet来部署。StatefulSet保证了Pods的唯一标识、有序部署和持久存储,这在数据库集群中至关重要。 3. **PersistentVolume(PV)与...

Global site tag (gtag.js) - Google Analytics