kubernetes
  • Introduction
  • 安装
    • 组件端口
    • 二进制安装
    • Kubeadm
      • 安装单Master集群
      • 安装高可用集群(手动分发证书)
      • 安装高可用集群(自动上传证书)
      • 安装ETCD集群
      • 安装高可用集群(外部ETCD)
    • 启动参数解析
      • ETCD相关参数
  • 负载均衡
    • Service
    • Ingress
    • 安装MetalLB
    • Nginx-ingress-controller
      • 转发TCP与UDP服务
      • 启动参数
      • 自定义Nginx模板
  • 存储
    • Volume
    • PV与PVC
    • StorageClass
    • Local-PV
      • Static-Provisioner
    • 实践
      • Ceph-RBD
      • NFS
  • 有状态服务
    • Mysql实践
    • Operator
      • Etcd
      • Zookeeper
      • Mysql
  • 认证与授权
    • 认证
      • 实践
    • 授权
  • Helm
    • 安装
    • Chart
      • 依赖
    • Helm命令
    • Repository
  • 日志
  • 监控
    • Prometheus体系
      • Prometheus
        • 内置函数
        • 配置
          • 规则文件
        • PromQL
      • Exporter
        • Metrics
      • Grafana
        • 配置
      • AlertManager
        • 配置
    • 容器监控
      • Cadvisor的指标
      • k8s中部署Prom与Cadvisor
  • Istio
  • 资源预留
    • imagefs与nodefs
    • 总结
  • 集群联邦
    • 联邦DNS原理
    • 联邦DNS安装
    • 安装federation-v1
  • Other
    • ImagePullSecret
    • QOS
    • Apiserver的代理
    • 资源配额
Powered by GitBook
On this page

Was this helpful?

有状态服务

《StatefulSet与Headless Service》

在k8s中,Deployment能够很好地用来管理无状态服务。而如果我们要发布有状态服务,则一般需要使用到另一种资源:StatefulSet。本文将以Mysql为例,来讲解StatefulSet的原理。

首先我们来看一下Mysql的一些特点:

(1)Mysql有主从之分,从节点第一次启动初始化时需要连主节点,即主节点启动后,从节点才能启动。主从节点的启动顺序如何保证?

如下是一个最简单的statefulset:

可以看出,StatefulSet的定义与Deployment几乎没什么差别,除了多了一个spec.serviceName字段。这个字段这里先不讲,本节后面会讲到。

上面的StatefulSet会创建三个Pod,与Deployment不同是,三个Pod的命名是固定的,分别为mysql-0、mysql-1、mysql-2,且三个Pod的启动是有顺序的,只有mysql-0启动成功后,mysql-1才会开始创建。而且,任何一个Pod被重启后,其命名不会改变

所以,我们可以用一个statefulset来创建一个mysql集群,mysql-0作为主节点,mysql-1和mysql-2作为从节点

(2)mysql的从节点需要连接主节点,主节点mysql-0的访问方式是什么,如何保持不变?

这里,我们就需要介绍到k8s的另一个对象:Headless Service。如下是一个Headless Service的定义文件:

它与普通的Service不同的是,spec.clusterIP明确指定为了None。也就是说,这个Service将不会有一个ClusterIP。

我们知道,对于普通的Service,DNS插件会生成一条A记录,记录<serviceName>.<namespace>.svc.cluster.local这个域名的IP地址为clusterIP。

而对于Headless Service,DNS插件会为Service的每个Pod都生成一条A记录。这条A记录的域名为<podName>.<ServiceName>.<namespace>.svc.cluster.local,A记录的IP为Pod的IP。

所以,当从节点mysql-1与mysql-2去访问主节点时,使用域名mysql-0.mysql.default.svc.cluster.local就可以了,不管mysql-0这个Pod的IP是多少。

(3)mysql的数据如何持久化?

我们直接给出statefulset持久化数据的方案,如下:

上面的statefulset中,我们使用了一个volumeClaimTemplates。在Pod的volumeMounts中,使用了mysql这个Template。

那么,statefulset controller在创建Podmysql-0的时候,同时会根据这个Template创建一个名字为mysqldata-mysql-0的PVC,并且会在Podmysql-0中使用这个PVC。同理,为mysql-1创建并使用的PVC为mysqldata-mysql-1。这样,就保证了每个Pod都能有自已单独的存储。

当mysql-0被重启后,statefulset constroller会先寻找PVCmysqldata-mysql-0是否存在,如果存在则直接使用。这样,就保证了Pod被重启后,还能使用到原来的存储。

当然,实际中mysql的容器化不只是上面那么简单,下一节我们讲述mysql容器化实践。

总结

最后,我们用三个词来总结一下StatefulSet的特点

  • 启动顺序固定性

  • 网络标识唯一性

  • 存储状态不变性

疑问:statefulset中为什么需要spec.serviceName?上面的分析中好像这个字段并没有用到?

PreviousNFSNextMysql实践

Last updated 5 years ago

Was this helpful?