安全地使用 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 服务部署。通过加密关键配置和细心设计日志存储,显著提升整个系统的安全性。日常运维中,请注意定期检查和更新安全设置,修改密码,确保系统能防范新的安全威胁。

相关推荐
独行soc41 分钟前
#渗透测试#漏洞挖掘#红蓝攻防#护网#sql注入介绍08-基于时间延迟的SQL注入(Time-Based SQL Injection)
数据库·sql·安全·渗透测试·漏洞挖掘
Clockwiseee2 小时前
php伪协议
windows·安全·web安全·网络安全
黑客Ash2 小时前
安全算法基础(一)
算法·安全
云云3212 小时前
搭建云手机平台的技术要求?
服务器·线性代数·安全·智能手机·矩阵
云云3212 小时前
云手机有哪些用途?云手机选择推荐
服务器·线性代数·安全·智能手机·矩阵
玖疯子2 小时前
介绍 Docker 的基本概念和优势,以及在应用程序开发中的实际应用。
docker
暴富的Tdy2 小时前
【快速上手Docker 简单配置方法】
docker·容器·eureka
cominglately2 小时前
centos单机部署seata
linux·运维·centos
CircleMouse3 小时前
Centos7, 使用yum工具,出现 Could not resolve host: mirrorlist.centos.org
linux·运维·服务器·centos
xcLeigh3 小时前
网络安全 | 防火墙的工作原理及配置指南
安全·web安全