[Kubernetes]深刻理解StatefulSet

前面我写的一系列博客,若是你可以耐心看到这一篇,那你应该对一个概念就不是太陌生了:Deployment.
为何提这个概念呢,这就要说到Deployment的一个不足了.Deployment不足以覆盖全部的应用编排问题,由于在它看来,一个应用的全部Pod,是彻底同样的,因此它们之间就没有顺序,也无所谓运行在哪台宿主机上.须要时,Deployment就经过Pod模板建立新的Pod,不须要时,就"杀掉"任意一个Pod.
可是在实际场景中,并非全部应用都知足这样的要求.好比:主从关系,主备关系,还有就是数据存储类应用,多个实例一般会在本地磁盘上保存一份数据,而这些实例一旦被杀掉,即便重建出来,实例与数据之间的对应关系也已经丢失,从而致使应用失败.
这种实例之间有不对等关系,或者有依赖关系的应用,被称为"有状态应用"(Stateful Application)
为了能对"有状态应用"作出支持,Kubernetes在Deployment基础上,扩展出了:StatefulSet.
nginx

StatefulSet设计

StatefulSet将真实世界里的应用状态,抽象为了两种状况:web

  • 1,拓扑状态.这种状况是说,应用的多个实例之间不是彻底对等的关系.这些应用实例,必须按照某些顺序启动,好比某个应用的主节点A要先于B启动,那么当我把A和B两个节点删除以后,从新建立出来时,也要是这个顺序才行.而且,新建立出来的A和B,必须和原来的A和B网络标识同样,这样原先的访问者才能使用一样的方法,访问到这个新Pod.
  • 2,存储状态.这种状况是说,应用的多个实例分别绑定了不一样的存储数据.对于这些应用实例来讲,Pod A第一次读取到的数据,和隔了十分钟以后再次读取到的数据,应该是同一份,哪怕在此期间Pod A被从新建立过.
因此,StatefulSet的核心功能,就是经过某种方式,记录这些状态,而后在Pod被从新建立时,可以为新Pod恢复这些状态.
Headless Service

在深刻了解StatefulSet以前,我们先来说讲Headless Service.
咱们知道,Service是Kubernetes项目中用来将一组Pod暴露给外界访问的一种机制,好比,一个Deployment有3个Pod,那么我就能够定义一个Service,而后用户只要能访问到这个Service,就能访问到某个具体的Pod.
可是,这个Service是怎么被访问到的呢?
api

第一种方式,以Service的VIP(Virtual IP,即:虚拟IP)方式.好比:当我访问192.168.0.1这个Service的IP地址时,它就是一个VIP.在实际中,它会把请求转发到Service代理的具体Pod上.
第二种方式,就是以Service的DNS方式.在这里又分为两种处理方法:第一种是Normal Service.这种状况下,当访问DNS记录时,解析到的是Service的VIP.第二种是Headless Service.这种状况下,访问DNS记录时,解析到的就是某一个Pod的IP地址.
能够看到,Headless Service不须要分配一个VIP,而是能够直接以DNS记录的方式解析出被代理Pod的IP地址.这样设计有什么好处呢?
这样设计可使Kubernetes项目为Pod分配惟一"可解析身份".而有了这个身份以后,只要知道了一个Pod的名字以及它对应的Service的名字,就能够很是肯定地经过这条DNS记录访问到Pod的IP地址.
服务器

再回到StatefulSet

介绍完Headless Service以后,我们再回来说讲,StatefulSet的核心功能,是如何在Pod被从新建立时,可以为新Pod恢复这些状态.网络

为了详细讲解,如今编写一个StatefulSet的YAML文件,以下:app

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  serviceName: "nginx"
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.9.1
        ports:
        - containerPort: 80
          name: web

能够看到,在这个YAML文件中,多了一个serviceName=nginx字段.这个字段的做用,就是告诉StatefulSet控制器,在执行控制循环时,要使用nginx这个Headless Service来保证Pod的"可解析身份."这样,在建立Pod过程当中,StatefulSet给它所管理的全部Pod名字,进行编号,使得每一个Pod实例不重复.而更重要的是,这些Pod的建立,也是严格按照编号顺序来进行的.
这样的意思就是说,当有主从关系时,有明确前后关系时,StatefulSet经过这种机制,使得前后建立顺序成为可能.
less

整个StatefulSet流程

接下来回顾一下整个流程.
首先,StatefulSet的控制器直接管理的是Pod,而StatefulSet区分这些实例的方式,就是经过在Pod的名字里面加上事先约定好的编号.
其次,Kubernetes经过Headless Service,为这些有编号的Pod,在DNS服务器中生成带有一样编号的DNS记录.只要StatefulSet可以保证这些Pod名字里的编号不变,那么Service中DNS记录也就不会变.
最后,StatefulSet还为每个Pod分配并建立一个一样编号的PVC.这样就能够保证每一个Pod都拥有一个独立的Volume.在这种状况下,即便Pod被删除,它所对应的PVC和PV依然会留下来,因此当这个Pod被从新建立出来以后,Kubernetes会为它找到一样编号的PVC,挂载这个PVC对应的Volume,从而获取到之前保存在Volume中的数据.
svg

其实StatefulSet就是一种特殊的Deployment,只不过它的每一个Pod都被编号了.正是因为这种机制,使得具备主从关系的建立成为可能.学习

关于StatefulSet相关内容到这里就介绍的差很少了.
以上内容来自我学习<深刻剖析Kubernetes>专栏文章以后的一些看法,有偏颇之处,还望指出.
感谢您的阅读~
设计

相关文章
相关标签/搜索