Rundeck

  1. 1. Rundeck 概述
  2. 2. 安装 Rundeck
    1. 2.1. 使用 Docker 安装(推荐)
    2. 2.2. Docker Compose
    3. 2.3. Linux 手动安装
  3. 3. 核心概念
    1. 3.1. 项目(Project)
    2. 3.2. 节点(Nodes)
    3. 3.3. 作业(Jobs)
  4. 4. 创建作业示例
    1. 4.1. 1. 简单命令作业
    2. 4.2. 2. 脚本作业
    3. 4.3. 3. 多步骤作业
  5. 5. 作业选项(Job Options)
  6. 6. 节点过滤器
  7. 7. 访问控制(ACL)
  8. 8. 通知配置
    1. 8.1. Email 通知
    2. 8.2. Webhook 通知
  9. 9. API 使用
    1. 9.1. 基本认证
    2. 9.2. 使用 rd CLI
  10. 10. 插件扩展
    1. 10.1. 常用插件
    2. 10.2. Ansible 集成示例
  11. 11. 总结核心知识要点
    1. 11.1. Rundeck 架构
    2. 11.2. 核心功能示例
      1. 11.2.1. 1. 简单定时任务
      2. 11.2.2. 2. 带参数的作业
      3. 11.2.3. 3. 错误处理
    3. 11.3. 作业调度对比
    4. 11.4. 最佳实践
    5. 11.5. 常用场景
    6. 11.6. 核心命令
    7. 11.7. 核心概念
  12. 12. 对比 Airflow
    1. 12.1. 何时选择 Rundeck
    2. 12.2. 何时选择 Airflow
  13. 13. References

Rundeck is an open source automation service with a web console, command line tools and a WebAPI. It lets you easily run automation tasks across a set of nodes.

Rundeck 概述

Rundeck 是一个开源的运维自动化平台,提供任务调度、执行和监控功能。核心特性包括:

  • Web UI: 友好的图形界面,易于操作
  • 作业调度: 支持 Cron 表达式定时调度
  • 节点管理: 管理和组织目标服务器
  • 访问控制: 基于角色的权限管理(ACL)
  • API 集成: RESTful API 支持自动化集成
  • 插件扩展: 丰富的插件生态系统

注意: Rundeck 适合中小规模的任务调度,但对于复杂的依赖关系管理不如 Apache Airflow 方便。对于有复杂 DAG 依赖的场景,建议使用 Airflow。

安装 Rundeck

使用 Docker 安装(推荐)

1
2
3
4
5
6
7
8
9
10
11
# 快速启动
docker run -d \
--name rundeck \
-p 4440:4440 \
-v /path/to/data:/home/rundeck/server/data \
rundeck/rundeck:latest

# 访问
# http://localhost:4440
# 默认用户名: admin
# 默认密码: admin

Docker Compose

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
version: '3'
services:
rundeck:
image: rundeck/rundeck:latest
container_name: rundeck
ports:
- "4440:4440"
environment:
RUNDECK_GRAILS_URL: http://localhost:4440
RUNDECK_DATABASE_DRIVER: org.postgresql.Driver
RUNDECK_DATABASE_URL: jdbc:postgresql://postgres/rundeck
RUNDECK_DATABASE_USERNAME: rundeck
RUNDECK_DATABASE_PASSWORD: rundeck
volumes:
- rundeck-data:/home/rundeck/server/data
depends_on:
- postgres

postgres:
image: postgres:13
container_name: rundeck-postgres
environment:
POSTGRES_DB: rundeck
POSTGRES_USER: rundeck
POSTGRES_PASSWORD: rundeck
volumes:
- postgres-data:/var/lib/postgresql/data

volumes:
rundeck-data:
postgres-data:

Linux 手动安装

1
2
3
4
5
6
7
8
9
# Debian/Ubuntu
wget https://packagecloud.io/pagerduty/rundeck/packages/any/any/rundeck_4.17.0-1_all.deb
sudo dpkg -i rundeck_4.17.0-1_all.deb

# 启动服务
sudo service rundeckd start

# 检查状态
sudo service rundeckd status

核心概念

项目(Project)

项目是 Rundeck 中的顶层组织单元,用于隔离不同的环境或应用。

1
2
3
4
5
# 创建项目(通过 Web UI)
1. 点击 "New Project"
2. 输入项目名称和描述
3. 配置节点源(Nodes)
4. 保存项目

节点(Nodes)

节点是 Rundeck 可以执行任务的目标服务器。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# resources.yaml - 节点定义文件
web-01:
nodename: web-01
hostname: 192.168.1.10
username: deploy
osFamily: unix
tags: web,production

web-02:
nodename: web-02
hostname: 192.168.1.11
username: deploy
osFamily: unix
tags: web,production

db-01:
nodename: db-01
hostname: 192.168.1.20
username: deploy
osFamily: unix
tags: database,production

作业(Jobs)

作业是 Rundeck 中定义的自动化任务。

创建作业示例

1. 简单命令作业

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# deploy-app.yaml
- description: Deploy Application
executionEnabled: true
loglevel: INFO
name: Deploy Application
nodeFilterEditable: false
scheduleEnabled: true
sequence:
commands:
- exec: cd /opt/app && git pull
- exec: docker-compose up -d --build
keepgoing: false
strategy: node-first
uuid: 12345678-1234-1234-1234-123456789012

2. 脚本作业

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
- description: Backup Database
name: Backup Database
sequence:
commands:
- script: |
#!/bin/bash
BACKUP_DIR="/backups"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="${BACKUP_DIR}/db_backup_${TIMESTAMP}.sql"

# 创建备份
mysqldump -u root -p${DB_PASSWORD} mydb > ${BACKUP_FILE}

# 压缩备份
gzip ${BACKUP_FILE}

# 清理旧备份(保留7天)
find ${BACKUP_DIR} -name "*.sql.gz" -mtime +7 -delete

echo "Backup completed: ${BACKUP_FILE}.gz"
keepgoing: false
strategy: node-first
schedule:
crontab: '0 2 * * *' # 每天凌晨2点执行

3. 多步骤作业

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
- description: Complete Deployment Pipeline
name: Full Deployment
sequence:
commands:
# 步骤1: 备份当前版本
- description: Backup current version
exec: cp -r /opt/app /opt/app.backup.$(date +%Y%m%d)

# 步骤2: 拉取代码
- description: Pull latest code
exec: cd /opt/app && git pull origin main

# 步骤3: 构建应用
- description: Build application
exec: cd /opt/app && docker build -t myapp:latest .

# 步骤4: 停止旧容器
- description: Stop old container
exec: docker stop myapp || true

# 步骤5: 启动新容器
- description: Start new container
exec: |
docker run -d \
--name myapp \
-p 8080:8080 \
--restart unless-stopped \
myapp:latest

# 步骤6: 健康检查
- description: Health check
script: |
#!/bin/bash
for i in {1..30}; do
if curl -f http://localhost:8080/health; then
echo "Application is healthy"
exit 0
fi
echo "Waiting for application... ($i/30)"
sleep 2
done
echo "Health check failed"
exit 1

keepgoing: false
strategy: node-first
notification:
onfailure:
email:
recipients: ops@example.com
onsuccess:
email:
recipients: ops@example.com

作业选项(Job Options)

作业可以接受参数输入:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
- name: Deploy Specific Version
description: Deploy application with version selection
options:
VERSION:
description: Application version to deploy
required: true
value: latest
ENVIRONMENT:
description: Target environment
required: true
values: dev,staging,production
enforced: true
sequence:
commands:
- exec: echo "Deploying version ${option.VERSION} to ${option.ENVIRONMENT}"
- exec: docker pull myapp:${option.VERSION}
- exec: |
docker run -d \
--name myapp-${option.ENVIRONMENT} \
-e ENV=${option.ENVIRONMENT} \
myapp:${option.VERSION}

节点过滤器

通过节点过滤器选择目标服务器:

1
2
3
4
5
6
7
8
9
10
- name: Update Web Servers
nodefilters:
dispatch:
threadcount: 3
keepgoing: true
rankOrder: ascending
filter: tags: web+production # 选择带有 web 和 production 标签的节点
sequence:
commands:
- exec: apt update && apt upgrade -y

访问控制(ACL)

创建 ACL 策略文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# /etc/rundeck/admin.aclpolicy
description: Admin ACL Policy
context:
project: '.*'
for:
resource:
- allow: [read, create, update, delete, run, kill]
adhoc:
- allow: [read, run, kill]
job:
- allow: [read, create, update, delete, run, kill]
node:
- allow: [read, create, update, delete, run]
by:
group: admin

---
# /etc/rundeck/developer.aclpolicy
description: Developer ACL Policy
context:
project: 'dev-.*'
for:
resource:
- allow: [read]
job:
- allow: [read, run]
node:
- allow: [read]
by:
group: developer

通知配置

Email 通知

1
2
3
4
5
6
7
8
9
10
11
- name: Backup with Notification
notification:
onfailure:
email:
recipients: ops@example.com
subject: '[FAILED] Backup Job'
attachLog: true
onsuccess:
email:
recipients: ops@example.com
subject: '[SUCCESS] Backup Job'

Webhook 通知

1
2
3
4
5
6
7
8
9
10
11
12
- name: Deploy with Webhook
notification:
onsuccess:
webhook:
urls: https://hooks.slack.com/services/YOUR/WEBHOOK/URL
format: json
content: |
{
"text": "Deployment completed successfully",
"username": "Rundeck",
"icon_emoji": ":rocket:"
}

API 使用

基本认证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 获取 API Token
# Web UI -> User Profile -> API Tokens -> + Add

# 使用 API Token
export RD_TOKEN="your-api-token"
export RD_URL="http://localhost:4440"

# 列出所有项目
curl -H "X-Rundeck-Auth-Token: ${RD_TOKEN}" \
${RD_URL}/api/40/projects

# 列出项目中的所有作业
curl -H "X-Rundeck-Auth-Token: ${RD_TOKEN}" \
${RD_URL}/api/40/project/MyProject/jobs

# 执行作业
curl -X POST \
-H "X-Rundeck-Auth-Token: ${RD_TOKEN}" \
${RD_URL}/api/40/job/JOB-ID/run

# 查看执行状态
curl -H "X-Rundeck-Auth-Token: ${RD_TOKEN}" \
${RD_URL}/api/40/execution/EXECUTION-ID

使用 rd CLI

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 安装 rd CLI
npm install -g @rundeck/cli

# 配置
rd config create \
--name local \
--url http://localhost:4440 \
--token ${RD_TOKEN}

# 列出作业
rd jobs list -p MyProject

# 执行作业
rd jobs run -j "Deploy Application" -p MyProject

# 查看执行历史
rd executions query -p MyProject

插件扩展

常用插件

1
2
3
4
5
6
# 安装插件
1. Ansible Plugin: 集成 Ansible Playbook
2. Kubernetes Plugin: 管理 K8s 资源
3. Slack Plugin: Slack 通知
4. Git Plugin: Git 仓库加载作业定义
5. HashiCorp Vault: 密钥管理

Ansible 集成示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
- name: Run Ansible Playbook
sequence:
commands:
- type: com.batix.rundeck.plugins.AnsiblePlaybookInlineWorkflowStep
nodeStep: false
configuration:
playbook: |
---
- hosts: web
tasks:
- name: Update packages
apt:
update_cache: yes
upgrade: dist
- name: Restart service
service:
name: nginx
state: restarted
inventory: |
[web]
web-01
web-02

总结核心知识要点

Rundeck 架构

  • 单体应用: Web UI + 调度引擎 + 数据库
  • 执行方式: SSH、WinRM、本地执行
  • 调度引擎: 基于 Quartz 的 Cron 调度
  • 存储: 支持 H2、MySQL、PostgreSQL

核心功能示例

1. 简单定时任务

1
2
3
4
5
6
name: Daily Log Cleanup
schedule:
crontab: '0 1 * * *' # 每天凌晨1点
sequence:
commands:
- exec: find /var/log -name "*.log" -mtime +30 -delete

2. 带参数的作业

1
2
3
4
5
6
7
8
9
10
11
name: Service Control
options:
SERVICE:
required: true
values: nginx,mysql,redis
ACTION:
required: true
values: start,stop,restart
sequence:
commands:
- exec: systemctl ${option.ACTION} ${option.SERVICE}

3. 错误处理

1
2
3
4
5
6
7
8
name: Deployment with Rollback
sequence:
commands:
- description: Deploy new version
exec: deploy.sh
errorhandler:
description: Rollback on failure
exec: rollback.sh

作业调度对比

特性 Rundeck Airflow Cron
Web UI
DAG 支持
节点管理
权限控制
API
复杂依赖 ⚠️

最佳实践

  • 项目隔离: 按环境或应用划分项目
  • 版本控制: 将作业定义导出到 Git
  • 密钥管理: 使用 Key Storage 或 Vault
  • 日志保留: 配置日志清理策略
  • 监控告警: 配置失败通知
  • 权限最小化: 遵循最小权限原则

常用场景

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 场景1: 自动化部署
- 拉取代码
- 构建镜像
- 滚动更新
- 健康检查

# 场景2: 定时备份
- 数据库备份
- 文件备份
- 上传到 S3
- 清理旧备份

# 场景3: 运维巡检
- 磁盘空间检查
- 服务状态检查
- 日志错误扫描
- 生成报告

# 场景4: 批量操作
- 批量更新配置
- 批量重启服务
- 批量软件升级

核心命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 服务管理
sudo service rundeckd start
sudo service rundeckd stop
sudo service rundeckd restart

# 导出作业
rd jobs list -p MyProject -f yaml > jobs.yaml

# 导入作业
rd jobs load -p MyProject -f yaml -F jobs.yaml

# 查看日志
tail -f /var/log/rundeck/service.log

# 备份配置
tar -czf rundeck-backup.tar.gz \
/etc/rundeck \
/var/lib/rundeck

核心概念

  • Project: 顶层组织单元,隔离不同环境
  • Node: 执行目标,可以是服务器、容器等
  • Job: 自动化任务定义
  • Execution: 作业的一次执行实例
  • ACL: 访问控制列表,控制权限

对比 Airflow

何时选择 Rundeck

  • 简单的定时任务
  • 以 SSH 远程执行为主
  • 需要友好的 Web UI
  • 小型团队快速上手

何时选择 Airflow

  • 复杂的数据管道
  • 大量任务依赖(DAG)
  • 数据工程/ETL 场景
  • Python 生态集成

References