clickhouse运维篇(三):生产环境一键生成配置并快速部署ck集群

请添加图片描述

前提条件:先了解集群搭建流程是什么样,需要改哪些配置,有哪些环境,这个文章目的是简化部署。

clickhouse运维篇(一):docker-compose 快速部署clickhouse集群
clickhouse运维篇(二):多机器手动部署ck集群

!https://i-blog.csdnimg.cn/direct/7677be0676904a7687c2f4cc8aef0a46.png

项目目录解析:

 $ tree .
.
├── cluster.conf   #集群配置,  集群包含哪些机器、端口分别为多少
├── config  
│   ├── config_node1.xml  # 生成的ck节点配置文件
│   ├── config_node2.xml
│   ├── config_template.xml  # config模版
│   ├── users_node1.xml     # 生成的ck节点用户配置文件
│   ├── users_node2.xml
│   └── users_template.xml   # users模版
├── dep   #下面包含需要的远程依赖, zookeeper、clickhouse、jdk,根据自己的需求更改
├── gen_cluster_config.sh  
├── gen_login_cmd.sh
├── install.conf  # 远程登录的主机conf,需要在跳板机或者中间机器上去ssh、scp使用
└── main.sh   #启动入口

1、main.sh

CUR_FOLDER=$(cd "/Users/admin/scripts/my_app/ckcluster";pwd). ${CUR_FOLDER}/cluster.conf
. ${CUR_FOLDER}/gen_cluster_config.sh
. ${CUR_FOLDER}/gen_login_cmd.shCONFIG_FOLDER="${CUR_FOLDER}/config"
DEP_FOLDER="${CUR_FOLDER}/dep"
TEMPLATE_FILE="${CONFIG_FOLDER}/config_template.xml"if [ ! -d "$CONFIG_FOLDER" ]; thenmkdir -p "$CONFIG_FOLDER"
fiif [ ! -d "$DEP_FOLDER" ]; thenmkdir -p "$DEP_FOLDER"
fizk_index=1
# 首先读取所有节点信息并根据 shard 进行分组
while true; dohost_var="zk_node_${zk_index}_host"# 检查所有变量是否为空,若有一个为空则跳出循环if [ -z "${!host_var}" ]; thenbreakfi# 远程安装jdk、zookeeperinstall_path=$(get_install_path ${!host_var})echo $(get_scp_command ${!host_var} . "${DEP_FOLDER}/jdk-8u202-nonroot.tar.gz ${DEP_FOLDER}/apache-zookeeper-3.7.2-bin.tar.gz")`get_scp_command ${!host_var} . "${DEP_FOLDER}/jdk-8u202-nonroot.tar.gz ${DEP_FOLDER}/apache-zookeeper-3.7.2-bin.tar.gz"`echo $(get_ssh_command ${!host_var} "cd ${install_path};tar -xzvf ${install_path}/jdk-8u202-nonroot.tar.gz")echo $(get_ssh_command ${!host_var} "cd ${install_path};tar -xzvf ${install_path}/apache-zookeeper-3.7.2-bin.tar.gz")`get_ssh_command ${!host_var} "cd ${install_path};tar -xzvf ${install_path}/jdk-8u202-nonroot.tar.gz"``get_ssh_command ${!host_var} "cd ${install_path};tar -xzvf ${install_path}/apache-zookeeper-3.7.2-bin.tar.gz"`zk_index=$((zk_index + 1))
done# 生成ck集群配置文件
gen_config# 远程安装clickhouse
ck_index=1
# 首先读取所有节点信息并根据 shard 进行分组
while true; dohost_var="ck_node_${ck_index}_host"# 检查所有变量是否为空,若有一个为空则跳出循环if [ -z "${!host_var}" ]; thenbreakfi
#     <users_config>/opt/appaduudit/my_app-2.4/clickhouse-23.4.2.9/ck_node_1/config/users_node.xml</users_config>    install_path=$(get_install_path ${!host_var})    `get_scp_command ${!host_var} . "${DEP_FOLDER}/clickhouse-23.4.2.9.tar.gz"`echo $(get_ssh_command ${!host_var} "cd ${install_path};tar -xzvf ${install_path}/clickhouse-23.4.2.9.tar.gz")NODE_CK_PATH="${BASE_CK_PATH}/ck_node_${ck_index}"echo $(get_scp_command ${!host_var} ${NODE_CK_PATH}/config  "${CONFIG_FOLDER}/user_node${ck_index}.xml")`get_scp_command ${!host_var} ${NODE_CK_PATH}/config "${CONFIG_FOLDER}/config_node${ck_index}.xml"``get_scp_command ${!host_var} ${NODE_CK_PATH}/config  "${CONFIG_FOLDER}/users_node${ck_index}.xml"`echo $(get_ssh_command ${!host_var} "${install_path}/clickhouse-23.4.2.9.tar.gz/bin/clickhouse server --config-file  ${install_path}/config_node${ck_index}.xml")`get_ssh_command ${!host_var} "${install_path}/clickhouse-23.4.2.9.tar.gz/bin/clickhouse server --config-file  ${install_path}/config_node${ck_index}.xml"`    ck_index=$((ck_index + 1))
done

2、cluster.conf

# 定义变量
target_install_path="/opt/app/ck_cluster"
BASE_CK_PATH="/opt/app/my_app-2.4/clickhouse-23.4.2.9"
CK_CLUSTER_NAME="my_ck_cluster_test"#port为zk的clientPort
zk_node_1_host=172.168.1.206
zk_node_1_port=8551zk_node_2_host=172.168.1.207
zk_node_2_port=8551zk_node_3_host=172.168.1.208
zk_node_3_port=8551ck_node_1_host=172.168.1.206
ck_node_1_tcp_port=8601
ck_node_1_http_port=8602
ck_node_1_interserver_http_port=8603
ck_node_1_user=default
ck_node_1_password=password
ck_node_1_shard=01
ck_node_1_replica=replica_63ck_node_2_host=172.168.1.207
ck_node_2_tcp_port=8611
ck_node_2_http_port=8612
ck_node_2_interserver_http_port=8613
ck_node_2_user=default
ck_node_2_password=password
ck_node_2_shard=02
ck_node_2_replica=replica_63#ck_node_3_host=ck_host_3
#ck_node_3_tcp_port=ck_tcp_port_3
#ck_node_3_http_port=ck_http_port_3
#ck_node_3_interserver_http_port=ck_interserver_http_port_3
#ck_node_3_user=user3
#ck_node_3_password=password3
#ck_node_3_shard=02
#ck_node_3_replica=replica_209

3、install.conf

ssh.172.168.1.206=root:app:/opt/app/ck_cluste
ssh.172.168.1.207=admin:adminpass:/opt/app/ck_cluste
ssh.172.168.1.208=admin:adminpass:/opt/app/ck_cluste

4、gen_login_cmd.sh

#!/bin/bash
cd /Users/admin/scripts/my_app/ckcluster
# 读取配置文件并解析
CONFIG_FILE="install.conf"
declare -A HOSTSwhile IFS='=' read -r key user_password || [[ -n "$key" ]]; dokey=$(echo "$key" | xargs)user_password=$(echo "$user_password" | xargs)if [[ $key == ssh.* ]]; thenhost=${key#ssh.}HOSTS["$host"]="$user_password"fi
done < "$CONFIG_FILE"# 获取 SSH 命令
get_ssh_command() {local host=$1local cmd=$2local user_password=${HOSTS["$host"]}IFS=':' read -r user password install_path<<< "$user_password"# echo "sshpass -p '$password' ssh $user@$host $cmd"echo "sshpass -p '$password' ssh $user@$host \"$cmd\""}# 获取 SCP 命令
get_scp_command() {local host=$1local extra_dir=$2local files=$3    local user_password=${HOSTS[$host]}# root:idss:/opt/idss/ck_clusteIFS=':' read -r user password install_path<<< "$user_password"if [ "$extra_dir" != "." ]; theninstall_path=$extra_dirfimkdir_cmd=$(get_ssh_command $host "mkdir -p $install_path")eval "$mkdir_cmd"echo "sshpass -p '$password' scp -r $files $user@$host:$install_path"
}get_install_path() {local host=$1local user_password=${HOSTS[$host]}# root:idss:/opt/idss/ck_clusteIFS=':' read -r user password install_path<<< "$user_password"echo $install_path
}
# ssh_command=$(get_scp_command "10.87.102.206" "/Users/admin/scripts/my_app/ckcluster/dep/jdk-8u202-nonroot.tar.gz /Users/admin/scripts/my_app/ckcluster/dep/apache-zookeeper-3.7.2-bin.tar.gz")
# echo $ssh_command
# scp_command=$(get_ssh_command "10.87.102.206" "ls /opt/idss/ck_cluste")
# echo $scp_command
# `$scp_command`

5、gen_cluster_config.sh

#!/bin/bash
# 定义基础路径和模板文件名function gen_config() {# 生成 zookeeper 配置
ZOOKEEPER_CONFIG="<zookeeper>\n"
# 循环遍历 zk_node_*_host 和 zk_node_*_port 变量
zk_index=1
while true; dohost_var="zk_node_${zk_index}_host"port_var="zk_node_${zk_index}_port"# 检查变量是否已定义,如果未定义则跳出循环if [ -z "${!host_var}" ] || [ -z "${!port_var}" ]; thenbreakfiZOOKEEPER_CONFIG+="    <node index=\"${zk_index}\">\n"ZOOKEEPER_CONFIG+="        <host>${!host_var}</host>\n"ZOOKEEPER_CONFIG+="        <port>${!port_var}</port>\n"ZOOKEEPER_CONFIG+="    </node>\n"zk_index=$((zk_index + 1))
done
ZOOKEEPER_CONFIG+="</zookeeper>"# 生成 remote_servers 配置
declare -A shard_nodes config_contentck_index=1
# 首先读取所有节点信息并根据 shard 进行分组
while true; dohost_var="ck_node_${ck_index}_host"tcp_port_var="ck_node_${ck_index}_tcp_port"http_port_var="ck_node_${ck_index}_http_port"interserver_port_var="ck_node_${ck_index}_interserver_http_port"user_var="ck_node_${ck_index}_user"password_var="ck_node_${ck_index}_password"shard_var="ck_node_${ck_index}_shard"replica_var="ck_node_${ck_index}_replica"# 检查所有变量是否为空,若有一个为空则跳出循环if [ -z "${!host_var}" ] || \[ -z "${!tcp_port_var}" ] || \[ -z "${!http_port_var}" ] || \[ -z "${!interserver_port_var}" ] || \[ -z "${!user_var}" ] || \[ -z "${!password_var}" ] || \[ -z "${!shard_var}" ] || \[ -z "${!replica_var}" ]; thenbreakfi# 将当前节点信息存入以 shard 为 key 的数组shard_nodes["${!shard_var}"]+=$(cat <<-NODE<replica><host>${!host_var}</host><port>${!tcp_port_var}</port><user>${!user_var}</user><password>${!password_var}</password></replica>\n
NODE)NODE_CK_PATH="${BASE_CK_PATH}/ck_node_${ck_index}"config_template=$(cat ${CONFIG_FOLDER}/config_template.xml)config_template=$(echo "$config_template" | sed "s|\${BASE_CK_PATH}|${NODE_CK_PATH}|g")config_template=$(echo "$config_template" | sed "s|\${HTTP_PORT}|${!http_port_var}|g")config_template=$(echo "$config_template" | sed "s|\${TCP_PORT}|${!tcp_port_var}|g")config_template=$(echo "$config_template" | sed "s|\${INTERSERVER_HTTP_PORT}|${!interserver_port_var}|g")config_template=$(echo "$config_template" | sed "s|\${MACROS_SHARD}|${!shard_var}|g")config_template=$(echo "$config_template" | sed "s|\${MACROS_REPLICA}|${!replica_var}|g")config_template=$(echo "$config_template" | sed "s|\${CK_PASSWORD}|${!password_var}|g")    config_template=$(echo "$config_template" | sed "s|\${ck_index}|${!ck_index}|g")        # 将生成的配置内容存入字典config_content["config_node${ck_index}"]="$config_template"# users文件生成users_template=$(cat ${CONFIG_FOLDER}/users_template.xml)users_template=$(echo "$users_template" | sed "s|\${CK_PASSWORD}|${!password_var}|g")    echo -e "$users_template" > "${CONFIG_FOLDER}/users_node${ck_index}.xml"ck_index=$((ck_index + 1))
done# 构建最终的 XML 配置
REMOTE_SERVERS_CONFIG="<remote_servers>\n"
REMOTE_SERVERS_CONFIG+="    <${CK_CLUSTER_NAME}>\n"
for shard in "${!shard_nodes[@]}"; doREMOTE_SERVERS_CONFIG+="        <shard>\n"REMOTE_SERVERS_CONFIG+="            <internal_replication>true</internal_replication>  \n"REMOTE_SERVERS_CONFIG+="${shard_nodes[$shard]}"REMOTE_SERVERS_CONFIG+="        </shard>\n"
done
REMOTE_SERVERS_CONFIG+="    </${CK_CLUSTER_NAME}>\n"
REMOTE_SERVERS_CONFIG+="</remote_servers>"# 动态修改配置文件(插入 Zookeeper\CK集群 配置)
for node_config in "${!config_content[@]}"; doecho "处理 $node_config ..."# 创建临时文件temp_file="${node_config}_tmp.xml"echo -e "${config_content[$node_config]}" > "$temp_file"sed -i '' '/<\/yandex>/d' "$temp_file"# linux下为# sed -i '/<\/yandex>/d' "$temp_file"    # 拼接 Zookeeper 和 Remote Servers 配置combined_insert="${ZOOKEEPER_CONFIG}
${REMOTE_SERVERS_CONFIG}"echo -e "$combined_insert" >> "$temp_file"echo "</yandex>" >> "$temp_file"mv "$temp_file" "$CONFIG_FOLDER/${node_config}.xml"echo "生成 $node_config 完成: ${node_config}.xml"
done}

6、config_template.xml

<?xml version="1.0"?>
<yandex><logger><level>notice</level><log>${BASE_CK_PATH}/log/clickhouse-server.log</log><errorlog>${BASE_CK_PATH}/log/clickhouse-server.err.log</errorlog><size>1000M</size><count>10</count></logger><path>${BASE_CK_PATH}/data/</path><tmp_path>${BASE_CK_PATH}/tmp/</tmp_path><user_files_path>${BASE_CK_PATH}/data/user_files/</user_files_path><users_config>${BASE_CK_PATH}/config/users_node${ck_index}.xml</users_config>    <users><default><password>${CK_PASSWORD}</password> <!-- 空密码 --><networks><ip>::/0</ip> <!-- 允许所有IP访问 --></networks><profile>default</profile><quota>default</quota><access_management>1</access_management></default></users>    <default_profile>default</default_profile><default_database>default</default_database><http><port>${HTTP_PORT}</port><max_connections>1024</max_connections><async_insert>1</async_insert></http><listen_host>0.0.0.0</listen_host><listen_host>::</listen_host><http_port>${HTTP_PORT}</http_port><tcp_port>${TCP_PORT}</tcp_port><interserver_http_port>${INTERSERVER_HTTP_PORT}</interserver_http_port><distributed_ddl><!-- Path in ZooKeeper to queue with DDL queries --><path>/clickhouse/task_queue/ddl</path></distributed_ddl><macros><shard>${MACROS_SHARD}</shard><replica>${MACROS_REPLICA}</replica></macros>
</yandex>

7、users_template.xml

<?xml version="1.0"?>
<yandex><!-- Profiles of settings. --><profiles><!-- Default settings. --><default><!-- Maximum memory usage for processing single query, in bytes. --><max_memory_usage>10000000000</max_memory_usage><load_balancing>random</load_balancing></default><!-- Profile that allows only read queries. --><readonly><readonly>1</readonly></readonly></profiles><users><default><password>${CK_PASSWORD}</password> <networks><ip>::/0</ip> <!-- 允许所有IP访问 --></networks><profile>default</profile><quota>default</quota><access_management>1</access_management></default></users>    <!-- Quotas. --><quotas><!-- Name of quota. --><default><!-- Limits for time interval. You could specify many intervals with different limits. --><interval><!-- Length of interval. --><duration>3600</duration><distributed_product_mode>allow</distributed_product_mode><!-- No limits. Just calculate resource usage for time interval. --><queries>0</queries><errors>0</errors><result_rows>0</result_rows><read_rows>0</read_rows><execution_time>0</execution_time></interval></default></quotas>
</yandex>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/884098.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

快速入门kotlin编程(精简但全面版)

注&#xff1a;本文章为个人学习记录&#xff0c;如有错误&#xff0c;欢迎留言指正。 目录 1. 变量 1.1 变量声明 1.2 数据类型 2. 函数 3. 判断语句 3.1 if 3.2 when语句 4. 循环语句 4.1 while 4.2 for-in 5. 类和对象 5.1 类的创建和对象的初始化 5.2 继承 5…

云原生Istio基础

一&#xff0e;Service Mesh 架构 Service Mesh&#xff08;服务网格&#xff09;是一种用于处理服务到服务通信的专用基础设施层。它的主要目的是将微服务之间复杂的通信和治理逻辑从微服务代码中分离出来&#xff0c;放到一个独立的层中进行管理。传统的微服务架构中&#x…

【网页布局技术】项目五 使用CSS设置导航栏

《CSSDIV网页样式与布局案例教程》 徐琴 目录 任务一 制作简单纵向导航栏支撑知识点1&#xff0e;合理利用display:block属性2&#xff0e;利用margin-bottom设置间隔效果3&#xff0e;利用border设置特殊边框 任务二 制作简单横向导航栏任务三 制作带图片效果的横向导航栏任务…

银河麒麟v10 xrdp安装

为了解决科技被卡脖子的问题&#xff0c;国家正在大力推进软硬件系统的信创替代&#xff0c;对于一些平时对Linux操作系统不太熟练的用户来讲提出了更高的挑战和要求。本文以银河麒麟v10 24.03为例带领大家配置kylin v10的远程桌面。 最近公司为了配置信创开发新购了几台银河麒…

什么是x86架构,什么是arm架构

什么是 x86 架构&#xff1f; x86 架构是一种经典的指令集架构&#xff08;ISA&#xff09;&#xff0c;最早由英特尔在 1978 年推出&#xff0c;主要用于 PC、服务器等领域。 它是一种复杂指令集计算&#xff08;CISC&#xff09;架构&#xff0c;支持大量的复杂指令和操作&…

客户的奇葩要求—在CAN网络的基础上加入了CAN_FD的节点

1&#xff1a;客户的奇葩要求 最近的工作中&#xff0c;遇到了一个有点奇葩的事&#xff0c;客户需要开发一个系统&#xff0c;我们负责其中的一个ECU&#xff0c;这个系统采取的是经典11bit ID的CAN网络。 今天突然提了一个要求&#xff0c;说要在网络中&#xff0c;加入支持…

4G 模组的 FTP 应用:技术科普

众所周知FTP协议包括两个组成部分&#xff0c;其一为FTP服务器&#xff0c;其二为FTP客户端&#xff0c;今天我将为大家带来一场4G 模组的 FTP 应用技术科普&#xff1a; 以低功耗模组Air780E核心板为例。 1、FTP 概述 FTP&#xff08;File Transfer Protocol&#xff0c;文件…

PAT甲级-1074 Reversing Linked List

题目 题目大意 给一个链表的头结点和总节点个数&#xff0c;以及k。每k个节点的链表都要翻转。 思路 链表可以用一个结构体数组来存储&#xff0c;先遍历一遍&#xff0c;过滤掉不在链表中的节点。然后将过滤好的节点放入res数组中&#xff0c;每k个元素用一次reverse()&…

44-RK3588s调试 camera-engine-rkaiq(rkaiq_3A_server)

在RK3588s平台上调试imx415 camera sensor 过程中&#xff0c;已经识别到了camera sensor ID&#xff0c;并且可以拿到raw图和isp处理后的图像&#xff0c;但是isp处理后的图像偏绿&#xff0c;来看查看后台服务发现rkaiq_3A_server没有运行&#xff0c;然后单独运行rkaiq_3A_s…

Python 变量在函数中的作用域

什么是局部变量&#xff1f; 作用范围在函数内部&#xff0c;在函数外部无法使用 什么是全局变量&#xff1f; 在函数内部和外部均可使用 如何将函数内定义的变量声明为全局变量&#xff1f; 使用global关键字&#xff0c; global变量 练习&#xff1a; 演示局部变量 #…

百数功能更新——表单提交支持跳转到外部链接并支持传参

百数的表单外链功能允许用户将表单以链接的形式分享给外部用户&#xff0c;外部用户无需登录或加入团队即可访问并填写表单。 本次更新的表单提交后跳转指定链接的功能&#xff0c;在支持跳转内部链接的基础上&#xff0c;支持用户在完成表单填写并提交后&#xff0c;自动跳转…

BSV区块链为供应链管理带来效率革命

​​发表时间&#xff1a;2024年10月10日 供应链管理是众多行业的重中之重&#xff0c;它确保了商品能够从制造商处顺畅地传递到消费者手中。然而&#xff0c;传统的供应链管理面临着许多挑战&#xff0c;包括缺乏透明度、延误、欺诈和协调上的低效率等等。 BSV区块链技术的出…

Linux基础(七):Linux文件与目录管理

Linux文件与目录管理 1.目录与路径1.1 cd1.2 pwd1.3 mkdir1.4 rmdir1.5 ls1.6 cp1.7 rm1.8 mv 2.可执行文件路径的变量&#xff1a;$PATH3.从字符串中获取目录名称和文件名称4.文件内容读取4.1 cat与tac4.2 nl4.3 more和less4.4 head与tail4.5 od 5 使用touch来改变文件的时间6…

C语言初阶:十一.代码调试技巧

❤欢迎各位大佬访问&#xff1a;折枝寄北-CSDN博客折枝寄北擅长C语言初阶,等方面的知识,折枝寄北关注python,c,java,qt,c语言领域.https://blog.csdn.net/2303_80170533?typeblog❤文章所属专栏https://blog.csdn.net/2303_80170533/category_12794764.html?spm1001.2014.300…

什么是aps排产管理软件?aps排产管理软件有什么用?最详细解释!

近几年&#xff0c;APS排产管理软件特别火&#xff0c;很多制造业企业都在谈论和使用它。不过&#xff0c;因为信息太多太杂&#xff0c;我们平时接收到的往往都是零零碎碎的介绍&#xff0c;很难全面了解它。所以&#xff0c;今天这篇文章就来给大家做个整合&#xff0c;把APS…

微信小程序25__实现卡片变换

先看效果图 实现代码如下&#xff1a; <view class"page" style"filter:hue-rotate({{rotation}}deg)"><view class"prev" catchtap"toPrev">《《《</view><view class"next" catchtap"toNext&q…

vue项目中如何在路由变化时增加一个进度条

在 Vue.js 项目中&#xff0c;使用路由&#xff08;如 Vue Router&#xff09;时&#xff0c;为了提升用户体验&#xff0c;你可能会想要在路由变化时显示一个进度条。这可以通过多种方式实现&#xff0c;其中一种流行的做法是使用第三方库&#xff0c;如 vue-loading-bar 或 n…

4款专业音频在线剪辑工具帮你开启创意之路。

音频在线剪辑工具能够为我们提供很大的便利&#xff0c;对于不管是专业的音乐制作人还是音频创作爱好者来说&#xff0c;都能借助一些音频编辑工具来充分发挥自己的创意。所以这一次&#xff0c;我要给大家介绍几个专业方便的音频剪辑工具。 1、福昕音频在线 直达链接&#x…

JK触发器(Quartus与Modelsim联合仿真)

JK触发器由于其灵活的逻辑功能&#xff0c;被广泛应用于数字电路设计中&#xff0c;如计数器、寄存器、序列信号发生器等。它可以通过改变J和K的输入来实现不同的逻辑操作&#xff0c;使得设计更加简洁高效。 在数字电子技术中&#xff0c;JK触发器的真值表是理解其工作原理和设…

Redis高频面试题

一、Redis有什么好处? 高性能:Redis是一个基于内存的数据存储系统,相比于传统的基于磁盘的数据库系统,它能够提供更高的读写性能。支持丰富的数据类型:Redis支持多种数据结构,包括字符串、哈希、列表、集合、有序集合等,这使得它可以用于多种不同的应用场景。持久化:Re…