Kubernetes进阶之StatefulSet有状态部署
statefulset
statefulset主要是用来部署有状态应用
无状态应用
我们原来使用deployment,部署的都是无状态的应用,那什么是无状态应用?
- 认为Pod都是一样的
- 没有顺序要求
- 不考虑应用在哪个node上运行
- 能够进行随意伸缩和扩展
有状态应用
上述的因素都需要考虑到
- 让每个Pod独立的
- 让每个Pod独立的,保持Pod启动顺序和唯一性
- 唯一的网络标识符,持久存储
- 有序,比如mysql中的主从
部署有状态应用
无头service, ClusterIp:none
这里就需要使用 StatefulSet部署有状态应用
statefulSet是一个控制器,与Deployment存在的原则一样,都是部署应用的,而Statefulset它主要是部署有状态应用的,而deployment是部署无状态应用的
Headless Service 其实和service差不多,这不过定义的这个叫无头服务,它们之间唯一的区别就是将Cluster ip 设置为了none,不会帮你配置ip
[root@k8s-master demo]# mkdir headless-service [root@k8s-master demo]# cd headless-service/ [root@k8s-master headless-service]# vim headless-svc.yaml apiVersion: v1 kind: Service metadata: name: my-service spec: clusterIP: None selector: app: nginx ports: - protocol: TCP port: 80 targetPort: 9376 [root@k8s-master headless-service]# kubectl create -f headless-svc.yaml service/my-service created [root@k8s-master headless-service]# kubectl get svc kubernetes ClusterIP 10.1.0.1 <none> 443/TCP 23h my-service ClusterIP None <none> 80/TCP 6s service NodePort 10.1.207.32 <none> 80:30963/TCP 87m zhao ClusterIP 10.1.75.232 <none> 80/TCP 9m1s zhaocheng ClusterIP 10.1.27.206 <none> 80/TCP 10m
这里有状态的约定,肯定不是简简单单通过名称来进行约定,而是更加复杂的操作
- deployment:是有身份的,有唯一标识
- statefulset:根据主机名 + 按照一定规则生成域名
每个pod有唯一的主机名,并且有唯一的域名
- 格式:主机名称.service名称.名称空间.svc.cluster.local
- 举例:nginx-statefulset-0.default.svc.cluster.local
怎么去访问?我们给它定义一个标识
创建完之后会有这个标识符,它会使用这个DNS来解析这个名称,来相互的访问,headless就不会通过ip去访问了,必须通过名称去访问,
[root@k8s-master headless-service]# vim statefulset.yaml apiVersion: apps/v1beta1 kind: StatefulSet metadata: name: nginx-statefulset namespace: default spec: serviceName: my-service replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:latest ports: - containerPort: 80 [root@k8s-master headless-service]# kubectl apply -f statefulset.yaml [root@k8s-master headless-service]# kubectl get pod my-pod 1/1 Running 0 3h50m nfs-744d977b46-dh9xj 1/1 Running 0 22h nfs-744d977b46-kcx6h 1/1 Running 0 22h nfs-744d977b46-wqhc6 1/1 Running 0 22h nfs-client-provisioner 1/1 Running 0 4h nginx-797db8dc57-tdd5s 1/1 Running 0 100m nginx-statefulset-0 1/1 Running 0 73s nginx-statefulset-1 1/1 Running 0 46s nginx-statefulset-2 1/1 Running 0 24s
这里的statfulset的 serviceName: my-service字段要关联起来,这样才能去基于名称去访问
可以通过busybox测试工具通过nslookup去测试解析。解析我们的my-service就能解析到
这里会分配一个名称,这个my-service和这个编号是永久的,可以通过这个名称访问pod
要是mysql主从的话就可以通过访问这个标签来连接我们从库的状态,这个是维护的网络状态
然后再来看一下存储状态
官方文档这个实例
https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/
这个其实我们也是部署一个nginx,使用的headless,ClusterIP为none,然后用headless来维护statefulset起得pod网络id为1,以 volumeClaimTemplates:来维护pod独立的一个存储
apiVersion: v1 kind: Service metadata: name: nginx labels: app: nginx spec: ports: - port: 80 name: web clusterIP: None selector: app: nginx --- apiVersion: apps/v1 kind: StatefulSet metadata: name: web spec: selector: matchLabels: app: nginx # has to match .spec.template.metadata.labels serviceName: "nginx" replicas: 3 # by default is 1 template: metadata: labels: app: nginx # has to match .spec.selector.matchLabels spec: terminationGracePeriodSeconds: 10 containers: - name: nginx image: nginx ports: - containerPort: 80 name: web volumeMounts: - name: www mountPath: /usr/share/nginx/html volumeClaimTemplates: - metadata: name: www spec: accessModes: [ "ReadWriteOnce" ] storageClassName: "managed-nfs-storage" resources: requests: storage: 1Gi
这是我们的存储要写我们nfs的名称
managed-nfs-storage
[root@k8s-master headless-service]# kubectl get sc
managed-nfs-storage fuseim.pri/ifs 22h
这里会给我们自动创建pv,并挂载到我们的NFS上
[root@k8s-master headless-service]# kubectl get pod my-pod 1/1 Running 0 6h4m nfs 1/1 Running 0 24h nfs 1/1 Running 0 24h nfs 1/1 Running 0 24h nfs-client-provisioner-fbc 1/1 Running 0 6h23m nginx-797db8dc57-tdd5s 1/1 Running 0 3h54m nginx-a1-6d5fd7b8dd-w647x 1/1 Running 0 3m28s nginx-statefulset-0 1/1 Running 0 135m nginx-statefulset-1 1/1 Running 0 135m nginx-statefulset-2 1/1 Running 0 134m web-0 1/1 Running 0 3 web-1 1/1 Running 0 85s web-2 1/1 Running 0 57s [root@k8s-master headless-service]# kubectl get pv pvc-06 1Gi RWO Delete Bound default/www-web-2 managed-nfs-storage 63s pvc-4f 1Gi RWO Delete Bound default/www-web-0 managed-nfs-storage 6m3s pvc-a2 5Gi RWX Delete Bound default/my-pvc managed-nfs-storage 6h4m pvc-bc 1Gi RWO Delete Bound default/www-web-1 managed-nfs-storage
headless保证它的网络,statefulset存储模版来保证每个pod存储的唯一性,这样才解决了有状态应用的两大痛点