作者: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. Android开发学习之路--数据持久化之初体验

    上班第一天,虽然工作上处于酱油模式,但是学习上依旧不能拉下,接着学习android开发吧,这里学习数据持久化的 知识. 其实数据持久化就是数据可以保存起来,一般我们保存数据都是以文件,或者数据库的形式 ...

  2. Linux上程序调试的基石(2)--GDB

    3. GDB的实现 GDB是GNU发布的一个强大的程序调试工具,用以调试C/C++程序.可以使程序员在程序运行的时候观察程序在内存/寄存器中的使用情况.它的实现也是基于ptrace系统调用来完成的.  ...

  3. LCD 常用的客观效果指标和测试方法

    1.DPI--精密度: 评分标准 DPI 评分 DPI<200 50 200≤DPI<250 60 250≤DPI<300 70 300≤DPI<350 80 350≤DPI& ...

  4. Android 面向协议编程 体会优雅编程之旅

    Android中面向协议编程的深入浅出 http://blog.csdn.net/sk719887916/article/details skay编写 说起协议,现实生活中大家第一感觉会想到规则或者约 ...

  5. IDEA中运行KafkaWordCount程序

    1,从spark的example中找到KafkaWordCount.scala文件复制到idea编辑器中,引入包: 2,编辑configuration,     (1)KafkaWordCountPr ...

  6. Spark-streaming 连接flume

    1,程序为spark的example中的FlumeEventCount示例 object FlumeEventCount { def main(args: Array[String]) { Strea ...

  7. OpenCV Python教程(1、图像的载入、显示和保存)

    原文地址:http://blog.csdn.net/sunny2038/article/details/9057415 转载请详细注明原作者及出处,谢谢! 本文是OpenCV  2 Computer ...

  8. Mybatis插件原理分析(二)

    在上一篇中Mybatis插件原理分析(一)中我们主要介绍了一下Mybatis插件相关的几个类的源码,并对源码进行了一些解释,接下来我们通过一个简单的插件实现来对Mybatis插件的运行流程进行分析. ...

  9. Mybatis插件原理分析(一)

    我们首先介绍一下Mybatis插件相关的几个类,并对源码进行了简单的分析. Mybatis插件相关的接口或类有:Intercept.InterceptChain.Plugin和Invocation,这 ...

  10. Linux的启动流程 (二)

    引:本文以RedHat9.0和i386平台为例,剖析了从用户打开电源直到屏幕出现命令行提示符的整个Linux启动过程.并且介绍了启动中涉及到的各种文件.阅读Linux源代码,无疑是深入学习Linux的 ...