• [Kubernetes]深入理解StatefulSet


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

    StatefulSet设计

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

    • 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是怎么被访问到的呢?

    第一种方式,以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文件,如下:

    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通过这种机制,使得先后创建顺序成为可能.

    整个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中的数据.

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

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

  • 相关阅读:
    css定位
    css盒子
    css元素分类
    Css属性
    Css基础2
    啊啊啊啊
    函数指针
    重载函数
    成员函数
    资源网站
  • 原文地址:https://www.cnblogs.com/zll-0405/p/10786548.html
Copyright © 2020-2023  润新知