苏州怎么制作网页网站,桂平市住房和城乡建设局网站,合肥网站设计培训,连云港建设局网站一、部署思路
1、前期设想
zookeeper集群至少需要运行3个pod集群才能够正常运行#xff0c;考虑到节点会有故障的风险这个3个pod最好分别运行在#xff13;个不同的节点上(为了实现这一需要用到亲和性和反亲和性概念)#xff0c;在部署的时候对zookeeper运行的pod打标签加…一、部署思路
1、前期设想
zookeeper集群至少需要运行3个pod集群才能够正常运行考虑到节点会有故障的风险这个3个pod最好分别运行在个不同的节点上(为了实现这一需要用到亲和性和反亲和性概念)在部署的时候对zookeeper运行的pod打标签加入appzk那么假设当zookeeper-1在node1节点上运行那么zookeeper-2部署的时候发现node1节点上已经存在appzk标签就不会在再node1节点上运行(这里可能会用到硬策略 亲和性(NotIn)或者硬策略反亲和性(In))来实现。个pod至少需要3台机器而实验环境只用3台机器(一台master节点和2台node节点)因为污点原因master节点不参与集群节点的调度工作所以为了完成部署可能需要引入污点与容忍概念。 2、实现思路
1、创建一个service类型的无头服务zk-headless(因为zookeeper集群服务可能会进行销毁创建IP不固定所以zookeeper配置文件中不能配置IP所以要创建一个clusterIP: None的service表示不分配ip通过域名进行访问)
产生的域名格式pod-name.service-name.namespace.svc.cluster.local。
2、要创建一个zookeeper集群配置清单(将上述的生成的域名写入到配置中)。
3、创建PodDisruptionBudget确保集群正常可用。
4、创建StatefulSet有状态服务(绑定上述的无头服务serviceName: zk-headless)配置亲和性或污点容忍策略。
5、创建一个NodePort类型的service用于外部连接测试使用。 二、部署 zookeeper集群
一、zookeeper pod部署
1、将master上的污点设置为PreferNoSchedule
表示 k8s 将尽量避免将 Pod 调度到具有该污点的 Node 上
#将污点设置为PreferNoSchedule表示 k8s 将尽量避免将 Pod 调度到具有该污点的 Node 上
kubectl taint node master node-role.kubernetes.io/master:PreferNoSchedule 2、创建PodDisruptionBudget资源对象
2.1、PodDisruptionBudget资源对象简介 在 KubernetesK8s里PodDisruptionBudgetPDB是一种非常重要的资源对象它主要用于保障应用的高可用性避免因计划内的中断比如节点维护、集群升级等而导致过多的 Pod 同时被终止。下面为你详细介绍 PodDisruptionBudget。 2.1.1、核心作用 在 Kubernetes 集群中计划内的中断事件是难以避免的像节点维护、节点升级、节点驱逐等操作都可能导致 Pod 被终止。PodDisruptionBudget 的作用就是对这些计划内中断进行管控确保在任何时候都有足够数量的 Pod 处于运行状态从而保障应用的正常运行和服务的稳定性。 2.1.2、关键概念 minAvailable该参数规定了在计划内中断期间必须保持运行的最小 Pod 数量或者比例。例如设置 minAvailable: 3 表示至少要有 3 个 Pod 处于运行状态设置 minAvailable: 50% 则意味着至少要有一半的 Pod 保持运行。maxUnavailable此参数定义了在计划内中断期间允许不可用的最大 Pod 数量或者比例。例如设置 maxUnavailable: 2 表示最多允许 2 个 Pod 不可用设置 maxUnavailable: 25% 则表示最多允许 25% 的 Pod 不可用。 2.1.3、配置示例 以下是一个 PodDisruptionBudget 的 YAML 配置示例 pod-disruption-budget-examplePodDisruptionBudget 配置示例 V1 生成 pod-disruption-budget.yaml 2.1.4、配置解释 apiVersion指定使用的 Kubernetes API 版本这里使用的是 policy/v1。kind表明资源对象的类型为 PodDisruptionBudget。metadata包含资源对象的元数据name 为该 PodDisruptionBudget 的名称。spec定义了 PodDisruptionBudget 的具体规格。 minAvailable设置为 2表示在计划内中断期间至少要有 2 个带有 app: my-app 标签的 Pod 保持运行状态。selector用于筛选要应用该 PodDisruptionBudget 的 Pod这里通过 matchLabels 选择带有 app: my-app 标签的 Pod。 2.1.5、工作机制 当计划内中断事件发生时Kubernetes 会检查 PodDisruptionBudget 的规则。如果中断操作会导致不符合 minAvailable 或 maxUnavailable 的要求那么该操作将会被阻止直到满足 PodDisruptionBudget 的条件为止。 2.1.6、使用场景 关键业务应用对于像数据库、缓存服务这类关键业务应用使用 PodDisruptionBudget 可以确保在集群维护或升级期间有足够数量的 Pod 继续运行避免服务中断。多副本应用对于运行多个副本的应用PodDisruptionBudget 可以防止过多的副本同时被终止保证服务的稳定性和可用性。 通过使用 PodDisruptionBudget你可以在 Kubernetes 集群中更好地管理计划内中断保障应用的高可用性。 分享 如何创建一个PodDisruptionBudget 查看PodDisruptionBudget的详细信息。 如何调整PodDisruptionBudget的配置 2.2、怎样查看PodDisruptionBudget的apiVersion需要填什么
kubectl explain poddisruptionbudget 2.3、创建PodDisruptionBudget
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:name: zookeepernamespace: kafka
spec:minAvailable: 2selector:matchLabels:app: zookeeper 3、创建无头服务
创建一个名为zk-headless(因为zookeeper集群服务可能会进行销毁创建IP不固定所以zookeeper配置文件中不能配置IP要创建一个clusterIP: None的service表示不分配ip通过域名进行访问)。
产生的域名格式pod-name.service-name.namespace.svc.cluster.local。
apiVersion: v1
kind: Service
metadata:name: zk-headlessnamespace: kafka
spec:clusterIP: None # Headless Service不分配IPselector:app: zookeeperports:- name: clientport: 2181targetPort: 2181- name: peer-electionport: 3888targetPort: 3888- name: peer-communicationport: 2888targetPort: 2888 4、创建一个zookeeper集群配置清单
apiVersion: v1
kind: ConfigMap
metadata:name: zoo-confnamespace: kafka
data:zoo.cfg: |tickTime2000dataDir/var/lib/zookeeper/datadataLogDir/var/lib/zookeeper/logclientPort2181initLimit5syncLimit2# 动态生成集群节点如3节点server.0zk-0.zk-headless.kafka.svc.cluster.local:2888:3888server.1zk-1.zk-headless.kafka.svc.cluster.local:2888:3888server.2zk-2.zk-headless.kafka.svc.cluster.local:2888:3888后边部署的pod名称是zk是所以这里填入zk-0、zk-1、zk-2 。 5、创建StatefulSet有状态服务
apiVersion: apps/v1
kind: StatefulSet #部署服务的类型
metadata:name: zknamespace: kafka
spec:replicas: 3 # 集群节点数selector:matchLabels:app: zookeeperserviceName: zk-headless #绑定的无头服务名称template:metadata:labels:app: zookeeperspec:containers:- name: zookeeperimage: zookeeper:3.8.0 # 官方镜像ports:- containerPort: 2181name: client- containerPort: 3888name: zk-leader- containerPort: 2888name: zk-serverenv:- name: POD_NAMEvalueFrom:fieldRef:fieldPath: metadata.name # 获取Pod名称如zk-0volumeMounts:- name: datamountPath: /var/lib/zookeeper/data- name: logmountPath: /var/lib/zookeeper/log- name: configmountPath: /conf/zoo.cfgsubPath: zoo.cfgresources:requests:cpu: 500mmemory: 1GiinitContainers:- name: write-myidimage: alpine:3.17command: [sh, -c]args:- |# 从Pod名称中提取序号如zk-0 → 0#ID$(echo $(POD_NAME) | cut -d- -f2)cat /proc/1/environ|tr \0 \n|grep HOSTNAME|awk -F {print $2}|cut -d- -f2 /var/lib/zookeeper/data/myidvolumeMounts:- name: datamountPath: /var/lib/zookeeper/dataaffinity:podAntiAffinity:requiredDuringSchedulingIgnoredDuringExecution:- labelSelector:matchExpressions:- key: appoperator: Invalues:- zookeepertopologyKey: kubernetes.io/hostnamevolumes:- name: configconfigMap:name: zoo-confvolumeClaimTemplates:- metadata:name: dataspec:accessModes:- ReadWriteOnceresources:requests:storage: 5GistorageClassName: nfs-client- metadata:name: logspec:accessModes:- ReadWriteOnceresources:requests:storage: 5GistorageClassName: nfs-client5.1、配置亲和性策略 affinity:podAntiAffinity: #反亲和requiredDuringSchedulingIgnoredDuringExecution: #硬策略- labelSelector:matchExpressions:- key: app #指定key是appoperator: In values:- zookeeper #即匹配appzookeeper的标签topologyKey: kubernetes.io/hostname6、创建一个NodePort类型的service用于外部连接测试使用
apiVersion: v1
kind: Service
metadata:name: zk-clientnamespace: kafka
spec:selector:app: zookeeperports:- name: clientport: 2181targetPort: 2181type: NodePort # 如需外部访问可改为NodePort或LoadBalancer 二、部署过程问题排查
1、pod节点没有创建因为变量命名规则大于15个字符导致报错问题处理
#查看描述
kubectl get statefulset -n zookeeper
kubectl describe statefulset -n zookeeper zk-cluster | tail -n 10 2、配置文件名称不一致问题处理
kubectl get pod -n zookeeper -w
kubectl describe pod zk-cluster-0 -n zookeeper|tail -n10
kubectl logs zk-cluster-0 -n zookeeper 3、statefulset服务将pod信息存储在/var/lib/kubelet/pods中删除动态卷下的数据会导致再次部署的时候发生报错。 报错 解决执行kubectl delete -f *yaml 将之前部署到所有yaml清单全部删除。 4、POD_NAME变量获取不到问题处理
在部署zookeeper集群时需要在每个zookeeper节点的myid中填入对应的值这里直接将POD_NAME变量名后的数字写入但是在部署的过程中发现metadata.name值无法获取所以在这里使用shell获取pod名称编号写入myid方法如下
#在实验中POD_NAME变量的名称获取不到env:- name: POD_NAMEvalueFrom:fieldRef:fieldPath: metadata.name # 获取Pod名称如zk-0#解决方法使用如下命令获取pod的名称cat /proc/1/environ|tr \0 \n|grep HOSTNAME|awk -F {print $2}|cut -d- -f2 /var/lib/zookeeper/data/myid 三、完整的zookeeper集群部署流程清单
#创建配置apiVersion: v1
kind: ConfigMap
metadata:name: zoo-confnamespace: zookeeper
data:zoo.cfg: |tickTime2000dataDir/var/lib/zookeeper/datadataLogDir/var/lib/zookeeper/logclientPort2181initLimit5syncLimit2# 动态生成集群节点如3节点server.0zk-0.zk-headless.zookeeper.svc.cluster.local:2888:3888server.1zk-1.zk-headless.zookeeper.svc.cluster.local:2888:3888server.2zk-2.zk-headless.zookeeper.svc.cluster.local:2888:3888---
#创建PodDisruptionBudgetapiVersion: policy/v1
kind: PodDisruptionBudget
metadata:name: zookeepernamespace: zookeeper
spec:minAvailable: 2selector:matchLabels:app: zookeeper---
apiVersion: v1
kind: Service
metadata:name: zk-clientnamespace: zookeeper
spec:selector:app: zookeeperports:- name: clientport: 2181targetPort: 2181type: ClusterIP # 如需外部访问可改为NodePort或LoadBalancer---#创建无头服务
apiVersion: v1
kind: Service
metadata:name: zk-headlessnamespace: zookeeper
spec:clusterIP: None # Headless Service不分配IPselector:app: zookeeperports:- name: clientport: 2181targetPort: 2181- name: peer-electionport: 3888targetPort: 3888- name: peer-communicationport: 2888targetPort: 2888---#创建有状态副本集apiVersion: apps/v1
kind: StatefulSet
metadata:name: zknamespace: zookeeper
spec:replicas: 3 # 集群节点数selector:matchLabels:app: zookeeperserviceName: zk-headlesstemplate:metadata:labels:app: zookeeperspec:containers:- name: zookeeperimage: zookeeper:3.8.0 # 官方镜像ports:- containerPort: 2181name: client- containerPort: 3888name: zk-leader- containerPort: 2888name: zk-serverenv:- name: POD_NAMEvalueFrom:fieldRef:fieldPath: metadata.name # 获取Pod名称如zk-0volumeMounts:- name: datamountPath: /var/lib/zookeeper/data- name: logmountPath: /var/lib/zookeeper/log- name: configmountPath: /conf/zoo.cfgsubPath: zoo.cfgresources:requests:cpu: 500mmemory: 1GiinitContainers:- name: write-myidimage: alpine:3.17command: [sh, -c]args:- |# 从Pod名称中提取序号如zk-0 → 0#ID$(echo $(POD_NAME) | cut -d- -f2)cat /proc/1/environ|tr \0 \n|grep HOSTNAME|awk -F {print $2}|cut -d- -f2 /var/lib/zookeeper/data/myidvolumeMounts:- name: datamountPath: /var/lib/zookeeper/dataaffinity:podAntiAffinity:requiredDuringSchedulingIgnoredDuringExecution:- labelSelector:matchExpressions:- key: appoperator: Invalues:- zookeepertopologyKey: kubernetes.io/hostnamevolumes:- name: configconfigMap:name: zoo-confvolumeClaimTemplates:- metadata:name: dataspec:accessModes:- ReadWriteOnceresources:requests:storage: 5GistorageClassName: nfs-client- metadata:name: logspec:accessModes:- ReadWriteOnceresources:requests:storage: 5GistorageClassName: nfs-client---
#创建与外部连接的serviceapiVersion: v1
kind: Service
metadata:name: zk-clientnamespace: zookeeper
spec:selector:app: zookeeperports:- name: clientport: 2181targetPort: 2181type: ClusterIP # 如需外部访问可改为NodePort或LoadBalancer
[rootmaster zookeeper]#四、集群访问测试
1、查看集群状态是否正常
#进入集群内部
kubectl exec -it zk-0 -n kafka -- /bin/bash#查看zk-0的状态
echo srvr|nc zk-0.zk-headless.kafka.svc.cluster.local 2181#查看zk-1的状态
echo srvr|nc zk-1.zk-headless.kafka.svc.cluster.local 2181#查看zk-2的状态
echo srvr|nc zk-2.zk-headless.kafka.svc.cluster.local 2181 2、在zookeeper集群中写入数据
编写python代码往zookeeper集群中写入1000个数据
from kazoo.client import KazooClientdef xixi(path, data):hosts 192.168.72.130:30459# 创建 KazooClient 实例zk KazooClient(hostshosts)try:# 连接到 ZooKeeper 集群zk.start()print(成功连接到 ZooKeeper 集群)# 要写入的路径# path /test_node# # 要写入的数据# data bHello, ZooKeeper!# 检查路径是否存在如果不存在则创建if not zk.exists(path):zk.create(path, data)print(f成功在路径 {path} 创建节点并写入数据)else:# 如果节点已存在更新数据zk.set(path, data)print(f成功更新路径 {path} 下的数据)except Exception as e:print(f发生错误: {e})finally:# 关闭连接if zk.connected:zk.stop()print(已断开与 ZooKeeper 集群的连接)if __name__ __main__:# ZooKeeper 集群地址hosts 192.168.72.130:30459# 创建 KazooClient 实例zk KazooClient(hostshosts)for i in range(1,1000):print(i)path f/test_{i}data_1 fzookeeper-{i}data data_1.encode(utf-8)xixi(path, data) 三、污点与容忍
(一)、不设置污点容忍master节点无法参与调度
将master主节点上的污点修改成NoSchedule (修改之后zookeeper pod将不能再调度到master节点上这意味着剩下两个节点中的有一个节点要运行两个pod而我们在yaml中配置了亲和性所以已经存在zookeeper标签的节点不能再运行因此3个副本中只有两个副本是正常的还有一个处于异常状态)
为了验证上述的说法我开始以下测试
步骤一将之前部署的zookeeper集群删除掉环境清理 执行脚本 sh deploy.sh delete deploy.sh脚本内容如下
##创建命名空间
#kubectl create namespace zookeeper
#
##根据配置文件创建configmapx
#kubectl create configmap zoo.cfg --from-filezoo.conf
#
##创建PodDisruptionBudget只能指定集群运行节点的最小数
#kubectl apply -f podDisruptionBudget.yaml
#
##创建一个service使得pod之间产生一个可用互相访问的域名用于 StatefulSet 的稳定 DNS 解析格式为 pod-name.service-name.namespace.svc.cluster.local
#
apply ()
{kubectl apply -f podDisruptionBudget.yamlkubectl apply -f zk-client-service.yamlkubectl apply -f zk-headless-service.yamlkubectl apply -f zoo-config.yamlkubectl apply -f zk-statefulset.yaml
}delete ()
{kubectl delete -f podDisruptionBudget.yamlkubectl delete -f zk-client-service.yamlkubectl delete -f zk-headless-service.yamlkubectl delete -f zoo-config.yamlkubectl delete -f zk-statefulset.yaml
}main ()
{case $1 inapply)apply;;delete)deleteesac
}main $1 步骤二将master污点设置成NoSchedule
#将污点设置为NoSchedule
kubectl taint node master node-role.kubernetes.io/master:NoSchedule#查看污点是否设置成功
kubectl describe nodes master|grep -i taint 步骤三执行脚本sh deploy.sh apply 重新部署zookeeper集群 测试结果master节点无法参与调度
只有两个pod成功运行一个pod处于Pending状态 报错信息与设想的结果一致 (二)、设置污点容忍master上可以参与调度
假设将zookeeper集群的yaml文件中配置污点容忍那么master节点也可以参与调度之前3个副本只能运行两个如果添加了污点容忍那么master节点上也可以参与调度即3个pod都能正常运行
1、污点容忍配置 在 Kubernetesk8s里污点Taints和容忍度Tolerations是用来控制 Pod 调度到特定节点的机制。污点应用于节点而容忍度则设置在 Pod 上允许 Pod 调度到带有特定污点的节点。下面详细介绍如何设置污点和容忍度。 1.1. 设置节点污点 可以使用 kubectl taint 命令为节点添加污点。污点的格式为 keyvalue:effect其中 effect 有三种类型 NoSchedule新的 Pod 不会被调度到带有该污点的节点但已在该节点上运行的 Pod 不受影响。PreferNoSchedule系统会尽量避免将新的 Pod 调度到带有该污点的节点但不是强制的。NoExecute新的 Pod 不会被调度到带有该污点的节点并且如果已在该节点上运行的 Pod 没有相应的容忍度它们会被驱逐。 以下是添加污点的示例命令 # 添加一个 NoSchedule 类型的污点
kubectl taint nodes node-name key1value1:NoSchedule# 添加一个 PreferNoSchedule 类型的污点
kubectl taint nodes node-name key2value2:PreferNoSchedule# 添加一个 NoExecute 类型的污点
kubectl taint nodes node-name key3value3:NoExecute要将 node-name 替换成实际的节点名称。 1.2. 删除节点污点 若要删除节点上的污点可以使用以下命令 kubectl taint nodes node-name key1:NoSchedule-这里的 - 表示删除该污点。 1.3. 设置 Pod 容忍度 在 Pod 的 YAML 文件中添加容忍度设置以下是一个示例 pod-with-tolerations带有容忍度设置的 Pod YAML 文件 生成 pod-with-tolerations.yaml apiVersion: v1
kind: Pod
metadata:name: pod-with-tolerations
spec:containers:- name: nginximage: nginx:1.14.2ports:- containerPort: 80tolerations:- key: key1operator: Equalvalue: value1effect: NoSchedule- key: key2operator: Equalvalue: value2effect: PreferNoSchedule- key: key3operator: Equalvalue: value3effect: NoExecutetolerationSeconds: 3600 # 表示在节点添加该污点后Pod 还能继续运行 3600 秒 在这个示例中 key对应节点上污点的键。operator有 Equal 和 Exists 两种取值。Equal 表示容忍度的 key 和 value 必须与污点的 key 和 value 完全匹配Exists 表示只要节点上存在该 key 的污点不管 value 是什么都能容忍。value对应节点上污点的值。effect对应节点上污点的效果。tolerationSeconds仅在 effect 为 NoExecute 时有效表示在节点添加该污点后Pod 还能继续运行的时间。 1.4. 部署带有容忍度的 Pod 将上述 YAML 文件保存为 pod-with-tolerations.yaml然后使用以下命令部署 Pod kubectl apply -f pod-with-tolerations.yaml通过上述步骤你就可以设置节点的污点和 Pod 的容忍度从而控制 Pod 的调度。 2、在zookeeper部署的yaml中配置污点容忍
步骤一查看污点所对应的key值
#查看污点所对应的key
kubectl get nodes master -o yaml 步骤二在yaml中加入污点容忍 #在pod的spec下加入tolerations:- key: node-role.kubernetes.io/masteroperator: Existseffect: NoSchedule- key: node-role.kubernetes.io/masteroperator: Existseffect: PreferNoSchedule步骤三部署3个pod的zookeeper集群
sh -x deploy.sh apply 测试结果master节点参与调度污点容忍策略生效 参考博客链接k8s设置容器环境变量service服务无法获取到环境变量的解决方法_yaml podname 变量-CSDN博客