作者:Jack47

转载请保留作者和原文出处

PS:如果喜欢我写的文章,欢迎关注我的微信公众账号程序员杰克,两边的文章会同步,也可以添加我的RSS订阅源

Kubernetes对无状态服务有完善的支持,但是对于有状态的服务,是从1.3版本开始,才逐渐支持的。

有状态的应用程序

一般情况下,nginx或者web server(不包含MySQL)自身都是不需要保存数据的,对于 web server,数据会保存在专门做持久化的节点上。所以这些节点可以随意扩容或者缩容,只要简单的增加或减少副本的数量就可以。但是很多有状态的程序都需要集群式的部署,意味着节点需要形成群组关系,每个节点需要一个唯一的ID(例如Kafka BrokerId, Zookeeper myid)来作为集群内部每个成员的标识,集群内节点之间进行内部通信时需要用到这些标识。传统的做法是管理员会把这些程序部署到稳定的,长期存活的节点上去,这些节点有持久化的存储和静态的IP地址。这样某个应用的实例就跟底层物理基础设施比如某台机器,某个IP地址耦合在一起了。Kubernets中StatefulSet的目标是通过把标识分配给应用程序的某个不依赖于底层物理基础设施的特定实例来解耦这种依赖关系。(消费方不使用静态的IP,而是通过DNS域名去找到某台特定机器)

StatefulSet

前提

使用StatefulSet的前提:

  1. Kubernetes集群的版本 >=1.5
  2. 安装好DNS集群插件,版本 >=15

特点

StatefulSet(1.5版本之前叫做PetSet)为什么适合有状态的程序,因为它相比于Deployment有以下特点:

  1. 稳定的,唯一的网络标识,可以用来发现集群内部的其他成员。比如StatefulSet的名字叫kafka,那么第一个起来的Pet叫kafka-0,第二个叫 kafk-1,依次类推。
  2. 稳定的持久化存储:通过Kubernetes的PV/PVC或者外部存储(预先提供的)来实现
  3. 启动或关闭时保证有序:优雅的部署和伸缩性: 操作第n个pod时,前n-1个pod已经是运行且准备好的状态。 有序的,优雅的删除和终止操作:从 n, n-1, ... 1, 0 这样的顺序删除

上述提到的“稳定”指的是Pod在多次重新调度时保持稳定,即存储,DNS名称,hostname都是跟Pod绑定到一起的,跟Pod被调度到哪个节点没关系。

所以Zookeeper, Etcd 或 Elasticsearch这类需要稳定的集群成员的应用时,就可以用StatefulSet。通过查询无头服务域名的A记录,就可以得到集群内成员的域名信息。

限制

StatefulSet也有一些限制:

  1. Pod的存储必须是通过 PersistentVolume Provisioner基于 storeage类来提供,或者是管理员预先提供的外部存储
  2. 删除或者缩容不会删除跟StatefulSet相关的卷,这是为了保证数据的安全
  3. StatefulSet现在需要一个无头服务(Headless Service)来负责生成Pods的唯一网络标示,需要开发人员创建这个服务
  4. StatefulSet的升级是一个手工的过程

无头服务(Headless Service)

要定义一个服务(Service)为无头服务(Headless Service),需要把Service定义中的ClusterIP配置项设置为空: spec.clusterIP:None。和普通Service相比,Headless Service没有ClusterIP(所以没有负载均衡),它会给一个集群内部的每个成员提供一个唯一的DNS域名来作为每个成员的网络标识,集群内部成员之间使用域名通信。无头服务管理的域名是如下的格式:$(service_name).$(k8s_namespace).svc.cluster.local。其中的 "cluster.local"是集群的域名,除非做了配置,否则集群域名默认就是cluster.local。StatefulSet下创建的每个Pod,得到一个对应的DNS子域名,格式如下:

$(podname).$(governing_service_domain),这里 governing_service_domain是由StatefulSet中定义的serviceName来决定。举例子,无头服务管理的kafka的域名是:kafka.test.svc.cluster.local, 创建的Pod得到的子域名是 kafka-1.kafka.test.svc.cluster.local。注意这里提到的域名,都是由kuber-dns组件管理的集群内部使用的域名,可以通过命令来查询:

$ nslookup my-nginx
Server: 192.168.16.53
Address 1: 192.168.16.53 Name: my-nginx
Address 1: 192.168.16.132

而普通Service情况下,Pod名字后面是随机数,需要通过Service来做负载均衡。

当一个StatefulSet挂掉,新创建的StatefulSet会被赋予跟原来的Pod一样的名字,通过这个名字来匹配到原来的存储,实现了状态保存。因为上文提到了,每个Pod的标识附着在Pod上,无论pod被重新调度到了哪里。

成员发现

一个Pod可以通过 Downward api机制来知道自己的pod名字,也可以运行hostname来发现自己的DNS名字。StatefuleSet的服务名(governing service)在创建的时刻就已知了,所以只需要通过一个约定的环境变量把服务名传递给POD就可以。

一点八卦

为什么从PetSet改名字到StatefulSet,也是很有意思的,感兴趣的同学可以去这里看看:

Please Consider changing the name of PetSet before General Availability

实例

Kubernetes官方博客上有一个在Kubernetes上运行MogoDB的例子,见这里

借用一下里面的架构图:

在StatefulSet之上运行MongoDB


如果您看了本篇博客,觉得对您有所收获,请点击右下角的“推荐”,让更多人看到!

资助Jack47写作,打赏一个鸡蛋灌饼吧
微信打赏
支付宝打赏

Kubernetes如何支持有状态服务的部署?的更多相关文章

  1. k8s之有状态服务部署基石(基础知识)

    PV&PVC&HeadlessService 4.1.什么是无状态/有状态服务? 无状态服务: 1.没有实时的数据需要存储 (即使有,也是静态数据) 2.服务集群网络中,拿掉一个服务后 ...

  2. Kubernetes服务之“运行单实例的有状态服务”

    目标 在你的环境中创建一个PV 创建一个MySQl的Deployment 在集群中以DNS名称的方式,将MySQL暴露给其他的pod 开始之前 你需要一个Kubernetes集群,一个可以连接到集群的 ...

  3. 揭秘有状态服务上 Kubernetes 的核心技术

    背景 随着 Kubernetes 成为云原生的最热门的解决方案,越来越多的传统服务从虚拟机.物理机迁移到 Kubernetes,各云厂商如腾讯自研上云也主推业务通过Kubernetes来部署服务,享受 ...

  4. Kubernetes SatefulSet(有状态应用部署)

    Kubernetes SatefulSet(有状态应用部署) • 部署有状态应用• 解决Pod独立生命周期,保持Pod启动顺序和唯一性1. 稳定,唯一的网络标识符,持久存储2. 有序,优雅的部署和扩展 ...

  5. 基于kubernetes平台微服务的部署

    基于kubernetes平台微服务的部署 首先下载插件: kubernetes Continuous Deploy 然后去找 .kube/ 里的config 复制里面的内容 去添加凭据: 然后就是脚本 ...

  6. 使用IIS服务器部署网页,需要开启服务里的“ASP.NET 状态服务”

    否则会提示“请确保 ASP.NET State Service (ASP.NET 状态服务)已启动,并且客户端端口与服务器端口相同.如果服务器位于远程计算机上,请检查 HKEY_LOCAL_MACHI ...

  7. kubernetes的无状态服务和有状态服务介绍

    无状态服务 1)是指该服务运行的实例不会在本地存储需要持久化的数据,并且多个实例对于同一个请求响应的结果是完全一致的 2)多个实例可以共享相同的持久化数据.例如: nginx实例和tomcat实例 3 ...

  8. kubeadm安装kubernetes 1.13.1集群完整部署记录

    k8s是什么 Kubernetes简称为k8s,它是 Google 开源的容器集群管理系统.在 Docker 技术的基础上,为容器化的应用提供部署运行.资源调度.服务发现和动态伸缩等一系列完整功能,提 ...

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

    在最新发布的 Kubernetes 1.5 我们将过去的 PetSet 功能升级到了 Beta 版本,并重新命名为StatefulSet.除了依照社区民意改了名字之外,这一 API 对象并没有太大变化 ...

随机推荐

  1. SSH深度历险(四) Maven初步学习

    这几天接触这个词,很多遍了,只是浅显的体会到它在GXPT中的好处,功能之强大,又通过网络查询了资料进一步的认识学习了,和大家分享. Maven是基于项目对象模型(POM),可以通过一小段描述信息来管理 ...

  2. java linux 项目经常无故被关闭 进程无故消息

    布了几个项目.居然天天会自动的挂掉.急了.花时间解决了一下.总结方案如下: 1.磁盘满了.这大家都懂,清一下 2.tomcat在关闭的或是重启的时候,常常后台进程没有被关闭.需要用ps aux|gre ...

  3. 【Unity技巧】LOGO闪光效果

    写在前面 本文参考了风宇冲的博文,在按照这篇博文实现LOGO闪光时,发现了一些问题.最严重的就是背景无法透明,看上去背景始终是黑色的:其次就是各个变量的意义不是非常明确,调节起来不方便:而且在闪光条的 ...

  4. 分布式进阶(八)Linux提示Unable to locate package该如何处理?

    Linux提示Unable to locate package该如何处理? 当你在修改Linux软件源的时候,提示Unable to locate package错误,这是由什么原因导致的呢?又该如何 ...

  5. FT5X06 如何应用在10寸电容屏(linux-3.5电容屏驱动简析&移植10寸电容屏驱动到Android4.2) (by liukun321咕唧咕唧)

    这是几个月以前的东西了,在彻底遗忘之前拿出来好好写写.做个笔记,也算是造福后来人了.在做这个项目之前,没有做过电容屏的驱动,印象中的电容触摸屏是不需要校正的.IC支持多大的屏就要配多大的屏.但是拿到需 ...

  6. Python基础:条件判断与循环的两个要点

    一.条件判断: Python中,条件判断用if语句实现,多个条件判断时用if...elif实现:看下面一段程序 #python 3.3.5 #test if...elif age = 20 if ag ...

  7. 运行React-Native项目

    首先需要配置好环境.集体配置安装Homebrew,Node.js,React Native; 命令行开启RN项目 (如要cd 进入到当前项目的跟目录下) 1. npm install 2. react ...

  8. STL常用查找算法介绍

    adjacent_find() 在iterator对标识元素范围内,查找一对相邻重复元素,找到则返回指向这对元素的第一个元素的迭代器.否则返回past-the-end. #include <io ...

  9. Android电话拦截实现以及TelephonyManager监听的取消

    由于毕业设计题目涉及到电话拦截这一块.所以鼓捣了一下.遇到了一些问题,总结一下,以免忘记,也希望能帮助其他新人们. 本篇博客目的:实现电话的拦截 会遇到的问题:android studio下AIDL的 ...

  10. SMO实现

    #include "stdio.h" #include <vector> using namespace std; float function(float alfa[ ...