Kubernetes的资源控制器StatefulSet详解与示例

主机配置规划

服务器名称(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的具体状态和行为。

部分控制器类型如下:
  • ReplicationController 和 ReplicaSet
  • Deployment
  • DaemonSet
  • StatefulSet
  • Job/CronJob
  • HorizontalPodAutoscaler

StatefulSet

StatefulSet 是用来管理有状态应用的工作负载 API 对象。

StatefulSet 中的 Pod 拥有一个具有黏性的、独一无二的身份标识。这个标识基于 StatefulSet 控制器分配给每个 Pod 的唯一顺序索引。Pod 的名称的形式为<statefulset name>-<ordinal index> 。例如:web的StatefulSet 拥有两个副本,所以它创建了两个 Pod:web-0和web-1。

和 Deployment 相同的是,StatefulSet 管理了基于相同容器定义的一组 Pod。但和 Deployment 不同的是,StatefulSet 为它们的每个 Pod 维护了一个固定的 ID。这些 Pod 是基于相同的声明来创建的,但是不能相互替换:无论怎么调度,每个 Pod 都有一个永久不变的 ID。

【使用场景】StatefulSets 对于需要满足以下一个或多个需求的应用程序很有价值:

  • 稳定的、唯一的网络标识符,即Pod重新调度后其PodName和HostName不变【当然IP是会变的】
  • 稳定的、持久的存储,即Pod重新调度后还是能访问到相同的持久化数据,基于PVC实现
  • 有序的、优雅的部署和缩放
  • 有序的、自动的滚动更新

如上面,稳定意味着 Pod 调度或重调度的整个过程是有持久性的。

如果应用程序不需要任何稳定的标识符或有序的部署、删除或伸缩,则应该使用由一组无状态的副本控制器提供的工作负载来部署应用程序,比如使用 Deployment 或者 ReplicaSet 可能更适用于无状态应用部署需要。

限制

  • 给定 Pod 的存储必须由 PersistentVolume 驱动 基于所请求的 storage class 来提供,或者由管理员预先提供。
  • 删除或者收缩 StatefulSet 并不会删除它关联的存储卷。这样做是为了保证数据安全,它通常比自动清除 StatefulSet 所有相关的资源更有价值。
  • StatefulSet 当前需要 headless 服务 来负责 Pod 的网络标识。你需要负责创建此服务。
  • 当删除 StatefulSets 时,StatefulSet 不提供任何终止 Pod 的保证。为了实现 StatefulSet 中的 Pod 可以有序和优雅的终止,可以在删除之前将 StatefulSet 缩放为 0。
  • 在默认 Pod 管理策略(OrderedReady) 时使用滚动更新,可能进入需要人工干预才能修复的损坏状态。

有序索引

对于具有 N 个副本的 StatefulSet,StatefulSet 中的每个 Pod 将被分配一个整数序号,从 0 到 N-1,该序号在 StatefulSet 上是唯一的。

StatefulSet 中的每个 Pod 根据 StatefulSet 中的名称和 Pod 的序号来派生出它的主机名。组合主机名的格式为$(StatefulSet 名称)-$(序号)。

部署和扩缩保证

  • 对于包含 N 个 副本的 StatefulSet,当部署 Pod 时,它们是依次创建的,顺序为 0~(N-1)。
  • 当删除 Pod 时,它们是逆序终止的,顺序为 (N-1)~0。
  • 在将缩放操作应用到 Pod 之前,它前面的所有 Pod 必须是 Running 和 Ready 状态。
  • 在 Pod 终止之前,所有的继任者必须完全关闭。

StatefulSet 不应将 pod.Spec.TerminationGracePeriodSeconds 设置为 0。这种做法是不安全的,要强烈阻止。

部署顺序

在下面的 nginx 示例被创建后,会按照 web-0、web-1、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示例

说明:本次示例不涉及存储,StatefulSet的存储示例会在「Kubernetes K8S之存储PV-PVC详解」文章中演示。

yaml文件

 [root@k8s-master controller]# pwd
/root/k8s_practice/controller
[root@k8s-master controller]# cat statefulset.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port:
name: http
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: # by default is
template:
metadata:
labels:
app: nginx # has to match .spec.selector.matchLabels
spec:
terminationGracePeriodSeconds: # 默认30秒
containers:
- name: nginx
image: registry.cn-beijing.aliyuncs.com/google_registry/nginx:1.17
ports:
- containerPort:
name: http

启动StatefulSet和Service,并查看状态

 [root@k8s-master controller]# kubectl apply -f statefulset.yaml
service/nginx created
statefulset.apps/web created
[root@k8s-master controller]# kubectl get service -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kubernetes ClusterIP 10.96.0.1 <none> /TCP 17d <none>
nginx ClusterIP None <none> /TCP 87s app=nginx
[root@k8s-master controller]#
[root@k8s-master controller]# kubectl get statefulset -o wide
NAME READY AGE CONTAINERS IMAGES
web / 15m nginx registry.cn-beijing.aliyuncs.com/google_registry/nginx:1.17
[root@k8s-master controller]#
[root@k8s-master controller]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web- / Running 16m 10.244.2.95 k8s-node02 <none> <none>
web- / Running 16m 10.244.3.103 k8s-node01 <none> <none>
web- / Running 16m 10.244.3.104 k8s-node01 <none> <none>

由上可见,StatefulSet 中的pod是有序的。有N个副本,那么序列号为0~(N-1)。

查看StatefulSet相关的域名信息

启动一个pod

 [root@k8s-master test]# pwd
/root/k8s_practice/test
[root@k8s-master test]# cat myapp_demo.yaml
apiVersion: v1
kind: Pod
metadata:
name: myapp-demo
namespace: default
labels:
k8s-app: myapp
spec:
containers:
- name: myapp
image: registry.cn-beijing.aliyuncs.com/google_registry/myapp:v1
imagePullPolicy: IfNotPresent
ports:
- name: httpd
containerPort:
protocol: TCP
[root@k8s-master test]#
[root@k8s-master test]# kubectl apply -f myapp_demo.yaml
pod/myapp-demo created
[root@k8s-master test]#
[root@k8s-master test]# kubectl get pod -o wide | grep 'myapp'
myapp-demo / Running 3m24s 10.244.2.101 k8s-node02 <none> <none>

进入pod并查看StatefulSet域名信息

 # 进入一个k8s管理的myapp镜像容器。
[root@k8s-master test]# kubectl exec -it myapp-demo sh
/ # nslookup 10.244.2.95
nslookup: can't resolve '(null)': Name does not resolve Name: 10.244.2.95
Address : 10.244.2.95 web-.nginx.default.svc.cluster.local
/ #
/ #
/ # nslookup 10.244.3.103
nslookup: can't resolve '(null)': Name does not resolve Name: 10.244.3.103
Address : 10.244.3.103 web-.nginx.default.svc.cluster.local
/ #
/ #
/ # nslookup 10.244.3.104
nslookup: can't resolve '(null)': Name does not resolve Name: 10.244.3.104
Address : 10.244.3.104 web-.nginx.default.svc.cluster.local
/ #
/ #
##### nginx.default.svc.cluster.local 为service的域名信息
/ # nslookup nginx.default.svc.cluster.local
nslookup: can't resolve '(null)': Name does not resolve Name: nginx.default.svc.cluster.local
Address : 10.244.3.104 web-.nginx.default.svc.cluster.local
Address : 10.244.3.103 web-.nginx.default.svc.cluster.local
Address : 10.244.2.95 web-.nginx.default.svc.cluster.local

StatefulSet网络标识与PVC

有上文可得如下信息:

1、匹配StatefulSet的Pod name(网络标识)的模式为:$(statefulset名称)-$(序号),比如StatefulSet名称为web,副本数为3。则为:web-0、web-1、web-2

2、StatefulSet为每个Pod副本创建了一个DNS域名,这个域名的格式为:$(podname).(headless service name),也就意味着服务之间是通过Pod域名来通信而非Pod IP。当Pod所在Node发生故障时,Pod会被漂移到其他Node上,Pod IP会发生改变,但Pod域名不会变化

3、StatefulSet使用Headless服务来控制Pod的域名,这个Headless服务域名的为:$(service name).$(namespace).svc.cluster.local,其中 cluster.local 指定的集群的域名

4、根据volumeClaimTemplates,为每个Pod创建一个PVC,PVC的命令规则为:$(volumeClaimTemplates name)-$(pod name),比如volumeClaimTemplates为www,pod name为web-0、web-1、web-2;那么创建出来的PVC为:www-web-0、www-web-1、www-web-2

5、删除Pod不会删除对应的PVC,手动删除PVC将自动释放PV。

相关阅读

1、Kubernetes K8S之资源控制器RC、RS、Deployment详解

完毕!


———END———
如果觉得不错就关注下呗 (-^O^-) !

Kubernetes K8S之资源控制器StatefulSets详解的更多相关文章

  1. Kubernetes K8S之资源控制器Daemonset详解

    Kubernetes的资源控制器Daemonset详解与示例 主机配置规划 服务器名称(hostname) 系统版本 配置 内网IP 外网IP(模拟) k8s-master CentOS7.7 2C/ ...

  2. Kubernetes K8S之资源控制器Job和CronJob详解

    Kubernetes的资源控制器Job和CronJob详解与示例 主机配置规划 服务器名称(hostname) 系统版本 配置 内网IP 外网IP(模拟) k8s-master CentOS7.7 2 ...

  3. Kubernetes K8S之资源控制器RC、RS、Deployment详解

    Kubernetes的资源控制器ReplicationController(RC).ReplicaSet(RS).Deployment(Deploy)详解与示例 主机配置规划 服务器名称(hostna ...

  4. Kubernetes K8S之鉴权RBAC详解

    Kubernetes K8S之鉴权概述与RBAC详解 K8S认证与授权 认证「Authentication」 认证有如下几种方式: 1.HTTP Token认证:通过一个Token来识别合法用户. H ...

  5. Kubernetes K8S之调度器kube-scheduler详解

    Kubernetes K8S之调度器kube-scheduler概述与详解 kube-scheduler调度概述 在 Kubernetes 中,调度是指将 Pod 放置到合适的 Node 节点上,然后 ...

  6. kubernetes运行应用2之DaemonSet详解

    kubernetes运行应用1之Deployment详解   查看daemonset 如下,k8s自身的 DaemonSet kube-flannel-ds和kube-proxy分别负责在每个结点上运 ...

  7. Docker Kubernetes Service 网络服务代理模式详解

    Docker Kubernetes  Service 网络服务代理模式详解 Service service是实现kubernetes网络通信的一个服务 主要功能:负载均衡.网络规则分布到具体pod 注 ...

  8. 小甲鱼PE详解之资源(PE详解11)

    原文出自:www.fishc.com 最近一直在安排第一届鱼C 学习班的事情,忙活了好一阵子,真是对不住大家,还大家久等了,这里要跟大家说声不好意思 ^_^ 今天我们来谈谈资源部分,资源部分可以说是 ...

  9. HTTP权威指南读书笔记(一)HTTP概述、URL和资源及报文详解

    一.HTTP概述 1.WEB客户端和服务器. 2.资源:资源可以是各种格式的静态文件,也可以是应用程序. 3.媒体类型 4.URI:统一资源标识符 URL:统一资源定位符. URL的第一部分称为方案: ...

随机推荐

  1. type 创建类,赋予类\静态方法等

    类方法 class ObjectCreator(object): pass @classmethod def testClass(cls): cls.temp = 666 print(cls.temp ...

  2. 转载——完整的ASCII码表

    完整的ASCII码表,转载自下面的博主: http://www.cnblogs.com/xmxu/archive/2012/07/10/2584032.html

  3. C/C++编程笔记:C++入门知识丨函数和函数模板

    本篇要学习的内容和知识结构概览 函数的参数及其传递方式 1. 函数参数传递方式 传值: 传变量值: 将实参内存中的内容拷贝一份给形参, 两者是不同的两块内存 传地址值: 将实参所对应的内存空间的地址值 ...

  4. Android SQLite轻量级数据库的删除和查找操作

    今天主要是补充昨天的内容,本打算合成一章的,但是毕竟一天一天的内容写习惯了. 就这样继续昨天的,昨天只讲了创建以及增加和查询, 其实用法都差不多,今天学长也是在原有的基础上写的,还顺便融合了Share ...

  5. Android 生命周期,解决savedInstanceState一直为null的问题

    在此之前还是补充下关于监听器的两个要点:   向下一个活动传递数据 : button1.setOnClickListener(new View.OnClickListener() { @Overrid ...

  6. Linux 安装 PostgreSQL

    Linux 安装 PostgreSQL CentOS 7 安装 PostgreSQL 10 步骤 官网安装步骤,选择服务器和数据库版本,会给出相应的安装命令 # 安装 yum install -y h ...

  7. java_线程、同步、线程池

    线程 Java使用 java.lang.Thread 类代表线程,所有的线程对象都必须是Thread类或其子类的实例 Thread类常用方法 构造方法 public Thread():分配一个新的线程 ...

  8. layui 事件监听触发

    1:监听select 改变 <!-- 不用form 用div也可以 --> <form class="layui-form"> <div class= ...

  9. 【API进阶之路】帮公司省下20万调研费!如何巧用情感分析API实现用户偏好调研

    摘要:自从学习API后,仿佛解锁了新技能,可别小看了一个小小的API接口,用好了都是能力无穷.这不,用情感分析API来做用户偏好调研,没想到这么一个小创意给公司省了20万调研费用. 上次借着高考热点整 ...

  10. 用Java制作斗地主

    首先,按照斗地主规则,完成洗牌发牌的动作.如图: 具体规则: 1. 组装54张扑克牌 2. 将54张牌顺序打乱 3. 三个玩家参与游戏,三人交替摸牌,每人17张牌,最后三张留作底牌. 4. 查看三人各 ...