k8s 控制器-Statefulset
Posted 笨小孩@GF 知行合一
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了k8s 控制器-Statefulset相关的知识,希望对你有一定的参考价值。
-
StatefulSet 是为了管理有状态服务的问题而设计
- 扩展:有状态服务?
StatefulSet 是有状态的集合,管理有状态的服务,它所管理的 Pod 的名称不能随意变化。数据持久化的目录也是不一样,每一个 Pod 都有自己独有的数据持久化存储目录。比如 mysql 主从、redis集群等。
- Deployment 管理 pod,pod 名字怎么组成?
replicaset-随机数
无状态服务?
RS、Deployment、DaemonSet 都是管理无状态的服务,它们所管理的 Pod 的 IP、名字,启停顺序等都是随机的。个体对整体无影响,所有 pod 都是共用一个数据卷的,部署的 tomcat 就是无状态的服务,tomcat 被删除,在启动一个新的 tomcat,加入到集群即可,跟 tomcat 的名字无关。
- StatefulSet 由以下几个部分组成:
1. Headless Service(没有 ip 的 service):用来定义 pod 网路标识,生成可解析的 DNS 记录service ip 存在哪?iptables 或者 ipvs 规则中
2. volumeClaimTemplates:存储卷申请模板,创建 pvc,指定 pvc 名称大小,自动创建 pvc,且 pvc 由存储类供应。
3. StatefulSet:管理 pod 的
- 扩展:什么是 Headless service?
Headless service 不分配 clusterIP,headless service 可以通过解析 service 的 DNS,返回所有Pod 的 dns 和 ip 地址 (statefulSet 部署的 Pod 才有 DNS),普通的 service,只能通过解析 service 的DNS 返回 service 的 ClusterIP。 -
为什么要用 headless service(没有 service ip 的 service)?
-
在使用 Deployment 时,创建的 Pod 名称是没有顺序的,是随机字符串
用 statefulset 管理pod 时要求 pod 名称必须是有序的 ,每一个 pod 不能被随意取代,pod 重建后 pod 名称还是一样
因为 pod IP 是变化的,所以要用 Pod 名称来识别。pod 名称是 pod 唯一性的标识符,必须持久稳定有效。这时候要用到无头服务,它可以给每个 Pod 一个唯一的名称。 -
1.headless service 会为 service 分配一个域名 <service name>.$<namespace name>.svc.cluster.local
K8s 中资源的全局 FQDN 格式:
Service_NAME.NameSpace_NAME.Domain.LTD. Domain.LTD.=svc.cluster.local. #这是默认 k8s 集群的域名。
FQDN 全称 Fully Qualified Domain Name 即全限定域名:同时带有主机名和域名的名称
FQDN = Hostname + DomainName
如 主机名是 GF
域名是 beyond.com
FQDN= GF.beyond.com
2.StatefulSet 会为关联的 Pod 保持一个不变的 Pod Name
statefulset 中 Pod 的名字格式为$(StatefulSet name)-$(pod 序号)
3.StatefulSet 会为关联的 Pod 分配一个 dnsName
$<Pod Name>.$<service name>.$<namespace name>.svc.cluster.local
-
为什么要用 volumeClaimTemplate?
对于有状态应用都会用到持久化存储,比如 mysql 主从,由于主从数据库的数据是不能存放在一个目录下的,每个 mysql 节点都需要有自己独立的存储空间。
而在 deployment 中创建的存储卷是一个共享的存储卷,多个 pod 使用同一个存储卷,它们数据是同步的,而 statefulset 定义中的每一个 pod 都不能使用同一个存储卷,这就需要使用 volumeClaimTemplate
当在使用 statefulset 创建 pod 时,volumeClaimTemplate 会自动生成一个 PVC,从而请求绑定一个 PV,每一个 pod 都有自己专用的存储卷。
Pod、PVC 和 PV 对应的关系图如下: -
Statefulset 资源清单文件编写技巧
-
#查看定义 Statefulset 资源需要的字段
-
[~]# kubectl explain statefulset
KIND: StatefulSet
VERSION: apps/v1
DESCRIPTION:
StatefulSet represents a set of pods with consistent identities. Identities
are defined as:
- Network: A single stable DNS and hostname.
- Storage: As many VolumeClaims as requested. The StatefulSet guarantees
that a given network identity will always map to the same storage identity.
FIELDS:
apiVersion <string> #定义 statefulset 资源需要使用的 api 版本
kind <string> #定义的资源类型
metadata <Object> #元数据
spec <Object> #定义容器相关的信息
#查看 statefulset.spec 字段如何定义?
[~]# kubectl explain statefulset.spec
KIND: StatefulSet
VERSION: apps/v1
RESOURCE: spec <Object>
DESCRIPTION:
Spec defines the desired identities of pods in this set.
A StatefulSetSpec is the specification of a StatefulSet.
FIELDS:
podManagementPolicy <string> #pod 管理策略
replicas <integer> #副本数
revisionHistoryLimit <integer> #保留的历史版本
selector <Object> -required- #标签选择器,选择它所关联的 pod
serviceName <string> -required- #headless service 的名字
template <Object> -required- #生成 pod 的模板
updateStrategy <Object> #更新策略
volumeClaimTemplates <[]Object> #存储卷申请模板
#查看 statefulset 的 spec.template 字段如何定义?
#对于 template 而言,其内部定义的就是 pod,pod 模板是一个独立的对象
[~]# kubectl explain statefulset.spec.template
KIND: StatefulSet
VERSION: apps/v1
RESOURCE: template <Object>
DESCRIPTION:
FIELDS:
metadata <Object>
spec <Object> #定义容器属性
通过上面可以看到,statefulset 资源中有两个 spec 字段。
第一个 spec 声明的是 statefulset 定义多少个 Pod 副本(默认将仅部署 1 个 Pod)、匹配 Pod 标签的选择器、创建 pod 的模板、存储卷申请模板
第二个 spec 是 spec.template.spec:主要用于 Pod 里的容器属性等配置。
tatefulset.spec.template 里的内容是声明 Pod 对象时要定义的各种属性,所以这部分也叫做 PodTemplate(Pod 模板)。
还有一个值得注意的地方是:在tatefulset.spec.selector 中定义的标签选择器必须能够匹配到spec.template.metadata.labels 里定义的 Pod 标签,否则 Kubernetes 将不允许创建 statefulset。
-
Statefulset 使用案例-部署 web 站点
-
1、创建运行 nfs-provisioner 需要的 sa 账号
vim serviceaccount.yaml2、对 sa 授权
kubectl create clusterrolebinding nfs-provisioner --clusterrole=cluster-admin --serviceaccount=default:nfs-provisioner
3、安装 nfs-provisioner 程序
# mkdir /data/nfs_pro -p
#把/data/nfs_pro 变成 nfs 共享的目录
vim /etc/exports
vim nfs-deployment.yaml
provisioner 相当于一个 pod,必须正常运行才可以
-
4、#创建存储类
# vim class-web.yaml
vim statefulset.yaml#通过上面可以看到创建的 pod 是有序的 web-[ ]
-
#使用 kubectl run 运行一个提供 nslookup 命令的容器的,改命令来自于 dnsutils 包,通过对pod 主机名执行 nslookup,可以检查它们在集群内部的 DNS 地址:
kubectl exec -it web-0 -- /bin/bash
apt update
apt install dnsutils -y
nslookup web-0.nginx.default.svc.cluster.local#statefulset 创建的 pod 也是有 dns 记录的
Server: 10.96.0.10
Address: 10.96.0.10#53Name: nginx.default.svc.cluster.local
Address: 10.244.61.198
Name: nginx.default.svc.cluster.local
Address: 10.244.179.6资源清单详细解读:
apiVersion: v1 #定义 api 版本
kind: Service #定义要创建的资源:service
metadata:
name: nginx #定义 service 的名字
labels:
app: nginx #service 的标签
spec:
ports:
- port: 80
name: web
clusterIP: None #创建一个没有 ip 的 service
selector:
app: nginx #选择拥有 app=nginx 标签的 pod
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
selector:
matchLabels:
app: nginx
serviceName: "nginx" # 上面定义的 headless service 的名字
replicas: 2 #副本数
template: #定义 pod 的模板
metadata:
labels:
app: nginx
spec:
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: "nfs-web" #指定从哪个存储类申请 pv
resources:
requests:
storage: 1Gi #需要 1G 的 pvc,会自动跟符合条件的 pv 绑定
-
Statefulset 管理 pod-扩容、缩容、更新
-
Statefulset 实现 pod 的动态扩容
-
如果觉得两个副本太少了,想要增加,只需要修改配置文件 statefulset.yaml 里的 replicas 的值即可,原来 replicas: 2,现在变成 replicaset: 3,修改之后,执行更新:
也可以直接编辑控制器实现扩容,这个是把请求提交给了 apiserver,实时修改
Statefulset 实现 pod 的动态缩容
如果觉得 4 个 Pod 副本太多了,想要减少,只需要修改配置文件 statefulset.yaml 里的replicas 的值即可,把 replicaset:4 变成 replicas: 2,修改之后,执行更新:#Statefulset 实现 pod 里面容器 的更新
kubectl edit statefulsets.apps web
#修改镜像 nginx 变成- image: ikubernetes/myapp:v2,修改之后保存退出 -
k8s 配置管理中心-Configmap
-
Configmap 概述
-
什么是 Configmap?
Configmap 是 k8s 中的资源对象,用于保存非机密性的配置的,数据可以用 key/value 键值对的形式保存,也可通过文件的形式保存。 - Configmap 能解决哪些问题?
在部署服务的时候,每个服务都有自己的配置文件,如果一台服务器上部署多个服务:nginx、tomcat、apache 等,那么这些配置都存在这个节点上,假如一台服务器不能满足线上高并发的要求,需要对服务器扩容,扩容之后的服务器还是需要部署多个服务:nginx、tomcat、apache,新增加的服务器上还是要管理这些服务的配置,如果有一个服务出现问题,需要修改配置文件,每台物理节点上的配置都需要修改,这种方式肯定满足不了线上大批量的配置变更要求。
所以,k8s 中引入了 Configmap资源对象,可以当成 volume 挂载到 pod 中,实现统一的配置管理。 -
1、Configmap 是 k8s 中的资源, 相当于配置管理中心,可以有一个或者多个 Configmap;
2、Configmap 可以做成 Volume,k8s pod 启动之后,通过 volume 形式映射到容器内部指定目录上; - Configmap 应用场景
1、使用 k8s 部署应用,当你将应用配置写进代码中,更新配置时也需要打包镜像,configmap 可以将配置信息和 docker 镜像解耦,以便实现镜像的可移植性和可复用性,因为一个 configMap 其实就是一系列配置信息的集合,可直接注入到 Pod 中给容器使用。configmap 注入方式有两种,一种将configMap 做为存储卷,一种是将 configMap 通过 env 中 onfigMapKeyRef 注入到容器中。
2、使用微服务架构的话,存在多个服务共用配置的情况,如果每个服务中单独一份配置的话,那么更新配置就很麻烦,使用 configmap 可以友好的进行配置共享。
局限性
ConfigMap 在设计上不是用来保存大量数据的。在 ConfigMap 中保存的数据不可超过 1 MiB。
如果你需要保存超出此尺寸限制的数据,可以考虑挂载存储卷或者使用独立的数据库或者文件服务。
-
Configmap 创建方法
-
编写 configmap 资源清单 YAML 文件
# vim mysql-configmap.yaml使用 Configmap,把 configmap 做成 volume,挂载到 pod
vim mysql-pod-volume.yaml
以上是关于k8s 控制器-Statefulset的主要内容,如果未能解决你的问题,请参考以下文章
从零开始入门 K8s | 有状态应用编排 - StatefulSet