Systemd构建容器化微服务集群管理系统
实训背景
你是一家云计算公司的 DevOps 工程师,需为某客户设计一套基于 Docker 的微服务集群管理系统,需求如下:
- 容器自启管理:确保三个服务(
webapp
、api
、redis
)在系统启动时自动运行。 - 依赖顺序控制:
redis
必须在api
之前启动,api
必须在webapp
之前启动。 - 健康检查与自愈:若
webapp
崩溃,10秒内自动重启。 - 资源隔离:限制
redis
容器最多使用 1GB 内存和 2 核 CPU。
环境准备
- 操作系统:Ubuntu 22.04 LTS。
- 软件依赖:
sudo apt install docker.io sudo systemctl enable docker # 启用 Docker 服务
- 镜像准备:
docker pull nginx:alpine # 模拟 webapp docker pull node:18 # 模拟 api docker pull redis:7 # 数据库
实训步骤
任务1:定义容器服务单元文件
目标:为每个容器创建独立的 systemd 服务文件。
操作步骤:
-
创建
redis
服务文件:sudo nano /etc/systemd/system/redis-container.service
内容:
[Unit] Description=Redis Container After=docker.service Requires=docker.service [Service] Type=simple Restart=always ExecStartPre=-/usr/bin/docker rm -f redis # 清理旧容器 ExecStart=/usr/bin/docker run --name redis \ --memory="1g" --cpus="2.0" \ # 资源限制 redis:7 ExecStop=/usr/bin/docker stop redis [Install] WantedBy=multi-user.target
-
创建
api
服务文件:sudo nano /etc/systemd/system/api-container.service
内容:
[Unit] Description=API Container After=redis-container.service # 依赖 Redis Requires=redis-container.service [Service] Type=simple Restart=on-failure ExecStartPre=-/usr/bin/docker rm -f api ExecStart=/usr/bin/docker run --name api \ --link redis:redis \ # 连接 Redis node:18 npm start ExecStop=/usr/bin/docker stop api
-
创建
webapp
服务文件:sudo nano /etc/systemd/system/webapp-container.service
内容:
[Unit] Description=WebApp Container After=api-container.service # 依赖 API Requires=api-container.service [Service] Type=notify # 等待健康检查信号 Restart=always RestartSec=10 # 崩溃后等待10秒重启 ExecStartPre=-/usr/bin/docker rm -f webapp ExecStart=/usr/bin/docker run --name webapp \ --link api:api \ # 连接 API -p 80:80 \ nginx:alpine ExecStop=/usr/bin/docker stop webapp [Install] WantedBy=multi-user.target
任务2:配置服务依赖与启动顺序
目标:确保服务按 redis → api → webapp
顺序启动。
操作步骤:
-
验证依赖关系:
systemctl list-dependencies webapp-container.service # 查看依赖链
-
手动测试启动顺序:
sudo systemctl stop docker sudo systemctl start redis-container api-container webapp-container journalctl -f # 观察启动顺序是否符合预期
任务3:实现健康检查与自愈
目标:当 webapp
容器崩溃时自动重启。
操作步骤:
-
修改
webapp
服务文件:
在[Service]
部分添加:Restart=always RestartSec=10 TimeoutStartSec=300 # 等待容器启动的最长时间
-
模拟崩溃测试:
sudo docker kill webapp # 手动杀死容器 systemctl status webapp-container.service # 观察是否重启 journalctl -u webapp-container.service | grep "Starting container"
任务4:应用资源限制
目标:限制 redis
容器资源使用。
操作步骤:
-
修改
redis
服务文件:
在ExecStart
中已包含--memory="1g" --cpus="2.0"
。 -
验证资源限制:
docker stats redis # 查看实时资源占用 stress-ng --vm 2 --vm-bytes 800M # 在容器内运行压力测试
实训总结
通过本次实训,你实现了以下功能:
- 容器生命周期管理:通过 systemd 控制 Docker 容器的启动、停止和重启。
- 服务依赖链:确保微服务按正确顺序初始化。
- 故障自愈:结合
Restart
策略实现服务高可用。 - 资源隔离:防止单个容器耗尽系统资源。
知识要点
-
Docker 与 systemd 集成:
- 使用
ExecStart
直接调用docker run
命令。 - 通过
--memory
和--cpus
限制容器资源。
- 使用
-
服务依赖控制:
After
和Requires
定义启动顺序和强依赖。- 使用
systemctl list-dependencies
可视化依赖链。
-
健康检查机制:
Type=notify
等待容器发送就绪信号。RestartSec
控制重启间隔,避免频繁重启风暴。
-
日志调试技巧:
journalctl -u webapp-container.service --since "5 minutes ago" docker logs webapp # 查看容器内部日志
扩展挑战:
- 为服务添加动态扩缩容逻辑(如 CPU 使用率超过 80% 时自动增加实例)。
- 结合
systemd socket
实现 API 服务的按需启动。 - 使用
EnvironmentFile
将容器配置(如端口号)外置到文件。