Kubernetes中的statefulset控制器
华子目录
- `statefulset`控制器
- 功能
- StatefulSet的组成部分
- 问题复现示例
- statefulset示例
- 总结
statefulset
控制器
功能
Statefulset
是为了解决有状态服务
的问题
设计的StatefulSet
将应用状态
抽象成了两种情况
拓扑状态
:应用实例
必须按照某种顺序
启动。新
创建的Pod
必须和原来Pod
的网络标识(pod的名字)
一样存储状态
:应用
的多个实例
分别绑定
了不同存储数据
StatefulSet控制器
给所有
的Pod
进行了编号
,编号规则
是:$(statefulset名称)-$(序号)
,从0
开始Pod
被删除
后重建
,重建Pod
的网络标识
也不会改变
,Pod
的拓扑状态
按照Pod
的“名字+编号
”的方式固定下来
,并且为每个Pod
提供了一个固定且唯一
的访问入口
,Pod
对应的DNS记录
StatefulSet的组成部分
Headless Service无头服务
:用来定义pod
网络标识
,生成可解析的DNS记录
volumeClaimTemplates
:创建pvc
,指定pvc
名称,自动创建pvc
且pvc
由存储类
供应StatefulSet
:管理pod
的
问题复现示例
#创建一个名为test的deployment控制器,运行2个pod,运行myapp镜像
[root@k8s-master volume]# kubectl create deployment test --image myapp:v1 --replicas 2 --dry-run=client -o yaml > test.yml
[root@k8s-master volume]# vim test.yml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: test
name: test
spec:
replicas: 2
selector:
matchLabels:
app: test
template:
metadata:
labels:
app: test
spec:
containers:
- image: myapp:v1
name: myapp
[root@k8s-master volume]# kubectl apply -f test.yml
deployment.apps/test created
[root@k8s-master volume]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
test-db99b9599-cw8g5 1/1 Running 0 9s 10.244.2.3 k8s-node2.org <none> <none>
test-db99b9599-lws9h 1/1 Running 0 9s 10.244.1.4 k8s-node1.org <none> <none>
#控制器名字-repliacset的id-pod的id
回收
控制器中的pod
- 将
--replicas
设为0
#将--replicas设为0
[root@k8s-master volume]# kubectl scale deployment test --replicas 0
deployment.apps/test scaled
#虽然pods没有了
[root@k8s-master volume]# kubectl get pods -o wide
No resources found in default namespace.
#但是deployment控制器还在
[root@k8s-master volume]# kubectl get deployments.apps
NAME READY UP-TO-DATE AVAILABLE AGE
test 0/0 0 0 5m48s
再重新开2
个pod
[root@k8s-master volume]# kubectl scale deployment test --replicas 2
deployment.apps/test scaled
[root@k8s-master volume]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
test-db99b9599-9s488 1/1 Running 0 7s 10.244.2.4 k8s-node2.org <none> <none>
test-db99b9599-d7qs5 1/1 Running 0 7s 10.244.1.5 k8s-node1.org <none> <none>
#我们发现:pod的id在变化,pod中的ip也在变化
我们发现:在控制器
中重新建立pod
,pod
的id
在变化
,pod
中的ip
也在变化
,那么StatefulSet
控制器就是解决这一问题
#回收
[root@k8s-master volume]# kubectl delete -f test.yml
deployment.apps "test" deleted
statefulset示例
建立statefulset控制器
#建立一个名为web的statefulset控制器
[root@k8s-master volume]# vim statefulset.yml
apiVersion: apps/v1 #Kubernetes API版本,这里是apps/v1
kind: StatefulSet #声明这是一个StatefulSet资源
metadata: #资源的元数据
name: web #StatefulSet的名称,这里是web
spec: #StatefulSet的具体规格
serviceName: "nginx-svc" #指定了用于这个StatefulSet内部通信的服务名称,这里是nginx-svc。这个服务会负责为StatefulSet中的每个Pod提供一个DNS名称,格式为<pod-name>.<service-name>
replicas: 3
selector:
matchLabels:
app: nginx #标签选择器,这里选择标签app: nginx的Pod
template:
metadata:
labels:
app: nginx #Pod定义标签,这里是app: nginx
spec:
containers:
- name: nginx
image: nginx
volumeMounts: #容器需要挂载的卷
- name: www #引用的卷名称,这里与后面定义的volumeClaimTemplates中的卷名称对应
mountPath: /usr/share/nginx/html #卷在容器内的挂载路径
volumeClaimTemplates: #定义了用于持久化存储的持久卷声明模板。这些模板会为每个Pod创建一个独立的持久卷声明(PVC)
- metadata: #持久卷声明的元数据
name: www #持久卷声明的名称,这里与volumeMounts中引用的卷名称对应
spec: #持久卷声明的规格
storageClassName: nfs-client #指定了存储类名称,这里是nfs-client
accessModes: #访问模式
- ReadWriteOnce #单点读写
resources: #定义了资源请求
requests: #具体的资源请求
storage: 1Gi #请求的存储大小为1GiB
建立无头服务
[root@k8s-master volume]# vim headless.yml
apiVersion: v1
kind: Service
metadata:
labels:
run: nginx-svc
name: nginx-svc
spec:
ports:
- port: 80
selector:
app: nginx
type: ClusterIP
clusterIP: None
[root@k8s-master volume]# kubectl apply -f statefulset.yml
statefulset.apps/web created
[root@k8s-master volume]# kubectl apply -f headless.yml
service/nginx-svc created
#查看控制器
[root@k8s-master volume]# kubectl get statefulsets.apps
NAME READY AGE
web 3/3 7m23s
#查看pod
[root@k8s-master volume]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web-0 1/1 Running 0 7m7s 10.244.2.5 k8s-node2.org <none> <none>
web-1 1/1 Running 0 3m59s 10.244.1.6 k8s-node1.org <none> <none>
web-2 1/1 Running 0 3m56s 10.244.2.6 k8s-node2.org <none> <none>
[root@k8s-master volume]# kubectl get svc nginx-svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-svc ClusterIP None <none> 80/TCP 10m
[root@k8s-master volume]# kubectl describe svc nginx-svc
Name: nginx-svc
Namespace: default
Labels: run=nginx-svc
Annotations: <none>
Selector: app=nginx
Type: ClusterIP
IP Family Policy: SingleStack
IP Families: IPv4
IP: None
IPs: None
Port: <unset> 80/TCP
TargetPort: 80/TCP
Endpoints: 10.244.1.6:80,10.244.2.5:80,10.244.2.6:80
Session Affinity: None
Events: <none>
#查看pvc,发现自动创建了pvc
[root@k8s-master volume]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
www-web-0 Bound pvc-b6b51ed2-0272-415b-af86-3f3661aaa7b7 1Gi RWO nfs-client <unset> 16m
www-web-1 Bound pvc-0cc1c027-458a-4ccf-be2a-c42e12a429ba 1Gi RWO nfs-client <unset> 13m
www-web-2 Bound pvc-b03203d1-3430-4661-af7c-fa13ca826f27 1Gi RWO nfs-client <unset> 13m
#查看pv,发现自动创建了pv
[root@k8s-master volume]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS VOLUMEATTRIBUTESCLASS REASON AGE
pvc-0cc1c027-458a-4ccf-be2a-c42e12a429ba 1Gi RWO Delete Bound default/www-web-1 nfs-client <unset> 14m
pvc-b03203d1-3430-4661-af7c-fa13ca826f27 1Gi RWO Delete Bound default/www-web-2 nfs-client <unset> 14m
pvc-b6b51ed2-0272-415b-af86-3f3661aaa7b7 1Gi RWO Delete Bound default/www-web-0 nfs-client <unset> 18m
#我们发现:在nfs服务器上自动创建了目录
[root@harbor nfsdata]# ls
default-www-web-0-pvc-b6b51ed2-0272-415b-af86-3f3661aaa7b7
default-www-web-1-pvc-0cc1c027-458a-4ccf-be2a-c42e12a429ba
default-www-web-2-pvc-b03203d1-3430-4661-af7c-fa13ca826f27
#创建index.html测试文件
[root@harbor nfsdata]# echo web2 > default-www-web-2-pvc-b03203d1-3430-4661-af7c-fa13ca826f27/index.html
[root@harbor nfsdata]# echo web1 > default-www-web-1-pvc-0cc1c027-458a-4ccf-be2a-c42e12a429ba/index.html
[root@harbor nfsdata]# echo web0 > default-www-web-0-pvc-b6b51ed2-0272-415b-af86-3f3661aaa7b7/index.html
[root@k8s-master volume]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web-0 1/1 Running 0 23m 10.244.2.5 k8s-node2.org <none> <none>
web-1 1/1 Running 0 20m 10.244.1.6 k8s-node1.org <none> <none>
web-2 1/1 Running 0 20m 10.244.2.6 k8s-node2.org <none> <none>
[root@k8s-master volume]# curl 10.244.2.5
web0
[root@k8s-master volume]# curl 10.244.1.6
web1
[root@k8s-master volume]# curl 10.244.2.6
web2
回收statefulset控制器中的pod
[root@k8s-master volume]# kubectl scale statefulset web --replicas 0
statefulset.apps/web scaled
重新建立pod
[root@k8s-master volume]# kubectl scale statefulset web --replicas 3
statefulset.apps/web scaled
#我们发现虽然ip变了,但是pod的名字没有变,及pod的域名没有变
[root@k8s-master volume]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web-0 1/1 Running 0 24s 10.244.2.7 k8s-node2.org <none> <none>
web-1 1/1 Running 0 22s 10.244.1.7 k8s-node1.org <none> <none>
web-2 1/1 Running 0 22s 10.244.2.8 k8s-node2.org <none> <none>
我们可以通过访问域名
来访问之前重建过
的pod中的应用
- 访问域名:
pod名.service名
[root@k8s-master volume]# kubectl run -it test --image busyboxplus
/ # curl web-0.nginx-svc
web0
/ # curl web-1.nginx-svc
web1
/ # curl web-2.nginx-svc
web2
#当删除整个statefulset控制器时
[root@k8s-master volume]# kubectl delete -f statefulset.yml
statefulset.apps "web" deleted
[root@k8s-master volume]# kubectl get pods
No resources found in default namespace.
#发现数据依然保留
[root@harbor nfsdata]# ls
default-www-web-0-pvc-b6b51ed2-0272-415b-af86-3f3661aaa7b7
default-www-web-1-pvc-0cc1c027-458a-4ccf-be2a-c42e12a429ba
default-www-web-2-pvc-b03203d1-3430-4661-af7c-fa13ca826f27
#重新建立statefulset控制器时
[root@k8s-master volume]# kubectl apply -f statefulset.yml
statefulset.apps/web created
#发现之前的数据也会被继续使用
[root@k8s-master volume]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web-0 1/1 Running 0 17s 10.244.2.10 k8s-node2.org <none> <none>
web-1 1/1 Running 0 15s 10.244.1.8 k8s-node1.org <none> <none>
web-2 1/1 Running 0 13s 10.244.2.11 k8s-node2.org <none> <none>
[root@k8s-master volume]# kubectl run -it test --image busyboxplus
/ # curl web-0.nginx-svc
web0
/ # curl web-1.nginx-svc
web1
/ # curl web-2.nginx-svc
web2
只有当删除pvc
时,nfs服务器
中的数据
才会被删除
#删除pvc
[root@k8s-master volume]# kubectl delete pvc --all
persistentvolumeclaim "www-web-0" deleted
persistentvolumeclaim "www-web-1" deleted
persistentvolumeclaim "www-web-2" deleted
#发现nfs服务器中的数据没了
[root@harbor nfsdata]# ls
[root@harbor nfsdata]#
总结
在statefulset控制器
创建的pod
,每次重新创建pod
时,虽然pod
的ip
会变,但是每个pod
的网络标识
(pod的名字
)和pod
的存储状态
不会变