├── CNAME ├── favicon.ico ├── init-mysql.sql ├── js └── main.js ├── docker-compose.yaml ├── init-application.sh ├── README.md ├── css └── style.css └── index.html /CNAME: -------------------------------------------------------------------------------- 1 | ansible.ops-coffee.com -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ops-coffee/ansible-job-platform/HEAD/favicon.ico -------------------------------------------------------------------------------- /init-mysql.sql: -------------------------------------------------------------------------------- 1 | CREATE DATABASE IF NOT EXISTS cruiser DEFAULT CHARACTER SET utf8mb4; 2 | 3 | CREATE USER IF NOT EXISTS 'code_devops'@'%' IDENTIFIED BY 'ops-coffee'; 4 | GRANT ALL PRIVILEGES ON cruiser.* TO 'code_devops'@'%'; 5 | FLUSH PRIVILEGES; 6 | -------------------------------------------------------------------------------- /js/main.js: -------------------------------------------------------------------------------- 1 | // 确保DOM内容加载完毕后再执行脚本 2 | document.addEventListener("DOMContentLoaded", function() { 3 | // 移动端菜单控制 4 | const btn = document.getElementById('menu-btn'); 5 | const nav = document.getElementById('mobile-nav'); 6 | if (btn && nav) { 7 | btn.addEventListener('click', () => { 8 | nav.classList.toggle('active'); 9 | btn.innerHTML = nav.classList.contains('active') 10 | ? '' 11 | : ''; 12 | }); 13 | } 14 | 15 | // 1. 初始化 Swiper 16 | const swiper = new Swiper(".swiper-container", { 17 | loop: true, 18 | autoplay: { 19 | delay: 3000, 20 | disableOnInteraction: false, 21 | }, 22 | pagination: { 23 | el: ".swiper-pagination", 24 | clickable: true, 25 | }, 26 | navigation: { 27 | nextEl: ".swiper-button-next", 28 | prevEl: ".swiper-button-prev", 29 | }, 30 | slidesPerView: 1, 31 | spaceBetween: 20, 32 | }); 33 | 34 | // 2. 初始化 AOS (Animate On Scroll) 35 | AOS.init({ 36 | duration: 800, 37 | once: true // 动画是否只播放一次 38 | }); 39 | 40 | }); -------------------------------------------------------------------------------- /docker-compose.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | 3 | mysql: 4 | image: crpi-deapf9g57ymi8i4g.cn-hangzhou.personal.cr.aliyuncs.com/ops_coffee/mysql:8.0 5 | container_name: ops-mysql 6 | restart: always 7 | environment: 8 | TZ: Asia/Shanghai 9 | MYSQL_ALLOW_EMPTY_PASSWORD: yes 10 | volumes: 11 | - mysql-data:/var/lib/mysql 12 | - ./init-mysql.sql:/docker-entrypoint-initdb.d/init-mysql.sql 13 | networks: 14 | ops-coffee: 15 | ipv4_address: 172.22.0.2 16 | ports: 17 | - '3306:3306' 18 | healthcheck: 19 | test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] 20 | interval: 5s 21 | timeout: 5s 22 | retries: 10 23 | start_period: 30s # ✅ 给 MySQL 初始化 SQL 预留时间 24 | 25 | redis: 26 | image: crpi-deapf9g57ymi8i4g.cn-hangzhou.personal.cr.aliyuncs.com/ops_coffee/redis:6.2 27 | container_name: ops-redis 28 | restart: always 29 | environment: 30 | TZ: Asia/Shanghai 31 | volumes: 32 | - redis-data:/data 33 | networks: 34 | ops-coffee: 35 | ipv4_address: 172.22.0.3 36 | ports: 37 | - '6379:6379' 38 | healthcheck: 39 | test: ["CMD", "redis-cli", "ping"] 40 | interval: 5s 41 | timeout: 5s 42 | retries: 10 43 | 44 | ops-app: 45 | image: crpi-deapf9g57ymi8i4g.cn-hangzhou.personal.cr.aliyuncs.com/ops_coffee/cruiser:latest 46 | container_name: ops-app 47 | environment: 48 | TZ: Asia/Shanghai 49 | depends_on: 50 | mysql: 51 | condition: service_healthy # ✅ 等待 DB 完全 ready 52 | redis: 53 | condition: service_healthy 54 | working_dir: /home/project/devops 55 | volumes: 56 | - ./init-application.sh:/tmp/init-application.sh 57 | command: > 58 | bash -c "chmod +x /tmp/init-application.sh && \ 59 | /tmp/init-application.sh && \ 60 | while true; do sleep 3600; done" 61 | networks: 62 | ops-coffee: 63 | ipv4_address: 172.22.0.10 64 | ports: 65 | - '8001:8001' 66 | 67 | volumes: 68 | mysql-data: 69 | driver: local 70 | name: mysql-data 71 | redis-data: 72 | driver: local 73 | name: redis-data 74 | 75 | networks: 76 | ops-coffee: 77 | name: ops_coffee_network 78 | driver: bridge 79 | ipam: 80 | driver: default 81 | config: 82 | - subnet: "172.22.0.0/24" 83 | -------------------------------------------------------------------------------- /init-application.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | MAX_RETRIES=30 5 | SLEEP_INTERVAL=5 6 | 7 | wait_for_db() { 8 | echo "⏳ 等待数据库 172.22.0.2:3306 就绪..." 9 | 10 | for i in $(seq 1 $MAX_RETRIES); do 11 | # 使用 Python 检查数据库连接(无需 mysql 客户端) 12 | if python3 << END 13 | import sys 14 | import pymysql 15 | 16 | try: 17 | conn = pymysql.connect( 18 | host="172.22.0.2", 19 | port=3306, 20 | user="code_devops", 21 | password="ops-coffee", 22 | database="cruiser", 23 | connect_timeout=10 24 | ) 25 | conn.close() 26 | print("✅ 数据库连接成功") 27 | sys.exit(0) 28 | except Exception as e: 29 | print(f"❌ 连接失败: {e}") 30 | sys.exit(1) 31 | END 32 | then 33 | return 0 34 | else 35 | echo "🔁 第 $i 次尝试失败,${SLEEP_INTERVAL} 秒后重试..." 36 | sleep $SLEEP_INTERVAL 37 | fi 38 | done 39 | 40 | echo "❌ 数据库连接超时,已重试 $MAX_RETRIES 次。" 41 | exit 1 42 | } 43 | 44 | # 等待数据库 45 | wait_for_db 46 | 47 | # 初始化数据库及静态资源 48 | echo "⚙️ Running Django migrations & collectstatic..." 49 | 50 | python3 manage.py collectstatic --noinput 51 | python3 manage.py makemigrations --noinput || true 52 | python3 manage.py migrate || { echo >&2 "migrate failed. Aborting."; exit 1; } 53 | 54 | # 创建管理员账号 55 | echo "👤 创建管理员账号..." 56 | python3 manage.py shell -c " 57 | from django.contrib.auth import get_user_model; 58 | User = get_user_model(); 59 | if User.objects.filter(username='admin@ops-coffee.com').exists(): 60 | print('管理员已存在') 61 | else: 62 | User.objects.create_superuser( 63 | username='admin@ops-coffee.com', 64 | password='ops-coffee.com', 65 | mfa_enable=False, 66 | ) 67 | " || { echo >&2 "创建管理员失败"; exit 1; } 68 | 69 | # 新建默认项目 70 | echo "📦 新建默认项目..." 71 | python3 manage.py shell -c " 72 | from django.contrib.auth import get_user_model; 73 | from sadmin.project.models import Project, Member; 74 | if Project.objects.filter(english_name='default').exists(): 75 | print('默认项目已存在') 76 | else: 77 | Project.objects.create( 78 | create_user_id=1, 79 | english_name='default', 80 | chinese_name='默认项目', 81 | ) 82 | if Member.objects.filter(project_id=1, user_id=1).exists(): 83 | print('默认项目成员已存在') 84 | else: 85 | Member.objects.create( 86 | project=Project.objects.get(english_name='default'), 87 | user=get_user_model().objects.get(username='admin@ops-coffee.com'), 88 | is_owner=True, 89 | ) 90 | " || { echo >&2 "新建默认项目失败"; exit 1; } 91 | 92 | # 启动应用服务 93 | echo "🚀 启动服务..." 94 | cp supervisor.conf /etc/supervisor/conf.d/devops.conf || \ 95 | { echo >&2 "An error occurred. Aborting."; exit 1; } 96 | 97 | mkdir -p /home/logs 98 | /etc/init.d/supervisor start 99 | 100 | echo "$(date) ✅ Start ok. ^_^" 101 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ansible-job-platform:一个强大的运维自动化作业平台 2 | 3 | [![Python Version](https://img.shields.io/badge/Python-3.8+-blue.svg)](https://www.python.org/) 4 | [![Django Version](https://img.shields.io/badge/Django-3.2+-green.svg)](https://www.djangoproject.com/) 5 | [![Ansible](https://img.shields.io/badge/Ansible-2.9+-red.svg)](https://www.ansible.com/) 6 | [![License](https://img.shields.io/badge/License-MIT-brightgreen.svg)](LICENSE) 7 | 8 | `ansible-job-platform` 是一个基于 **Django** 开发、深度集成 **Ansible** 的企业级运维自动化平台。 9 | 10 | 它提供了一个现代化的 Web 界面,帮助运维团队将 Ansible 自动化能力平台化、自助化。它不仅仅是一个 Ansible 的 Web UI,更是一个集成了 **CMDB资产管理**、**SSH凭据/网关管理**、**任务调度** 和 **审计日志** 的一站式解决方案。 11 | 12 | --- 13 | 14 | ## 🚀 核心功能 15 | 16 | 本平台围绕 Ansible 自动化构建了一套完整的运维生态。 17 | 18 | ### 1. 资产管理 (CMDB) 19 | 20 | * **业务关系树 (`Relation`):** 21 | * 提供灵活的多级业务树来组织和归类服务器资产,替代传统的 `hosts` 文件。 22 | * 资产(`Instance`)可与业务节点绑定,方便按业务批量执行任务。 23 | * **服务器实例 (`Instance`):** 24 | * 集中管理所有服务器实例,包含内网IP、外网IP、实例状态等。 25 | * 支持从云厂商(`cloud_id`)或其他来源导入和同步资产。 26 | 27 | ### 2. 安全与连接 28 | 29 | * **凭据管理 (`Account`):** 30 | * 集中管理服务器的 SSH 登录凭据(用户名、私钥)。 31 | * 私钥(`private_key`)在数据库中通过 **AES 加密** 存储,确保安全。 32 | * **网关管理 (`Gateway`):** 33 | * 内置 SSH 网关(跳板机)管理功能。 34 | * 允许 Ansible 任务通过指定的网关(`Gateway`)连接到处于内网或隔离区的服务器(`InstanceConnect`)。 35 | * **连接配置 (`InstanceConnect`):** 36 | * 可为每台服务器单独指定 SSH 端口、登录用户(`ssh_user`)和连接网关(`gateway`)。 37 | 38 | ### 3. Ansible 自动化作业 39 | 40 | * **Ad-Hoc 即时命令:** 41 | * 支持在选定的主机上快速执行 Ansible 模块(`shell`, `copy`, `file`, `yum` 等)。 42 | * **Playbook 管理 (`Playbook`):** 43 | * 提供在线的 Playbook 编辑器,支持语法高亮。 44 | * **版本控制:** 自动保存 Playbook 的历史版本(`PlaybookHistory`),支持查看 `diff` 和回滚。 45 | * **脚本管理 (`Script`):** 46 | * 提供在线的脚本(Shell, Python 等)编辑器。 47 | * **版本控制:** 同样支持脚本的历史版本管理(`ScriptHistory`)。 48 | * 在 `ansible` 模块(如 `script` 或 `shell`)中可方便调用。 49 | 50 | ### 4. 任务调度与执行 51 | 52 | * **作业任务 (`AnsibleTask`):** 53 | * 将 Ad-hoc 命令或 Playbook 保存为可重复执行的 "作业模板"。 54 | * 支持在执行前指定额外参数(`args`)。 55 | * **周期性任务 (Celery Beat):** 56 | * 基于 `django-celery-beat` 深度集成,可将任何 `AnsibleTask` 设置为周期性任务。 57 | * 支持标准的 Crontab 表达式(`crontab`),实现无人值守自动化运维。 58 | * **命令过滤 (`CommandFilterRule`):** 59 | * 可配置命令过滤规则(如正则表达式),用于限制高危命令的执行,增强安全性。 60 | 61 | ### 5. 审计与日志 62 | 63 | * **作业日志 (`AnsibleTaskLog`):** 64 | * 详细记录每一次作业(`AnsibleTask`)的执行历史。 65 | * 实时(通过 Celery)更新任务状态:`进行中`、`成功`、`失败` 等。 66 | * 完整保存 Ansible 执行的原始输出(`details`)。 67 | * **任务重做:** 68 | * 支持对已失败或已完成的任务进行 "Redo"(重新执行)。 69 | * **结果通知:** 70 | * 可配置任务执行结果的通知策略(`notify_level`),并将结果发送到指定通知组(`notify_group`)。 71 | 72 | ## 🚀 快速开始 73 | 74 | 1. 安装docker compose 75 | 76 | ``` 77 | curl -fsSL https://get.docker.com -o get-docker.sh | sudo sh 78 | ``` 79 | 80 | 新版本docker已经默认安装了docker compose无需额外安装 81 | 82 | ``` 83 | sudo curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose 84 | sudo chmod +x /usr/local/bin/docker-compose 85 | ``` 86 | 87 | 2. 拉取deploy部署代码 88 | 89 | ``` 90 | mkdir ansible-job-platform && cd ansible-job-platform 91 | git clone git@github.com:ops-coffee/ansible-job-platform.git 92 | ``` 93 | 94 | 3. 启动docker compose 95 | 96 | ``` 97 | docker-compose up -d 98 | ``` 99 | 100 | 4. 浏览器访问:`https://ip_or_domain:8001` 101 | 102 | 默认为8001端口,首次部署有数据初始化等操作,大约会占用几分钟时间,需等待完全启动后访问,可通过查看`ops-app`容器日志,输出`Start ok. ^_^`后表示启动完成 103 | 104 | ``` 105 | # docker logs ops-app -n 10 106 | 👤 创建管理员账号... 107 | 🚀 启动服务... 108 | Starting supervisor: supervisord. 109 | Mon Oct 27 18:57:31 CST 2025 ✅ Start ok. ^_^ 110 | ``` 111 | 112 | 5. 登录账号密码 113 | - 账号:admin@ops-coffee.com 114 | - 密码:ops-coffee.com 115 | -------------------------------------------------------------------------------- /css/style.css: -------------------------------------------------------------------------------- 1 | /* 全局变量和基础样式 */ 2 | :root { 3 | --glass: #ffffff; 4 | --muted: #6b7280; 5 | } 6 | 7 | body { 8 | font-family: Inter, ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial; 9 | background: #f8fafc; 10 | color: #0f172a; 11 | scroll-behavior: smooth; 12 | } 13 | 14 | /* 导航栏和 Hero 部分的样式 */ 15 | 16 | .hero-gradient { 17 | background: linear-gradient(90deg, #0ea5e9 0%, #3b82f6 50%, #6366f1 100%); 18 | -webkit-background-clip: text; 19 | -webkit-text-fill-color: transparent; 20 | } 21 | 22 | .badge { 23 | background: #eef2ff; 24 | color: #065fcb; 25 | padding: 6px 10px; 26 | border-radius: 999px; 27 | font-weight: 600; 28 | } 29 | 30 | /* 卡片样式 */ 31 | 32 | .card { 33 | background: var(--glass); 34 | border: 1px solid #eef2f7; 35 | border-radius: 14px; 36 | padding: 24px; 37 | box-shadow: 0 8px 20px rgba(0, 0, 0, 0.04); 38 | transition: transform 0.2s, box-shadow 0.2s; 39 | } 40 | 41 | .card:hover, 42 | .card:focus-within { 43 | transform: translateY(-4px); 44 | box-shadow: 0 12px 24px rgba(0, 0, 0, 0.08); 45 | } 46 | 47 | /* 代码和动画样式 */ 48 | 49 | pre { 50 | background: #0b1220; 51 | color: #e6f0ff; 52 | padding: 16px; 53 | border-radius: 8px; 54 | overflow: auto; 55 | } 56 | 57 | .animate-slide-in { 58 | animation: slide-in 0.8s ease-out; 59 | } 60 | 61 | @keyframes slide-in { 62 | 0% { 63 | opacity: 0; 64 | transform: translateY(12px); 65 | } 66 | 100% { 67 | opacity: 1; 68 | transform: translateY(0); 69 | } 70 | } 71 | 72 | /* ===== 表格样式 (最终修正) ===== */ 73 | table { 74 | /* 确保边框合并,消除边框间距 */ 75 | border-collapse: collapse; 76 | /* 移除表格整体的外边框 */ 77 | border: none; 78 | } 79 | 80 | table th, 81 | table td { 82 | /* 内部单元格边框 */ 83 | border: 1px solid #e5e7eb; 84 | padding: 12px; 85 | text-align: left; 86 | } 87 | 88 | table thead th { 89 | /* 表头背景和颜色 */ 90 | background: #f3f4f6; 91 | color: #374151; 92 | font-weight: 600; 93 | } 94 | 95 | table tbody tr:hover { 96 | background: #f1f5f9; 97 | } 98 | 99 | .scroll-x { 100 | overflow-x: auto; 101 | } 102 | 103 | /* 自定义 Swiper 箭头样式 */ 104 | .swiper-button-next, 105 | .swiper-button-prev { 106 | color: #3b82f6; /* 蓝色,更贴合品牌色 */ 107 | width: 2rem; 108 | height: 2rem; 109 | background-color: rgba(255, 255, 255, 0.8); 110 | border-radius: 9999px; 111 | display: flex; 112 | align-items: center; 113 | justify-content: center; 114 | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); 115 | transition: all 0.2s; 116 | } 117 | 118 | .swiper-button-next:hover, 119 | .swiper-button-prev:hover { 120 | background-color: #3b82f6; 121 | color: white; 122 | } 123 | 124 | .swiper-button-next::after, 125 | .swiper-button-prev::after { 126 | font-size: 1.25rem; 127 | font-weight: bold; 128 | } 129 | 130 | /* ===== 移动端适配增强 ===== */ 131 | 132 | /* 让卡片与容器在小屏幕上有更紧凑的间距 */ 133 | @media (max-width: 768px) { 134 | body { 135 | font-size: 15px; 136 | } 137 | 138 | header .max-w-7xl { 139 | padding-left: 1rem; 140 | padding-right: 1rem; 141 | } 142 | 143 | /* 针对 Tailwind CSS 默认的 padding 进行覆盖,使其更紧凑 */ 144 | section { 145 | padding-top: 2.5rem !important; 146 | padding-bottom: 2.5rem !important; 147 | } 148 | 149 | .card { 150 | padding: 18px; 151 | } 152 | 153 | h1 { 154 | font-size: 1.875rem; /* text-3xl */ 155 | line-height: 1.3; 156 | } 157 | 158 | h2 { 159 | font-size: 1.5rem; 160 | } 161 | 162 | h3 { 163 | font-size: 1.125rem; 164 | } 165 | 166 | /* 让 hero 部分改为单列 */ 167 | /* 使用更强的选择器覆盖 Tailwind 的 lg:grid-cols-2 */ 168 | .grid.lg\:grid-cols-2 { 169 | grid-template-columns: 1fr !important; 170 | } 171 | 172 | /* Swiper 图片保持等比缩放 */ 173 | .swiper-container img { 174 | width: 100%; 175 | height: auto; 176 | object-fit: contain; 177 | } 178 | 179 | /* 按钮垂直堆叠 */ 180 | .mt-8.flex.flex-col.sm\:flex-row { 181 | flex-direction: column !important; 182 | } 183 | 184 | /* 表格横向滚动提示 */ 185 | .scroll-x::after { 186 | content: "← 左右滑动查看 →"; 187 | display: block; 188 | text-align: center; 189 | font-size: 0.75rem; 190 | color: #94a3b8; 191 | margin-top: 6px; 192 | } 193 | 194 | /* 页脚栅格改为单列 */ 195 | footer .grid { 196 | grid-template-columns: 1fr !important; 197 | } 198 | 199 | footer .flex { 200 | justify-content: flex-start; 201 | } 202 | 203 | /* 调整微信二维码弹出在视口内显示 */ 204 | footer .group:hover .group-hover\:opacity-100 { 205 | left: 50%; 206 | transform: translateX(-50%); 207 | } 208 | 209 | /* 优化导航栏:隐藏原桌面菜单,添加汉堡按钮 */ 210 | nav.md\:flex { 211 | display: none !important; 212 | } 213 | 214 | .mobile-menu-btn { 215 | display: flex !important; 216 | align-items: center; 217 | justify-content: center; 218 | width: 2.5rem; 219 | height: 2.5rem; 220 | border: 1px solid #e2e8f0; 221 | border-radius: 0.5rem; 222 | color: #0f172a; 223 | background: white; 224 | } 225 | 226 | .mobile-nav { 227 | display: none; 228 | flex-direction: column; 229 | background: white; 230 | border-top: 1px solid #e5e7eb; 231 | position: absolute; 232 | top: 100%; 233 | left: 0; 234 | width: 100%; 235 | z-index: 50; 236 | } 237 | 238 | .mobile-nav a { 239 | padding: 0.75rem 1.5rem; 240 | border-bottom: 1px solid #f1f5f9; 241 | } 242 | 243 | .mobile-nav.active { 244 | display: flex; 245 | } 246 | } 247 | 248 | /* 小屏幕 Swiper 箭头更小更靠内 */ 249 | @media (max-width: 640px) { 250 | .swiper-button-next, 251 | .swiper-button-prev { 252 | width: 1.75rem; 253 | height: 1.75rem; 254 | } 255 | 256 | .swiper-button-next::after, 257 | .swiper-button-prev::after { 258 | font-size: 1rem; 259 | } 260 | } -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 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 | Ansible · 安全 · 可控 34 |
35 | 44 | 45 | 48 | 49 |
50 | 痛点 51 | 能力 52 | 流程 53 | 安全 54 | 反馈 55 | 文档 56 | 免费下载 57 |
58 | 59 |
60 |
61 | 62 |
63 |
64 |
65 |
免费
66 |

67 | 企业级 Ansible 自动化作业服务中枢 68 |

69 |

70 | 集中托管 Playbook 资产,实现 动态 Inventory 调度,并提供企业级 凭证安全托管操作合规审计。 71 |

72 | 73 | 83 | 84 |
85 |
86 | 87 |
88 |
凭证安全托管
89 |

私钥 AES 加密存储,执行时动态注入,凭证不落地

90 |
91 |
92 |
93 | 94 |
95 |
动态 Inventory
96 |

统一主机资产管理,支持业务维度灵活分组和精确调度

97 |
98 |
99 |
100 |
101 | 102 |
103 |
104 |
105 |
106 |
总主机数
107 |
2,560
108 |
109 |
110 |
今日作业成功率
111 |
98.5%
112 |
113 |
114 | 115 |
116 |
117 |
118 | 作业执行界面截图 121 |
122 |
123 | 任务调度列表截图 126 |
127 |
128 | 主机资产管理截图 131 |
132 |
133 |
134 |
135 |
136 | 137 |
138 |
即时作业
139 |
周期任务
140 |
操作历史
141 |
142 |
143 |
144 |
145 | 146 |
147 |

常见痛点(为什么选择我们)

148 |
149 |
150 | 151 |
152 |

凭证分散,安全失控

153 |

SSH 私钥、连接密码等凭证散落在个人,缺乏统一加密存储和权限隔离。

154 |
155 |
156 |
157 | 158 |
159 |

自动化资产混乱,难以复用

160 |

Playbook/脚本缺乏版本控制,自动化能力被少数专家垄断,难以赋能。

161 |
162 |
163 |
164 | 165 |
166 |

操作黑盒,合规性缺失

167 |

难以有效追踪“操作人、目标主机、执行命令”,无法满足安全审计和合规要求。

168 |
169 |
170 |
171 |
172 | 173 |
174 |

八大核心能力 · 提升企业自动化效率与安全性

175 |
176 | 177 |
178 |
179 | 180 |

1. 动态 Inventory

181 |
182 |

集中管理主机资产,通过业务关系实现动态分组,告别静态清单(Static Inventory)。

183 |
184 | 185 |
186 |
187 | 188 |

2. 凭证安全托管

189 |
190 |

私钥 AES-256 加密存储,执行时动态解密并注入 Ansible 环境,遵循凭证不落地原则。

191 |
192 | 193 |
194 |
195 | 196 |

3. Playbook版本控制

197 |
198 |

内置在线编辑器管理自动化资产,提供完整的版本历史和代码变更对比功能。

199 |
200 | 201 |
202 |
203 | 204 |

4. 能力服务化

205 |
206 |

将复杂 Playbook 封装为简单易用的“作业模板”,授权团队成员通过 Web UI 一键触发。

207 |
208 | 209 |
210 |
211 | 212 |

5. 周期性任务调度

213 |
214 |

基于 Crontab 表达式,提供高可靠的周期性任务调度,支持无人值守的自动化维护。

215 |
216 | 217 |
218 |
219 | 220 |

6. 高风险操作拦截

221 |
222 |

通过正则表达式配置高危命令过滤规则,在任务执行前进行拦截,确保生产环境安全。

223 |
224 | 225 |
226 |
227 | 228 |

7. SSH 网关收敛

229 |
230 |

支持配置 SSH 跳板机/网关,将任务连接流量收敛至特定路径,简化网络安全管理。

231 |
232 | 233 |
234 |
235 | 236 |

8. 操作审计与追溯

237 |
238 |

完整的任务执行日志和结果,满足 SOX/等保等合规要求,并支持失败任务一键重做。

239 |
240 |
241 |
242 | 243 |
244 |

自动化作业的核心流程

245 |
246 |
247 |

1. 资产与凭证定义

248 |

主机管理 定义目标服务器,将 SSH 私钥托管至 系统用户,完成自动化准备工作。

249 |
250 |
251 |

2. 编排与规则制定

252 |

剧本管理 编写 Playbook,通过 命令过滤 模块设定安全红线,定义操作范围。

253 |
254 |
255 |

3. 任务调度与执行

256 |

通过 作业执行 (Ad-Hoc)作业列表 (Task) 触发任务,平台动态构建执行环境并校验安全规则。

257 |
258 |
259 |

4. 结果追溯与合规

260 |

执行结果、详细输出和操作人等信息实时保存于 作业历史 模块,确保操作全程可审计。

261 |
262 |
263 |
264 | 265 |
266 |

平台内建的纵深安全与合规

267 |
268 |
269 | 270 |

凭证不落地原则

271 |

加密私钥仅在内存中使用,任务结束后立即销毁,杜绝凭证泄露风险。

272 |
273 |
274 | 275 |

细粒度访问控制 (RBAC)

276 |

基于角色的权限模型,支持对主机组、作业模板、功能模块进行精确授权。

277 |
278 |
279 | 280 |

不可篡改的审计日志

281 |

所有操作和执行结果均记录在案,作为合规审计的唯一证据链。

282 |
283 |
284 |
285 | 286 | 287 |
288 |

与传统 Ansible 模式对比

289 |
290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 |
运维自动化作业平台与传统 Ansible 模式对比表
功能传统 Ansible (Git + CLI)运维自动化作业平台
主机清单 (Inventory)❌ 静态 hosts 文件,维护复杂✅ 动态 Inventory,按业务实时分组
SSH 凭证安全❌ 凭证分散,依赖 Vault 手动加密✅ 集中加密托管,动态注入,凭证不落地
高风险操作控制❌ 缺乏事前拦截和校验✅ 内置命令过滤规则,强制执行安全规范
任务调度❌ 依赖 Crontab,缺乏统一管理✅ Web UI 调度中心,支持高可靠周期性任务
操作审计❌ 依赖 Shell 历史或日志分析✅ 完整的作业历史,满足合规追溯要求
327 |
328 |
329 | 330 |
331 |

立即免费部署

332 |

通过 Docker 或源码,快速构建企业级自动化作业平台,提升运维效率和规范性。

333 | 免费下载 334 |
335 | 336 | 374 | 375 | 376 | 377 | 378 | 379 | --------------------------------------------------------------------------------