6-2-1-k8s实际应用-zookeeper集群部署(一)
zookeeper是一个开源的分布式协调服务 , 由知名互联网公司Yahoo创建 , 它是Chubby的开源实现;换句话讲 , zookeeper是一个典型的分布式数据一致性解决方案 , 分布式应用程序可以基于它实现数据的发布/订阅、负载均衡、名称服务、分布式协调/通知、集群管理、Master选举、分布式锁和分布式队列;

1. 构建zookeeper镜像
下载
java环境基础镜像,将对应镜像修改本地harbor地址上传至harborroot@k8s-master01:~# nerdctl pull elevy/slim_java:8 WARN[0000] skipping verifying HTTPS certs for "docker.io" docker.io/elevy/slim_java:8: resolved |++++++++++++++++++++++++++++++++++++++| manifest-sha256:044e42fb89cda51e83701349a9b79e8117300f4841511ed853f73caf7fc98a51: done |++++++++++++++++++++++++++++++++++++++| config-sha256:0776147f4957ebff0e3314117258e09933273d45b83f07f1a4e1863201eac2b0: done |++++++++++++++++++++++++++++++++++++++| layer-sha256:fd529fe251b34db45de24e46ae4d8f57c5b8bbcfb1b8d8c6fb7fa9fcdca8905e: done |++++++++++++++++++++++++++++++++++++++| layer-sha256:88286f41530e93dffd4b964e1db22ce4939fffa4a4c665dab8591fbab03d4926: done |++++++++++++++++++++++++++++++++++++++| layer-sha256:7141511c4dad1bb64345a3cd38e009b1bcd876bba3e92be040ab2602e9de7d1e: done |++++++++++++++++++++++++++++++++++++++| elapsed: 15.4s total: 31.0 M (2.0 MiB/s) root@k8s-master01:~# nerdctl tag elevy/slim_java:8 harbor.cbear.top/baseimages/slim_java:8 root@k8s-master01:~# nerdctl push harbor.cbear.top/baseimages/slim_java:8 INFO[0000] pushing as a reduced-platform image (application/vnd.docker.distribution.manifest.v2+json, sha256:044e42fb89cda51e83701349a9b79e8117300f4841511ed853f73caf7fc98a51) WARN[0000] skipping verifying HTTPS certs for "harbor.cbear.top" manifest-sha256:044e42fb89cda51e83701349a9b79e8117300f4841511ed853f73caf7fc98a51: done |++++++++++++++++++++++++++++++++++++++| config-sha256:0776147f4957ebff0e3314117258e09933273d45b83f07f1a4e1863201eac2b0: done |++++++++++++++++++++++++++++++++++++++| elapsed: 1.2 s total: 18.0 K (15.0 KiB/s) 准备相关配置文件
root@k8s-master01:/opt/k8s-data/dockerfile/cbear/zookeeper# cat bin/zkReady.sh #!/bin/bash /zookeeper/bin/zkServer.sh status | egrep 'Mode: (standalone|leading|following|observing)' root@k8s-master01:/opt/k8s-data/dockerfile/cbear/zookeeper# cat entrypoint.sh #!/bin/bash ##将$MYID的值写入MYID文件,如果变量为空就默认为1,$MYID为pod中的系统级别环境变量,该变量由部署zk的yaml清单中的环境变量指定 echo ${MYID:-1} > /zookeeper/data/myid #如果$SERVERS不为空则向下执行,SERVERS为pod中的系统级别环境变量,该变量同样也是在zk部署yaml清单中指定的环境变量的 #IFS为bash内置变量用于分割字符并将结果形成一个数组 #${!servers[@]}表示获取servers中每个元素的索引值,此索引值会用做当前ZK的ID ##打印结果并输出重定向到文件/zookeeper/conf/zoo.cfg,其中%i和%s的值来分别自于后面变量"$((1 + $i))" "${servers[$i]}" if [ -n "$SERVERS" ]; then IFS=\, read -a servers <<<"$SERVERS" for i in "${!servers[@]}"; do printf "\nserver.%i=%s:2888:3888" "$((1 + $i))" "${servers[$i]}" >> /zookeeper/conf/zoo.cfg done fi #$@变量用于引用给脚本传递的所有参数,传递的所有参数会被作为一个数组列表,exec为终止当前进程、保留当前进程id、新建一个进程执行新的任务,即CMD [ "zkServer.sh", "start-foreground" ] cd /zookeeper exec "$@" root@k8s-master01:/opt/k8s-data/dockerfile/cbear/zookeeper# cat conf/ log4j.properties zoo.cfg root@k8s-master01:/opt/k8s-data/dockerfile/cbear/zookeeper# cat conf/zoo.cfg tickTime=2000 initLimit=20 syncLimit=20 dataDir=/zookeeper/data dataLogDir=/zookeeper/wal #snapCount=100000 autopurge.purgeInterval=1 clientPort=2181 quorumListenOnAllIPs=false root@k8s-master01:/opt/k8s-data/dockerfile/cbear/zookeeper# cat conf/log4j.properties # Define some default values that can be overridden by system properties zookeeper.root.logger=INFO, CONSOLE, ROLLINGFILE zookeeper.console.threshold=INFO zookeeper.log.dir=/zookeeper/log zookeeper.log.file=zookeeper.log zookeeper.log.threshold=INFO zookeeper.tracelog.dir=/zookeeper/log zookeeper.tracelog.file=zookeeper_trace.log # # ZooKeeper Logging Configuration # # Format is "<default threshold> (, <appender>)+ # DEFAULT: console appender only log4j.rootLogger=${zookeeper.root.logger} # Example with rolling log file #log4j.rootLogger=DEBUG, CONSOLE, ROLLINGFILE # Example with rolling log file and tracing #log4j.rootLogger=TRACE, CONSOLE, ROLLINGFILE, TRACEFILE # # Log INFO level and above messages to the console # log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender log4j.appender.CONSOLE.Threshold=${zookeeper.console.threshold} log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} [myid:%X{myid}] - %-5p [%t:%C{1}@%L] - %m%n # # Add ROLLINGFILE to rootLogger to get log file output # Log DEBUG level and above messages to a log file log4j.appender.ROLLINGFILE=org.apache.log4j.RollingFileAppender log4j.appender.ROLLINGFILE.Threshold=${zookeeper.log.threshold} log4j.appender.ROLLINGFILE.File=${zookeeper.log.dir}/${zookeeper.log.file} # Max log file size of 10MB log4j.appender.ROLLINGFILE.MaxFileSize=10MB # uncomment the next line to limit number of backup files log4j.appender.ROLLINGFILE.MaxBackupIndex=5 log4j.appender.ROLLINGFILE.layout=org.apache.log4j.PatternLayout log4j.appender.ROLLINGFILE.layout.ConversionPattern=%d{ISO8601} [myid:%X{myid}] - %-5p [%t:%C{1}@%L] - %m%n # # Add TRACEFILE to rootLogger to get log file output # Log DEBUG level and above messages to a log file log4j.appender.TRACEFILE=org.apache.log4j.FileAppender log4j.appender.TRACEFILE.Threshold=TRACE log4j.appender.TRACEFILE.File=${zookeeper.tracelog.dir}/${zookeeper.tracelog.file} log4j.appender.TRACEFILE.layout=org.apache.log4j.PatternLayout ### Notice we are including log4j's NDC here (%x) log4j.appender.TRACEFILE.layout.ConversionPattern=%d{ISO8601} [myid:%X{myid}] - %-5p [%t:%C{1}@%L][%x] - %m%n 为对应文件添加执行权限
root@k8s-master01:/opt/k8s-data/dockerfile/cbear/zookeeper# chmod +x entrypoint.sh bin/zkReady.sh配置对应
Dockerfile文件root@k8s-master01:/opt/k8s-data/dockerfile/cbear/zookeeper# cat Dockerfile #FROM harbor-linux38.local.com/linux38/slim_java:8 FROM harbor.cbear.top/pub-images/jdk-17-base:v2 ENV ZK_VERSION 3.9.2 RUN yum install -y \ ca-certificates \ gnupg \ tar \ wget && \ # # Install dependencies yum install -y \ bash && \ # # Download Zookeeper wget -nv -O /tmp/zk.tgz "https://dlcdn.apache.org/zookeeper/current/apache-zookeeper-3.9.2-bin.tar.gz" && \ wget -nv -O /tmp/zk.tgz.asc "https://dlcdn.apache.org/zookeeper/current/apache-zookeeper-3.9.2-bin.tar.gz.asc" && \ wget -nv -O /tmp/KEYS https://archive.apache.org/dist/zookeeper/KEYS && \ # # Verify the signature export GNUPGHOME="$(mktemp -d)" && \ gpg -q --batch --import /tmp/KEYS && \ gpg -q --batch --no-auto-key-retrieve --verify /tmp/zk.tgz.asc /tmp/zk.tgz && \ # # Set up directories # mkdir -p /zookeeper/data /zookeeper/wal /zookeeper/log && \ # # Install tar -x -C /zookeeper --strip-components=1 --no-same-owner -f /tmp/zk.tgz && \ # # Slim down cd /zookeeper && \ #cp dist-maven/zookeeper-${ZK_VERSION}.jar . && \ rm -rf \ *.txt \ *.xml \ *.md \ bin/README.txt \ bin/*.cmd \ conf/* \ zookeeper-contrib \ dist-maven \ docs \ lib/*.txt \ lib/cobertura \ lib/jdiff \ recipes \ src \ zookeeper-*.asc \ zookeeper-*.md5 \ zookeeper-*.sha1 && \ # # Clean up #apk del .build-deps && \ rm -rf /tmp/* "$GNUPGHOME" ## 拷贝配置文件和脚本 COPY conf /zookeeper/conf/ COPY bin/zkReady.sh /zookeeper/bin/ COPY entrypoint.sh / ENV PATH=/zookeeper/bin:${PATH} \ ZOO_LOG_DIR=/zookeeper/log \ ZOO_LOG4J_PROP="INFO, CONSOLE, ROLLINGFILE" \ JMXPORT=9010 \ ZOOKEEPER_HOME=/zookeeper #启动zookeeper,entrypoint 脚本和cmd联合使用,entrypoint会把cmd当作参数传递给entrypoint脚本执行,即entrypoint脚本通常用来做一些环境初始化;比如这里就是用来在线生成zk集群配置 ENTRYPOINT [ "/entrypoint.sh" ] CMD [ "zkServer.sh", "start-foreground" ] EXPOSE 2181 2888 3888 9010 创建构建脚本
root@k8s-master01:/opt/k8s-data/dockerfile/cbear/zookeeper# cat build-command.sh #!/bin/bash TAG=$1 nerdctl build -t harbor.cbear.top/cbear/zookeeper:${TAG} . echo "镜像构建完成 , 即将上传到harbor" sleep 1 nerdctl push harbor.cbear.top/cbear/zookeeper :${TAG} echo "镜像上传到harbor完成"运行构建脚本
root@k8s-master01:/opt/k8s-data/dockerfile/cbear/zookeeper# bash build-command.sh v3.9.2 验证上传的
zookeeper容器镜像是否正常root@k8s-master01:/opt/k8s-data/dockerfile/cbear/zookeeper# nerdctl run -it --rm -p 2181:2181 harbor.cbear.top/cbear/zookeeper:v3.9.2
2. 在K8s环境中运行zookeeper集群
在
nfs上准备pv目录root@harbor:~# mkdir -pv /data/k8sdata/cbear/zookeeper-datadir-{1,2,3} mkdir: created directory '/data/k8sdata/cbear/zookeeper-datadir-1' mkdir: created directory '/data/k8sdata/cbear/zookeeper-datadir-2' mkdir: created directory '/data/k8sdata/cbear/zookeeper-datadir-3' root@harbor:~# cat /etc/exports # /etc/exports: the access control list for filesystems which may be exported # to NFS clients. See exports(5). # # Example for NFSv2 and NFSv3: # /srv/homes hostname1(rw,sync,no_subtree_check) hostname2(ro,sync,no_subtree_check) # # Example for NFSv4: # /srv/nfs4 gss/krb5i(rw,sync,fsid=0,crossmnt,no_subtree_check) # /srv/nfs4/homes gss/krb5i(rw,sync,no_subtree_check) # /data/k8sdata/cbear/nginx/static *(rw,no_root_squash,no_subtree_check) /data/k8sdata/cbear/nginx/images *(rw,no_root_squash,no_subtree_check) /data/html *(rw,no_root_squash,no_subtree_check) /data/v1 *(rw,no_root_squash,no_subtree_check) /data/volumes *(rw,no_root_squash,no_subtree_check) /data/k8sdata/cbear/zookeeper-datadir-1 *(rw,no_root_squash,no_subtree_check) /data/k8sdata/cbear/zookeeper-datadir-2 *(rw,no_root_squash,no_subtree_check) /data/k8sdata/cbear/zookeeper-datadir-3 *(rw,no_root_squash,no_subtree_check) root@harbor:~# exportfs -rv exporting *:/data/k8sdata/cbear/zookeeper-datadir-3 exporting *:/data/k8sdata/cbear/zookeeper-datadir-2 exporting *:/data/k8sdata/cbear/zookeeper-datadir-1 exporting *:/data/volumes exporting *:/data/v1 exporting *:/data/html exporting *:/data/k8sdata/cbear/nginx/images exporting *:/data/k8sdata/cbear/nginx/static 在
k8s上创建pvroot@k8s-master01:/opt/k8s-data/yaml/cbear/zookeeper# vi zookeeper-pv.yaml --- apiVersion: v1 kind: PersistentVolume metadata: name: zookeeper-datadir-pv-1 spec: capacity: storage: 20Gi accessModes: - ReadWriteOnce nfs: server: 192.168.71.34 path: /data/k8sdata/cbear/zookeeper-datadir-1 --- apiVersion: v1 kind: PersistentVolume metadata: name: zookeeper-datadir-pv-2 spec: capacity: storage: 20Gi accessModes: - ReadWriteOnce nfs: server: 192.168.71.34 path: /data/k8sdata/cbear/zookeeper-datadir-2 --- apiVersion: v1 kind: PersistentVolume metadata: name: zookeeper-datadir-pv-3 spec: capacity: storage: 20Gi accessModes: - ReadWriteOnce nfs: server: 192.168.71.34 path: /data/k8sdata/cbear/zookeeper-datadir-3启用并验证配置
root@k8s-master01:/opt/k8s-data/yaml/cbear/zookeeper# kubectl apply -f zookeeper-pv.yaml persistentvolume/zookeeper-datadir-pv-1 created persistentvolume/zookeeper-datadir-pv-2 created persistentvolume/zookeeper-datadir-pv-3 created root@k8s-master01:/opt/k8s-data/yaml/cbear/zookeeper# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS VOLUMEATTRIBUTESCLASS REASON AGE pvc-26e5524a-c11a-4416-89b7-66ea8576fa5e 1Gi RWO Retain Bound default/www-web-1 managed-nfs-storage <unset> 16h pvc-4c91cd11-fca0-42ab-a986-8ef75e396d75 1Gi RWO Retain Bound default/www-web-0 managed-nfs-storage <unset> 16h pvc-935cb882-eff4-4438-b3ca-65e12ad2bb40 100Mi RWX Retain Bound default/test-claim managed-nfs-storage <unset> 17h zookeeper-datadir-pv-1 20Gi RWO Retain Available <unset> 35s zookeeper-datadir-pv-2 20Gi RWO Retain Available <unset> 35s zookeeper-datadir-pv-3 20Gi RWO Retain Available <unset> 35s在
k8s上创建pvcroot@k8s-master01:/opt/k8s-data/yaml/cbear/zookeeper# cat zookeeper-pvc.yaml --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: zookeeper-datadir-pvc-1 namespace: cbear spec: accessModes: - ReadWriteOnce volumeName: zookeeper-datadir-pv-1 resources: requests: storage: 10Gi --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: zookeeper-datadir-pvc-2 namespace: cbear spec: accessModes: - ReadWriteOnce volumeName: zookeeper-datadir-pv-2 resources: requests: storage: 10Gi --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: zookeeper-datadir-pvc-3 namespace: cbear spec: accessModes: - ReadWriteOnce volumeName: zookeeper-datadir-pv-3 resources: requests: storage: 10Gi启用并验证配置
root@k8s-master01:/opt/k8s-data/yaml/cbear/zookeeper# kubectl apply -f zookeeper-pvc.yaml persistentvolumeclaim/zookeeper-datadir-pvc-1 created persistentvolumeclaim/zookeeper-datadir-pvc-2 created persistentvolumeclaim/zookeeper-datadir-pvc-3 created root@k8s-master01:/opt/k8s-data/yaml/cbear/zookeeper# kubectl get pvc -n cbear NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE zookeeper-datadir-pvc-1 Bound zookeeper-datadir-pv-1 20Gi RWO <unset> 12s zookeeper-datadir-pvc-2 Bound zookeeper-datadir-pv-2 20Gi RWO <unset> 12s zookeeper-datadir-pvc-3 Bound zookeeper-datadir-pv-3 20Gi RWO <unset> 12s部署
zookeeperroot@k8s-master01:/opt/k8s-data/yaml/cbear/zookeeper# cat zookeeper.yaml apiVersion: v1 kind: Service metadata: name: zookeeper namespace: cbear spec: ports: - name: client port: 2181 selector: app: zookeeper --- apiVersion: v1 kind: Service metadata: name: zookeeper1 namespace: cbear spec: clusterIP: None ports: - name: client port: 2181 - name: followers port: 2888 - name: election port: 3888 selector: app: zookeeper server-id: "1" --- apiVersion: v1 kind: Service metadata: name: zookeeper2 namespace: cbear spec: clusterIP: None ports: - name: client port: 2181 - name: followers port: 2888 - name: election port: 3888 selector: app: zookeeper server-id: "2" --- apiVersion: v1 kind: Service metadata: name: zookeeper3 namespace: cbear spec: clusterIP: None ports: - name: client port: 2181 - name: followers port: 2888 - name: election port: 3888 selector: app: zookeeper server-id: "3" --- kind: Deployment #apiVersion: extensions/v1beta1 apiVersion: apps/v1 metadata: name: zookeeper1 namespace: cbear spec: replicas: 1 selector: matchLabels: app: zookeeper template: metadata: labels: app: zookeeper server-id: "1" spec: volumes: - name: data emptyDir: {} - name: wal emptyDir: medium: Memory containers: - name: server image: harbor.cbear.top/cbear/zookeeper:v2 imagePullPolicy: Always env: - name: MYID value: "1" - name: SERVERS value: "zookeeper1,zookeeper2,zookeeper3" - name: JVMFLAGS value: "-Xmx2G" ports: - containerPort: 2181 - containerPort: 2888 - containerPort: 3888 volumeMounts: - mountPath: "/zookeeper/data" name: zookeeper-datadir-pvc-1 volumes: - name: zookeeper-datadir-pvc-1 persistentVolumeClaim: claimName: zookeeper-datadir-pvc-1 --- kind: Deployment apiVersion: apps/v1 metadata: name: zookeeper2 namespace: cbear spec: replicas: 1 selector: matchLabels: app: zookeeper template: metadata: labels: app: zookeeper server-id: "2" spec: volumes: - name: data emptyDir: {} - name: wal emptyDir: medium: Memory containers: - name: server image: harbor.cbear.top/cbear/zookeeper:v2 imagePullPolicy: Always env: - name: MYID value: "2" - name: SERVERS value: "zookeeper1,zookeeper2,zookeeper3" - name: JVMFLAGS value: "-Xmx2G" ports: - containerPort: 2181 - containerPort: 2888 - containerPort: 3888 volumeMounts: - mountPath: "/zookeeper/data" name: zookeeper-datadir-pvc-2 volumes: - name: zookeeper-datadir-pvc-2 persistentVolumeClaim: claimName: zookeeper-datadir-pvc-2 --- kind: Deployment #apiVersion: extensions/v1beta1 apiVersion: apps/v1 metadata: name: zookeeper3 namespace: cbear spec: replicas: 1 selector: matchLabels: app: zookeeper template: metadata: labels: app: zookeeper server-id: "3" spec: volumes: - name: data emptyDir: {} - name: wal emptyDir: medium: Memory containers: - name: server image: harbor.cbear.top/cbear/zookeeper:v2 imagePullPolicy: Always env: - name: MYID value: "3" - name: SERVERS value: "zookeeper1,zookeeper2,zookeeper3" - name: JVMFLAGS value: "-Xmx2G" ports: - containerPort: 2181 - containerPort: 2888 - containerPort: 3888 volumeMounts: - mountPath: "/zookeeper/data" name: zookeeper-datadir-pvc-3 volumes: - name: zookeeper-datadir-pvc-3 persistentVolumeClaim: claimName: zookeeper-datadir-pvc-3
3. 验证zookeeper集群状态
进入任意一个
pod内部, 查看集群角色和配置文件
参考链接
k8s实战案例之部署Zookeeper集群 - Linux-1874 - 博客园 (cnblogs.com)