• 基于 Kubernetes 部署 Zookeeper(StatefulSet方式)


    随着云原生化流行的大趋势,我们的基础组件也需要逐渐上Kubernetes了。Apache Zookeeper作为目前最流行的分布式协调组件,在我们的微服务架构中负责扮演注册中心的角色。

    在Kubernetes中运行Zookeeper集群是很有意义的,可以利用其原生的弹性扩缩容、高可用特性。

    先说下使用的k8s的版本是1.25.0,对于PodDisruptionBudget的apiVersion会有影响,某些更老的k8s版本,apiVersion是policy/v1bata,1.25.0的k8s对应的apiVersion是policy/v1。

    使用StatefulSet部署Zookeeper

    官方提供了使用statefulSet的方式来部署 Zookeeper 运行 Zookeeper,它会创建一个headless service,一个cluster service,一个podDisruptionBudget,一个statefulSet。

    1. apiVersion: v1
    2. kind: PersistentVolume
    3. metadata:
    4. name: zk-pv
    5. spec:
    6. capacity:
    7.   storage: 512Mi
    8. accessModes:
    9.   - ReadWriteOnce
    10. hostPath:
    11.   path: /data
    12. ---
    13. apiVersion: v1
    14. kind: Service
    15. metadata:
    16. name: zk-hs
    17. labels:
    18.   app: zk
    19. spec:
    20. ports:
    21. - port: 2888
    22.   name: server
    23. - port: 3888
    24.   name: leader-election
    25. clusterIP: None
    26. selector:
    27.   app: zk
    28. ---
    29. apiVersion: v1
    30. kind: Service
    31. metadata:
    32. name: zk-cs
    33. labels:
    34.   app: zk
    35. spec:
    36. ports:
    37. - port: 2181
    38.   name: client
    39. selector:
    40.   app: zk
    41. ---
    42. apiVersion: policy/v1
    43. kind: PodDisruptionBudget
    44. metadata:
    45. name: zk-pdb
    46. spec:
    47. selector:
    48.   matchLabels:
    49.     app: zk
    50. maxUnavailable: 1
    51. ---
    52. apiVersion: apps/v1
    53. kind: StatefulSet
    54. metadata:
    55. name: zk
    56. spec:
    57. selector:
    58.   matchLabels:
    59.     app: zk
    60. serviceName: zk-hs
    61. replicas: 3
    62. updateStrategy:
    63.   type: RollingUpdate
    64. podManagementPolicy: OrderedReady
    65. template:
    66.   metadata:
    67.     labels:
    68.       app: zk
    69.   spec:
    70.     affinity:
    71.       podAntiAffinity:
    72.         requiredDuringSchedulingIgnoredDuringExecution:
    73.           - labelSelector:
    74.               matchExpressions:
    75.                 - key: "app"
    76.                   operator: In
    77.                   values:
    78.                   - zk
    79.             topologyKey: "kubernetes.io/hostname"
    80.     containers:
    81.     - name: kubernetes-zookeeper
    82.       imagePullPolicy: IfNotPresent
    83.       image: "harbor.martin.cc/google_containers/kubernetes-zookeeper:1.0-3.4.10"
    84.       resources:
    85.         requests:
    86.           memory: "0.5Gi"
    87.           cpu: "0.5"
    88.       ports:
    89.       - containerPort: 2181
    90.         name: client
    91.       - containerPort: 2888
    92.         name: server
    93.       - containerPort: 3888
    94.         name: leader-election
    95.       command:
    96.       - sh
    97.       - -c
    98.       - "start-zookeeper \
    99.         --servers=3 \
    100.         --data_dir=/var/lib/zookeeper/data \
    101.         --data_log_dir=/var/lib/zookeeper/data/log \
    102.         --conf_dir=/opt/zookeeper/conf \
    103.         --client_port=2181 \
    104.         --election_port=3888 \
    105.         --server_port=2888 \
    106.         --tick_time=2000 \
    107.         --init_limit=10 \
    108.         --sync_limit=5 \
    109.         --heap=512M \
    110.         --max_client_cnxns=60 \
    111.         --snap_retain_count=3 \
    112.         --purge_interval=12 \
    113.         --max_session_timeout=40000 \
    114.         --min_session_timeout=4000 \
    115.         --log_level=INFO"
    116.       readinessProbe:
    117.         exec:
    118.           command:
    119.           - sh
    120.           - -c
    121.           - "zookeeper-ready 2181"
    122.         initialDelaySeconds: 10
    123.         timeoutSeconds: 5
    124.       livenessProbe:
    125.         exec:
    126.           command:
    127.           - sh
    128.           - -c
    129.           - "zookeeper-ready 2181"
    130.         initialDelaySeconds: 10
    131.         timeoutSeconds: 5
    132.       volumeMounts:
    133.       - name: datadir
    134.         mountPath: /var/lib/zookeeper
    135.     securityContext:
    136.       runAsUser: 1000
    137.       fsGroup: 1000
    138. volumeClaimTemplates:
    139. - metadata:
    140.     name: datadir
    141.   spec:
    142.     accessModes: [ "ReadWriteOnce" ]
    143.     resources:
    144.       requests:
    145.         storage: 512Mi

    使用 kubectl apply应用这个配置文件,等待一会之后,发现pod和service都已创建成功。

    kubectl get pod 查看到 zk-0 pod一直pending.

    kubectl describe pod zk-0 看到事件原因是:

    0/4 nodes are available: 4 pod has unbound immediate PersistentVolumeClaims. preemption: 0/4 nodes are available: 4 Preemption is not helpful for scheduling.
    

    再使用:

    kubectl logs -n kube-system kube-controller-manager-k8s-master01.example.local

    查看controller-manager的pod日志:

    I0513 08:13:08.710572       1 event.go:294] "Event occurred" object="default/datadir-zk-0" fieldPath="" kind="PersistentVolumeClaim" apiVersion="v1" type="Normal" reason="FailedBinding" message="no persistent volumes available for this claim and no storage class is set"
    

    这么看,原来PV和 storage class 都没搞。这个网上的参考还是需要自己补充一下的,PV的API定义已经加到上面的资源清单了。

    PV弄了个HostPath的。但是也不知道存在哪个节点上。

    然后再执行kubectl apply -f zookeeper.yml创建,POD zk-0未启动成功,出来错误CrashLoopBackOff。通过kubectl logs zk-0查看POD日志:

    #This file was autogenerated DO NOT EDIT
    clientPort=2181
    dataDir=/var/lib/zookeeper/data
    dataLogDir=/var/lib/zookeeper/data/log
    tickTime=2000
    initLimit=10
    syncLimit=5
    maxClientCnxns=60
    minSessionTimeout=4000
    maxSessionTimeout=40000
    autopurge.snapRetainCount=3
    autopurge.purgeInteval=12
    server.1=zk-0.zk-hs.default.svc.cluster.local:2888:3888
    server.2=zk-1.zk-hs.default.svc.cluster.local:2888:3888
    server.3=zk-2.zk-hs.default.svc.cluster.local:2888:3888
    Creating ZooKeeper log4j configuration
    mkdir: cannot create directory '/var/lib/zookeeper/data': Permission denied
    chown: cannot access '/var/lib/zookeeper/data': No such file or directory
    mkdir: cannot create directory '/var/lib/zookeeper/data': Permission denied
    chown: invalid group: 'zookeeper:USER'
    /usr/bin/start-zookeeper: line 176: /var/lib/zookeeper/data/myid: No such file or directory
    

    有个疑问,这个日志是一直存着吗,还是POD没启动成功,我用kubectl delete -f zookeeper删除掉POD,再看下,还有没有这个日志。肯定没了:

    kubectl logs zk-0
    Error from server (NotFound): pods "zk-0" not found

    原来是POD及容器对于卷的目录主机目录没有写与创建子目录的权限。把对应的目录POD部署节点的目录 /data/,权限修改成全部可以读写创建:

    chmod 777 /data/

    重启后,还是有问题:

    发现pod zk-0启动成功了,但是到了zk-1启动失败,原来是每个pod要创建一个hostPath的PV。接下来创建两个zk-pv1,zk-pv2,在node2和node3上创建好对应的host文件夹/data/,并设置权限777。然后重启,三个pod都启动成功了。

    恭喜自己,部署看起来是成功了,那么就真正测试一下部署好的zk集群吧。

    要测试在 Kubernetes 上部署的 ZooKeeper 集群,可以执行以下步骤:

    1. 获取 ZooKeeper 的客户端工具,例如 ZooKeeper 命令行客户端 zkCli.sh。可以在 ZooKeeper 的官方网站下载安装包,并解压获取相关工具。

    2. 进入 Kubernetes 集群中的任意一个 Pod,可以使用 kubectl exec 命令进入 Pod 的容器内部。

      kubectl exec -it  -- /bin/bash

    3. 在容器内部,使用 ZooKeeper 客户端工具连接到 ZooKeeper 集群。根据您的部署方式和服务发现配置,可以使用 Service 名称或 Pod IP 连接到 ZooKeeper。

      ./zkCli.sh -server :

      或者

      ./zkCli.sh -server :

      这里的 是您 ZooKeeper 服务的名称, 是服务的端口号。如果您使用的是 StatefulSet 部署方式,可以使用 zk-{index}. 的方式连接到每个 ZooKeeper Pod。

    4. 连接成功后,您可以执行各种 ZooKeeper 的命令和操作,例如创建节点、设置数据、监听事件等。可以通过命令 help? 获取更多可用的命令列表和用法。

      1. [zk: :] help
      2. [zk: :] ?

      例如,可以使用以下命令创建一个节点并设置数据:

      [zk: :] create /test mydata

      然后使用以下命令获取节点的数据:

      [zk: :] get /test

      通过执行各种命令和操作,可以验证 ZooKeeper 集群的功能和可用性。

    请注意,上述命令中的 需要替换为实际的 ZooKeeper 服务名称和端口。具体的连接信息取决于您的部署方式和配置。

    都是验证通过的,说明安装成功了,Oh Yeah!

    附:安装的容器镜像描述信息:

    The ZooKeeper package is installed into the /opt/zookeeper directory, all configuration is sym linked into the /usr/etc/zookeeper/, and all executables are sym linked into /usr/bin. The ZooKeeper data directories are contained in /var/lib/zookeeper. This is identical to the RPM distribution that users should be familiar with.

    所以 /var/lib/zookeeper这个文件夹是放数据的,所以我们就明白为什么要把这个文件夹放到PV了。

  • 相关阅读:
    四六级听力考试高频词汇分类记忆-职场工作类
    软件安全学习课程实践3:软件漏洞利用实验
    2023,全网最真实的自动化测试学习路线,看不懂来打我!
    什么是浏览器的缓存机制
    嵌入式软件bug从哪里来,到哪里去
    【C++】算法STL库
    25分钟了解命令执行漏洞【例题+详细讲解】(二)
    springboot毕设项目个人博客的设计与实现i03nz(java+VUE+Mybatis+Maven+Mysql)
    HTML新手入门笔记整理:HTML基本介绍
    Vue2 测试解决方案
  • 原文地址:https://blog.csdn.net/mojinchuan/article/details/131146470