k8s中pod资源分为有状态(数据类型的container)和无状态(服务类型container)。
k8s中的数据存储一般是以volume挂载存储卷,在多node集群模式下,最优的方案就是提供一个存储系统(存储系统的选择条件: 可以远程访问,可以多线程读写等),k8s提供的nfs,gluster,cepf等,具体的使用方法可以使用kubectl explain pod.spec查看。一般的无状态服务类型直接把文件存储在存储系统固定的目录下,在k8s的pod创建时,mount该存储目录即可。但是有些服务不能使用该存储模式,例如redis集群,es等,这些数据都是分开存储的,当pod重启之后,pod的ip和主机名数据都已经变化了,所以对于有状态的服务日常volume就不适用。
可以创建一个StatefulSet资源代替ReplicaSet来运行这类pod.它们是专门定制的一类应用,这类应用中每一个实例都是不可替代的个体,都拥有稳定的名字和状态。
对比StatefulSet 与 ReplicaSet 或 ReplicationController
RS或RC管理的pod副本比较像牛,它们都是无状态的,任何时候它们都可以被一个全新的pod替换。然后有状态的pod需要不同的方法,当一个有状态的pod挂掉后,这个pod实例需要在别的节点上重建,但是新的实例必须与被替换的实例拥有相同的名称、网络标识和状态。这就是StatefulSet如何管理pod的。
StatefulSet 保证了pod在重新调度后保留它们的标识和状态。它让你方便地扩容、缩容。与RS类似,StatefulSet也会指定期望的副本数,它决定了在同一时间内运行的宠物数。也是依据pod模版创建的,与RS不同的是,StatefulSet 创建的pod副本并不是完全一样的。每个pod都可以拥有一组独立的数据卷(持久化状态)。另外pod的名字都是规律的(固定的),而不是每个新pod都随机获取一个名字。
提供稳定的网络标识
StatefulSet 创建的pod的名称,按照从零开始的顺序索引,这个会体现在pod的名称和主机名称上,同样还会体现在pod对应的固定存储上。
创建statefulset服务,存储使用nfs
先基于nfs创建pv,master和node节点上必须安装nfs-utils不然无法mount
查看nfs共享的目录:
[root@k8s-3 ~]# showmount -e 192.168.191.50 Export list for 192.168.191.50: /data/nfs/04 192.168.191.0/24 /data/nfs/03 192.168.191.0/24 /data/nfs/02 192.168.191.0/24 /data/nfs/01 192.168.191.0/24 /data/nfs 192.168.191.0/24
apiVersion: v1 kind: PersistentVolume metadata: name: pv02 labels: app: pv02 spec: storageClassName: nfs accessModes: ["ReadWriteMany"] capacity: storage: 2Mi nfs: path: /data/nfs/02 server: zy.nfs.com --- apiVersion: v1 kind: PersistentVolume metadata: name: pv03 labels: app: pv03 spec: storageClassName: nfs accessModes: ["ReadWriteMany"] capacity: storage: 2Mi nfs: path: /data/nfs/03 server: zy.nfs.com --- apiVersion: v1 kind: PersistentVolume metadata: name: pv04 labels: app: pv04 spec: storageClassName: nfs accessModes: ["ReadWriteMany"] capacity: storage: 2Mi nfs: path: /data/nfs/04 server: zy.nfs.com
查看pv
[root@k8s-3 ~]# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pv02 2Mi RWX Retain Available nfs 5h27m pv03 2Mi RWX Retain Available nfs 5h27m pv04 2Mi RWX Retain Available nfs 5h27m
* access modes访问模式,
ReadWriteOnce -可以通过单个节点以读写方式安装该卷
ReadOnlyMany -该卷可以被许多节点只读挂载
ReadWriteMany -该卷可以被许多节点读写安装
* RECLAIM POLICY pv的回收策略
retain 删除pvc后,pv一直存储,数据不会丢失
delete 删除pvc后,pv自动删除
storageclass 自定义的内同
创建headless服务
[root@k8s-3 statefulset]# cat svc.yaml apiVersion: v1 kind: Service metadata: name: headless-svc spec: clusterIP: None selector: app: sfs ports: - name: http port: 80 protocol: TCP
查看headless服务,注意clusterIP: None
[root@k8s-3 ~]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE headless-svc ClusterIP None80/TCP 11m
创建statefulset
[root@k8s-3 statefulset]# cat statefulset.yaml apiVersion: apps/v1 kind: StatefulSet metadata: name: nginx spec: serviceName: sfs replicas: 2 selector: matchLabels: app: sfs template: metadata: name: sfs labels: app: sfs spec: containers: - name: sfs image: nginx:latest ports: - name: http containerPort: 80 volumeMounts: - name: www mountPath: /usr/share/nginx/html volumeClaimTemplates: - metadata: name: www spec: accessModes: ["ReadWriteMany"] storageClassName: nfs resources: requests: storage: 2Mi
执行后查看pod的创建情况和pv,pvc
pod的创建过程,pod命名 name-0/1/2/......,依次创建pod
[root@k8s-3 ~]# kubectl get pod -w NAME READY STATUS RESTARTS AGE nginx-0 0/1 Pending 0 0s nginx-0 0/1 Pending 0 0s nginx-0 0/1 Pending 0 1s nginx-0 0/1 ContainerCreating 0 1s nginx-0 1/1 Running 0 22s nginx-1 0/1 Pending 0 0s nginx-1 0/1 Pending 0 0s nginx-1 0/1 Pending 0 0s nginx-1 0/1 ContainerCreating 0 0s nginx-1 1/1 Running 0 25s # 最终的结果 [root@k8s-3 ~]# kubectl get pod NAME READY STATUS RESTARTS AGE nginx-0 1/1 Running 0 2m53s nginx-1 1/1 Running 0 2m31s
pvc的创建与pv的绑定
[root@k8s-3 ~]# kubectl get pvc -w NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE www-nginx-0 Bound pv04 2Mi RWX nfs 16s www-nginx-1 Pending nfs 0s www-nginx-1 Pending pv02 0 nfs 0s www-nginx-1 Bound pv02 2Mi RWX nfs 0s [root@k8s-3 ~]# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pv02 2Mi RWX Retain Bound default/www-nginx-1 nfs 10m pv03 2Mi RWX Retain Available nfs 10m pv04 2Mi RWX Retain Bound default/www-nginx-0 nfs 10m
查看headless与后端pod的关系
[root@k8s-3 ~]# kubectl describe svc headless-svc Name: headless-svc Namespace: default Labels:Annotations: kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"headless-svc","namespace":"default"},"spec":{"clusterIP":"None","... Selector: app=sfs Type: ClusterIP IP: None Port: http 80/TCP TargetPort: 80/TCP Endpoints: 10.244.1.50:80,10.244.3.86:80 Session Affinity: None Events:
headless因为没有clusterIP,所以无法在外网访问,自己测试的使用浏览器访问的话,可以把windows的host文件添加解析
10.244.1.50:80,10.244.3.86:80,这里就不配置了,在node节点直接curl
[root@k8s3-1 ~]# curl 10.244.1.50:80 this is 02 [root@k8s3-1 ~]# curl 10.244.3.86:80 this is 04
nfs共享目录设置
[root@zy nfs]# echo "this is 02" > 02/index.html [root@zy nfs]# echo "this is 03" > 03/index.html [root@zy nfs]# echo "this is 04" > 04/index.html
到此一个statefulset的服务与存储测试结束。对于statefulset类型的扩容和缩容,都可以使用使用kubectl get pod -w 查看,扩容新加pod-num+1(已存在最大num);缩容,删除pod-num(已存在最大num),这里就不在演示了,有兴趣的可以验证下。