安全地使用 Docker 和 Systemctl 部署 Kafka 的综合指南

引言

在现代数据架构中,Kafka 作为一种高性能的消息队列系统,已被广泛应用于处理实时数据流。在企业级部署中,保证数据传输的安全性以及服务的稳定性变得尤为重要。本文将详细介绍如何在 Docker 环境下部署 Kafka 服务,并使用 Systemctl 进行管理,特别注重在部署过程中安全性的处理,包括密码的加密存储与日志的安全输出的完整流程

当前部署方式

当前环境使用docker docker-compose 部署raft模式的kafka三节点集群,某一个节点的docker-compose.yaml配置文件如下:

bash 复制代码
version: "3"
services:
  kafka:
    image: 'bitnami/kafka:3.7.0'
    network_mode: "host"
    ports:
      - '9092:9092'
      - '9093:9093'
      - '9999:9999'
    privileged: true
    environment:
      - KAFKA_CFG_NODE_ID=0
      - TZ=Asia/Shanghai
      - KAFKA_CFG_PROCESS_ROLES=controller,broker
      - KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=0@192.168.0.10:9093,1@192.168.0.13:9093,2@192.168.0.11:9093
      - KAFKA_KRAFT_CLUSTER_ID=metabank
      - KAFKA_CFG_LISTENERS=PLAINTEXT://0.0.0.0:9092,CONTROLLER://0.0.0.0:9093
      - KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://192.168.0.10:9092
      - KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=PLAINTEXT:SASL_PLAINTEXT,CONTROLLER:SASL_PLAINTEXT
      - KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER
      - KAFKA_CFG_INTER_BROKER_LISTENER_NAME=PLAINTEXT
      - KAFKA_CLIENT_USERS=vuser
      - KAFKA_CLIENT_PASSWORDS=vuserpwd123
      - KAFKA_CFG_SASL_MECHANISM_CONTROLLER_PROTOCOL=PLAIN
      - KAFKA_CONTROLLER_USER=vuser
      - KAFKA_CONTROLLER_PASSWORD=vuserpwd123
      - KAFKA_CFG_SASL_MECHANISM_INTER_BROKER_PROTOCOL=PLAIN
      - KAFKA_INTER_BROKER_USER=vuser
      - KAFKA_INTER_BROKER_PASSWORD=vuserpwd123
      - KAFKA_CFG_SSL_ENDPOINT_IDENTIFICATION_ALGORITHM=
      - KAFKA_CFG_SASL_ENABLED_MECHANISMS=PLAIN,SCRAM-SHA-512
      - KAFKA_TLS_TYPE=JKS
      - KAFKA_JMX_ENABLED=true 
      - KAFKA_JMX_OPTS=-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9999 -Dcom.sun.management.jmxremote.rmi.port=9999 -Dcom.sun.management.jmxremote.local.only=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false
volumes:
      - ./kafka_data:/bitnami/kafka

系统服务使用**systemctl ** 管理:

bash 复制代码
[Unit]
Description=kafka Service
Requires=docker.service
After=docker.service
[Service]
Type=oneshot
RemainAfterExit=yes
User=apppub
Group=apppub
WorkingDirectory=/app/metabank/kafka
ExecStart=/usr/bin/docker-compose up -d
ExecStop=/usr/bin/docker-compose down
TimeoutStartSec=0
[Install]
WantedBy=multi-user.target

服务的启停管理使用systemctl ** start|stop|status **参数管理kafka服务

安全需求

最新需求密码不得以明文形式 在任何配置文件或命令行中出现。

Kafka 的运行日志需要被安全地记录并存储。

解决方案设计

密码的加密存储和使用

考虑到安全性,我们将使用 OpenSSL 工具为 Kafka 的密码生成密钥,并进行 AES-256 加密,确保即使在配置文件被泄露的情况下,敏感信息也不会直接暴露。

生成和管理加密密钥

您应该生成一个强加密密钥,并将其存储在安全的位置。这个密钥将用于加密和解密 Kafka 配置中的密码。

bash 复制代码
mkdir /app/metabank/kafka/secrets/
openssl rand -hex 16 > /app/metabank/kafka/secrets/encryption_key
chmod 400 /app/metabank/kafka/secrets/encryption_key
chown apppub:apppub /app/metabank/kafka/secrets/encryption_key

密码加密脚本

创建一个脚本 encrypt_kafka_password.sh 来加密 Kafka 的密码:

bash 复制代码
#!/bin/bash

ENCRYPTION_KEY=$(cat /app/metabank/kafka/secrets/encryption_key)

encrypt_password() {
    local password=$1
    echo -n "$password" | openssl enc -aes-256-cbc -base64 -pbkdf2 -salt -k "$ENCRYPTION_KEY" 2>/dev/null
}

echo "Enter Kafka client password:"
read -s password
ENCRYPTED_CLIENT_PASSWORD=$(encrypt_password "$password")
echo -e "\nEnter Kafka controller password:"
read -s password
ENCRYPTED_CONTROLLER_PASSWORD=$(encrypt_password "$password")
echo -e "\nEnter Kafka broker password:"
read -s password
ENCRYPTED_BROKER_PASSWORD=$(encrypt_password "$password")

# 将加密后的密码写入环境变量文件
cat > /app/metabank/kafka/secrets/kafka_passwords.env << EOF
ENCRYPTED_CLIENT_PASSWORD='${ENCRYPTED_CLIENT_PASSWORD}'
ENCRYPTED_CONTROLLER_PASSWORD='${ENCRYPTED_CONTROLLER_PASSWORD}'
ENCRYPTED_BROKER_PASSWORD='${ENCRYPTED_BROKER_PASSWORD}'
EOF

echo -e "\nPasswords have been encrypted and saved to kafka_passwords.env"

该脚本读取原始密码,利用预存的密钥进行加密,并输出加密后的密码。

密码解密脚本

bash 复制代码
#!/bin/bash

ENCRYPTION_KEY=$(cat /app/metabank/kafka/secrets/encryption_key)

decrypt_password() {
    local encrypted_password=$1
    # 移除可能的引号
    encrypted_password="${encrypted_password//\'/}"
    echo "$encrypted_password" | openssl enc -aes-256-cbc -base64 -pbkdf2 -salt -d -k "$ENCRYPTION_KEY" 2>/dev/null
}

# 从环境变量文件读取加密密码
if [ -f "/app/metabank/kafka/secrets/kafka_passwords.env" ]; then
    # 使用 source 命令加载环境变量
    source /app/metabank/kafka/secrets/kafka_passwords.env
    
    # 解密并导出密码
    export KAFKA_CLIENT_PASSWORDS=$(decrypt_password "$ENCRYPTED_CLIENT_PASSWORD")
    export KAFKA_CONTROLLER_PASSWORD=$(decrypt_password "$ENCRYPTED_CONTROLLER_PASSWORD")
    export KAFKA_INTER_BROKER_PASSWORD=$(decrypt_password "$ENCRYPTED_BROKER_PASSWORD")
    
    # 验证解密是否成功(可选)
    if [ -n "$KAFKA_CLIENT_PASSWORDS" ] && [ -n "$KAFKA_CONTROLLER_PASSWORD" ] && [ -n "$KAFKA_INTER_BROKER_PASSWORD" ]; then
        echo "Passwords decrypted successfully"
    else
        echo "Error: Failed to decrypt one or more passwords"
        exit 1
    fi
else
    echo "Error: kafka_passwords.env file not found"
    exit 1
fi

启动脚本与安全日志处理

将 Kafka 的日志输出到特定目录,并确保这些日志文件的访问权限受到严格控制。

bash 复制代码
#!/bin/bash
# start-kafka.sh

source ./decrypt_kafka_passwords.sh
# 检查解密是否成功
if [ $? -ne 0 ]; then
    echo "Failed to decrypt passwords"
    exit 1
fi

exec /usr/bin/docker-compose up & 
sleep 5 
/usr/bin/docker-compose logs -f kafka >> /app/metabank/kafka/kafka_logs/kafka.log 2>&1

使用 Systemctl 管理 Kafka 服务

创建一个名为 kafka.service 的 Systemctl 单元文件,提供了 Kafka 服务的启动和停止命令,并能够让服务在系统启动时自动启动。

bash 复制代码
[Unit]
Description=kafka Service
Requires=docker.service
After=docker.service

[Service]
Type=simple
User=apppub
Group=apppub
WorkingDirectory=/app/metabank/kafka
ExecStart=/bin/bash /app/metabank/kafka/start-kafka-service.sh
ExecStop=/bin/bash -c '/usr/bin/docker-compose down'
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target

其他日志切割与回收

由于我七天内的日志可能会查看,我启用了延迟压缩:

bash 复制代码
/app/metabank/kafka/kafka_logs/kafka.log {
    su apppub apppub
    daily
    rotate 30            # 增大rotate值以确保能保留足够的日志
    dateext
    dateformat -%Y%m%d
    delaycompress        # 延迟压缩
    maxage 7            # 7天后才压缩
    missingok
    notifempty
    create 0640 apppub apppub
    sharedscripts
}

注意:配置文件中不能添加注释,这里只做演示,配置文件记得自己去除配置!

使用如下命令测试日志切割:

bash 复制代码
touch -d "yesterday" /app/metabank/kafka/kafka_logs/*.log
logrotate -f /etc/logrotate.d/kafka

另外journalctl中这样日志的量级会比较大,还很烦人:

我需要处理一下:

修改了kafka.service

bash 复制代码
[Unit]
Description=kafka Service
Requires=docker.service
After=docker.service

[Service]
Type=simple
User=apppub
Group=apppub
WorkingDirectory=/app/metabank/kafka
ExecStart=/bin/bash /app/metabank/kafka/start-kafka-service.sh
ExecStop=/bin/bash -c '/usr/bin/docker-compose down'
Restart=always
RestartSec=10
StandardOutput=null
StandardError=null

[Install]
WantedBy=multi-user.target

嗯查看了一下journalctl 总算没有那么多烦人的日志了

实施步骤

安装必要的软件:确保系统已安装 Docker、Docker Compose 和 OpenSSL。

配置 Kafka 的 Docker Compose:根据需求配置 Kafka,并注意在环境变量中使用加密密码。

创建并部署加密脚本:将 encrypt_kafka_password.sh 部署到服务器上,保证其执行权限并对密码进行加密。

配置 Systemctl 服务:部署 kafka.service 文件至 /etc/systemd/system/ 目录。

启动服务:使用 systemctl start kafka.service 启动服务。

验证:确保 Kafka 运行正常,加密脚本工作良好,且日志按预期记录。

其他可以完善的

总结

通过本教程,您可以实现一个安全、可靠的 Kafka 服务部署。通过加密关键配置和细心设计日志存储,显著提升整个系统的安全性。日常运维中,请注意定期检查和更新安全设置,修改密码,确保系统能防范新的安全威胁。

相关推荐
chenbin52033 分钟前
Jenkins 自动构建Job
运维·jenkins
java 凯35 分钟前
Jenkins插件管理切换国内源地址
运维·jenkins
xidianjiapei00136 分钟前
Kubernetes的Ingress 资源是什么?
云原生·容器·kubernetes
AI服务老曹38 分钟前
运用先进的智能算法和优化模型,进行科学合理调度的智慧园区开源了
运维·人工智能·安全·开源·音视频
网络安全King2 小时前
华为 网络安全 认证
安全·web安全
sszdzq2 小时前
Docker
运维·docker·容器
book01212 小时前
MySql数据库运维学习笔记
运维·数据库·mysql
dmy2 小时前
docker 快速构建开发环境
后端·docker·容器
网络安全-老纪3 小时前
网络安全-js安全知识点与XSS常用payloads
javascript·安全·web安全
API_technology3 小时前
电商API安全防护:JWT令牌与XSS防御实战
前端·安全·xss