目录
一、无状态与有状态
1.1无状态
1.2有状态
二、StatefulSet 控制器
2.1 StatefulSet 控制器概述
2.2StatefulSet 控制器:网络标识
2.3StatefulSet 控制器:独享存储
一、无状态与有状态
Deployment控制器设计原则: 管理的所有Pod一模一样,提供同一个服务, 也不考虑在哪台Node 运行,可随意扩容和缩容。这种应用称为“无状态”,例如Web服务。
在实际的场景中,并不能满足所有应用,尤其是分布式应用,会部署多个实例, 这些实例之间往往有依赖关系,例如主从关系、主备关系, 这种应用称为“有状态”, 例如MySQL主从、 Etcd集群。
1.1无状态
(1)指该服务运行的实例不会在本地存储需要持久化的数据,并且多个实例对于同一个请求响应的结果是完全一致的。
(2)多个实例可以共享相同的持久化数据。例如:nginx实例,tomcat实例等
(3)相关的k8s资源有:ReplicaSet、ReplicationController、Deployment等,由于是无状态服务,所以这些控制器创建的pod序号都是随机值。并且在缩容的时候并不会明确缩容某一个pod,而是随机的,因为所有实例得到的返回值都是一样,所以缩容任何一个pod都可以
1.2有状态
(1)有状态服务 可以说是 需要数据存储功能的服务、或者指多线程类型的服务,队列等。(mysql数据库、kafka、zookeeper等)
(2)每个实例都需要有自己独立的持久化存储,并且在k8s中是通过申明模板来进行定义。持久卷申明模板在创建pod之前创建,绑定到pod中,模板可以定义多个。
二、StatefulSet 控制器
2.1 StatefulSet 控制器概述
StatefulSet控制器用于部署有状态应用, 满足一些有状态应用的需求:
• Pod有序的部署、扩容、删除和停止
• Pod分配一个稳定的且唯一的网络标识
• Pod分配一个独享的存储
2.2StatefulSet 控制器:网络标识
稳定的网络标识: 使用Headless Service (相比普通Service只是将spec.clusterIP定义为None) 来维 护Pod网络身份,会为每个Pod分配一个数字编号并且按照编号顺序部署。还需要在StatefulSet添加 serviceName: “nginx”字段指定StatefulSet控制器要使用这个Headless Service。
稳定主要体现在主机名和Pod A记录:
• 主机名: <statefulset名称>- <编号>
• Pod DNS A记录: <statefulset名称-编号>. <service-name> . <namespace>.svc.cluster.local
service.yaml
apiVersion: v1
kind: Service
metadata:
name: headless-web
namespace: default
spec:
clusterIP: None
ports:
- port: 80 # service端口
protocol: TCP # 协议
targetPort: 80 # 容器端口
selector: # 标签选择器
app: nginx # 指定关联的 Pod的标签
type: ClusterIP # 服务类型
查看 创建的 headless-web service
statefulset-web.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: statefulset-web
spec:
serviceName: headless-web
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
name: web
从web0开始创建 pod
我们发现 创建的 三个容器的主机名与pod 的名称是一致的,即使pod 删除 重新创建 主机名也是 不变的,有稳定的主机名。
启动一个容器 dns-test 查看web , headless-web service的DNS 解析结果
kubectl run -i -t dns-test --image busybox:1.28.4 /bin/sh
nslookup (全称 name server lookup) ,是一个在命令行界面下的网络工具
使用 nslookup 查看 DNS的结果
[root@k8s-master1 statefulset]# kubectl run -i -t dns-test --rm --image busybox:1.28.4 /bin/sh
If you don't see a command prompt, try pressing enter.
/ # nslookup headless-web
Server: 10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local
Name: headless-web
Address 1: 10.244.36.75 statefulset-web-1.headless-web.default.svc.cluster.local
Address 2: 10.244.36.76 statefulset-web-2.headless-web.default.svc.cluster.local
Address 3: 10.244.169.136 statefulset-web-0.headless-web.default.svc.cluster.local
/ # nslookup statefulset-web-1.headless-web.default.svc.cluster.local
Server: 10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local
Name: statefulset-web-1.headless-web.default.svc.cluster.local
Address 1: 10.244.36.75 statefulset-web-1.headless-web.default.svc.cluster.local
即使我们pod 重启 IP 发生变化,三条 DNS记录名称是不变的 ,我们可以使用固定的DNS名称。
2.3StatefulSet 控制器:独享存储
独享存储: StatefulSet的存储卷使用VolumeClaimTemplate创建,称为卷申请模板, 当StatefulSet使用 VolumeClaimTemplate创建一个PersistentVolume时,同样也会为每个Pod分配并创建一个编号的PVC, 每个PVC绑定对应的PV,从而保证每个Pod都拥有独立的存储。
statefulset-web.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: statefulset-web
spec:
serviceName: headless-web
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates: ## statefulset 专属
- metadata:
name: www
spec:
storageClassName: "managed-nfs-storage" ## 基于PV的动态创建
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
验证pvc和pv
NFS Server 服务器上成功创建存储路径
输入内容 ,可以成功访问
cd /ifs/kubernetes/
echo ' hello pod 00' > default-www-web-0-pvc-c976defd-bd81-4c7c-b489-9801fc50cc60/index.html
echo ' hello pod 01' > default-www-web-1-pvc-385c9232-4e5f-4e46-9f7a-a4ba58f45577/index.html
echo ' hello pod 02' > default-www-web-2-pvc-74ad04fa-ab96-444f-92a0-9bb3e03c1118/index.html
我们 删除 pod 后, 存储的文件还是存在的 ,如果重新创建pod , k8s会重新 创建pv 和pvc, 绑定 对用的路径,数据不会发生变化。
小结
StatefulSet与Deployment区别:有身份的!
身份三要素:
• 域名
• 主机名
• 存储(PVC)