[TOC]
## **StatefulSet与Headless Service**
在k8s中,Deployment能够很好地用来管理无状态服务。而如果我们要发布有状态服务,则一般需要使用到另一种资源:StatefulSet。本文将以Mysql为例,来讲解StatefulSet的原理。
首先我们来看一下Mysql的一些特点:
(1)Mysql有主从之分,从节点第一次启动初始化时需要连主节点,即主节点启动后,从节点才能启动。主从节点的启动顺序如何保证?
如下是一个最简单的statefulset:
```
to be added
```
可以看出,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的定义文件:
```
to be added
```
它与普通的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,并且会在Pod `mysql-0` 中使用这个PVC。同理,为 `mysql-1` 创建并使用的PVC为`mysqldata-mysql-1`。这样,就保证了每个Pod都能有自已单独的存储。
当mysql-0被重启后,statefulset constroller会先寻找PVC `mysqldata-mysql-0` 是否存在,如果存在则直接使用。这样,就保证了Pod被重启后,还能使用到原来的存储。
当然,实际中mysql的容器化不只是上面那么简单,下一节我们讲述mysql容器化实践。
## **总结**
最后,我们用三个词来总结一下StatefulSet的特点
* 启动顺序固定性
* 网络标识唯一性
* 存储状态不变性
疑问:statefulset中为什么需要spec.serviceName?上面的分析中好像这个字段并没有用到?
- 常用命令
- 安装
- 安装Kubeadm
- 安装单Master集群
- 安装高可用集群(手动分发证书)
- 安装高可用集群(自动分发证书)
- 启动参数解析
- certificate-key
- ETCD相关参数
- Kubernetes端口汇总
- 安装IPv4-IPv6双栈集群
- 下载二进制文件
- 使用Kata容器
- 快速安装shell脚本
- 存储
- 实践
- Ceph-RBD实践
- CephFS实践
- 对象存储
- 阿里云CSI
- CSI
- 安全
- 认证与授权
- 认证
- 认证-实践
- 授权
- ServiceAccount
- NodeAuthorizor
- TLS bootstrapping
- Kubelet的认证
- 准入控制
- 准入控制示例
- Pod安全上下文
- Selinux-Seccomp-Capabilities
- 给容器配置安全上下文
- PodSecurityPolicy
- K8S-1.8手动开启认证与授权
- Helm
- Helm命令
- Chart
- 快速入门
- 内置对象
- 模板函数与管道
- 模板函数列表
- 流程控制
- Chart依赖
- Repository
- 开源的Chart包
- CRD
- CRD入门
- 工作负载
- Pod
- Pod的重启策略
- Container
- 探针
- 工作负载的状态
- 有状态服务
- 网络插件
- Multus
- Calico+Flannel
- 容器网络限速
- 自研网络插件
- 设计文档
- Cilium
- 安装Cilium
- Calico
- Calico-FAQ
- IPAM
- Whereabouts
- 控制平面与Pod网络分开
- 重新编译
- 编译kubeadm
- 编译kubeadm-1.23
- 资源预留
- 资源预留简介
- imagefs与nodefs
- 资源预留 vs 驱逐 vs OOM
- 负载均衡
- 灰度与蓝绿
- Ingress的TLS
- 多个NginxIngressController实例
- Service的会话亲和
- CNI实践
- CNI规范
- 使用cnitool模拟调用
- CNI快速入门
- 性能测试
- 性能测试简介
- 制作kubemark镜像
- 使用clusterloader2进行性能测试
- 编译clusterloader2二进制文件
- 搭建性能测试环境
- 运行density测试
- 运行load测试
- 参数调优
- Measurement
- TestMetrics
- EtcdMetrics
- SLOMeasurement
- PrometheusMeasurement
- APIResponsivenessPrometheus
- PodStartupLatency
- FAQ
- 调度
- 亲和性与反亲和性
- GPU
- HPA
- 命名规范
- 可信云认证
- 磁盘限速
- Virtual-kubelet
- VK思路整理
- Kubebuilder
- FAQ
- 阿里云日志服务SLS