原文地址:Kubernetes如何支持有状态服务的部署?

作者: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.53Name:      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

Kubernetes支持有状态服务的部署相关推荐

  1. zookeeper和etcd有状态服务部署

    zookeeper和etcd有状态服务部署实践 docker etcd zookeeper kubernetes 4k 次阅读  ·  读完需要 78 分钟 0 一. 概述 kubernetes通过s ...

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

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

  3. Java / Cloud:如何快速创建支持Kubernetes的REST微服务

    可以肯定地说,如今微服务与云的结合风靡一时. 微服务的开发比以往任何时候都多,从而导致应用程序部署数量增加. 在过去的十年中,开发了诸如Docker和Kubernetes之类的容器化和编排工具,从而使 ...

  4. k8s 有状态服务部署

    可以使用 kubesphere,快速搭建 MySQL 环境. 有状态服务抽取配置为 ConfigMap 对应界面中的配置中心->配置 有状态服务必须使用 pvc 持久化数据 对应界面中的存储卷 ...

  5. apollo 配置中心 支持php,apollo配置中心服务端部署

    apollo配置中心服务端部署 木某人 • 2020 年 05 月 07 日 Apollo服务端安装部署 apollo-configservice:提供配置获取接口,提供配置更新推送接口,接口服务对象 ...

  6. Kubernetes 无状态服务和有状态服务

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

  7. K8s 应用管理之道 - 有状态服务

    背景 用户通过 Deployment.ReplicationController 可以方便地在 kubernetes 中部署一套高可用.可扩展的分布式无状态服务.这类应用不在本地存储数据,通过简单的负 ...

  8. 后Kubernetes时代的微服务

    \ 本文要点 \\ 当前微服务架构依然是最流行的分布式系统架构风格.Kubernetes和云原生运动已大规模地重新定义了应用设计和开发中的一些方面.\\t 在云原生平台上,服务仅具备可观测性是不够的. ...

  9. 实现Kubernetes跨集群服务应用的高可用

    我们在进行生产环境部署时得到的一个明确的需求,是Kubernetes用户希望服务部署能够zone.跨区域.跨集群甚至跨云边界(译者:如跨云供应商).相比单集群多zone部署,跨集群服务提供按地域分布, ...

最新文章

  1. iBATIS之父:iBATIS框架的成功蜕变
  2. python风变编程是骗局吗-风变编程:花时间学Python,是对自己未来最好的投资
  3. Python知识点笔记-列表list、元组tuple和dict类型
  4. Asp.net 面向接口可扩展框架之核心容器
  5. [中山市选]杀人游戏 (Tarjan缩点)
  6. UML总结---UML九种图关系说明
  7. 核心指导网络由任务编码器_指导新编码员的最佳做法
  8. C++ IO常用读写操作
  9. html 中rem是什么单位,了解并使用CSS中的rem单位
  10. 防爆技术在工业电子秤中的最新应用(转)
  11. 晒一波程序员的桌面,逼格超级高
  12. 态度决定一切细节决定成败_字体设计可以决定设计的成败:选择字体的过程
  13. 全平台视频转GIF软件对比与推荐(iOS/安卓/Windows/Mac)
  14. java猜拳_java实现猜拳小游戏
  15. CSMA/CD协议详解
  16. java0.632数据类型_Object-c提供基本数据类型
  17. http.ListenAndServe
  18. 笔记本电脑无法连接无法检测到第二显示屏
  19. 基于MT5的短线反向交易策略
  20. c语言程序编程线性方程,C语言编程求解线性方程.doc

热门文章

  1. JavaScript中的输入输出语句
  2. gitlab之主要目录介绍
  3. gitlab之 修改默认的仓库存储目录及数据迁移
  4. PCL之求点云的BoundingBox
  5. MySQL基本介绍(一)
  6. c语言如何找一个数的ac码,详细解析C语言中的开方实现
  7. 动态规划算法经典例题_c动态规划精简例题
  8. Linux常用基本命令:三剑客命令之-awk内置函数用法
  9. 如何使用Selenium-Grid
  10. 性能测试监控工具nmon使用方法