查看服务状态_在K8S上部署zookeeper有状态集群
点击上方「蓝字」关注我们ZooKeeper 基础 Apache ZooKeeper 是一个分布式的开源协调服务,用于分布式系统。ZooKeeper 允许你读取、写入数据和发现数据更新。数据按层次结构组织在文件系统中,并复制到 ensemble(一个 ZooKeeper 服务的集合) 中所有的 ZooKeeper 服务。对数据的所有操作都是原子的和顺序一致的。ZooKeeper 通过...
点击上方「蓝字」关注我们
ZooKeeper 基础
Apache ZooKeeper 是一个分布式的开源协调服务,用于分布式系统。ZooKeeper 允许你读取、写入数据和发现数据更新。数据按层次结构组织在文件系统中,并复制到 ensemble(一个 ZooKeeper 服务的集合) 中所有的 ZooKeeper 服务。对数据的所有操作都是原子的和顺序一致的。ZooKeeper 通过 Zab 一致性协议在 ensemble 的所有服务之间复制一个状态机来确保这个特性。
ensemble 使用 Zab 协议选举一个 leader,在选举出 leader 前不能写入数据。一旦选举出了 leader,ensemble 使用 Zab 保证所有写入被复制到一个 quorum,然后这些写入操作才会被确认并对客户端可用。如果没有遵照加权 quorums,一个 quorum 表示包含当前 leader 的 ensemble 的多数成员。例如,如果 ensemble 有3个服务,一个包含 leader 的成员和另一个服务就组成了一个 quorum。如果 ensemble 不能达成一个 quorum,数据将不能被写入。
ZooKeeper 在内存中保存它们的整个状态机,但是每个改变都被写入一个在存储介质上的持久 WAL(Write Ahead Log)。当一个服务故障时,它能够通过回放 WAL 恢复之前的状态。为了防止 WAL 无限制的增长,ZooKeeper 服务会定期的将内存状态快照保存到存储介质。这些快照能够直接加载到内存中,所有在这个快照之前的 WAL 条目都可以被安全的丢弃。
k8s集群信息
创建一个zookeeper集群
[root@worker01 middleware]# vim zk.yml#创建一个无头服务Headless serviceapiVersion: v1kind: Servicemetadata: name: zk-hs labels: app: zkspec: ports: - port: 2888 name: server - port: 3888 name: leader-election clusterIP: None selector:app: zk#创建一个service---apiVersion: v1kind: Servicemetadata: name: zk-cs labels: app: zkspec: type: ClusterIP ports: - port: 2181 targetPort: 2181 name: client selector:app: zk#创建一个PDB,确保最大不可用pod数量1---apiVersion: policy/v1beta1kind: PodDisruptionBudgetmetadata: name: zk-pdbspec: selector: matchLabels: app: zk maxUnavailable: 1
#创建有状态服务,3副本,pod反亲和性,节点亲和性,持久化存储[root@worker01 middleware]# cat zk-statefulset.yamlapiVersion: apps/v1kind: StatefulSetmetadata: name: zkspec: serviceName: zk-hs replicas: 3 selector: matchLabels: app: zk template: metadata: labels: app: zk spec: affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: "app" operator: In values: - zk topologyKey: "kubernetes.io/hostname" nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: "app" operator: In values: - "true" containers: - name: kubernetes-zookeeper imagePullPolicy: IfNotPresent image: leolee32/kubernetes-library:kubernetes-zookeeper1.0-3.4.10 resources: requests: memory: "1Gi" cpu: "0.5" ports: - containerPort: 2181 name: client - containerPort: 2888 name: server - containerPort: 3888 name: leader-election command: - sh - -c - "start-zookeeper \ --servers=3 \ --data_dir=/var/lib/zookeeper/data \ --data_log_dir=/var/lib/zookeeper/data/log \ --conf_dir=/opt/zookeeper/conf \ --client_port=2181 \ --election_port=3888 \ --server_port=2888 \ --tick_time=2000 \ --init_limit=10 \ --sync_limit=5 \ --heap=512M \ --max_client_cnxns=60 \ --snap_retain_count=3 \ --purge_interval=12 \ --max_session_timeout=40000 \ --min_session_timeout=4000 \ --log_level=INFO" readinessProbe: exec: command: - sh - -c - "zookeeper-ready 2181" initialDelaySeconds: 10 timeoutSeconds: 5 livenessProbe: exec: command: - sh - -c - "zookeeper-ready 2181" initialDelaySeconds: 10 timeoutSeconds: 5 volumeMounts: - name: zk-data mountPath: /var/lib/zookeeper volumeClaimTemplates: - metadata: name: zk-data spec: accessModes: [ "ReadWriteOnce" ] resources: requests: storage: 10Gi
[root@worker01 middleware]# kubectl apply -f . statefulset.apps/zk createdservice/zk-hs createdservice/zk-cs createdpoddisruptionbudget.policy/zk-pdb createdstatefulset.apps/zk configured
获取 StatefulSet 的 PersistentVolumeClaims
StatefulSet 控制器为 StatefulSet 中的每个 Pod 生成一个PersistentVolumeClaim。
当 zk
StatefulSet 中的一个 Pod 被(重新)调度时,它总是拥有相同的 PersistentVolume,挂载到 ZooKeeper 服务的数据目录。即使在 Pods 被重新调度时,所有对 ZooKeeper 服务的 WALs 的写入和它们的全部快照都仍然是持久的。
pods查看
Service查看
查看zk StatefulSet 中 Pods 的主机名和myid
FQDN查看
Kubernetes DNS 中的 A 记录将 FQDNs 解析成为 Pods 的 IP 地址。如果 Pods 被调度,这个 A 记录将会使用 Pods 的新 IP 地址更新,但 A 记录的名称不会改变。
在 zk-0 Pod 中查看 zoo.cfg 文件的内容
文件底部为 server.1、server.2 和 server.3,其中的 1、2和3分别对应 ZooKeeper 服务的 myid 文件中的标识符。它们被设置为 zk StatefulSet 中的 Pods 的 FQDNs。
我们现在来重建一下statefulset观察他的状态变化
创建 zk StatefulSet 时,StatefulSet 控制器按照 Pods 的序号索引顺序的创建每个 Pod,创建下一个 Pod 前会等待每个 Pod 变成 Running 和 Ready 状态
另外,每个 Pod 的 A 记录仅在 Pod 变成 Ready状态时被录入。因此,ZooKeeper 服务的 FQDNs 只会解析到一个 endpoint,这保证了 ZooKeepers 的 zoo.cfg
文件中的 servers
属性代表了一个正确配置的 ensemble。
健康状态检测
使用 zkCli.sh
脚本在 zk-0
Pod 上写入 yes 到路径 /k8s
在另一个pod zk-1上获取数据,查看数据已同步
pod的分布节点查看
可以确认StatefulSe 中所有的 Pods 都被部署在不同的节点,这是因为 StatefulSet 中的 Pods 指定了 PodAntiAffinity。requiredDuringSchedulingRequiredDuringExecution
告诉 Kubernetes 调度器,在以 topologyKey
指定的域中,绝对不要把带有键为 app
,值为 zk
的标签的两个 Pods 调度到相同的节点。这也是为了防止由于某台机器断连引起服务中断,最佳实践是防止应用的多个示例在相同的机器上共存。
PodDisruptionBudget zk-pdb查看
max-unavailable
字段指示 Kubernetes 在任何时候,zk
StatefulSet 至多有1个 Pods 是不可用的。
Pod Disruption Budget (pod中断预算) 简称PDB,含义其实是终止pod前通过labelSelector机制获取正常运行的pod数目的限制,目的是对自愿中断的保护措施。Kubernetes version >= 1.7 才支持PodDisruptionBudget
环境变量查看
THE END
野有蔓草
野有蔓草,零露漙兮。
有美一人,清扬婉兮。
邂逅相遇,适我愿兮。
野有蔓草,零露瀼瀼。
有美一人,婉如清扬。
邂逅相遇,与子偕臧。
往期推荐
基于k8s的Prometheus服务自动发现配置
Kubernetes监控方案kube-prometheus部署指北
更多推荐
所有评论(0)