设置服务器初始配置

设置历史记录

为了保留更多命令历史、防止覆盖并显示执行时间,需要修改用户 Shell 配置文件(通常为 ~/.bashrc 或 ~/.bash_profile)。

vim /root/.bashrc

添加一下配置

# 设置 history 条数(例如 10000 条)
export HISTSIZE=10000
export HISTFILESIZE=10000
# 显示命令执行时间
HISTTIMEFORMAT="【%F %T】"  # 年-月-日 时:分:秒
# 防止历史记录被覆盖,每次登录追加到历史文件
shopt -s histappend
# 每次执行命令后立即保存历史记录
export PROMPT_COMMAND="history -a; $PROMPT_COMMAND"
# 自定义历史文件路径(可选,避免覆盖)
export HISTFILE="/root/.bash_history"

设置计算机名

hostnamectl set-hostname [myservername]

设置时区

设置服务器为北京时间

timedatectl set-timezone Asia/Shanghai

启动时间同步(NTP)

sudo yum install chrony
sudo systemctl enable chronyd
sudo systemctl start chronyd

配置NTP服务器

vim  /etc/chrony.conf

添加或修改为中国 NTP 服务器:

server ntp.aliyun.com iburst
server cn.pool.ntp.org iburst

重启chronyd并验证同步

sudo systemctl restart chronyd
chronyc sources

3. 安装常用工具

# Ubuntu/Debian
sudo apt update
sudo apt install -y vim net-tools curl wget htop git tree unzip telnet

# CentOS/RHEL
sudo yum install -y epel-release
sudo yum install -y vim net-tools curl wget htop git tree unzip telnet

4. 配置 Swap

如果服务器内存不足,添加 Swap:

sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

5. 优化网络

增大 TCP 缓冲区(适用于高并发)

sudo vim /etc/sysctl.conf

添加:

net.core.rmem_max=16777216
net.core.wmem_max=16777216
net.ipv4.tcp_rmem=4096 87380 16777216
net.ipv4.tcp_wmem=4096 65536 16777216

应用:

sudo sysctl -p

安装Docker

使用国内源

sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

创建安装脚本

vim install_docker.sh
#!/bin/bash

read -p "安装(y/n):" judge_1

if [ "$judge_1" = "y" ]; then
    # 安装 yum-utils
    sudo yum install -y yum-utils
    if [ $? != 0 ]; then
        echo "安装 yum-utils 失败"
        exit 1
    fi

    # 使用阿里云镜像源并添加重试机制
    for i in {1..3}; do
        sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
        if [ $? == 0 ]; then
            break
        fi
        echo "设置远程仓库失败,尝试第 $i 次重试..."
        sleep 3
    done

    if [ $? != 0 ]; then
        echo "设置远程仓库失败,请检查网络或更换其他镜像源"
        exit 1
    fi

    # 安装 Docker
    sudo yum install -y docker-ce docker-ce-cli containerd.io
    if [ $? != 0 ]; then
        echo "安装 Docker 失败"
        exit 1
    fi

    echo "Docker 安装完成"
    # 启动并启用 Docker 服务
    sudo systemctl start docker
    sudo systemctl enable docker
    echo "Docker 服务已启动并设置为开机自启"
else
    echo "退出"
    exit 0
fi
bash install_docker.sh

安装docker-compose

安装脚本

sudo curl -L "https://github.com/docker/compose/releases/download/v2.20.3/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

如果大陆下载失败,可在香港服务器下载后导入/usr/local/bin/docker-compose

sudo chmod +x /usr/local/bin/docker-compose
# 验证安装
docker-compose --version

安装jumperver

参考官方文档:https://docs.jumpserver.org/zh/v4/installation/setup_linux_standalone/online_install/

cd /opt
wget https://resource.fit2cloud.com/jumpserver/installer/releases/download/v4.10.1/jumpserver-installer-v4.10.1.tar.gz
tar -xf jumpserver-installer-v4.10.1.tar.gz
cd jumpserver-installer-v4.10.1
# 安装
./jmsctl.sh install

# 启动
./jmsctl.sh start

在安装的时候如果提示无法pull镜像
这是因为网络的原因。可以在海外服务器上执行上述操作,下载完镜像后导出镜像,再在国内服务器导入镜像

# 导出镜像(下面几个镜像都需要)
docker save -o jumpserver_koko.tar jumpserver/koko
docker save -o jumpserver_lion.tar jumpserver/lion
docker save -o jumpserver_chen.tar jumpserver/chen
docker save -o jumpserver_core.tar jumpserver/core
docker save -o jumpserver_web.tar jumpserver/web
docker save -o redis.tar redis
docker save -o postgres.tar postgres

# 导入镜像
docker load -i jumpserver_koko.tar
docker load -i jumpserver_lion.tar
docker load -i jumpserver_chen.tar
docker load -i jumpserver_core.tar
docker load -i jumpserver_web.tar
docker load -i redis.tar
docker load -i postgres.tar

然后再执行上面的安装脚本(因为已存在镜像,所以脚本将跳过拉取镜像的步骤)

# 安装
./jmsctl.sh install

# 启动
./jmsctl.sh start

安装完成后 JumpServer 配置文件路径为: /opt/jumpserver/config/config.txt
HTTP_PORT=80改为HTTP_PORT=8080,便于安装宝塔
设置DOMAINS="10.8.0.1:8080",便于登录web页(由于堡垒机不想暴露到公网,若不指定内网地址,内网将无法登录web堡垒机后台页面)
jumpserver-installer-v4.10.1/config-example.txt也设置DOMAINS="10.8.0.1:8080"

设置好后重启堡垒机:

cd /opt/jumpserver-installer-v4.10.1

# 启动
./jmsctl.sh start
# 停止
./jmsctl.sh down
# 卸载
./jmsctl.sh uninstall
# 帮助
./jmsctl.sh -h

访问堡垒机

端口8080
账号账号密码:admin/ChangeMe

地址: http://<JumpServer服务器IP地址>:<服务运行端口>
用户名: admin
密码: ChangeMe

安装spug

spug是运维发布系统。
参考之前写的文章:https://www.moyuwa.com/1893.html
同样在海外服务器导出镜像

# 导出镜像(下面几个镜像都需要)
docker save -o spug-service.tar openspug/spug-service
docker save -o mariadb.tar mariadb

# 导入镜像
docker load -i mariadb.tar
docker load -i spug-service.tar

创建脚本

mkdir /opt/spug && cd /opt/spug
vi docker-compose.yml
version: "3.3"
services:
  db:
    image: mariadb:10.8.2
    container_name: spug-db
    restart: always
    command: --port 3306 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
    volumes:
      - /data/spug/mysql:/var/lib/mysql
    environment:
      - MYSQL_DATABASE=spug
      - MYSQL_USER=spug
      - MYSQL_PASSWORD=spug.cc
      - MYSQL_ROOT_PASSWORD=spug.cc
  spug:
    image: openspug/spug-service
    container_name: spug
    privileged: true # 特权模式
    restart: always
    volumes:
      - /data/spug:/data/spug
      - /data/repos:/data/repos
      - /var/run/docker.sock:/var/run/docker.sock  # 挂载docker套接字,容器内能运行docker命令
      - /usr/bin/docker:/usr/bin/docker # 挂载docker客户端工具,容器内能运行docker命令
      - /data/scripts:/scripts
    ports:
      # 如果80端口被占用可替换为其他端口,例如: - "8000:80"
      - "8088:80"
    environment:
      - DOCKER_HOST=unix:///var/run/docker.sock # 设置环境变量,确保Spug容器知道如何连接到 Docker守护进程
      - MYSQL_DATABASE=spug
      - MYSQL_USER=spug
      - MYSQL_PASSWORD=spug.cc
      - MYSQL_HOST=spug-db
      - MYSQL_PORT=3306
    depends_on:
      - db

启动容器

docker compose up -d

初始化

docker exec spug init_spug ops 123456

这将创建一个用户名为ops密码为123456的管理员账户,可自行替换管理员账户/密码。

安装宝塔

注意,安装宝塔后,会默认启动防火墙。在宝塔的控制面板的安全里管理安全规则

安装openvpn

使用的脚本是:https://github.com/angristan/openvpn-install
但是大陆访问会因为网络问题安装失败。
所以我在没有网络限制的海外Linux服务器上提前下载所需的软件包,并修改脚本以使用这些本地包。
以下为已修改的软件包
点击下载

安装Apollo

参考该文档
注意,apollo、eureka为内部使用,不要将端口暴露到公网,可用openvpn服务器的nginx转发
比如运维服务器为服务器A,基础环境为服务器B
在A上安装了openvpn、堡垒机、宝塔
在B上安装了apollo、eureka
可在A的宝塔上配置反代,将B的8070和8080转发到服务器B
这样,用户在连接openvpn后,就可通过http://10.8.0.1:8070 访问到B的8070了

安装rabbitmq

导入rabbitmq镜像

准备用docker安装rabbitmq,但是由于大陆服务器无法拉取docker镜像
所以在海外服务器上下载rabbitmq镜像

# 在海外服务器拉取镜像
sudo docker pull rabbitmq:3.13-management
# 保存镜像
docker save -o rabbitmq3.13.tar rabbitmq:3.13-management

# 拷贝到国内服务器后,导入到docker
docker load -i rabbitmq3.13.tar

创建持久化目录

默认情况下,RabbitMQ 数据存储在容器内,容器删除后数据会丢失。为持久化数据,添加卷挂载:
假如要创建三台MQ集群
为每台机器创建持久化目录,用于存储 RabbitMQ 数据和日志

sudo mkdir -p /data/rabbitmq/{node1,node2,node3}
sudo chown -R 999:999 /data/rabbitmq
# 999:999 是 RabbitMQ 镜像默认的用户/组 ID,确保容器有写权限。

配置主机名解析

RabbitMQ 集群依赖主机名通信,需确保节点主机名可解析。编辑每台机器的 /etc/hosts 文件:

vim /etc/hosts
# 给mq的节点创建主机名
172.17.32.9 rabbitmq-node1
172.17.32.10 rabbitmq-node2
172.17.32.11 rabbitmq-node3

测试是否正常

ping rabbitmq-node1
ping rabbitmq-node2
ping rabbitmq-node3

部署RabbitMQ节点

将在三台机器上各部署一个 RabbitMQ 节点(rabbitmq-node1、rabbitmq-node2、rabbitmq-node3),使用 rabbitmq:3.13-management 镜像(带管理界面,稳定版本)。每个节点配置相同的用户、密码和 Erlang Cookie。

节点1

运行以下命令启动第一个节点:

sudo docker run -d \
  --name rabbitmq-node1 \
  --hostname rabbitmq-node1 \
  --net host \
  --add-host rabbitmq-node1:172.17.0.15 \
  --add-host rabbitmq-node2:172.17.0.10 \
  --add-host rabbitmq-node3:172.17.16.7 \
  -e RABBITMQ_DEFAULT_USER=admin \
  -e RABBITMQ_DEFAULT_PASS=qyBegs0SeQ5b9H \
  -e RABBITMQ_ERLANG_COOKIE='rabbitmqCookie' \
  -e RABBITMQ_NODENAME=rabbit@rabbitmq-node1 \
  -v /data/rabbitmq/node1:/var/lib/rabbitmq \
  --restart=always \
  rabbitmq:3.13-management

节点2


sudo docker run -d \
  --name rabbitmq-node2 \
  --hostname rabbitmq-node2 \
  --net host \
  --add-host rabbitmq-node1:172.17.0.15 \
  --add-host rabbitmq-node2:172.17.0.10 \
  --add-host rabbitmq-node3:172.17.16.7 \
  -e RABBITMQ_DEFAULT_USER=admin \
  -e RABBITMQ_DEFAULT_PASS=qyBegs0SeQ5b9H \
  -e RABBITMQ_ERLANG_COOKIE='rabbitmqCookie' \
  -e RABBITMQ_NODENAME=rabbit@rabbitmq-node2 \
  -v /data/rabbitmq/node2:/var/lib/rabbitmq \
  --restart=always \
  rabbitmq:3.13-management

节点3

sudo docker run -d \
  --name rabbitmq-node3 \
  --hostname rabbitmq-node3 \
  --net host \
  --add-host rabbitmq-node1:172.17.0.15 \
  --add-host rabbitmq-node2:172.17.0.10 \
  --add-host rabbitmq-node3:172.17.16.7 \
  -e RABBITMQ_DEFAULT_USER=admin \
  -e RABBITMQ_DEFAULT_PASS=qyBegs0SeQ5b9H \
  -e RABBITMQ_ERLANG_COOKIE='rabbitmqCookie' \
  -e RABBITMQ_NODENAME=rabbit@rabbitmq-node3 \
  -v /data/rabbitmq/node3:/var/lib/rabbitmq \
  --restart=always \
  rabbitmq:3.13-management

配置说明:

  • –hostname:设置唯一主机名,用于集群通信。
  • -e RABBITMQ_ERLANG_COOKIE:所有节点必须使用相同的 Cookie(rabbitmqCookie)。
  • -v:持久化数据到 /data/rabbitmq/nodeX。
  • –add-host:确保容器内部能解析所有节点的主机名,避免手动修改 /etc/hosts
  • –restart=always:容器自动重启。

验证端口监听

在每台服务器上运行:

sudo netstat -tuln | grep -E '4369|25672|5672|15672'

确保看到 0.0.0.0:4369、0.0.0.0:25672 等端口在监听。

验证 Erlang Cookie 一致性

由于使用了持久化卷,需确保 .erlang.cookie 文件一致:

检查 Cookie 文件

进入每个容器,查看 Cookie:

docker exec -it rabbitmq-node1 bash
cat /var/lib/rabbitmq/.erlang.cookie

重复检查 rabbitmq-node2 和 rabbitmq-node3,确保内容均为 rabbitmqCookie。

同步 Cookie

如果不一致,复制主节点的 Cookie:

docker cp rabbitmq-node1:/var/lib/rabbitmq/.erlang.cookie ./cookie
docker cp ./cookie rabbitmq-node2:/var/lib/rabbitmq/.erlang.cookie
docker cp ./cookie rabbitmq-node3:/var/lib/rabbitmq/.erlang.cookie

设置权限

docker exec rabbitmq-node2 chmod 400 /var/lib/rabbitmq/.erlang.cookie
docker exec rabbitmq-node3 chmod 400 /var/lib/rabbitmq/.erlang.cookie

如果 Cookie 问题反复出现,清理持久化数据:

docker rm -f rabbitmq-node2 rabbitmq-node3
sudo rm -rf /data/rabbitmq/node2/* /data/rabbitmq/node3/*

然后重启容器

docker restart rabbitmq-node2 rabbitmq-node3

配置集群

将节点 2 和节点 3 加入节点 1 的集群,节点 1 作为主节点(磁盘节点),节点 2 和 3 为内存节点(RAM)以提高性能。

加入节点2

在节点2服务器上:

sudo docker exec -it rabbitmq-node2 bash
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster --ram rabbit@rabbitmq-node1
rabbitmqctl start_app
exit

加入节点3

在节点3服务器上:

sudo docker exec -it rabbitmq-node3 bash
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster --ram rabbit@rabbitmq-node1
rabbitmqctl start_app
exit

命令说明:

  • stop_app:停止 RabbitMQ 应用(不停止容器)。
  • reset:清除节点状态。
  • join_cluster –ram:以内存节点加入集群,rabbit@rabbitmq-node1 是节点 1 的标识。
  • start_app:启动 RabbitMQ 应用。

验证集群状态

在任意节点(建议主节点 rabbitmq-node1)上运行:

docker exec -it rabbitmq-node1 rabbitmqctl cluster_status

应看到类似输出,显示所有节点(rabbit@rabbitmq-node1、rabbit@rabbitmq-node2、rabbit@rabbitmq-node3)在集群中,且 rabbit@rabbitmq-node2 和 rabbit@rabbitmq-node3 为 RAM 节点。

访问管理界面

访问(http://172.17.32.9:15672
使用用户名 admin 和密码 qyBegs0SeQ5b9H,确认所有节点出现在集群中。

检查日志

如果加入集群仍失败,查看日志:

容器日志

docker logs rabbitmq-node1
docker logs rabbitmq-node2

RabbitMQ日志

docker exec -it rabbitmq-node2 bash
cat /var/log/rabbitmq/rabbit@rabbitmq-node2.log

其他注意事项

时间同步

确保所有服务器时间同步:

sudo ntpdate pool.ntp.org

验证 Erlang 节点

确认 Erlang 节点名称

docker exec -it rabbitmq-node1 rabbitmqctl eval 'net_adm:names().'

应返回类似 {ok, [{"rabbitmq-node1", 4369}]}。

清理并重新部署

如果问题持续,删除容器和数据,重新部署

docker rm -f rabbitmq-node1 rabbitmq-node2 rabbitmq-node3
sudo rm -rf /data/rabbitmq/*

搭建 ZooKeeper

ZooKeeper 是一个分布式协调服务,广泛用于分布式系统,比如 Kafka、Hadoop 等
搭建方式:通过docker方式安装。(docker安装方式略)

准备 ZooKeeper 配置文件

ZooKeeper 集群需要一个配置文件来定义集群的节点。我们会在每台服务器上创建一个 zoo.cfg 文件,内容基本相同,但需要指定每台服务器的角色。

  1. 创建目录
    在每台服务器上创建目录存放配置文件:

    mkdir -p /data/zookeeper/data
    mkdir -p /data/zookeeper/datalog
    chmod -R 777 /data/zookeeper
    chown -R 1000:1000 /data/zookeeper
  2. 在每台服务器上创建 /data/zookeeper/data/myid 文件,用于标识 ZooKeeper 节点的 ID:
    服务器 1(192.168.1.101):echo "1" > /data/zookeeper/data/myid
    服务器 2(192.168.1.102):echo "2" > /data/zookeeper/data/myid
    服务器 3(192.168.1.103):echo "3" > /data/zookeeper/data/myid
  3. 在每台服务器上创建 /data/zookeeper/zoo.cfg 文件,内容如下:
    tickTime=2000
    initLimit=10
    syncLimit=5
    dataDir=/zookeeper/data
    dataLogDir=/zookeeper/datalog
    clientPort=2181
    admin.serverPort=8081
    server.1=192.168.1.101:2888:3888
    server.2=192.168.1.102:2888:3888
    server.3=192.168.1.103:2888:3888

    解释

    • tickTime:ZooKeeper 的基本时间单位(毫秒)。
    • initLimit 和 syncLimit:控制节点间通信的超时时间。
    • dataDir 和 dataLogDir:数据和日志存储目录(Docker 容器内路径)。
    • clientPort:客户端连接 ZooKeeper 的端口。
    • server.X:定义集群中的节点,格式是 server.<ID>=<IP>:<数据同步端口>:<选举端口>

运行 ZooKeeper 容器

我们使用官方的 zookeeper Docker 镜像来启动服务。在每台服务器上运行以下命令,注意替换 myid 的值:

# 在海外服务器并打包保存下载
docker pull zookeeper:latest
 docker save -o zookeeper.tar zookeeper:latest
 sz zookeeper.tar
# 在大陆服务器
docker load -i zookeeper.tar

服务器1(ID=1):

docker run -d --name zookeeper \
--network host \
-v /data/zookeeper/data:/zookeeper/data \
-v /data/zookeeper/datalog:/zookeeper/datalog \
-v /data/zookeeper/zoo.cfg:/conf/zoo.cfg \
-e ZOO_MY_ID=1 \
zookeeper:latest

服务器2(ID=2):

docker run -d --name zookeeper \
--network host \
-v /data/zookeeper/data:/zookeeper/data \
-v /data/zookeeper/datalog:/zookeeper/datalog \
-v /data/zookeeper/zoo.cfg:/conf/zoo.cfg \
-e ZOO_MY_ID=2 \
zookeeper:latest

服务器3(ID=3):

docker run -d --name zookeeper \
--network host \
-v /data/zookeeper/data:/zookeeper/data \
-v /data/zookeeper/datalog:/zookeeper/datalog \
-v /data/zookeeper/zoo.cfg:/conf/zoo.cfg \
-e ZOO_MY_ID=3 \
zookeeper:latest

解释:

  • -d:后台运行容器。
  • –network host:使用主机网络模式,避免端口映射问题。
  • -v:挂载本地目录到容器,持久化数据和配置文件。
  • -e ZOO_MY_ID:设置 ZooKeeper 节点的 ID,与 myid 文件对应。

验证集群状态

检查容器是否正常运行:

docker ps

连接到任意一台服务器的 ZooKeeper 实例,检查集群状态:

docker exec -it zookeeper zkServer.sh status

输出会显示当前节点的角色(leader 或 follower)和集群状态。如果看到类似 Mode: leader 或 Mode: follower,说明集群正常运行!

也可以用 ZooKeeper 客户端测试连接:

docker run -it --rm zookeeper zkCli.sh -server 192.168.1.101:2181

进入 ZooKeeper 命令行后,输入 ls / 检查是否能正常访问。

搭建 kafka

什么是 Kafka?

Apache Kafka 是一个分布式流处理平台,简单来说,它是一个“消息中间件”,可以处理海量实时数据。想象 Kafka 像一个超级快递站:

  • 生产者(Producer):把包裹(消息)送到快递站。
  • 主题(Topic):包裹被分类放到不同的货架(比如“订单”、“日志”)。
  • 消费者(Consumer):从货架取走包裹进行处理。

Kafka 的典型用途包括:

  • 收集和传输日志(如服务器日志、用户点击数据)。
  • 构建实时数据管道(比如从数据库到分析系统)。
  • 实现事件驱动的微服务架构。

搭建 kafka 集群

0. 搭建集群前置条件

  • 三台 CentOS 服务器:IP 分别为 172.17.0.15 \ 172.17.0.10 \ 172.17.16.7,已安装 Docker。
  • ZooKeeper 集群已运行(也是在这3台服务器通过docker运行),端口 2181、2888 和 3888 已开放。
  • 网络连通性:三台服务器之间网络可达,防火墙已配置好。
  • 磁盘空间:Kafka 需要存储消息数据,建议每台服务器预留至少 10GB 磁盘空间。

1. 准备 Kafka 数据目录

Kafka 需要存储消息数据和日志,我们为每台服务器创建一个持久化目录。
在每台服务器上执行:

mkdir -p /data/kafka
chown 1001:1001 /data/kafka   # 1001是bitnami镜像默认用户

2. 运行 Kafka 容器

载入镜像

我们使用官方的 bitnami/kafka 镜像来启动 Kafka 集群。

# 在海外服务器下载镜像并打包传到大陆服务器
docker pull bitnami/kafka:3.8
docker save -o kafka.tar bitnami/kafka:3.8
scp kafka.tar x.x.x.x:/usr/local/src/
# 把镜像传到大陆服务器并载入
docker load -i kafka.tar

运行容器

在每台服务器上运行以下命令,每台服务器都需要指定唯一的 broker.id,并配置 zookeeper 集群地址

服务器 1(172.17.0.15):

docker run -d --name kafka --network host \
  -v /data/kafka:/bitnami/kafka \
  -e KAFKA_BROKER_ID=1 \
  -e KAFKA_CFG_ZOOKEEPER_CONNECT="172.17.0.15:2181,172.17.0.10:2181,172.17.16.7:2181" \
  -e KAFKA_CFG_LISTENERS="PLAINTEXT://172.17.0.15:9092" \
  -e KAFKA_CFG_ADVERTISED_LISTENERS="PLAINTEXT://172.17.0.15:9092" \
  bitnami/kafka:3.8

服务器 2(172.17.0.10):

docker run -d --name kafka --network host \
  -v /data/kafka:/bitnami/kafka \
  -e KAFKA_BROKER_ID=2 \
  -e KAFKA_CFG_ZOOKEEPER_CONNECT="172.17.0.15:2181,172.17.0.10:2181,172.17.16.7:2181" \
  -e KAFKA_CFG_LISTENERS="PLAINTEXT://172.17.0.10:9092" \
  -e KAFKA_CFG_ADVERTISED_LISTENERS="PLAINTEXT://172.17.0.10:9092" \
  bitnami/kafka:3.8

服务器 3(172.17.16.7):

  docker run -d --name kafka --network host \
  -v /data/kafka:/bitnami/kafka \
  -e KAFKA_BROKER_ID=3 \
  -e KAFKA_CFG_ZOOKEEPER_CONNECT="172.17.0.15:2181,172.17.0.10:2181,172.17.16.7:2181" \
  -e KAFKA_CFG_LISTENERS="PLAINTEXT://172.17.16.7:9092" \
  -e KAFKA_CFG_ADVERTISED_LISTENERS="PLAINTEXT://172.17.16.7:9092" \
  bitnami/kafka:3.8

解释:

  • -d:后台运行容器。
  • -v:挂载数据目录和配置文件到容器,持久化数据。
  • 如果你的 Zookeeper 服务监听的不是 2181,请相应修改端口。
  • KAFKA_CFG_ADVERTISED_LISTENERS 必须是本机在网络中的可访问地址(建议用实际 IP)。
  • 如果服务器防火墙开启,请开放 9092、2181 端口。
  • 生产环境建议配置 KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP、KAFKA_CFG_INTER_BROKER_LISTENER_NAME 等参数以增强安全性。

集群验证

1. 查看 Kafka Broker

在任意一台机器上进入容器:

docker exec -it kafka bash

使用 kafka-topics.sh 工具查看 broker 列表:

kafka-topics.sh --bootstrap-server 172.17.0.15:9092 --list

或通过 zookeeper 查询 broker:

kafka-broker-api-versions.sh --bootstrap-server 172.17.0.15:9092

2. 创建测试 Topic

创建一个名为 test-topic 的 Kafka 主题,有 3 个分区和 3 个副本。

kafka-topics.sh --create --topic test-topic \
  --bootstrap-server 172.17.0.15:9092 \
  --partitions 3 --replication-factor 3

含义说明

  • kafka-topics.sh
    Kafka 提供的主题管理工具脚本,可以用来创建、列出、删除、修改主题(topic)。
  • –create
    创建新的 topic。
  • –topic test-topic
    新建的 topic 名字叫 test-topic。
  • –bootstrap-server 172.17.0.15:9092
    指定 Kafka 集群的 broker 地址(IP:端口),用来连接集群。此地址必须是advertised.listeners 设置的那个 IP 和端口。
  • –partitions 3
    这个 topic 分为 3 个分区。分区越多,写入和消费的并发能力越强。
  • –replication-factor 3
    这个 topic 的数据有 3 份副本,也就是在集群的 3 个 broker 上各保存一份,增强容错能力。

3. 生产与消费消息

生产消息:

启动一个命令行界面,输入的每一行内容都会作为一条消息发送到 test-topic。

kafka-console-producer.sh --broker-list 172.17.0.15:9092 --topic test-topic

含义说明

  • kafka-console-producer.sh
    Kafka 提供的命令行生产者客户端,用来向指定 topic 发送消息。
  • –broker-list 172.17.0.15:9092
    指定 Kafka broker 的地址(IP:端口)。
  • –topic test-topic
    指定要发送消息的 topic 名称。

消费消息:

启动一个消费者,从 test-topic 读取消息,并在命令行实时显示出来。

kafka-console-consumer.sh --bootstrap-server 172.17.0.15:9092 --topic test-topic --from-beginning

含义说明

  • kafka-console-consumer.sh
    Kafka 提供的命令行消费者客户端,用来从指定 topic 消费消息。
  • –bootstrap-server 172.17.0.15:9092
    指定 Kafka broker 的地址(IP:端口)。
  • –topic test-topic
    指定要消费的 topic 名称。
  • –from-beginning
    表示从 topic 的第一条消息开始消费(否则只会消费启动后新产生的消息)。

常用命令

查看 topic 列表:

kafka-topics.sh --bootstrap-server 172.17.0.15:9092 --list

查看指定 topic 详情:

kafka-topics.sh --describe --topic test-topic --bootstrap-server 172.17.0.15:9092

ElasticSearch

0. 架构说明

  • Filebeat:轻量级日志收集器,部署在每台需要收集日志的服务器上。Filebeat 读取日志文件(如应用日志、系统日志),并将日志发送到 Kafka 或直接发送到 Elasticsearch。
  • Kafka:作为消息队列,接收 Filebeat 发送的日志数据,起到缓冲和解耦的作用。在上面的步骤中, Kafka 集群已经部署在三台服务器上,可以直接复用。
  • Elasticsearch:分布式搜索和分析引擎,存储和索引日志数据,支持全文搜索和分析。Elasticsearch 集群将部署在三台服务器上,形成高可用分布式架构。
  • Kibana:Elasticsearch 的可视化界面,用于展示和查询日志数据。Kibana 通常部署在一台服务器上,连接到 Elasticsearch 集群。
  • ZooKeeper:Kafka 依赖的协调服务,上面已经部署好,可以继续使用。

数据流向:

  • Filebeat 收集日志 → 发送到 Kafka(可选)或直接到 Elasticsearch。
  • 如果使用 Kafka,日志从 Kafka 消费到 Elasticsearch(需要 Logstash 或 Kafka Connect)。
  • Kibana 连接 Elasticsearch,展示日志数据。
    # 架构图
    `[应用服务器] -> Filebeat -> Kafka -> Logstash/Kafka Connect -> Elasticsearch -> Kibana`
    # 或者不通过kafka
    `[应用服务器] -> Filebeat -> Elasticsearch -> Kibana`

建议:

  • 由于服务器资源有限(三台),建议 Filebeat 直接发送日志到 Elasticsearch,简化架构,减少资源占用。
  • 如果需要 Kafka 的缓冲功能,可以使用 Logstash 或 Kafka Connect 将日志从 Kafka 传输到 Elasticsearch。
  • Elasticsearch 和 Kibana 部署在 Docker 容器中,与 Kafka 和 ZooKeeper 保持一致,便于管理。

所需组件

  • Elasticsearch:日志存储和搜索。
  • Kibana:日志可视化。
  • Filebeat:日志收集。
  • Logstash 或 Kafka Connect(可选):如果通过 Kafka 传输日志,需要此组件。
  • Docker 和 Docker Compose:用于部署和管理容器。

1. 安装步骤

规划集群

节点分配:

  • 172.17.0.15:Elasticsearch 节点 1(主节点候选)、Kibana。
  • 172.17.0.10:Elasticsearch 节点 2(主节点候选)。
  • 172.17.16.7:Elasticsearch 节点 3(主节点候选)。

端口:

  • Elasticsearch:9200(HTTP API)、9300(节点间通信)。
  • Kibana:5601(Web 界面)。
  • 存储:为 Elasticsearch 创建持久化存储卷,避免数据丢失。

配置服务器环境

在每台服务器上执行以下操作:

  1. 创建数据目录和设置权限:
    sudo mkdir -p /data/elasticsearch/data
    sudo chmod -R 777 /data/elasticsearch/data
  2. 调整系统参数
    (Elasticsearch 对系统要求较高): 编辑 /etc/sysctl.conf,添加:

    vm.max_map_count=262144

    应用设置

    sudo sysctl -w vm.max_map_count=262144
  3. 开放防火墙端口(如果启用防火墙):
    sudo firewall-cmd --permanent --add-port=9200/tcp
    sudo firewall-cmd --permanent --add-port=9300/tcp
    sudo firewall-cmd --permanent --add-port=5601/tcp  # 仅在 Kibana 节点
    sudo firewall-cmd --reload

部署 Elasticsearch 集群

在每台服务器上创建 Docker Compose 文件,配置 Elasticsearch 集群。

  1. 在 172.17.0.15 创建 docker-compose.yml:

    vim /data/elasticsearch/docker-compose.yml
    version: '3.8'
    services:
    elasticsearch1:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.15.0
    container_name: elasticsearch1
    environment:
      - node.name=es1
      - cluster.name=es-cluster
      - discovery.seed_hosts=172.17.0.15,172.17.0.10,172.17.16.7
      - cluster.initial_master_nodes=es1,es2,es3
      - bootstrap.memory_lock=true
      - xpack.security.enabled=false
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - /data/elasticsearch/data:/usr/share/elasticsearch/data
    network_mode: host
    kibana:
    image: docker.elastic.co/kibana/kibana:8.15.0
    container_name: kibana
    environment:
      - ELASTICSEARCH_HOSTS=["http://172.17.0.15:9200","http://172.17.0.10:9200","http://172.17.16.7:9200"]
    depends_on:
      - elasticsearch1
    network_mode: host
  2. 在 172.17.0.10 创建 docker-compose.yml:

vim /data/elasticsearch/docker-compose.yml
version: '3.8'
services:
  elasticsearch2:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.15.0
    container_name: elasticsearch2
    environment:
      - node.name=es2
      - cluster.name=es-cluster
      - discovery.seed_hosts=172.17.0.15,172.17.0.10,172.17.16.7
      - cluster.initial_master_nodes=es1,es2,es3
      - bootstrap.memory_lock=true
      - xpack.security.enabled=false
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - /data/elasticsearch/data:/usr/share/elasticsearch/data
    network_mode: host
  1. 在 172.17.16.7 创建 docker-compose.yml:
vim /data/elasticsearch/docker-compose.yml
version: '3.8'
services:
  elasticsearch3:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.15.0
    container_name: elasticsearch3
    environment:
      - node.name=es3
      - cluster.name=es-cluster
      - discovery.seed_hosts=172.17.0.15,172.17.0.10,172.17.16.7
      - cluster.initial_master_nodes=es1,es2,es3
      - bootstrap.memory_lock=true
      - xpack.security.enabled=false
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - /data/elasticsearch/data:/usr/share/elasticsearch/data
    network_mode: host
  1. 启动 Elasticsearch 集群:
    在每台服务器上依次执行:

    docker-compose up -d
  2. 验证 Elasticsearch 集群状态:
    访问任意节点的 HTTP API:

    curl http://172.17.0.15:9200/_cluster/health

    确保返回的 status 为 green 或 yellow,且 number_of_nodes 为 3。

  3. 验证kibana
    访问 http://172.17.0.15:5601 的 Kibana Web 界面,确保能正常加载。

部署 Filebeat

在每台需要收集日志的服务器上部署 Filebeat。以下以 172.17.0.15 为例,其他服务器类似。

1. 创建 Filebeat 配置文件:

在 172.17.0.15 上创建 mkdir /data/filebeat && vim /data/filebeat/filebeat.yml:

filebeat.inputs:
  - type: log
    enabled: true
    paths:
      - /data/a/logs/*.log  # 第一个日志目录
    index: "aa-%{[agent.version]}-%{+yyyy.MM.dd}"  # 自定义索引名称为 aa-<version>-<date>
  - type: log
    enabled: true
    paths:
      - /data/b/logs/*.log  # 第二个日志目录
    index: "bb-%{[agent.version]}-%{+yyyy.MM.dd}"  # 自定义索引名称为 bb-<version>-<date>
output.elasticsearch:
  hosts: ["172.17.0.15:9200", "172.17.0.10:9200", "172.17.16.7:9200"]
  ilm.enabled: false  # 禁用 ILM 以使用自定义索引名称
setup.kibana:
  host: "172.17.0.15:5601"
setup.template.enabled: true
setup.template.name: "custom"
setup.template.pattern: "{aa-*,bb-*}"

配置说明

  • 两个输入配置:
    • 第一个 filebeat.inputs 收集 /data/a/logs/*.log 的日志,并指定索引名称为 aa-%{[agent.version]}-%{+yyyy.MM.dd}(例如 aa-8.15.0-2025.06.19)。
    • 第二个 filebeat.inputs 收集 /data/b/logs/*.log 的日志,并指定索引名称为 bb-%{[agent.version]}-%{+yyyy.MM.dd}(例如 bb-8.15.0-2025.06.19)。
    • index 字段允许为每个输入指定独立的索引名称。
  • 禁用 ILM:
    • output.elasticsearch.ilm.enabled: false 禁用了 Filebeat 的默认索引生命周期管理(ILM),因为 ILM 会强制使用 filebeat-* 样式的索引名称。禁用 ILM 后,Filebeat 会直接使用 index 字段指定的名称。
  • 自定义索引模板:
    • setup.template.enabled: true 启用自定义索引模板。
    • setup.template.name: "custom" 和 setup.template.pattern: "{aa-,bb-}" 定义了一个名为 custom 的索引模板,匹配 aa- 和 bb- 索引。这确保 Elasticsearch 正确应用模板到你的自定义索引。

2. 创建 Filebeat 的 Docker Compose 文件:

创建 /data/filebeat/docker-compose.yml:

version: '3.8'
services:
  filebeat:
    image: docker.elastic.co/beats/filebeat:8.15.0
    container_name: filebeat
    volumes:
      - /data/filebeat/filebeat.yml:/usr/share/filebeat/filebeat.yml:ro
      - /var/log:/var/log:ro
    network_mode: host

创建网络(如果未自动创建):

docker network create es-net

3. 启动Filebeat

cd /data/filebeat
docker-compose up -d

在 172.17.0.10 和 172.17.16.7 上配置和启动 Filebeat,修改 filebeat.yml 中的日志路径为对应服务器的日志文件路径。

4. 初始化索引模板

初始化索引模板和仪表板: 在每台服务器上运行以下命令,确保 Filebeat 设置正确的索引模板:

docker exec filebeat filebeat setup --template
docker exec filebeat filebeat setup --dashboards

5. 配置kibana

打开 Kibana(http://172.17.0.15:5601)。
进入 Management -> Stack Management -> Index Patterns,创建索引模式(如 filebeat-*)。
进入 Discover,查看 Filebeat 收集的日志数据。
创建仪表板(Dashboard)或可视化(Visualize)以展示日志分析结果。

6. 验证和测试

  1. 检查 Elasticsearch:

    curl http://172.17.0.15:9200/_cat/indices?v

    预期看到类似 aa-8.15.0-2025.06.19bb-8.15.0-2025.06.19 的索引。
    登录 Kibana(http://172.17.0.15:5601) 在“Discover”页面选择 aa- 和 bb- 索引模式,确认日志数据正确显示。

  2. 检查 Kibana: 在 Kibana 的 Discover 页面,查看是否有日志数据。

  3. 检查 Filebeat: 查看 Filebeat 容器日志:

    docker logs filebeat

    注意事项

    • 资源分配:
      Elasticsearch 和 Kafka 都消耗较多内存和 CPU。确保每台服务器有足够资源(建议至少 4GB 内存)。
      调整 ES_JAVA_OPTS(如 -Xms2g -Xmx2g)根据实际内存大小。
    • 安全性:
      本示例禁用 Elasticsearch 的 X-Pack 安全功能(xpack.security.enabled=false)。生产环境中建议启用认证和 TLS。
      配置防火墙,限制对 9200、9300、5601 端口的访问。
    • 日志路径:
      确保 Filebeat 挂载的日志路径正确,且容器有读权限。
    • 版本兼容性:
      确保 Elasticsearch、Kibana、Filebeat、Logstash 版本一致(本例使用 8.15.0)。

导入redis数据

ucloud可以在控制台备份redis数据(RDB备份)
下载备份文件后,上传到腾讯云主机
下载导入工具

wget https://redis-doc-2020-1254408587.cos.ap-guangzhou.myqcloud.com/redis-port.tgz
tar -zxvf redis-port.tgz
cd redis-port
./redis-restore dump.rdb -t 172.17.0.10:6379

XXL-JOB安装

在香港服务器传输xuxueli/xxl-job-admin:3.1.1镜像并导入到服务器
在服务器编辑docker-compose.yml文件

version: '3'
services:
  xxl-job-admin:
    image: xuxueli/xxl-job-admin:3.1.1
    container_name: xxl_job_admin
    restart: always
    ports:
      - "8311:8080"
    environment:
      PARAMS: "--spring.datasource.url=jdbc:mysql://172.17.32.16:3306/xxl_job?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai --spring.datasource.username=jyb --spring.datasource.password=YHNBGT"
    volumes:
      - "./applogs:/data/applogs"
    networks:
      - xxl_job_net

networks:
  xxl_job_net:
    driver: bridge

运行容器

docker-compose up -d
版权所有,转载注明来源