如何在Kubernetes中管理有状态应用


在Kubernetes中,StatefulSet被用来管理有状态应用的API对象。StatefulSets在Kubernetes 1.9版本才稳定。StatefulSet管理Pod部署和扩容,并为这些Pod提供顺序和唯一性的保证。与Deployment相似的地方是,StatefulSet基于spec规格管理Pod;与Deployment不同的地方是,StatefulSet需要维护每一个Pod的唯一身份标识。这些Pod基于同样的spec创建,但互相之间不能替换,每一个Pod都保留自己的持久化标识。

1、使用StatefulSet的场景


对于下面的应用场景,StatefulSets是有价值的:

  • 稳定、唯一的网络标识
  • 稳定、持久的存储
  • 按照顺序、优雅的部署和扩容
  • 按照顺序、优雅的删除和终止
  • 按照顺序、自动滚动更新

上述的稳定是持久的同义词,如果应用不需要稳定的标识或者顺序的部署、删除、扩容,则应该使用无状态的副本集。Deployment或者ReplicaSet的控制器更加适合无状态业务场景。


2、StatefulSet的限制

  • 在Kubernetes 1.9版本之前是beta版本,在Kubernetes 1.5版本之前是不提供的。

  • Pod存储由PersistentVolume(storage类或者管理员预先创建)提供。

  • 删除或者缩容StatefulSet不会删除与StatefulSet关联的数据卷,这样能够保证数据的安全性。

  • 当前的StatefulSets需要一个Headless服务来为Pod提供网络标识,此Headless服务需要通过手工创建。


3、组件


下面是一个StatefuleSet组成的示例:

  • 一个名称为nginx的Headless服务,用来控制网络域。

  • 一个名称为web的statefulSet,它拥有nginx容器(在唯一的Pod启动)的3个副本集。


  • 使用PersistenVolumes(由PersistentVolume Provisioner提供)提供稳定存储的volumeClaimTemplates。


apiVersion:v1
kind:Service
metadata:
  name:nginx
  labels:
     app:nginx
spec:
  ports:
  -port:80
     name:web
  clusterIP:None //Headless服务
  selector:
     app:nginx
---
apiVersion:apps/v1
kind:StatefulSet
metadata:
  name:web
spec:
  selector:
     matchLabels:
       app:nginx# has to match .spec.template.metadata.labels
  serviceName:"nginx"
  replicas:3 # by default is 1
  template:
     metadata:
       labels:
         app:nginx # has to match .spec.selector.matchLabels
     spec:
       terminationGracePeriodSeconds:10
       containers:
       -name:nginx
         image:k8s.gcr.io/nginx-slim:0.8
         ports:
         -containerPort:80
           name:web
         volumeMounts: #挂接数据卷
         -name:www
           mountPath:/usr/share/nginx/html #挂接路径为容器的/usr/share/nginx/html
  volumeClaimTemplates: #数据卷生命模板
  -metadata:
       name:www
     spec:
       accessModes:["ReadWriteOnce"]
       storageClassName:my-storage-class
       resources:
         requests:
           storage:1Gi


4、Pod选择



必须设置StatefulSet的sepc.selector,以匹配.spec.template.metadata.labels。在Kubernetes 1.8之前,spec.selector是可以忽略的,它被设置一个默认值。在1.8或者后续的版本,如果不设置sepc.selector,则会导致创建StatefulSet失败。


5、Pod身份标识


StatfuleSet Pod拥有一个唯一的身份标识,它由顺序、稳定的网络标识和稳定的存储所组成。此身份标识一直跟随着Pod,不过它被调度到那个Node上。


5.1 序数索引(Ordinal Index)


对于拥有N个副本集的StatefulSet,在StatefulSet中的每一个Pod都会被指派一个整型的序数,此序数在0和N之间,在整个集合中是唯一的。


5.2 网络ID(Stable Network ID)


在StatefulSet中,每一个Pod的主机名称都由StatefulSet的名称和序数所组成。Pod的主机名称的格式:$(statefulset name)-$(ordinal)。如果创建了三个Pod,这他们的主机名称为web-0,web-1,web-2。StatefulSet能够使用Headless服务来控制Pod的域。Service管理的域的格式为:$(service name).$(namespace).svc.cluster.local,cluster.local是集群域。对于每一个被创建的Pod,它将得到一个DNS子域,格式为: $(podname).$(governing service domain),这里的管理服务在StatefulSet中,通过serviceName设置。

下面是StatefulSet中Pod在DNS中的名称:


5.3 稳定的存储


kubernetes为每一个VolumeClaimTemplate创建一个对应的PersistentVolume。在前面的nginx实例中,每一个Pod将会my-storage-class存储类型的PersistenVolume单一实例和1Gib的存储空间。

如果没有指定存储类,则会使用默认的存储。但一个Pod被调度到Node上,它的volumeMounts将会挂接PersistentVolumes,并将其与PersistentVolumeClaims进行关联。需要注意的是,即使在Pod被删除,PersistentVolumes与PersistentVolumeClaims之间的关联关系也不会被删除。


5.4 Pod命名标签


当StatefulSet控制器创建了Pod,它将会添加一个标签,为此Pod名称的集合。此标签将能够管理服务到指定的Pod。


6、部署和扩容保证

  • 对于一个带有N个副本集的StatefulSet,当Pod被部署,它们将按0到N-1的顺序被创建。
  • 当一Pod被删除时,它们将按照N-1到0的倒序被终止。
  • 在进行Pod扩容前,所有依赖的Pod应该都已在运行和准备好。
  • 在Pod被终止前,所有的依赖它的Pod都必须完全停止。

在前文创建的nginx例子中,将按照顺序部署web-0,web-1和web-2。web-1只能在web-0运行和准备好以后才能够被部署,web-2只能在web-1运行和准备好以后才能够被部署。如果web-0失败,就算web-1正在运行,web-2也是不能正常启动的,除非web-0被重启,并正常运行。

如果缩容上述例子,设置replicas=1,则web-2首先被终止,接着是web-1。如果在web-2被终止后,但在web-1被终止前,web-0失败了,web-1将不能被终止,除非web-0处于正常运行状态。


6.1 Pod管理策略


在Kubernetes 1.7以后,StatefulSet的唯一性标识可以通过.spec.podManagementPolicy的值进行保证。

6.1.1 OrderedReady Pod管理

OrderedReady pod管理是StatefulSets默认的管理模式,此模式安装顺序启动或者终止Pod。

6.1.2 并行Pod管理

并行Pod管理告诉StatefulSet控制器以并行的方式启动或者终止所有的Pod。


7、更新策略


在Kubernetes 1.7之后,运行通过配置StatefulSet的.spec.updateStrategy,实现Pod的容器、标签、资源请求/限制和注释自动更新。


7.1 On Delete策略


OnDelete更新策略是1.6之前版本的行为。当StatefulSet的.spec.updateStrategy.type被设置为OnDelete,则StatefulSet控制器将不会知道更新Pod。


7.2 Rolling Updates策略


RollingUpdate更新策略将实现StatefulSet中Pod的自动滚动更新,这是StatefulSet的默认更新模式。如果.spec.updateStrategy.type设置为 RollingUpdate,则StatefulSet控制器将会删除和重建StatefulSet中的每一Pod。它将会按照从最大到最小的序数终止Pod,并按照从小到大顺序重建Pod。


7.3 Partitions


RollingUpdate更新策略能够通过指定.spec.updateStrategy.rollingUpdate.partition进行分隔。当分隔被指定,所有序数大于或等于分隔的Pod将会被更新,其它的Pod将被不会进行更新。在大部分的情况下,不会使用分隔;当希望进行金丝雀发布,或者执行阶段发布时,分隔是很有用的。

作者简介:

季向远,北京神舟航天软件技术有限公司产品经理。本文版权归原作者所有。

原文地址:http://blog.51cto.com/12462495/2095531

时间: 2024-08-29 04:57:30

如何在Kubernetes中管理有状态应用的相关文章

Kubernetes中的PodIP、ClusterIP和外部IP

Kubernetes是Google开源的容器集群管理系统,是Docker容器的主要集群管理系统之一. 其中,Kubernetes中管理主要有三种类型的IP:Pod IP .Cluster IP 和 外部IP. Pod IP Kubernetes的最小部署单元是Pod.利用Flannel作为不同HOST之间容器互通技术时,由Flannel和etcd维护了一张节点间的路由表.Flannel的设计目的就是为集群中的所有节点重新规划IP地址的使用规则,从而使得不同节点上的容器能够获得"同属一个内网&qu

如何在 Kubernetes 环境中运行 Spark 集群

处理这么大量的数据,背后的机器可能是数以千计,无法通过人工来监控机器的状态.因此,本文将介绍用 Kubernetes 容器管理工具,并通过简单示例,告诉你如何建立一个 Spark 集群. 准备阶段 1.需要拥有正在运行的 Kubernetes 集群,并使用 Kubectl 为其配置访问权限.如果你还没有可用的 Kubernetes 集群,则可以使用 Minikube 在本地计算机上设置测试集群 . 我们建议将 Minikube 更新为最新版本(编写本文档时为0.19.0),因为某些早期版本可能无

(译) Google Flutter 中的简单状态管理

原文链接 我是如何遇见 Google Flutter的 这对我来这是像往常一样的码代码的一天.我的一个朋友在我们的开发者群组中发了这么一个问题,是否有人尝试过Google Flutter.它想要知道React Native 和 Google Flutter之间的比较.这个问题让我种草了Google Flutter.我之前从没有听过Google Flutter.它是否值得与React Native进行比较,就像AngularJS相较于ReactJS? 我必须承认.我是一个React的迷弟.我已经使

如何在CAD中对图纸进行图层管理

在需要绘制CAD图纸的行业中,CAD制图是日常中不能在日常的工作了,完整的一张CAD图纸中是有许多的图层进行组合起来的,在查看的过程中也可以对图层进行一些简单的管理,以便我们更方便的进行查看,但是如何在CAD中对图纸进行图层管理呢?要怎么来进行设置了,下面就来教教大家具体操作技巧. 第一步:首先还是需要将电脑打开,在电脑中任意的打开一个浏览器,在浏览器的搜索框中搜索迅捷CAD看图,之后点击进入官网,根据系统提示操作步骤下载最新版本的CAD编辑器到电脑桌面上. 第二步:之后,将CAD看图安装完成之

如何在Win10中安装RSAT对AD进行日常管理?

如何在Win10中安装RSAT以对AD进行日常管理? ?Lander Zhang 专注外企按需IT基础架构运维服务,IT Helpdesk 实战培训践行者博客:https://blog.51cto.com/lander IT Helpdesk 工程师实战培训课程:https://edu.51cto.com/lecturer/733218.html轻松进外企:IT Helpdesk工程师实战自学之路:https://blog.51cto.com/lander/2413018更新时间:2019/10

如何在iOS中使用Block

如何在iOS中使用Block Block可以帮助我们组织独立的代码段,并提高复用性和可读性.iOS4在UIKit中引入了该特征.超过100个的Apple API都使用了Block,所以这是一个我们必须开始熟悉的知识. Block是什么样的? 你可以使用^操作符来声明一个Block变量,它表示一个Block的开始. int num1 = 7; int(^aBlock)(int) = ^)int num2) { return num1+nunm2; }; 在如上代码中我们将Block声明为一个变量,

如何在C++中获得完整的类型名称

地球人都知道C++里有一个typeid操作符可以用来获取一个类型/表达式的名称: std::cout << typeid(int).name() << std::endl; 但是这个name()的返回值是取决于编译器的,在vc和gcc中打印出来的结果如下: int // vc i // gcc 一个稍微长一点的类型名称,比如: class Foo {}; std::cout << typeid(Foo*[10]).name() << std::endl; 打

监测和管理Xcache状态

Xcache是一个使用比较多的Opcode缓存器,很多时候,我们为了让脚本的执行效率更加高,可以采取这种缓存器,它可以让脚本引擎不用每次都去编译执行,可以在一次编译后,把Opcode缓存起来,直接去执行,效率会提升30%-40%左右,当PHP文件被更改过以后,Xcache会自动讲该文件的缓存,从Opcode管理器中踢出,执行到该文件时,重新进行缓存,之前写过如何在Centos上部署安装Xcache. 在部署好以后,我们如何进一步去查看它的工作状态,是否为我们提升了效率呢,缓存命中率是多少呢,为它

Kubernetes 中的pv和pvc

原文地址:http://www.cnblogs.com/leidaxia/p/6485646.html 持久卷 PersistentVolumes 本文描述了 Kubernetes 中的 PersistentVolumes.要求读者有对卷 (volumes) 所有了解. 简介 存储管理跟计算管理是两个不同的问题.PersistentVolume 子系统,对存储的供应和使用做了抽象,以 API 形式提供给管理员和用户使用.要完成这一任务,我们引入了两个新的 API 资源:PersistentVol