Kubernetes的资源控制器StatefulSet详解与示例html
服务器名称(hostname) | 系统版本 | 配置 | 内网IP | 外网IP(模拟) |
---|---|---|---|---|
k8s-master | CentOS7.7 | 2C/4G/20G | 172.16.1.110 | 10.0.0.110 |
k8s-node01 | CentOS7.7 | 2C/4G/20G | 172.16.1.111 | 10.0.0.111 |
k8s-node02 | CentOS7.7 | 2C/4G/20G | 172.16.1.112 | 10.0.0.112 |
kubernetes中内建了不少controller(控制器),这些至关于一个状态机,用来控制pod的具体状态和行为。node
StatefulSet 是用来管理有状态应用的工做负载 API 对象。nginx
StatefulSet 中的 Pod 拥有一个具备黏性的、独一无二的身份标识。这个标识基于 StatefulSet 控制器分配给每一个 Pod 的惟一顺序索引。Pod 的名称的形式为<statefulset name>-<ordinal index> 。例如:web的StatefulSet 拥有两个副本,因此它建立了两个 Pod:web-0和web-1。web
和 Deployment 相同的是,StatefulSet 管理了基于相同容器定义的一组 Pod。但和 Deployment 不一样的是,StatefulSet 为它们的每一个 Pod 维护了一个固定的 ID。这些 Pod 是基于相同的声明来建立的,可是不能相互替换:不管怎么调度,每一个 Pod 都有一个永久不变的 ID。api
【使用场景】StatefulSets 对于须要知足如下一个或多个需求的应用程序颇有价值:安全
如上面,稳定意味着 Pod 调度或重调度的整个过程是有持久性的。服务器
若是应用程序不须要任何稳定的标识符或有序的部署、删除或伸缩,则应该使用由一组无状态的副本控制器提供的工做负载来部署应用程序,好比使用 Deployment 或者 ReplicaSet 可能更适用于无状态应用部署须要。网络
对于具备 N 个副本的 StatefulSet,StatefulSet 中的每一个 Pod 将被分配一个整数序号,从 0 到 N-1,该序号在 StatefulSet 上是惟一的。app
StatefulSet 中的每一个 Pod 根据 StatefulSet 中的名称和 Pod 的序号来派生出它的主机名。组合主机名的格式为$(StatefulSet 名称)-$(序号)。less
StatefulSet 不该将 pod.Spec.TerminationGracePeriodSeconds 设置为 0。这种作法是不安全的,要强烈阻止。
在下面的 nginx 示例被建立后,会按照 web-0、web-一、web-2 的顺序部署三个 Pod。在 web-0 进入 Running 和 Ready 状态前不会部署 web-1。在 web-1 进入 Running 和 Ready 状态前不会部署 web-2。
若是 web-1 已经处于 Running 和 Ready 状态,而 web-2 还没有部署,在此期间发生了 web-0 运行失败,那么 web-2 将不会被部署,要等到 web-0 部署完成并进入 Running 和 Ready 状态后,才会部署 web-2。
若是想将示例中的 StatefulSet 收缩为 replicas=1,首先被终止的是 web-2。在 web-2 没有被彻底中止和删除前,web-1 不会被终止。当 web-2 已被终止和删除;但web-1 还没有被终止,若是在此期间发生 web-0 运行失败,那么就不会终止 web-1,必须等到 web-0 进入 Running 和 Ready 状态后才会终止 web-1。
说明:本次示例不涉及存储,StatefulSet的存储示例会在「Kubernetes K8S之存储PV-PVC详解」文章中演示。
yaml文件
1 [root@k8s-master controller]# pwd 2 /root/k8s_practice/controller 3 [root@k8s-master controller]# cat statefulset.yaml 4 apiVersion: v1 5 kind: Service 6 metadata: 7 name: nginx 8 labels: 9 app: nginx 10 spec: 11 ports: 12 - port: 80 13 name: http 14 clusterIP: None 15 selector: 16 app: nginx 17 --- 18 apiVersion: apps/v1 19 kind: StatefulSet 20 metadata: 21 name: web 22 spec: 23 selector: 24 matchLabels: 25 app: nginx # has to match .spec.template.metadata.labels 26 serviceName: "nginx" 27 replicas: 3 # by default is 1 28 template: 29 metadata: 30 labels: 31 app: nginx # has to match .spec.selector.matchLabels 32 spec: 33 terminationGracePeriodSeconds: 10 # 默认30秒 34 containers: 35 - name: nginx 36 image: registry.cn-beijing.aliyuncs.com/google_registry/nginx:1.17 37 ports: 38 - containerPort: 80 39 name: http
启动StatefulSet和Service,并查看状态
1 [root@k8s-master controller]# kubectl apply -f statefulset.yaml 2 service/nginx created 3 statefulset.apps/web created 4 [root@k8s-master controller]# kubectl get service -o wide 5 NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR 6 kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 17d <none> 7 nginx ClusterIP None <none> 80/TCP 87s app=nginx 8 [root@k8s-master controller]# 9 [root@k8s-master controller]# kubectl get statefulset -o wide 10 NAME READY AGE CONTAINERS IMAGES 11 web 3/3 15m nginx registry.cn-beijing.aliyuncs.com/google_registry/nginx:1.17 12 [root@k8s-master controller]# 13 [root@k8s-master controller]# kubectl get pod -o wide 14 NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES 15 web-0 1/1 Running 0 16m 10.244.2.95 k8s-node02 <none> <none> 16 web-1 1/1 Running 0 16m 10.244.3.103 k8s-node01 <none> <none> 17 web-2 1/1 Running 0 16m 10.244.3.104 k8s-node01 <none> <none>
由上可见,StatefulSet 中的pod是有序的。有N个副本,那么序列号为0~(N-1)。
启动一个pod
1 [root@k8s-master test]# pwd 2 /root/k8s_practice/test 3 [root@k8s-master test]# cat myapp_demo.yaml 4 apiVersion: v1 5 kind: Pod 6 metadata: 7 name: myapp-demo 8 namespace: default 9 labels: 10 k8s-app: myapp 11 spec: 12 containers: 13 - name: myapp 14 image: registry.cn-beijing.aliyuncs.com/google_registry/myapp:v1 15 imagePullPolicy: IfNotPresent 16 ports: 17 - name: httpd 18 containerPort: 80 19 protocol: TCP 20 [root@k8s-master test]# 21 [root@k8s-master test]# kubectl apply -f myapp_demo.yaml 22 pod/myapp-demo created 23 [root@k8s-master test]# 24 [root@k8s-master test]# kubectl get pod -o wide | grep 'myapp' 25 myapp-demo 1/1 Running 0 3m24s 10.244.2.101 k8s-node02 <none> <none>
进入pod并查看StatefulSet域名信息
1 # 进入一个k8s管理的myapp镜像容器。 2 [root@k8s-master test]# kubectl exec -it myapp-demo sh 3 / # nslookup 10.244.2.95 4 nslookup: can't resolve '(null)': Name does not resolve 5 6 Name: 10.244.2.95 7 Address 1: 10.244.2.95 web-0.nginx.default.svc.cluster.local 8 / # 9 / # 10 / # nslookup 10.244.3.103 11 nslookup: can't resolve '(null)': Name does not resolve 12 13 Name: 10.244.3.103 14 Address 1: 10.244.3.103 web-1.nginx.default.svc.cluster.local 15 / # 16 / # 17 / # nslookup 10.244.3.104 18 nslookup: can't resolve '(null)': Name does not resolve 19 20 Name: 10.244.3.104 21 Address 1: 10.244.3.104 web-2.nginx.default.svc.cluster.local 22 / # 23 / # 24 ##### nginx.default.svc.cluster.local 为service的域名信息 25 / # nslookup nginx.default.svc.cluster.local 26 nslookup: can't resolve '(null)': Name does not resolve 27 28 Name: nginx.default.svc.cluster.local 29 Address 1: 10.244.3.104 web-2.nginx.default.svc.cluster.local 30 Address 2: 10.244.3.103 web-1.nginx.default.svc.cluster.local 31 Address 3: 10.244.2.95 web-0.nginx.default.svc.cluster.local
有上文可得以下信息:
一、匹配StatefulSet的Pod name(网络标识)的模式为:$(statefulset名称)-$(序号),好比StatefulSet名称为web,副本数为3。则为:web-0、web-一、web-2
二、StatefulSet为每一个Pod副本建立了一个DNS域名,这个域名的格式为:$(podname).(headless service name),也就意味着服务之间是经过Pod域名来通讯而非Pod IP。当Pod所在Node发生故障时,Pod会被漂移到其余Node上,Pod IP会发生改变,但Pod域名不会变化
三、StatefulSet使用Headless服务来控制Pod的域名,这个Headless服务域名的为:$(service name).$(namespace).svc.cluster.local,其中 cluster.local 指定的集群的域名
四、根据volumeClaimTemplates,为每一个Pod建立一个PVC,PVC的命令规则为:$(volumeClaimTemplates name)-$(pod name),好比volumeClaimTemplates为www,pod name为web-0、web-一、web-2;那么建立出来的PVC为:www-web-0、www-web-一、www-web-2
五、删除Pod不会删除对应的PVC,手动删除PVC将自动释放PV。
一、Kubernetes K8S之资源控制器RC、RS、Deployment详解
完毕!
———END———
若是以为不错就关注下呗 (-^O^-) !