package services
// PlaybookTemplate Playbook模板定义
type PlaybookTemplate struct {
ID string `json:"id"`
Name string `json:"name"`
Category string `json:"category"`
Description string `json:"description"`
Icon string `json:"icon"`
Content string `json:"content"`
Tags []string `json:"tags"`
}
// TemplateCategory 模板分类
type TemplateCategory struct {
ID string `json:"id"`
Name string `json:"name"`
Icon string `json:"icon"`
Count int `json:"count"`
}
// GetTemplateCategories 获取所有模板分类
func GetTemplateCategories() []TemplateCategory {
cats := map[string]TemplateCategory{}
for _, t := range GetPlaybookTemplates() {
c, ok := cats[t.Category]
if !ok {
c = TemplateCategory{ID: t.Category, Name: categoryNames[t.Category], Icon: categoryIcons[t.Category]}
}
c.Count++
cats[t.Category] = c
}
var result []TemplateCategory
// 按固定顺序输出
order := []string{"system", "web", "database", "container", "cluster", "devops", "security", "monitoring"}
for _, id := range order {
if c, ok := cats[id]; ok {
result = append(result, c)
}
}
return result
}
var categoryNames = map[string]string{
"system": "系统管理",
"web": "Web服务",
"database": "数据库",
"container": "容器化",
"cluster": "集群部署",
"devops": "DevOps",
"security": "安全加固",
"monitoring": "监控告警",
}
var categoryIcons = map[string]string{
"system": "🖥️",
"web": "🌐",
"database": "🗄️",
"container": "🐳",
"cluster": "☸️",
"devops": "🔧",
"security": "🔒",
"monitoring": "📊",
}
// GetPlaybookTemplates 获取所有Playbook模板
func GetPlaybookTemplates() []PlaybookTemplate {
return []PlaybookTemplate{
// ===== 系统管理 =====
{
ID: "update-packages", Name: "系统包更新", Category: "system",
Description: "自动更新系统软件包,支持Debian/RedHat系列",
Icon: "📦", Tags: []string{"update", "apt", "yum"},
Content: `---
- name: 系统包更新
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
update_cache: yes
upgrade_type: dist # dist(完整升级) 或 safe(安全升级)
tasks:
- name: 更新apt缓存
apt:
update_cache: yes
when: ansible_os_family == "Debian"
- name: 升级所有包(Debian)
apt:
upgrade: "{{ upgrade_type }}"
autoremove: yes
autoclean: yes
when: ansible_os_family == "Debian"
- name: 更新yum缓存
yum:
update_cache: yes
when: ansible_os_family == "RedHat"
- name: 升级所有包(RedHat)
yum:
name: "*"
state: latest
when: ansible_os_family == "RedHat"
- name: 检查是否需要重启
stat:
path: /var/run/reboot-required
register: reboot_required
when: ansible_os_family == "Debian"
- name: 提示重启
debug:
msg: "⚠️ 系统需要重启以完成更新"
when: ansible_os_family == "Debian" and reboot_required.stat.exists
`,
},
{
ID: "check-system", Name: "系统信息采集", Category: "system",
Description: "采集操作系统、硬件、网络等详细信息",
Icon: "🔍", Tags: []string{"info", "facts", "inventory"},
Content: `---
- name: 系统信息采集
hosts: "{{ target_hosts | default('all') }}"
gather_facts: yes
tasks:
- name: 操作系统信息
debug:
msg: |
══════════ 系统信息 ══════════
主机名: {{ ansible_facts['hostname'] }}
系统: {{ ansible_facts['distribution'] }} {{ ansible_facts['distribution_version'] }}
内核: {{ ansible_facts['kernel'] }}
架构: {{ ansible_facts['architecture'] }}
CPU: {{ ansible_facts['processor_vcpus'] }} vCPUs
内存: {{ (ansible_facts['memtotal_mb'] / 1024) | round(2) }} GB
IP: {{ ansible_facts['default_ipv4']['address'] | default('N/A') }}
═══════════════════════════════
- name: 磁盘使用
shell: df -h | grep -E '^/dev/'
register: disk_info
- name: 显示磁盘
debug:
msg: "{{ disk_info.stdout_lines }}"
- name: 运行时间
shell: uptime -p
register: uptime_info
- name: 显示运行时间
debug:
msg: "运行时间: {{ uptime_info.stdout }}"
`,
},
{
ID: "check-resources", Name: "资源监控检查", Category: "system",
Description: "检查CPU/内存/磁盘使用率,超阈值告警",
Icon: "📈", Tags: []string{"monitor", "cpu", "memory", "disk"},
Content: `---
- name: 资源监控检查
hosts: "{{ target_hosts | default('all') }}"
gather_facts: yes
vars:
warn_threshold: 80
crit_threshold: 90
tasks:
- name: 获取CPU使用率
shell: top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1
register: cpu_result
changed_when: false
- name: 获取内存使用率
shell: free | grep Mem | awk '{printf "%.0f", $3/$2*100}'
register: mem_result
changed_when: false
- name: 获取磁盘使用率
shell: df -h / | tail -1 | awk '{print $5}' | tr -d '%'
register: disk_result
changed_when: false
- name: 显示资源报告
debug:
msg: |
═══════ {{ inventory_hostname }} 资源报告 ═══════
CPU 使用率: {{ cpu_result.stdout }}%
内存使用率: {{ mem_result.stdout }}%
磁盘使用率: {{ disk_result.stdout }}%
告警阈值: {{ warn_threshold }}% / 严重: {{ crit_threshold }}%
═══════════════════════════════════════
- name: 严重告警
fail:
msg: "🚨 严重: {{ inventory_hostname }} 资源使用率超过 {{ crit_threshold }}%"
when: >
(cpu_result.stdout | int >= crit_threshold) or
(mem_result.stdout | int >= crit_threshold) or
(disk_result.stdout | int >= crit_threshold)
`,
},
{
ID: "log-cleanup", Name: "日志清理", Category: "system",
Description: "清理系统日志、临时文件,释放磁盘空间",
Icon: "🧹", Tags: []string{"cleanup", "log", "disk"},
Content: `---
- name: 日志清理
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
log_retention_days: 30
tmp_retention_days: 7
tasks:
- name: 清理journal日志
shell: journalctl --vacuum-time={{ log_retention_days }}d
register: journal_result
changed_when: "'Vacuuming' in journal_result.stdout"
- name: 清理旧日志文件
find:
paths: /var/log
patterns: "*.gz,*.old,*.[0-9]"
age: "{{ log_retention_days }}d"
register: old_logs
- name: 删除旧日志
file:
path: "{{ item.path }}"
state: absent
loop: "{{ old_logs.files }}"
- name: 清理临时文件
find:
paths: /tmp
age: "{{ tmp_retention_days }}d"
register: tmp_files
- name: 删除临时文件
file:
path: "{{ item.path }}"
state: absent
loop: "{{ tmp_files.files }}"
ignore_errors: yes
- name: 清理apt缓存
apt:
autoclean: yes
when: ansible_os_family == "Debian"
- name: 显示磁盘空间
shell: df -h /
register: disk_after
- name: 清理完成
debug:
msg: "{{ disk_after.stdout_lines }}"
`,
},
{
ID: "time-sync", Name: "时间同步(NTP)", Category: "system",
Description: "配置NTP时间同步,确保集群时间一致",
Icon: "⏰", Tags: []string{"ntp", "time", "chrony"},
Content: `---
- name: 时间同步配置
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
ntp_servers:
- ntp.aliyun.com
- ntp1.aliyun.com
- pool.ntp.org
tasks:
- name: 安装chrony
package:
name: chrony
state: present
- name: 配置NTP服务器
lineinfile:
path: /etc/chrony.conf
regexp: "^server "
line: "server {{ item }} iburst"
create: yes
loop: "{{ ntp_servers }}"
- name: 启动chrony
service:
name: chronyd
state: started
enabled: yes
- name: 验证时间同步
shell: chronyc tracking
register: chrony_status
changed_when: false
- name: 显示同步状态
debug:
msg: "{{ chrony_status.stdout_lines }}"
`,
},
// ===== Web服务 =====
{
ID: "deploy-nginx", Name: "部署Nginx", Category: "web",
Description: "安装配置Nginx,支持自定义站点和反向代理",
Icon: "🌐", Tags: []string{"nginx", "web", "proxy"},
Content: `---
- name: 部署Nginx
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
nginx_worker_processes: auto
nginx_worker_connections: 1024
server_name: localhost
listen_port: 80
proxy_pass: ""
root_dir: /var/www/html
tasks:
- name: 安装Nginx
package:
name: nginx
state: present
- name: 创建网站目录
file:
path: "{{ root_dir }}"
state: directory
owner: www-data
group: www-data
mode: '0755'
when: ansible_os_family == "Debian"
- name: 创建网站目录(RedHat)
file:
path: "{{ root_dir }}"
state: directory
owner: nginx
group: nginx
mode: '0755'
when: ansible_os_family == "RedHat"
- name: 部署默认页面
copy:
content: |
{{ server_name }}
Deployed by Ansible Deploy
Server: {{ inventory_hostname }}
dest: "{{ root_dir }}/index.html"
when: proxy_pass == ""
- name: 配置Nginx站点
copy:
content: |
server {
listen {{ listen_port }};
server_name {{ server_name }};
{% if proxy_pass != "" %}
location / {
proxy_pass {{ proxy_pass }};
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
{% else %}
root {{ root_dir }};
index index.html;
location / {
try_files $uri $uri/ =404;
}
{% endif %}
}
dest: /etc/nginx/conf.d/{{ server_name }}.conf
notify: Reload Nginx
- name: 启动Nginx
service:
name: nginx
state: started
enabled: yes
handlers:
- name: Reload Nginx
service:
name: nginx
state: reloaded
`,
},
{
ID: "deploy-apache", Name: "部署Apache", Category: "web",
Description: "安装配置Apache HTTP Server",
Icon: "🪶", Tags: []string{"apache", "httpd", "web"},
Content: `---
- name: 部署Apache
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
server_name: localhost
listen_port: 80
document_root: /var/www/html
tasks:
- name: 安装Apache(Debian)
apt:
name: apache2
state: present
when: ansible_os_family == "Debian"
- name: 安装Apache(RedHat)
yum:
name: httpd
state: present
when: ansible_os_family == "RedHat"
- name: 创建网站目录
file:
path: "{{ document_root }}"
state: directory
mode: '0755'
- name: 部署测试页面
copy:
content: "Apache on {{ inventory_hostname }}
"
dest: "{{ document_root }}/index.html"
- name: 启动Apache(Debian)
service:
name: apache2
state: started
enabled: yes
when: ansible_os_family == "Debian"
- name: 启动Apache(RedHat)
service:
name: httpd
state: started
enabled: yes
when: ansible_os_family == "RedHat"
`,
},
// ===== 数据库 =====
{
ID: "deploy-mysql", Name: "部署MySQL", Category: "database",
Description: "安装MySQL/MariaDB,配置root密码和基础优化",
Icon: "🐬", Tags: []string{"mysql", "mariadb", "database"},
Content: `---
- name: 部署MySQL
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
mysql_root_password: "ChangeMe@2024"
mysql_port: 3306
mysql_max_connections: 500
mysql_datadir: /var/lib/mysql
tasks:
- name: 安装MySQL(Debian)
apt:
name:
- mysql-server
- mysql-client
- python3-pymysql
state: present
when: ansible_os_family == "Debian"
- name: 安装MariaDB(RedHat)
yum:
name:
- mariadb-server
- mariadb
- python3-PyMySQL
state: present
when: ansible_os_family == "RedHat"
- name: 启动MySQL
service:
name: "{{ 'mysql' if ansible_os_family == 'Debian' else 'mariadb' }}"
state: started
enabled: yes
- name: 设置root密码
shell: |
mysql -u root -e "ALTER USER 'root'@'localhost' IDENTIFIED BY '{{ mysql_root_password }}'; FLUSH PRIVILEGES;"
ignore_errors: yes
no_log: true
- name: 优化配置
copy:
content: |
[mysqld]
port = {{ mysql_port }}
max_connections = {{ mysql_max_connections }}
datadir = {{ mysql_datadir }}
innodb_buffer_pool_size = 256M
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 2
dest: /etc/mysql/conf.d/optimize.cnf
when: ansible_os_family == "Debian"
notify: Restart MySQL
- name: 验证MySQL
shell: mysql -u root -p{{ mysql_root_password }} -e "SELECT VERSION();"
register: mysql_version
changed_when: false
no_log: true
- name: 显示版本
debug:
msg: "MySQL版本: {{ mysql_version.stdout_lines[-1] | default('unknown') }}"
handlers:
- name: Restart MySQL
service:
name: "{{ 'mysql' if ansible_os_family == 'Debian' else 'mariadb' }}"
state: restarted
`,
},
{
ID: "deploy-redis", Name: "部署Redis", Category: "database",
Description: "安装Redis,配置密码、内存限制和持久化",
Icon: "🔴", Tags: []string{"redis", "cache", "database"},
Content: `---
- name: 部署Redis
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
redis_port: 6379
redis_password: "ChangeMe@2024"
redis_maxmemory: "512mb"
redis_maxmemory_policy: allkeys-lru
redis_bind: "0.0.0.0"
tasks:
- name: 安装Redis
package:
name: redis-server
state: present
when: ansible_os_family == "Debian"
- name: 安装Redis(RedHat)
yum:
name: redis
state: present
when: ansible_os_family == "RedHat"
- name: 配置Redis
lineinfile:
path: /etc/redis/redis.conf
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
loop:
- { regexp: '^bind ', line: 'bind {{ redis_bind }}' }
- { regexp: '^port ', line: 'port {{ redis_port }}' }
- { regexp: '^requirepass ', line: 'requirepass {{ redis_password }}' }
- { regexp: '^maxmemory ', line: 'maxmemory {{ redis_maxmemory }}' }
- { regexp: '^maxmemory-policy ', line: 'maxmemory-policy {{ redis_maxmemory_policy }}' }
notify: Restart Redis
- name: 启动Redis
service:
name: "{{ 'redis-server' if ansible_os_family == 'Debian' else 'redis' }}"
state: started
enabled: yes
- name: 验证Redis
shell: redis-cli -a {{ redis_password }} ping
register: redis_ping
changed_when: false
no_log: true
- name: 显示状态
debug:
msg: "Redis状态: {{ redis_ping.stdout }}"
handlers:
- name: Restart Redis
service:
name: "{{ 'redis-server' if ansible_os_family == 'Debian' else 'redis' }}"
state: restarted
`,
},
{
ID: "deploy-postgresql", Name: "部署PostgreSQL", Category: "database",
Description: "安装PostgreSQL,配置用户和基础优化",
Icon: "🐘", Tags: []string{"postgresql", "postgres", "database"},
Content: `---
- name: 部署PostgreSQL
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
postgres_version: "15"
postgres_password: "ChangeMe@2024"
postgres_port: 5432
postgres_max_connections: 200
tasks:
- name: 安装PostgreSQL(Debian)
apt:
name:
- postgresql
- postgresql-contrib
- python3-psycopg2
state: present
when: ansible_os_family == "Debian"
- name: 安装PostgreSQL(RedHat)
yum:
name:
- postgresql-server
- postgresql-contrib
- python3-psycopg2
state: present
when: ansible_os_family == "RedHat"
- name: 初始化数据库(RedHat)
shell: postgresql-setup --initdb
when: ansible_os_family == "RedHat"
ignore_errors: yes
- name: 启动PostgreSQL
service:
name: postgresql
state: started
enabled: yes
- name: 设置postgres密码
become_user: postgres
shell: psql -c "ALTER USER postgres PASSWORD '{{ postgres_password }}';"
no_log: true
- name: 验证安装
become_user: postgres
shell: psql -c "SELECT version();"
register: pg_version
changed_when: false
- name: 显示版本
debug:
msg: "{{ pg_version.stdout_lines[0] | default('PostgreSQL installed') }}"
`,
},
// ===== 容器化 =====
{
ID: "deploy-docker", Name: "部署Docker", Category: "container",
Description: "安装Docker CE + Docker Compose,配置镜像加速",
Icon: "🐳", Tags: []string{"docker", "container", "compose"},
Content: `---
- name: 部署Docker
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
docker_mirror: "https://mirror.ccs.tencentyun.com"
docker_data_root: /var/lib/docker
docker_log_max_size: "100m"
docker_log_max_file: "3"
tasks:
- name: 安装依赖(Debian)
apt:
name:
- apt-transport-https
- ca-certificates
- curl
- gnupg
- lsb-release
state: present
when: ansible_os_family == "Debian"
- name: 添加Docker GPG密钥
shell: |
curl -fsSL https://download.docker.com/linux/{{ ansible_distribution | lower }}/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
when: ansible_os_family == "Debian"
ignore_errors: yes
- name: 添加Docker仓库
shell: |
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/{{ ansible_distribution | lower }} {{ ansible_distribution_release }} stable" > /etc/apt/sources.list.d/docker.list
when: ansible_os_family == "Debian"
- name: 安装Docker(Debian)
apt:
name:
- docker-ce
- docker-ce-cli
- containerd.io
- docker-compose-plugin
state: present
update_cache: yes
when: ansible_os_family == "Debian"
- name: 安装Docker(RedHat)
yum:
name:
- docker
- docker-compose-plugin
state: present
when: ansible_os_family == "RedHat"
- name: 配置Docker
copy:
content: |
{
"data-root": "{{ docker_data_root }}",
"registry-mirrors": ["{{ docker_mirror }}"],
"log-driver": "json-file",
"log-opts": {
"max-size": "{{ docker_log_max_size }}",
"max-file": "{{ docker_log_max_file }}"
},
"storage-driver": "overlay2",
"live-restore": true
}
dest: /etc/docker/daemon.json
notify: Restart Docker
- name: 启动Docker
service:
name: docker
state: started
enabled: yes
- name: 添加用户到docker组
user:
name: "{{ ansible_user }}"
groups: docker
append: yes
ignore_errors: yes
- name: 验证Docker
shell: docker version --format '{{.Server.Version}}'
register: docker_ver
changed_when: false
- name: 显示版本
debug:
msg: "Docker版本: {{ docker_ver.stdout }}"
handlers:
- name: Restart Docker
service:
name: docker
state: restarted
`,
},
{
ID: "deploy-portainer", Name: "部署Portainer", Category: "container",
Description: "部署Portainer CE容器管理面板",
Icon: "🎛️", Tags: []string{"portainer", "docker", "ui"},
Content: `---
- name: 部署Portainer
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
portainer_port: 9443
portainer_data: /opt/portainer
tasks:
- name: 创建数据目录
file:
path: "{{ portainer_data }}"
state: directory
- name: 拉取并启动Portainer
shell: |
docker volume create portainer_data
docker run -d \
-p 8000:8000 \
-p {{ portainer_port }}:9443 \
--name portainer \
--restart=always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer-ce:latest
register: portainer_result
ignore_errors: yes
- name: 显示访问地址
debug:
msg: "Portainer已部署: https://{{ ansible_host | default(inventory_hostname) }}:{{ portainer_port }}"
`,
},
// ===== DevOps =====
{
ID: "deploy-nodejs", Name: "部署Node.js", Category: "devops",
Description: "安装Node.js + PM2进程管理器",
Icon: "💚", Tags: []string{"nodejs", "npm", "pm2"},
Content: `---
- name: 部署Node.js
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
node_version: "20"
install_pm2: true
tasks:
- name: 安装NodeSource仓库
shell: |
curl -fsSL https://deb.nodesource.com/setup_{{ node_version }}.x | bash -
when: ansible_os_family == "Debian"
- name: 安装Node.js(Debian)
apt:
name: nodejs
state: present
update_cache: yes
when: ansible_os_family == "Debian"
- name: 安装Node.js(RedHat)
yum:
name: nodejs
state: present
when: ansible_os_family == "RedHat"
- name: 安装PM2
npm:
name: pm2
global: yes
when: install_pm2
- name: 设置PM2开机启动
shell: pm2 startup systemd -u {{ ansible_user }} --hp /home/{{ ansible_user }}
when: install_pm2
ignore_errors: yes
- name: 验证安装
shell: node --version && npm --version
register: node_ver
changed_when: false
- name: 显示版本
debug:
msg: "{{ node_ver.stdout_lines }}"
`,
},
{
ID: "deploy-python-app", Name: "部署Python应用", Category: "devops",
Description: "配置Python环境 + Gunicorn + Systemd服务",
Icon: "🐍", Tags: []string{"python", "gunicorn", "flask", "django"},
Content: `---
- name: 部署Python应用
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
app_name: myapp
app_dir: /opt/myapp
python_version: python3
venv_dir: /opt/myapp/venv
gunicorn_port: 8000
gunicorn_workers: 4
app_user: www-data
tasks:
- name: 安装Python和依赖
package:
name:
- "{{ python_version }}"
- "{{ python_version }}-venv"
- python3-pip
state: present
- name: 创建应用目录
file:
path: "{{ app_dir }}"
state: directory
owner: "{{ app_user }}"
mode: '0755'
- name: 创建虚拟环境
shell: "{{ python_version }} -m venv {{ venv_dir }}"
args:
creates: "{{ venv_dir }}/bin/activate"
- name: 安装Gunicorn
pip:
name: gunicorn
virtualenv: "{{ venv_dir }}"
- name: 创建Systemd服务
copy:
content: |
[Unit]
Description={{ app_name }} Gunicorn Service
After=network.target
[Service]
User={{ app_user }}
WorkingDirectory={{ app_dir }}
ExecStart={{ venv_dir }}/bin/gunicorn --workers {{ gunicorn_workers }} --bind 0.0.0.0:{{ gunicorn_port }} app:app
Restart=always
[Install]
WantedBy=multi-user.target
dest: /etc/systemd/system/{{ app_name }}.service
notify: Restart App
- name: 启动服务
systemd:
name: "{{ app_name }}"
state: started
enabled: yes
daemon_reload: yes
handlers:
- name: Restart App
systemd:
name: "{{ app_name }}"
state: restarted
daemon_reload: yes
`,
},
{
ID: "backup-data", Name: "数据备份", Category: "devops",
Description: "定时备份指定目录到本地或远程",
Icon: "💾", Tags: []string{"backup", "cron", "archive"},
Content: `---
- name: 数据备份
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
backup_source: /data
backup_dest: /backup
backup_retention_days: 7
backup_hour: "2"
backup_minute: "0"
tasks:
- name: 创建备份目录
file:
path: "{{ backup_dest }}"
state: directory
mode: '0700'
- name: 创建备份脚本
copy:
content: |
#!/bin/bash
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="{{ backup_dest }}/backup_${DATE}.tar.gz"
tar -czf "$BACKUP_FILE" {{ backup_source }} 2>/dev/null
find {{ backup_dest }} -name "backup_*.tar.gz" -mtime +{{ backup_retention_days }} -delete
echo "Backup completed: $BACKUP_FILE"
dest: /usr/local/bin/backup.sh
mode: '0755'
- name: 配置定时任务
cron:
name: "daily-backup"
hour: "{{ backup_hour }}"
minute: "{{ backup_minute }}"
job: "/usr/local/bin/backup.sh >> /var/log/backup.log 2>&1"
- name: 立即执行一次备份
shell: /usr/local/bin/backup.sh
register: backup_result
- name: 备份结果
debug:
msg: "{{ backup_result.stdout }}"
`,
},
// ===== 安全加固 =====
{
ID: "security-hardening", Name: "安全加固", Category: "security",
Description: "SSH加固、防火墙配置、禁用root远程登录",
Icon: "🔒", Tags: []string{"security", "ssh", "firewall", "hardening"},
Content: `---
- name: 安全加固
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
ssh_port: 22
disable_root_login: true
enable_firewall: true
allowed_ssh_users: []
tasks:
- name: 修改SSH端口
lineinfile:
path: /etc/ssh/sshd_config
regexp: "^#?Port "
line: "Port {{ ssh_port }}"
notify: Restart SSH
- name: 禁用root登录
lineinfile:
path: /etc/ssh/sshd_config
regexp: "^#?PermitRootLogin "
line: "PermitRootLogin no"
when: disable_root_login
notify: Restart SSH
- name: 禁用密码认证(仅密钥)
lineinfile:
path: /etc/ssh/sshd_config
regexp: "^#?PasswordAuthentication "
line: "PasswordAuthentication no"
notify: Restart SSH
- name: 设置SSH超时
lineinfile:
path: /etc/ssh/sshd_config
regexp: "^#?ClientAliveInterval "
line: "ClientAliveInterval 300"
notify: Restart SSH
- name: 安装UFW(Debian)
apt:
name: ufw
state: present
when: ansible_os_family == "Debian" and enable_firewall
- name: 配置UFW规则
shell: |
ufw allow {{ ssh_port }}/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw --force enable
when: ansible_os_family == "Debian" and enable_firewall
- name: 安装fail2ban
package:
name: fail2ban
state: present
ignore_errors: yes
- name: 启动fail2ban
service:
name: fail2ban
state: started
enabled: yes
ignore_errors: yes
- name: 加固完成
debug:
msg: "✅ 安全加固完成 - SSH端口: {{ ssh_port }}, Root登录: {{ '禁用' if disable_root_login else '允许' }}"
handlers:
- name: Restart SSH
service:
name: "{{ 'ssh' if ansible_os_family == 'Debian' else 'sshd' }}"
state: restarted
`,
},
{
ID: "ssl-cert", Name: "SSL证书部署", Category: "security",
Description: "使用Certbot自动申请Let's Encrypt证书",
Icon: "📜", Tags: []string{"ssl", "https", "certbot", "letsencrypt"},
Content: `---
- name: SSL证书部署
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
domain: example.com
email: admin@example.com
webroot: /var/www/html
tasks:
- name: 安装Certbot
package:
name:
- certbot
- python3-certbot-nginx
state: present
- name: 申请证书
shell: |
certbot certonly --webroot -w {{ webroot }} \
-d {{ domain }} \
--email {{ email }} \
--agree-tos --non-interactive
args:
creates: /etc/letsencrypt/live/{{ domain }}/fullchain.pem
- name: 配置自动续期
cron:
name: "certbot-renew"
hour: "3"
minute: "30"
job: "certbot renew --quiet --post-hook 'systemctl reload nginx'"
- name: 证书信息
shell: openssl x509 -in /etc/letsencrypt/live/{{ domain }}/fullchain.pem -noout -dates
register: cert_info
changed_when: false
ignore_errors: yes
- name: 显示证书
debug:
msg: "{{ cert_info.stdout_lines | default(['证书已申请']) }}"
`,
},
// ===== 监控告警 =====
{
ID: "deploy-node-exporter", Name: "部署Node Exporter", Category: "monitoring",
Description: "部署Prometheus Node Exporter采集主机指标",
Icon: "📡", Tags: []string{"prometheus", "monitoring", "exporter"},
Content: `---
- name: 部署Node Exporter
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
exporter_version: "1.7.0"
exporter_port: 9100
tasks:
- name: 创建用户
user:
name: node_exporter
system: yes
shell: /usr/sbin/nologin
create_home: no
- name: 下载Node Exporter
get_url:
url: "https://github.com/prometheus/node_exporter/releases/download/v{{ exporter_version }}/node_exporter-{{ exporter_version }}.linux-amd64.tar.gz"
dest: /tmp/node_exporter.tar.gz
- name: 解压
unarchive:
src: /tmp/node_exporter.tar.gz
dest: /tmp
remote_src: yes
- name: 安装二进制
copy:
src: "/tmp/node_exporter-{{ exporter_version }}.linux-amd64/node_exporter"
dest: /usr/local/bin/node_exporter
mode: '0755'
remote_src: yes
- name: 创建Systemd服务
copy:
content: |
[Unit]
Description=Node Exporter
After=network.target
[Service]
User=node_exporter
ExecStart=/usr/local/bin/node_exporter --web.listen-address=:{{ exporter_port }}
Restart=always
[Install]
WantedBy=multi-user.target
dest: /etc/systemd/system/node_exporter.service
- name: 启动服务
systemd:
name: node_exporter
state: started
enabled: yes
daemon_reload: yes
- name: 验证
shell: curl -s http://localhost:{{ exporter_port }}/metrics | head -5
register: metrics
changed_when: false
- name: 显示状态
debug:
msg: "Node Exporter运行在端口 {{ exporter_port }}"
`,
},
{
ID: "deploy-grafana", Name: "部署Grafana", Category: "monitoring",
Description: "部署Grafana可视化监控面板",
Icon: "📊", Tags: []string{"grafana", "dashboard", "visualization"},
Content: `---
- name: 部署Grafana
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
grafana_port: 3000
grafana_admin_password: "admin123"
tasks:
- name: 安装依赖
apt:
name:
- apt-transport-https
- software-properties-common
state: present
when: ansible_os_family == "Debian"
- name: 添加Grafana仓库
shell: |
curl -fsSL https://apt.grafana.com/gpg.key | gpg --dearmor -o /usr/share/keyrings/grafana.gpg
echo "deb [signed-by=/usr/share/keyrings/grafana.gpg] https://apt.grafana.com stable main" > /etc/apt/sources.list.d/grafana.list
when: ansible_os_family == "Debian"
- name: 安装Grafana
apt:
name: grafana
state: present
update_cache: yes
when: ansible_os_family == "Debian"
- name: 配置端口
lineinfile:
path: /etc/grafana/grafana.ini
regexp: "^;?http_port"
line: "http_port = {{ grafana_port }}"
- name: 启动Grafana
service:
name: grafana-server
state: started
enabled: yes
- name: 显示访问信息
debug:
msg: "Grafana: http://{{ ansible_host | default(inventory_hostname) }}:{{ grafana_port }} (admin/{{ grafana_admin_password }})"
`,
},
// ===== 系统管理(新增) =====
{
ID: "host-connectivity", Name: "主机连通性测试", Category: "system",
Description: "批量检测主机SSH连通性、DNS解析、端口可达性",
Icon: "🔗", Tags: []string{"ping", "connectivity", "network", "check"},
Content: `---
- name: 主机连通性测试
hosts: "{{ target_hosts | default('all') }}"
gather_facts: no
tasks:
- name: Ansible Ping 测试
ping:
register: ping_result
ignore_errors: yes
- name: 检测SSH端口
wait_for:
host: "{{ ansible_host | default(inventory_hostname) }}"
port: "{{ ansible_port | default(22) }}"
timeout: 5
delegate_to: localhost
register: ssh_port
ignore_errors: yes
- name: 检测DNS解析
shell: nslookup {{ inventory_hostname }} 2>/dev/null || host {{ inventory_hostname }} 2>/dev/null || echo "DNS解析失败"
delegate_to: localhost
register: dns_result
changed_when: false
ignore_errors: yes
- name: 检测常用端口
wait_for:
host: "{{ ansible_host | default(inventory_hostname) }}"
port: "{{ item }}"
timeout: 3
delegate_to: localhost
loop: [80, 443]
register: port_scan
ignore_errors: yes
- name: 输出连通性报告
debug:
msg: |
═══════ {{ inventory_hostname }} 连通性报告 ═══════
SSH Ping: {{ '✅ 成功' if ping_result is succeeded else '❌ 失败' }}
SSH 端口: {{ '✅ 开放' if ssh_port is succeeded else '❌ 不可达' }}
DNS 解析: {{ dns_result.stdout | default('N/A') }}
HTTP(80): {{ '✅ 开放' if port_scan.results[0] is succeeded else '❌ 关闭' }}
HTTPS(443): {{ '✅ 开放' if port_scan.results[1] is succeeded else '❌ 关闭' }}
═══════════════════════════════════════
`,
},
{
ID: "ubuntu-multi-ip", Name: "Ubuntu 22.04 多IP配置", Category: "system",
Description: "通过Netplan为Ubuntu 22.04配置多IP地址(主IP+辅助IP)",
Icon: "🌐", Tags: []string{"ubuntu", "netplan", "network", "multi-ip"},
Content: `---
- name: Ubuntu 22.04 多IP地址配置
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
# 主网卡名称(根据实际修改)
primary_nic: ens192
# 主IP配置
primary_ip: "192.168.1.100/24"
primary_gateway: "192.168.1.1"
primary_dns:
- 223.5.5.5
- 119.29.29.29
# 辅助IP列表(可添加多个)
secondary_ips:
- "192.168.1.101/24"
- "10.0.0.100/16"
tasks:
- name: 确认系统版本
assert:
that:
- ansible_distribution == "Ubuntu"
- ansible_distribution_version is version('22.04', '>=')
fail_msg: "此模板仅适用于 Ubuntu 22.04+"
success_msg: "系统版本: {{ ansible_distribution }} {{ ansible_distribution_version }}"
- name: 备份现有Netplan配置
shell: |
mkdir -p /etc/netplan/backup
cp /etc/netplan/*.yaml /etc/netplan/backup/ 2>/dev/null || true
args:
creates: /etc/netplan/backup
- name: 生成Netplan配置
copy:
content: |
network:
version: 2
ethernets:
{{ primary_nic }}:
addresses:
- {{ primary_ip }}
{% for ip in secondary_ips %}
- {{ ip }}
{% endfor %}
routes:
- to: default
via: {{ primary_gateway }}
nameservers:
addresses:
{% for dns in primary_dns %}
- {{ dns }}
{% endfor %}
dest: /etc/netplan/01-multi-ip.yaml
mode: '0600'
register: netplan_config
- name: 验证Netplan配置语法
shell: netplan try --timeout=10
environment:
NETPLAN_TRY_TIMEOUT: "10"
ignore_errors: yes
register: netplan_try
- name: 应用Netplan配置
shell: netplan apply
when: netplan_config is changed
- name: 等待网络恢复
wait_for:
host: "{{ primary_ip | ansible.utils.ipaddr('address') }}"
port: 22
timeout: 30
delegate_to: localhost
when: netplan_config is changed
ignore_errors: yes
- name: 验证IP配置
shell: ip addr show {{ primary_nic }} | grep "inet "
register: ip_verify
changed_when: false
- name: 显示配置结果
debug:
msg: |
═══════ 多IP配置完成 ═══════
网卡: {{ primary_nic }}
主IP: {{ primary_ip }}
网关: {{ primary_gateway }}
辅助IP:
{% for ip in secondary_ips %}
- {{ ip }}
{% endfor %}
当前IP列表:
{{ ip_verify.stdout }}
═══════════════════════════
`,
},
{
ID: "ipmitool-bmc", Name: "IPMI配置BMC地址", Category: "system",
Description: "使用ipmitool配置服务器BMC/IPMI管理口IP地址",
Icon: "🔧", Tags: []string{"ipmi", "bmc", "ipmitool", "hardware"},
Content: `---
- name: IPMI配置BMC地址
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
# BMC网络配置
bmc_ip: "10.10.10.100"
bmc_netmask: "255.255.255.0"
bmc_gateway: "10.10.10.1"
# BMC用户配置
bmc_user: "admin"
bmc_password: "Admin@123"
bmc_channel: 1
# 是否启用DHCP(设为true则忽略上面的静态IP配置)
bmc_dhcp: false
tasks:
- name: 安装ipmitool
package:
name: ipmitool
state: present
- name: 加载IPMI内核模块
modprobe:
name: "{{ item }}"
state: present
loop:
- ipmi_devintf
- ipmi_si
ignore_errors: yes
- name: 查看当前BMC配置
shell: ipmitool lan print {{ bmc_channel }}
register: bmc_current
changed_when: false
ignore_errors: yes
- name: 显示当前BMC信息
debug:
msg: "{{ bmc_current.stdout_lines | default(['无法读取BMC信息']) }}"
- name: 设置BMC为静态IP
shell: ipmitool lan set {{ bmc_channel }} ipsrc static
when: not bmc_dhcp
- name: 配置BMC IP地址
shell: ipmitool lan set {{ bmc_channel }} ipaddr {{ bmc_ip }}
when: not bmc_dhcp
- name: 配置BMC子网掩码
shell: ipmitool lan set {{ bmc_channel }} netmask {{ bmc_netmask }}
when: not bmc_dhcp
- name: 配置BMC默认网关
shell: ipmitool lan set {{ bmc_channel }} defgw ipaddr {{ bmc_gateway }}
when: not bmc_dhcp
- name: 设置BMC为DHCP模式
shell: ipmitool lan set {{ bmc_channel }} ipsrc dhcp
when: bmc_dhcp
- name: 配置BMC用户密码
shell: |
ipmitool user set name {{ bmc_channel }} 2 {{ bmc_user }} 2>/dev/null || true
ipmitool user set password 2 {{ bmc_password }}
ipmitool user enable 2
ipmitool channel setaccess {{ bmc_channel }} 2 privilege=4
no_log: true
ignore_errors: yes
- name: 验证BMC配置
shell: ipmitool lan print {{ bmc_channel }}
register: bmc_verify
changed_when: false
- name: 显示最终配置
debug:
msg: |
═══════ BMC配置完成 ═══════
模式: {{ 'DHCP' if bmc_dhcp else '静态IP' }}
IP: {{ bmc_ip }}
掩码: {{ bmc_netmask }}
网关: {{ bmc_gateway }}
用户: {{ bmc_user }}
═══════════════════════════
{{ bmc_verify.stdout }}
`,
},
{
ID: "apt-install", Name: "APT软件安装", Category: "system",
Description: "通过apt批量安装/卸载软件包,支持指定版本和仓库",
Icon: "📦", Tags: []string{"apt", "install", "package", "debian"},
Content: `---
- name: APT软件安装
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
# 要安装的软件包列表
packages_install:
- vim
- curl
- wget
- htop
- net-tools
- tree
- unzip
- git
# 要卸载的软件包列表
packages_remove: []
# 是否更新缓存
update_cache: yes
# 是否自动清理
autoremove: yes
# 安装推荐包
install_recommends: no
# 指定版本(可选,格式: "package=version")
# 例: packages_install: ["nginx=1.18.0-0ubuntu1"]
tasks:
- name: 确认Debian系统
assert:
that: ansible_os_family == "Debian"
fail_msg: "此模板仅适用于 Debian/Ubuntu 系统"
- name: 更新APT缓存
apt:
update_cache: yes
cache_valid_time: 3600
when: update_cache
- name: 安装软件包
apt:
name: "{{ packages_install }}"
state: present
install_recommends: "{{ install_recommends }}"
register: install_result
when: packages_install | length > 0
- name: 卸载软件包
apt:
name: "{{ packages_remove }}"
state: absent
purge: yes
when: packages_remove | length > 0
- name: 自动清理
apt:
autoremove: yes
autoclean: yes
when: autoremove
- name: 验证安装结果
shell: dpkg -l {{ packages_install | join(' ') }} 2>/dev/null | grep "^ii" | awk '{print $2, $3}'
register: verify_result
changed_when: false
when: packages_install | length > 0
- name: 显示安装报告
debug:
msg: |
═══════ APT安装报告 ═══════
已安装: {{ packages_install | length }} 个包
已卸载: {{ packages_remove | length }} 个包
变更: {{ install_result.changed | default(false) }}
{% if verify_result is defined and verify_result.stdout_lines is defined %}
已确认:
{% for line in verify_result.stdout_lines %}
✓ {{ line }}
{% endfor %}
{% endif %}
═══════════════════════════
`,
},
{
ID: "dpkg-install", Name: "DPKG软件安装", Category: "system",
Description: "通过dpkg安装本地.deb包,支持URL下载和依赖修复",
Icon: "📥", Tags: []string{"dpkg", "deb", "install", "offline"},
Content: `---
- name: DPKG软件安装
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
# 本地deb包路径列表(服务器上的路径)
local_deb_files: []
# 远程URL列表(会自动下载后安装)
remote_deb_urls: []
# 下载临时目录
download_dir: /tmp/dpkg_install
# 安装后是否修复依赖
fix_dependencies: yes
# 是否保留下载的deb文件
keep_deb_files: no
tasks:
- name: 确认Debian系统
assert:
that: ansible_os_family == "Debian"
fail_msg: "此模板仅适用于 Debian/Ubuntu 系统"
- name: 创建下载目录
file:
path: "{{ download_dir }}"
state: directory
mode: '0755'
when: remote_deb_urls | length > 0
- name: 下载远程deb包
get_url:
url: "{{ item }}"
dest: "{{ download_dir }}/{{ item | basename }}"
mode: '0644'
loop: "{{ remote_deb_urls }}"
register: download_result
when: remote_deb_urls | length > 0
- name: 安装本地deb包
apt:
deb: "{{ item }}"
state: present
loop: "{{ local_deb_files }}"
register: local_install
when: local_deb_files | length > 0
- name: 安装下载的deb包
apt:
deb: "{{ download_dir }}/{{ item | basename }}"
state: present
loop: "{{ remote_deb_urls }}"
register: remote_install
when: remote_deb_urls | length > 0
- name: 修复依赖关系
apt:
update_cache: yes
force_apt_get: yes
shell: apt-get install -f -y
when: fix_dependencies
ignore_errors: yes
- name: 清理下载文件
file:
path: "{{ download_dir }}"
state: absent
when: not keep_deb_files and remote_deb_urls | length > 0
- name: 显示安装报告
debug:
msg: |
═══════ DPKG安装报告 ═══════
本地包: {{ local_deb_files | length }} 个
远程包: {{ remote_deb_urls | length }} 个
{% if local_deb_files | length > 0 %}
本地安装:
{% for f in local_deb_files %}
✓ {{ f }}
{% endfor %}
{% endif %}
{% if remote_deb_urls | length > 0 %}
远程安装:
{% for u in remote_deb_urls %}
✓ {{ u | basename }}
{% endfor %}
{% endif %}
依赖修复: {{ '是' if fix_dependencies else '否' }}
═══════════════════════════
`,
},
// ===== 集群部署 =====
{
ID: "k8s-cluster", Name: "Kubernetes集群部署", Category: "cluster",
Description: "使用kubeadm部署K8S集群(Master+Worker),含容器运行时、网络插件、Dashboard",
Icon: "☸️", Tags: []string{"kubernetes", "k8s", "kubeadm", "cluster"},
Content: `---
# ============================================================
# Kubernetes 集群部署 (kubeadm)
# 使用方法:
# 1. 在inventory中定义 k8s_master 和 k8s_worker 组
# 2. 修改下方 vars 中的版本和网段
# 3. 执行本Playbook
# ============================================================
- name: K8S集群 - 基础环境准备
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
k8s_version: "1.29"
pod_network_cidr: "10.244.0.0/16"
service_cidr: "10.96.0.0/12"
cni_plugin: calico # calico 或 flannel
tasks:
- name: 关闭swap
shell: |
swapoff -a
sed -i '/swap/s/^/#/' /etc/fstab
- name: 加载内核模块
modprobe:
name: "{{ item }}"
state: present
loop:
- overlay
- br_netfilter
- name: 持久化内核模块
copy:
content: |
overlay
br_netfilter
dest: /etc/modules-load.d/k8s.conf
- name: 设置内核参数
sysctl:
name: "{{ item.key }}"
value: "{{ item.value }}"
sysctl_set: yes
reload: yes
loop:
- { key: "net.bridge.bridge-nf-call-iptables", value: "1" }
- { key: "net.bridge.bridge-nf-call-ip6tables", value: "1" }
- { key: "net.ipv4.ip_forward", value: "1" }
- name: 关闭防火墙
service:
name: firewalld
state: stopped
enabled: no
ignore_errors: yes
- name: 关闭SELinux
shell: setenforce 0 && sed -i 's/^SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
ignore_errors: yes
- name: 时间同步检查
shell: timedatectl set-ntp true
ignore_errors: yes
- name: K8S集群 - 安装容器运行时和K8S组件
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
k8s_version: "1.29"
tasks:
- name: 安装containerd依赖
apt:
name:
- apt-transport-https
- ca-certificates
- curl
- gnupg
state: present
update_cache: yes
when: ansible_os_family == "Debian"
- name: 安装containerd
shell: |
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" > /etc/apt/sources.list.d/docker.list
apt-get update && apt-get install -y containerd.io
when: ansible_os_family == "Debian"
ignore_errors: yes
- name: 配置containerd
shell: |
mkdir -p /etc/containerd
containerd config default > /etc/containerd/config.toml
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
systemctl restart containerd && systemctl enable containerd
ignore_errors: yes
- name: 添加K8S APT源
shell: |
curl -fsSL https://pkgs.k8s.io/core:/stable:/v{{ k8s_version }}/deb/Release.key | gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v{{ k8s_version }}/deb/ /" > /etc/apt/sources.list.d/kubernetes.list
apt-get update
when: ansible_os_family == "Debian"
- name: 安装kubeadm/kubelet/kubectl
apt:
name:
- kubelet
- kubeadm
- kubectl
state: present
update_cache: yes
when: ansible_os_family == "Debian"
- name: 锁定K8S包版本
shell: apt-mark hold kubelet kubeadm kubectl
when: ansible_os_family == "Debian"
- name: 启动kubelet
service:
name: kubelet
state: started
enabled: yes
- name: K8S集群 - 初始化Master
hosts: k8s_master
become: yes
vars:
pod_network_cidr: "10.244.0.0/16"
service_cidr: "10.96.0.0/12"
cni_plugin: calico
tasks:
- name: 初始化Master节点
shell: |
kubeadm init \
--pod-network-cidr={{ pod_network_cidr }} \
--service-cidr={{ service_cidr }} \
--upload-certs \
--ignore-preflight-errors=NumCPU
register: kubeadm_init
ignore_errors: yes
- name: 配置kubectl
shell: |
mkdir -p $HOME/.kube
cp -f /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
ignore_errors: yes
- name: 部署Calico网络
shell: kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml
when: cni_plugin == "calico"
ignore_errors: yes
- name: 部署Flannel网络
shell: kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml
when: cni_plugin == "flannel"
ignore_errors: yes
- name: 获取Worker加入命令
shell: kubeadm token create --print-join-command
register: join_command
changed_when: false
- name: 显示加入命令
debug:
msg: |
═══════ K8S Master 初始化完成 ═══════
Worker加入命令:
{{ join_command.stdout }}
═══════════════════════════════════
- name: K8S集群 - Worker加入集群
hosts: k8s_worker
become: yes
vars:
master_ip: "{{ hostvars[groups['k8s_master'][0]]['ansible_host'] | default(groups['k8s_master'][0]) }}"
tasks:
- name: 获取加入命令
shell: ssh -o StrictHostKeyChecking=no {{ master_ip }} "kubeadm token create --print-join-command"
register: join_cmd
delegate_to: "{{ groups['k8s_master'][0] }}"
ignore_errors: yes
- name: 加入集群
shell: "{{ join_cmd.stdout }}"
when: join_cmd is succeeded
ignore_errors: yes
- name: 验证节点状态
shell: kubectl get nodes
delegate_to: "{{ groups['k8s_master'][0] }}"
register: nodes_status
changed_when: false
ignore_errors: yes
- name: 显示集群状态
debug:
msg: "{{ nodes_status.stdout_lines | default(['等待Master就绪']) }}"
`,
},
{
ID: "ceph-cluster", Name: "Ceph存储集群部署", Category: "cluster",
Description: "使用cephadm部署Ceph集群(MON+OSD+MDS+RGW),含Dashboard",
Icon: "🐙", Tags: []string{"ceph", "storage", "cephadm", "cluster"},
Content: `---
# ============================================================
# Ceph 存储集群部署 (cephadm)
# 使用方法:
# 1. 在inventory中定义 ceph_mon, ceph_osd, ceph_mds 组
# 2. 修改下方 vars 中的网络和磁盘配置
# 3. 执行本Playbook
# ============================================================
- name: Ceph集群 - 基础环境准备
hosts: "{{ target_hosts | default('all') }}"
become: yes
vars:
ceph_release: reef # quincy 或 reef
cluster_network: "10.0.0.0/24"
public_network: "192.168.1.0/24"
tasks:
- name: 安装基础依赖
package:
name:
- python3
- lvm2
- chrony
- podman
state: present
- name: 配置时间同步
service:
name: chronyd
state: started
enabled: yes
ignore_errors: yes
- name: 关闭防火墙
service:
name: firewalld
state: stopped
enabled: no
ignore_errors: yes
- name: 设置主机名解析
lineinfile:
path: /etc/hosts
line: "{{ hostvars[item]['ansible_host'] | default(item) }} {{ item }}"
create: yes
loop: "{{ groups['all'] }}"
when: hostvars[item]['ansible_host'] is defined
- name: Ceph集群 - 安装cephadm
hosts: ceph_mon
become: yes
vars:
ceph_release: reef
tasks:
- name: 安装cephadm
shell: |
curl --silent --remote-name --location https://github.com/ceph/ceph/raw/{{ ceph_release }}/src/cephadm/cephadm
chmod +x cephadm
./cephadm add-repo --release {{ ceph_release }}
./cephadm install
args:
creates: /usr/sbin/cephadm
ignore_errors: yes
- name: 验证cephadm
shell: cephadm version
register: cephadm_ver
changed_when: false
- name: 显示版本
debug:
msg: "{{ cephadm_ver.stdout }}"
- name: Ceph集群 - 引导集群
hosts: ceph_mon[0]
become: yes
vars:
cluster_network: "10.0.0.0/24"
public_network: "192.168.1.0/24"
mon_ip: "{{ ansible_host | default(ansible_default_ipv4.address) }}"
tasks:
- name: 引导Ceph集群
shell: |
cephadm bootstrap \
--mon-ip {{ mon_ip }} \
--cluster-network {{ cluster_network }} \
--allow-overwrite
args:
creates: /etc/ceph/ceph.conf
register: bootstrap_result
ignore_errors: yes
- name: 配置Dashboard
shell: |
ceph dashboard set-rgw-api-ssl-verify False
ceph mgr services
ignore_errors: yes
- name: 获取Dashboard地址
shell: ceph mgr services | grep dashboard
register: dashboard_url
changed_when: false
ignore_errors: yes
- name: 显示集群信息
debug:
msg: |
═══════ Ceph集群引导完成 ═══════
MON IP: {{ mon_ip }}
集群网络: {{ cluster_network }}
公共网络: {{ public_network }}
Dashboard: {{ dashboard_url.stdout | default('http://' + mon_ip + ':8443') }}
═══════════════════════════════════
- name: Ceph集群 - 添加节点
hosts: ceph_osd
become: yes
vars:
mon_host: "{{ groups['ceph_mon'][0] }}"
tasks:
- name: 获取SSH公钥
shell: cat /etc/ceph/ceph.pub
delegate_to: "{{ mon_host }}"
register: ceph_pub_key
changed_when: false
- name: 分发SSH公钥
authorized_key:
user: root
key: "{{ ceph_pub_key.stdout }}"
- name: 添加节点到集群
shell: ceph orch host add {{ inventory_hostname }} {{ ansible_host | default(inventory_hostname) }}
delegate_to: "{{ mon_host }}"
ignore_errors: yes
- name: Ceph集群 - 部署OSD
hosts: ceph_mon[0]
become: yes
vars:
# OSD磁盘配置(根据实际修改)
osd_devices:
- /dev/sdb
- /dev/sdc
osd_all_available: false # 设为true则自动使用所有可用磁盘
tasks:
- name: 部署指定磁盘OSD
shell: ceph orch daemon add osd {{ item.split('/')[2] }}:{{ item }}
loop: "{{ osd_devices }}"
when: not osd_all_available
ignore_errors: yes
- name: 部署所有可用磁盘OSD
shell: ceph orch apply osd --all-available-devices
when: osd_all_available
ignore_errors: yes
- name: 等待OSD就绪
shell: ceph osd stat
register: osd_stat
changed_when: false
retries: 10
delay: 10
until: osd_stat.rc == 0
ignore_errors: yes
- name: 显示OSD状态
debug:
msg: "{{ osd_stat.stdout | default('等待OSD初始化') }}"
- name: Ceph集群 - 部署MDS和RGW
hosts: ceph_mon[0]
become: yes
vars:
deploy_mds: true
deploy_rgw: true
mds_placement: "ceph_mds"
rgw_placement: "ceph_rgw"
tasks:
- name: 部署MDS(CephFS元数据服务)
shell: ceph orch apply mds cephfs --placement="{{ mds_placement }}"
when: deploy_mds
ignore_errors: yes
- name: 部署RGW(对象存储网关)
shell: ceph orch apply rgw ceph-rgw --placement="{{ rgw_placement }}" --port=8080
when: deploy_rgw
ignore_errors: yes
- name: 显示集群状态
shell: ceph -s
register: ceph_status
changed_when: false
- name: 最终报告
debug:
msg: "{{ ceph_status.stdout_lines }}"
`,
},
{
ID: "k8s-rook-ceph", Name: "K8S + Rook-Ceph存储", Category: "cluster",
Description: "在K8S集群上部署Rook-Ceph operator,提供持久化存储",
Icon: "💎", Tags: []string{"kubernetes", "rook", "ceph", "storage", "csi"},
Content: `---
# ============================================================
# Rook-Ceph on Kubernetes
# 前提: K8S集群已部署完成
# ============================================================
- name: Rook-Ceph - 部署Operator
hosts: k8s_master[0]
become: yes
vars:
rook_version: "v1.13.3"
tasks:
- name: 克隆Rook仓库
git:
repo: https://github.com/rook/rook.git
dest: /tmp/rook
version: "{{ rook_version }}"
depth: 1
ignore_errors: yes
- name: 部署CRD和Operator
shell: |
cd /tmp/rook/deploy/examples
kubectl create -f crds.yaml -f common.yaml -f operator.yaml
ignore_errors: yes
- name: 等待Operator就绪
shell: kubectl -n rook-ceph get pod -l app=rook-ceph-operator -o jsonpath='{.items[0].status.phase}'
register: operator_status
retries: 30
delay: 10
until: operator_status.stdout == "Running"
ignore_errors: yes
- name: 显示Operator状态
debug:
msg: "Rook Operator: {{ operator_status.stdout | default('等待中') }}"
- name: Rook-Ceph - 创建CephCluster
hosts: k8s_master[0]
become: yes
vars:
# 存储设备配置
use_all_devices: false
devices:
- name: sdb
- name: sdc
# 或使用目录(测试环境)
use_directories: false
data_dir_host_path: /var/lib/rook
tasks:
- name: 创建CephCluster
shell: |
cat <<'EOF' | kubectl apply -f -
apiVersion: ceph.rook.io/v1
kind: CephCluster
metadata:
name: rook-ceph
namespace: rook-ceph
spec:
cephVersion:
image: quay.io/ceph/ceph:v18.2
dataDirHostPath: {{ data_dir_host_path }}
mon:
count: 3
allowMultiplePerNode: false
mgr:
count: 1
dashboard:
enabled: true
ssl: false
storage:
useAllNodes: true
{% if use_all_devices %}
useAllDevices: true
{% elif devices | length > 0 %}
nodes:
- name: "*"
devices:
{% for d in devices %}
- name: "{{ d.name }}"
{% endfor %}
{% elif use_directories %}
directories:
- path: {{ data_dir_host_path }}
{% endif %}
EOF
ignore_errors: yes
- name: 等待CephCluster就绪
shell: kubectl -n rook-ceph get cephcluster -o jsonpath='{.items[0].status.phase}'
register: cluster_phase
retries: 60
delay: 15
until: cluster_phase.stdout == "Ready"
ignore_errors: yes
- name: 显示集群状态
shell: kubectl -n rook-ceph get cephcluster
register: cluster_status
changed_when: false
- name: 报告
debug:
msg: "{{ cluster_status.stdout_lines }}"
- name: Rook-Ceph - 创建StorageClass
hosts: k8s_master[0]
become: yes
vars:
create_rbd_pool: true
create_cephfs_pool: true
rbd_pool_name: replicapool
rbd_pool_replicas: 3
tasks:
- name: 创建RBD StorageClass
shell: |
cat <<'EOF' | kubectl apply -f -
apiVersion: ceph.rook.io/v1
kind: CephBlockPool
metadata:
name: {{ rbd_pool_name }}
namespace: rook-ceph
spec:
failureDomain: host
replicated:
size: {{ rbd_pool_replicas }}
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: rook-ceph-block
provisioner: rook-ceph.rbd.csi.ceph.com
parameters:
clusterID: rook-ceph
pool: {{ rbd_pool_name }}
imageFormat: "2"
imageFeatures: layering
csi.storage.k8s.io/provisioner-secret-name: rook-csi-rbd-provisioner
csi.storage.k8s.io/provisioner-secret-namespace: rook-ceph
csi.storage.k8s.io/node-stage-secret-name: rook-csi-rbd-node
csi.storage.k8s.io/node-stage-secret-namespace: rook-ceph
reclaimPolicy: Delete
allowVolumeExpansion: true
EOF
when: create_rbd_pool
ignore_errors: yes
- name: 创建CephFS StorageClass
shell: |
cat <<'EOF' | kubectl apply -f -
apiVersion: ceph.rook.io/v1
kind: CephFilesystem
metadata:
name: ceph-filesystem
namespace: rook-ceph
spec:
metadataPool:
replicated:
size: 3
dataPools:
- name: data0
replicated:
size: 3
metadataServer:
activeCount: 1
activeStandby: true
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: rook-cephfs
provisioner: rook-ceph.cephfs.csi.ceph.com
parameters:
clusterID: rook-ceph
fsName: ceph-filesystem
pool: ceph-filesystem-data0
csi.storage.k8s.io/provisioner-secret-name: rook-csi-cephfs-provisioner
csi.storage.k8s.io/provisioner-secret-namespace: rook-ceph
csi.storage.k8s.io/node-stage-secret-name: rook-csi-cephfs-node
csi.storage.k8s.io/node-stage-secret-namespace: rook-ceph
reclaimPolicy: Delete
EOF
when: create_cephfs_pool
ignore_errors: yes
- name: 设置默认StorageClass
shell: kubectl patch storageclass rook-ceph-block -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
ignore_errors: yes
- name: 显示StorageClass
shell: kubectl get sc
register: sc_list
changed_when: false
- name: 最终报告
debug:
msg: |
═══════ Rook-Ceph 部署完成 ═══════
{{ sc_list.stdout }}
═══════════════════════════════════
`,
},
{
ID: "etcd-cluster", Name: "ETCD集群部署", Category: "cluster",
Description: "部署3/5节点ETCD集群,支持TLS加密和自动发现",
Icon: "🔐", Tags: []string{"etcd", "cluster", "kv", "consensus"},
Content: `---
# ============================================================
# ETCD 集群部署
# 使用方法: 在inventory中定义 etcd 组(3或5个节点)
# ============================================================
- name: ETCD集群 - 安装部署
hosts: etcd
become: yes
vars:
etcd_version: "3.5.12"
etcd_data_dir: /var/lib/etcd
etcd_initial_cluster_token: "etcd-cluster-prod"
# 节点间通信端口
client_port: 2379
peer_port: 2380
# 是否启用TLS
enable_tls: false
tasks:
- name: 创建etcd用户
user:
name: etcd
system: yes
shell: /usr/sbin/nologin
create_home: no
- name: 下载ETCD
get_url:
url: "https://github.com/etcd-io/etcd/releases/download/v{{ etcd_version }}/etcd-v{{ etcd_version }}-linux-amd64.tar.gz"
dest: /tmp/etcd.tar.gz
- name: 解压安装
unarchive:
src: /tmp/etcd.tar.gz
dest: /tmp
remote_src: yes
- name: 安装二进制
copy:
src: "/tmp/etcd-v{{ etcd_version }}-linux-amd64/{{ item }}"
dest: "/usr/local/bin/{{ item }}"
mode: '0755'
remote_src: yes
loop: [etcd, etcdctl]
- name: 创建数据目录
file:
path: "{{ etcd_data_dir }}"
state: directory
owner: etcd
group: etcd
mode: '0700'
- name: 构建集群节点列表
set_fact:
etcd_initial_cluster: "{{ groups['etcd'] | map('extract', hostvars, 'inventory_hostname') | zip(groups['etcd'] | map('extract', hostvars, ['ansible_host'])) | map('join', '=http://') | map('regex_replace', '^(.*)$', '\\1:' + (peer_port | string)) | join(',') }}"
- name: 创建Systemd服务
copy:
content: |
[Unit]
Description=ETCD Key-Value Store
After=network.target
[Service]
Type=notify
User=etcd
ExecStart=/usr/local/bin/etcd \
--name {{ inventory_hostname }} \
--data-dir {{ etcd_data_dir }} \
--listen-client-urls http://0.0.0.0:{{ client_port }} \
--advertise-client-urls http://{{ ansible_host | default(inventory_hostname) }}:{{ client_port }} \
--listen-peer-urls http://0.0.0.0:{{ peer_port }} \
--initial-advertise-peer-urls http://{{ ansible_host | default(inventory_hostname) }}:{{ peer_port }} \
--initial-cluster {{ etcd_initial_cluster }} \
--initial-cluster-token {{ etcd_initial_cluster_token }} \
--initial-cluster-state new
Restart=always
RestartSec=5
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
dest: /etc/systemd/system/etcd.service
- name: 启动ETCD
systemd:
name: etcd
state: started
enabled: yes
daemon_reload: yes
- name: ETCD集群 - 验证
hosts: etcd[0]
become: yes
vars:
client_port: 2379
tasks:
- name: 检查集群健康
shell: etcdctl endpoint health --cluster
register: health
changed_when: false
ignore_errors: yes
- name: 检查成员列表
shell: etcdctl member list -w table
register: members
changed_when: false
ignore_errors: yes
- name: 显示集群状态
debug:
msg: |
═══════ ETCD集群状态 ═══════
健康检查: {{ health.stdout | default('检查中...') }}
成员列表:
{{ members.stdout | default('等待集群就绪') }}
═══════════════════════════
`,
},
{
ID: "harbor-cluster", Name: "Harbor镜像仓库部署", Category: "cluster",
Description: "部署Harbor企业级容器镜像仓库,含HTTPS和持久化存储",
Icon: "⚓", Tags: []string{"harbor", "registry", "docker", "images"},
Content: `---
# ============================================================
# Harbor 容器镜像仓库部署
# ============================================================
- name: Harbor - 安装部署
hosts: "{{ target_hosts | default('harbor') }}"
become: yes
vars:
harbor_version: "2.10.0"
harbor_hostname: "harbor.example.com"
harbor_admin_password: "Harbor@12345"
harbor_data_dir: /data/harbor
# 协议: http 或 https
harbor_protocol: https
# HTTPS证书(自签名或已有证书)
ssl_cert: ""
ssl_cert_key: ""
tasks:
- name: 安装Docker(如未安装)
shell: |
if ! command -v docker &>/dev/null; then
curl -fsSL https://get.docker.com | sh
systemctl enable docker && systemctl start docker
fi
ignore_errors: yes
- name: 安装Docker Compose
shell: |
if ! command -v docker-compose &>/dev/null; then
curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
fi
ignore_errors: yes
- name: 创建数据目录
file:
path: "{{ harbor_data_dir }}"
state: directory
mode: '0755'
- name: 下载Harbor离线安装包
get_url:
url: "https://github.com/goharbor/harbor/releases/download/v{{ harbor_version }}/harbor-offline-installer-v{{ harbor_version }}.tgz"
dest: /tmp/harbor.tgz
timeout: 300
- name: 解压安装包
unarchive:
src: /tmp/harbor.tgz
dest: "{{ harbor_data_dir }}"
remote_src: yes
- name: 生成自签名证书
shell: |
mkdir -p /etc/harbor/ssl
openssl req -newkey rsa:4096 -nodes -sha256 \
-keyout /etc/harbor/ssl/harbor.key \
-x509 -days 3650 \
-subj "/CN={{ harbor_hostname }}" \
-addext "subjectAltName=DNS:{{ harbor_hostname }}" \
-out /etc/harbor/ssl/harbor.crt
when: harbor_protocol == "https" and ssl_cert == ""
args:
creates: /etc/harbor/ssl/harbor.crt
- name: 配置Harbor
shell: |
cd {{ harbor_data_dir }}/harbor
cp harbor.yml.tmpl harbor.yml
sed -i "s/^hostname: .*/hostname: {{ harbor_hostname }}/" harbor.yml
sed -i "s/^harbor_admin_password: .*/harbor_admin_password: {{ harbor_admin_password }}/" harbor.yml
sed -i "s|^data_volume: .*|data_volume: {{ harbor_data_dir }}/data|" harbor.yml
{% if harbor_protocol == "https" %}
sed -i "s|^ certificate: .*| certificate: {{ ssl_cert | default('/etc/harbor/ssl/harbor.crt') }}|" harbor.yml
sed -i "s|^ private_key: .*| private_key: {{ ssl_cert_key | default('/etc/harbor/ssl/harbor.key') }}|" harbor.yml
{% else %}
sed -i '/^https:/,/^[a-z]/{ /^https:/d; /^ port:/d; /^ certificate:/d; /^ private_key:/d }' harbor.yml
{% endif %}
- name: 运行Harbor安装脚本
shell: |
cd {{ harbor_data_dir }}/harbor
./install.sh --with-trivy
register: harbor_install
ignore_errors: yes
- name: 等待Harbor启动
wait_for:
port: "{{ 443 if harbor_protocol == 'https' else 80 }}"
timeout: 120
ignore_errors: yes
- name: 显示部署信息
debug:
msg: |
═══════ Harbor 部署完成 ═══════
地址: {{ harbor_protocol }}://{{ harbor_hostname }}
用户: admin
密码: {{ harbor_admin_password }}
数据目录: {{ harbor_data_dir }}
═══════════════════════════════════
`,
},
{
ID: "nfs-cluster", Name: "NFS共享存储集群", Category: "cluster",
Description: "部署NFS服务端+客户端,配置共享存储和自动挂载",
Icon: "📂", Tags: []string{"nfs", "storage", "share", "mount"},
Content: `---
# ============================================================
# NFS 共享存储部署
# 使用方法:
# 1. 在inventory中定义 nfs_server 和 nfs_client 组
# 2. 修改共享目录和客户端挂载配置
# ============================================================
- name: NFS - 服务端部署
hosts: nfs_server
become: yes
vars:
# 共享目录配置
nfs_exports:
- path: /data/nfs/share
clients: "192.168.1.0/24"
options: "rw,sync,no_root_squash,no_subtree_check"
- path: /data/nfs/backup
clients: "192.168.1.0/24"
options: "rw,sync,no_root_squash"
# NFS版本
nfs_versions: "4.2,4.1,4,3"
tasks:
- name: 安装NFS服务端
package:
name: nfs-kernel-server
state: present
when: ansible_os_family == "Debian"
- name: 安装NFS服务端(RedHat)
package:
name: nfs-utils
state: present
when: ansible_os_family == "RedHat"
- name: 创建共享目录
file:
path: "{{ item.path }}"
state: directory
mode: '0777'
loop: "{{ nfs_exports }}"
- name: 配置exports
lineinfile:
path: /etc/exports
line: "{{ item.path }} {{ item.clients }}({{ item.options }})"
create: yes
loop: "{{ nfs_exports }}"
register: exports_config
- name: 重启NFS服务
service:
name: nfs-kernel-server
state: restarted
when: ansible_os_family == "Debian" and exports_config is changed
- name: 重启NFS服务(RedHat)
service:
name: nfs-server
state: restarted
when: ansible_os_family == "RedHat" and exports_config is changed
- name: 导出共享
shell: exportfs -ra
changed_when: false
- name: 验证导出
shell: exportfs -v
register: export_list
changed_when: false
- name: 显示共享信息
debug:
msg: "{{ export_list.stdout_lines }}"
- name: NFS - 客户端挂载
hosts: nfs_client
become: yes
vars:
nfs_server_ip: "{{ hostvars[groups['nfs_server'][0]]['ansible_host'] | default(groups['nfs_server'][0]) }}"
# 客户端挂载配置
nfs_mounts:
- server_path: "/data/nfs/share"
local_path: "/mnt/nfs/share"
options: "rw,soft,timeo=30"
- server_path: "/data/nfs/backup"
local_path: "/mnt/nfs/backup"
options: "rw,soft,timeo=30"
tasks:
- name: 安装NFS客户端
package:
name: nfs-common
state: present
when: ansible_os_family == "Debian"
- name: 安装NFS客户端(RedHat)
package:
name: nfs-utils
state: present
when: ansible_os_family == "RedHat"
- name: 创建挂载点
file:
path: "{{ item.local_path }}"
state: directory
mode: '0755'
loop: "{{ nfs_mounts }}"
- name: 挂载NFS共享
mount:
path: "{{ item.local_path }}"
src: "{{ nfs_server_ip }}:{{ item.server_path }}"
fstype: nfs
opts: "{{ item.options }}"
state: mounted
loop: "{{ nfs_mounts }}"
- name: 验证挂载
shell: df -h | grep nfs
register: mount_check
changed_when: false
ignore_errors: yes
- name: 显示挂载状态
debug:
msg: "{{ mount_check.stdout_lines | default(['等待挂载']) }}"
`,
},
}
}