引言
在现代数据架构中,Kafka 作为一种高性能的消息队列系统,已被广泛应用于处理实时数据流。在企业级部署中,保证数据传输的安全性以及服务的稳定性变得尤为重要。本文将详细介绍如何在 Docker 环境下部署 Kafka 服务,并使用 Systemctl 进行管理,特别注重在部署过程中安全性的处理,包括密码的加密存储与日志的安全输出的完整流程
当前部署方式
当前环境使用docker docker-compose 部署raft模式的kafka三节点集群,某一个节点的docker-compose.yaml配置文件如下:
version: "3"
services:kafka:image: 'bitnami/kafka:3.7.0'network_mode: "host"ports:- '9092:9092'- '9093:9093'- '9999:9999'privileged: trueenvironment:- 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 ** 管理:
[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 配置中的密码。
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 的密码:
#!/bin/bashENCRYPTION_KEY=$(cat /app/metabank/kafka/secrets/encryption_key)encrypt_password() {local password=$1echo -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}'
EOFecho -e "\nPasswords have been encrypted and saved to kafka_passwords.env"
该脚本读取原始密码,利用预存的密钥进行加密,并输出加密后的密码。
密码解密脚本
#!/bin/bashENCRYPTION_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" ]; thenecho "Passwords decrypted successfully"elseecho "Error: Failed to decrypt one or more passwords"exit 1fi
elseecho "Error: kafka_passwords.env file not found"exit 1
fi
启动脚本与安全日志处理
将 Kafka 的日志输出到特定目录,并确保这些日志文件的访问权限受到严格控制。
#!/bin/bash
# start-kafka.shsource ./decrypt_kafka_passwords.sh
# 检查解密是否成功
if [ $? -ne 0 ]; thenecho "Failed to decrypt passwords"exit 1
fiexec /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 服务的启动和停止命令,并能够让服务在系统启动时自动启动。
[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
其他日志切割与回收
由于我七天内的日志可能会查看,我启用了延迟压缩:
/app/metabank/kafka/kafka_logs/kafka.log {su apppub apppubdailyrotate 30 # 增大rotate值以确保能保留足够的日志dateextdateformat -%Y%m%ddelaycompress # 延迟压缩maxage 7 # 7天后才压缩missingoknotifemptycreate 0640 apppub apppubsharedscripts
}
注意:配置文件中不能添加注释,这里只做演示,配置文件记得自己去除配置!
使用如下命令测试日志切割:
touch -d "yesterday" /app/metabank/kafka/kafka_logs/*.log
logrotate -f /etc/logrotate.d/kafka
另外journalctl中这样日志的量级会比较大,还很烦人:
我需要处理一下:
修改了kafka.service
[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 服务部署。通过加密关键配置和细心设计日志存储,显著提升整个系统的安全性。日常运维中,请注意定期检查和更新安全设置,修改密码,确保系统能防范新的安全威胁。