活动公告

系统通知
05-18 21:22
系统通知
通知:本站资源由网友上传分享,如有违规等问题请到版务模块进行投诉,资源失效请在帖子内回复要求补档,会尽快处理!
10-23 09:31

全面掌握Ansible集群管理脚本编写从入门到精通的实用指南让运维工作更高效轻松应对大规模服务器集群管理挑战提升自动化水平

SunJu_FaceMall

3万

主题

2860

科技点

3万

积分

白金月票

碾压王

积分
32872

塔罗立华奏

<font color=白金月票" /> 发表于 2025-9-19 01:50:35 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
引言

在当今快速发展的IT环境中,运维团队面临着管理成百上千台服务器的巨大挑战。手动管理这些服务器不仅效率低下,而且容易出错。Ansible作为一款强大的自动化工具,以其简单易用、无代理架构和强大的功能,成为了运维工程师的首选工具。本文将带您从零开始,逐步掌握Ansible集群管理脚本编写的精髓,帮助您提升自动化水平,轻松应对大规模服务器集群管理挑战。

Ansible基础概念

什么是Ansible

Ansible是一款开源的IT自动化工具,它可以帮助您自动化应用程序部署、配置管理、云服务预置和网络编排等任务。与其他自动化工具相比,Ansible的最大优势在于其简单性和无代理架构。

核心组件

Ansible由几个核心组件构成,理解这些组件是掌握Ansible的第一步:

• 控制节点(Control Node):安装Ansible并运行Ansible命令的机器。
• 受管节点(Managed Node):被Ansible管理的服务器或设备。
• 清单(Inventory):定义受管节点的文件,可以是静态的也可以是动态生成的。
• 模块(Modules):Ansible执行任务的工具,每个模块都有特定的功能。
• Playbook:使用YAML语言编写的文件,定义了一系列要执行的任务。
• 角色(Roles):组织Playbook的一种方式,使复杂的自动化任务更加结构化和可重用。

Ansible工作原理

Ansible通过SSH连接到受管节点,并在这些节点上执行模块。由于不需要在受管节点上安装任何特殊的代理软件,Ansible的部署和使用变得非常简单。控制节点将模块推送到受管节点,模块执行完成后将结果返回给控制节点。整个过程是幂等的,意味着无论运行多少次,结果都是一致的。

环境搭建

安装Ansible

在开始使用Ansible之前,我们需要在控制节点上安装Ansible。以下是不同操作系统上的安装方法:
  1. # 安装EPEL仓库
  2. sudo yum install epel-release -y
  3. # 安装Ansible
  4. sudo yum install ansible -y
复制代码
  1. # 更新包索引
  2. sudo apt update
  3. # 安装Ansible
  4. sudo apt install ansible -y
复制代码
  1. # 安装pip
  2. sudo apt install python3-pip -y  # Ubuntu/Debian
  3. sudo yum install python3-pip -y  # CentOS/RHEL
  4. # 使用pip安装Ansible
  5. pip3 install ansible
复制代码

配置SSH免密登录

Ansible通过SSH连接到受管节点,因此需要配置SSH免密登录以实现自动化操作:
  1. # 生成SSH密钥(如果还没有)
  2. ssh-keygen -t rsa
  3. # 将公钥复制到受管节点
  4. ssh-copy-id user@managed_node_ip
复制代码

创建Ansible配置文件

Ansible的配置文件通常位于/etc/ansible/ansible.cfg,您也可以在项目目录中创建自定义的配置文件。以下是一个基本的配置示例:
  1. [defaults]
  2. inventory = ./inventory
  3. host_key_checking = False
  4. remote_user = ansible
  5. private_key_file = ~/.ssh/id_rsa
复制代码

基础入门

创建清单文件

清单文件定义了Ansible要管理的主机。以下是一个简单的静态清单文件示例:
  1. [web_servers]
  2. web1.example.com
  3. web2.example.com
  4. [db_servers]
  5. db1.example.com
  6. db2.example.com
  7. [all:vars]
  8. ansible_ssh_user=ansible
复制代码

您也可以使用YAML格式的清单文件:
  1. all:
  2.   hosts:
  3.     web1.example.com:
  4.     web2.example.com:
  5.   children:
  6.     web_servers:
  7.       hosts:
  8.         web1.example.com:
  9.         web2.example.com:
  10.     db_servers:
  11.       hosts:
  12.         db1.example.com:
  13.         db2.example.com:
  14.   vars:
  15.     ansible_ssh_user: ansible
复制代码

使用Ad-hoc命令

Ad-hoc命令是Ansible的快速执行方式,适合执行简单的任务。以下是一些常用的Ad-hoc命令示例:
  1. # 检查所有主机的连通性
  2. ansible all -m ping
  3. # 在web_servers组上安装nginx
  4. ansible web_servers -m yum -a "name=nginx state=present"
  5. # 重启db_servers组上的mysql服务
  6. ansible db_servers -m service -a "name=mysql state=restarted"
  7. # 在所有主机上执行命令
  8. ansible all -m command -a "date"
复制代码

编写第一个Playbook

Playbook是Ansible的核心,它使用YAML语言定义了一系列任务。以下是一个简单的Playbook示例,用于在web服务器上安装和启动nginx:
  1. ---
  2. - name: Install and start nginx
  3.   hosts: web_servers
  4.   become: yes
  5.   
  6.   tasks:
  7.     - name: Install nginx
  8.       yum:
  9.         name: nginx
  10.         state: present
  11.    
  12.     - name: Start nginx service
  13.       service:
  14.         name: nginx
  15.         state: started
  16.         enabled: yes
复制代码

运行Playbook:
  1. ansible-playbook install_nginx.yml
复制代码

进阶技巧

使用变量

变量使Playbook更加灵活和可重用。您可以在多个地方定义变量:
  1. ---
  2. - name: Install and start nginx
  3.   hosts: web_servers
  4.   become: yes
  5.   vars:
  6.     nginx_version: 1.18.0
  7.   
  8.   tasks:
  9.     - name: Install specific version of nginx
  10.       yum:
  11.         name: nginx-{{ nginx_version }}
  12.         state: present
复制代码

创建一个变量文件vars.yml:
  1. nginx_version: 1.18.0
  2. nginx_port: 8080
复制代码

在Playbook中引用变量文件:
  1. ---
  2. - name: Install and configure nginx
  3.   hosts: web_servers
  4.   become: yes
  5.   vars_files:
  6.     - vars.yml
  7.   
  8.   tasks:
  9.     - name: Install nginx
  10.       yum:
  11.         name: nginx-{{ nginx_version }}
  12.         state: present
  13.    
  14.     - name: Configure nginx port
  15.       template:
  16.         src: nginx.conf.j2
  17.         dest: /etc/nginx/nginx.conf
  18.       notify: Restart nginx
  19.   
  20.   handlers:
  21.     - name: Restart nginx
  22.       service:
  23.         name: nginx
  24.         state: restarted
复制代码

您可以在清单文件目录中创建host_vars和group_vars目录来为特定主机或组定义变量:
  1. inventory/
  2. ├── group_vars/
  3. │   ├── web_servers.yml
  4. │   └── db_servers.yml
  5. ├── host_vars/
  6. │   ├── web1.example.com.yml
  7. │   └── web2.example.com.yml
  8. └── hosts
复制代码

使用模板

Ansible使用Jinja2模板引擎来生成配置文件。以下是一个nginx配置模板示例:
  1. # nginx.conf.j2
  2. user nginx;
  3. worker_processes {{ ansible_processor_vcpus }};
  4. error_log /var/log/nginx/error.log;
  5. pid /run/nginx.pid;
  6. events {
  7.     worker_connections 1024;
  8. }
  9. http {
  10.     log_format main '$remote_addr - $remote_user [$time_local] "$request" '
  11.                     '$status $body_bytes_sent "$http_referer" '
  12.                     '"$http_user_agent" "$http_x_forwarded_for"';
  13.     access_log /var/log/nginx/access.log main;
  14.     sendfile on;
  15.     tcp_nopush on;
  16.     tcp_nodelay on;
  17.     keepalive_timeout 65;
  18.     types_hash_max_size 2048;
  19.     include /etc/nginx/mime.types;
  20.     default_type application/octet-stream;
  21.     include /etc/nginx/conf.d/*.conf;
  22.     server {
  23.         listen {{ nginx_port }};
  24.         server_name _;
  25.         location / {
  26.             root /usr/share/nginx/html;
  27.             index index.html;
  28.         }
  29.     }
  30. }
复制代码

条件判断和循环

使用when语句来实现条件执行:
  1. ---
  2. - name: Configure web servers
  3.   hosts: web_servers
  4.   become: yes
  5.   
  6.   tasks:
  7.     - name: Install Apache on CentOS
  8.       yum:
  9.         name: httpd
  10.         state: present
  11.       when: ansible_os_family == "RedHat"
  12.    
  13.     - name: Install Apache on Ubuntu
  14.       apt:
  15.         name: apache2
  16.         state: present
  17.       when: ansible_os_family == "Debian"
复制代码

使用loop或with_items来重复执行任务:
  1. ---
  2. - name: Install multiple packages
  3.   hosts: web_servers
  4.   become: yes
  5.   
  6.   tasks:
  7.     - name: Install required packages
  8.       package:
  9.         name: "{{ item }}"
  10.         state: present
  11.       loop:
  12.         - nginx
  13.         - git
  14.         - htop
复制代码

错误处理

使用ignore_errors来忽略任务失败:
  1. ---
  2. - name: Example with error handling
  3.   hosts: web_servers
  4.   become: yes
  5.   
  6.   tasks:
  7.     - name: This task might fail
  8.       command: /bin/false
  9.       ignore_errors: yes
  10.    
  11.     - name: This task will run regardless
  12.       debug:
  13.         msg: "This task runs even if the previous one failed"
复制代码

使用failed_when来定义任务失败的条件:
  1. ---
  2. - name: Check disk space
  3.   hosts: all
  4.   become: yes
  5.   
  6.   tasks:
  7.     - name: Get disk usage
  8.       command: df -h /
  9.       register: disk_usage
  10.    
  11.     - name: Fail if disk space is low
  12.       fail:
  13.         msg: "Disk space is too low"
  14.       when: "'90%' in disk_usage.stdout"
复制代码

使用角色

角色是组织Playbook的一种方式,使复杂的自动化任务更加结构化和可重用。以下是一个角色的基本结构:
  1. roles/
  2. └── nginx/
  3.     ├── defaults/
  4.     │   └── main.yml
  5.     ├── files/
  6.     ├── handlers/
  7.     │   └── main.yml
  8.     ├── meta/
  9.     │   └── main.yml
  10.     ├── tasks/
  11.     │   └── main.yml
  12.     ├── templates/
  13.     ├── tests/
  14.     │   └── inventory
  15.     └── vars/
  16.         └── main.yml
复制代码

1. 创建角色目录结构:
  1. mkdir -p roles/nginx/{tasks,handlers,templates,vars,defaults,meta}
复制代码

1. 定义任务(roles/nginx/tasks/main.yml):
  1. ---
  2. - name: Install nginx
  3.   package:
  4.     name: nginx
  5.     state: present
  6. - name: Create nginx config
  7.   template:
  8.     src: nginx.conf.j2
  9.     dest: /etc/nginx/nginx.conf
  10.   notify: Restart nginx
  11. - name: Start nginx service
  12.   service:
  13.     name: nginx
  14.     state: started
  15.     enabled: yes
复制代码

1. 定义处理器(roles/nginx/handlers/main.yml):
  1. ---
  2. - name: Restart nginx
  3.   service:
  4.     name: nginx
  5.     state: restarted
复制代码

1. 创建模板文件(roles/nginx/templates/nginx.conf.j2):
  1. user nginx;
  2. worker_processes {{ ansible_processor_vcpus }};
  3. error_log /var/log/nginx/error.log;
  4. pid /run/nginx.pid;
  5. events {
  6.     worker_connections 1024;
  7. }
  8. http {
  9.     include /etc/nginx/mime.types;
  10.     default_type application/octet-stream;
  11.     sendfile on;
  12.     tcp_nopush on;
  13.     tcp_nodelay on;
  14.     keepalive_timeout 65;
  15.     types_hash_max_size 2048;
  16.     include /etc/nginx/conf.d/*.conf;
  17.     server {
  18.         listen {{ nginx_port | default(80) }};
  19.         server_name _;
  20.         location / {
  21.             root /usr/share/nginx/html;
  22.             index index.html;
  23.         }
  24.     }
  25. }
复制代码

1. 定义默认变量(roles/nginx/defaults/main.yml):
  1. ---
  2. nginx_port: 80
复制代码

1. 在Playbook中使用角色:
  1. ---
  2. - name: Configure web servers
  3.   hosts: web_servers
  4.   become: yes
  5.   roles:
  6.     - nginx
复制代码

集群管理实战

部署高可用Web集群

在这个实战案例中,我们将使用Ansible部署一个高可用的Web集群,包括负载均衡器和多个Web服务器。
  1. web_cluster/
  2. ├── group_vars/
  3. │   ├── all.yml
  4. │   ├── load_balancers.yml
  5. │   └── web_servers.yml
  6. ├── roles/
  7. │   ├── common/
  8. │   ├── haproxy/
  9. │   └── nginx/
  10. ├── inventory
  11. └── site.yml
复制代码
  1. [load_balancers]
  2. lb1.example.com
  3. lb2.example.com
  4. [web_servers]
  5. web1.example.com
  6. web2.example.com
  7. web3.example.com
  8. [cluster:children]
  9. load_balancers
  10. web_servers
复制代码

group_vars/all.yml:
  1. ---
  2. ansible_ssh_user: ansible
  3. ansible_ssh_private_key_file: ~/.ssh/id_rsa
复制代码

group_vars/load_balancers.yml:
  1. ---
  2. haproxy_port: 80
  3. haproxy_stats_port: 8404
复制代码

group_vars/web_servers.yml:
  1. ---
  2. nginx_port: 8080
复制代码

roles/common/tasks/main.yml:
  1. ---
  2. - name: Update system packages
  3.   package:
  4.     name: "*"
  5.     state: latest
  6.   when: update_packages | default(false)
  7. - name: Install common packages
  8.   package:
  9.     name: "{{ item }}"
  10.     state: present
  11.   loop:
  12.     - vim
  13.     - htop
  14.     - net-tools
  15.     - telnet
复制代码

roles/haproxy/tasks/main.yml:
  1. ---
  2. - name: Install HAProxy
  3.   package:
  4.     name: haproxy
  5.     state: present
  6. - name: Configure HAProxy
  7.   template:
  8.     src: haproxy.cfg.j2
  9.     dest: /etc/haproxy/haproxy.cfg
  10.   notify: Restart HAProxy
  11. - name: Start HAProxy service
  12.   service:
  13.     name: haproxy
  14.     state: started
  15.     enabled: yes
复制代码

roles/haproxy/templates/haproxy.cfg.j2:
  1. global
  2.     log         127.0.0.1 local2
  3.     chroot      /var/lib/haproxy
  4.     pidfile     /var/run/haproxy.pid
  5.     maxconn     4000
  6.     user        haproxy
  7.     group       haproxy
  8.     daemon
  9.     stats socket /var/lib/haproxy/stats
  10. defaults
  11.     mode                    http
  12.     log                     global
  13.     option                  httplog
  14.     option                  dontlognull
  15.     option http-server-close
  16.     option forwardfor       except 127.0.0.0/8
  17.     option                  redispatch
  18.     retries                 3
  19.     timeout http-request    10s
  20.     timeout queue           1m
  21.     timeout connect         10s
  22.     timeout client          1m
  23.     timeout server          1m
  24.     timeout http-keep-alive 10s
  25.     timeout check           10s
  26.     maxconn                 3000
  27. frontend main
  28.     bind *:{{ haproxy_port }}
  29.     acl url_static       path_beg       -i /static /images /javascript /stylesheets
  30.     acl url_static       path_end       -i .jpg .gif .png .css .js
  31.     use_backend static          if url_static
  32.     default_backend             app
  33. backend static
  34.     balance     roundrobin
  35.     server      static 127.0.0.1:4331 check
  36. backend app
  37.     balance     roundrobin
  38. {% for host in groups['web_servers'] %}
  39.     server  {{ hostvars[host]['inventory_hostname'] }} {{ hostvars[host]['ansible_host'] }}:{{ nginx_port }} check
  40. {% endfor %}
  41. listen stats
  42.     bind *:{{ haproxy_stats_port }}
  43.     stats enable
  44.     stats uri /
  45.     stats hide-version
  46.     stats auth admin:password
复制代码

roles/haproxy/handlers/main.yml:
  1. ---
  2. - name: Restart HAProxy
  3.   service:
  4.     name: haproxy
  5.     state: restarted
复制代码

roles/nginx/tasks/main.yml:
  1. ---
  2. - name: Install nginx
  3.   package:
  4.     name: nginx
  5.     state: present
  6. - name: Create nginx config
  7.   template:
  8.     src: nginx.conf.j2
  9.     dest: /etc/nginx/nginx.conf
  10.   notify: Restart nginx
  11. - name: Create custom index.html
  12.   template:
  13.     src: index.html.j2
  14.     dest: /usr/share/nginx/html/index.html
  15.   notify: Restart nginx
  16. - name: Start nginx service
  17.   service:
  18.     name: nginx
  19.     state: started
  20.     enabled: yes
复制代码

roles/nginx/templates/nginx.conf.j2:
  1. user nginx;
  2. worker_processes {{ ansible_processor_vcpus }};
  3. error_log /var/log/nginx/error.log;
  4. pid /run/nginx.pid;
  5. events {
  6.     worker_connections 1024;
  7. }
  8. http {
  9.     include /etc/nginx/mime.types;
  10.     default_type application/octet-stream;
  11.     sendfile on;
  12.     tcp_nopush on;
  13.     tcp_nodelay on;
  14.     keepalive_timeout 65;
  15.     types_hash_max_size 2048;
  16.     include /etc/nginx/conf.d/*.conf;
  17.     server {
  18.         listen {{ nginx_port }};
  19.         server_name _;
  20.         location / {
  21.             root /usr/share/nginx/html;
  22.             index index.html;
  23.         }
  24.     }
  25. }
复制代码

roles/nginx/templates/index.html.j2:
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4.     <title>Welcome to {{ inventory_hostname }}</title>
  5.     <style>
  6.         body {
  7.             font-family: Arial, sans-serif;
  8.             margin: 40px;
  9.             background-color: #f0f0f0;
  10.         }
  11.         .container {
  12.             background-color: white;
  13.             padding: 20px;
  14.             border-radius: 5px;
  15.             box-shadow: 0 0 10px rgba(0,0,0,0.1);
  16.         }
  17.         h1 {
  18.             color: #333;
  19.         }
  20.     </style>
  21. </head>
  22. <body>
  23.     <div class="container">
  24.         <h1>Welcome to {{ inventory_hostname }}</h1>
  25.         <p>This server is part of a web cluster managed by Ansible.</p>
  26.         <p>Server IP: {{ ansible_default_ipv4.address }}</p>
  27.         <p>Hostname: {{ inventory_hostname }}</p>
  28.     </div>
  29. </body>
  30. </html>
复制代码

roles/nginx/handlers/main.yml:
  1. ---
  2. - name: Restart nginx
  3.   service:
  4.     name: nginx
  5.     state: restarted
复制代码
  1. ---
  2. - name: Configure load balancers
  3.   hosts: load_balancers
  4.   become: yes
  5.   roles:
  6.     - common
  7.     - haproxy
  8. - name: Configure web servers
  9.   hosts: web_servers
  10.   become: yes
  11.   roles:
  12.     - common
  13.     - nginx
复制代码

运行这个Playbook:
  1. ansible-playbook -i inventory site.yml
复制代码

数据库集群部署

在这个案例中,我们将部署一个MySQL主从复制集群。
  1. mysql_cluster/
  2. ├── group_vars/
  3. │   ├── all.yml
  4. │   ├── mysql_master.yml
  5. │   └── mysql_slaves.yml
  6. ├── roles/
  7. │   ├── common/
  8. │   └── mysql/
  9. ├── inventory
  10. └── site.yml
复制代码
  1. [mysql_master]
  2. db1.example.com
  3. [mysql_slaves]
  4. db2.example.com
  5. db3.example.com
  6. [mysql_cluster:children]
  7. mysql_master
  8. mysql_slaves
复制代码

group_vars/all.yml:
  1. ---
  2. ansible_ssh_user: ansible
  3. ansible_ssh_private_key_file: ~/.ssh/id_rsa
  4. mysql_root_password: "SecureRootPassword123!"
  5. mysql_replication_user: "repl_user"
  6. mysql_replication_password: "ReplPassword123!"
复制代码

group_vars/mysql_master.yml:
  1. ---
  2. mysql_server_id: 1
复制代码

group_vars/mysql_slaves.yml:
  1. ---
  2. mysql_server_id: "{{ 10000 + play_hosts.index(inventory_hostname) }}"
复制代码

roles/mysql/tasks/main.yml:
  1. ---
  2. - name: Install MySQL server
  3.   package:
  4.     name: "{{ mysql_package }}"
  5.     state: present
  6. - name: Start MySQL service
  7.   service:
  8.     name: "{{ mysql_service }}"
  9.     state: started
  10.     enabled: yes
  11. - name: Set MySQL root password
  12.   mysql_user:
  13.     login_user: root
  14.     login_password: ""
  15.     user: root
  16.     password: "{{ mysql_root_password }}"
  17.     host_all: yes
  18.   ignore_errors: yes
  19. - name: Create .my.cnf file with root credentials
  20.   template:
  21.     src: my.cnf.j2
  22.     dest: /root/.my.cnf
  23.     owner: root
  24.     group: root
  25.     mode: 0600
  26. - name: Remove anonymous users
  27.   mysql_user:
  28.     login_user: root
  29.     login_password: "{{ mysql_root_password }}"
  30.     user: ""
  31.     host_all: yes
  32.     state: absent
  33. - name: Remove test database
  34.   mysql_db:
  35.     login_user: root
  36.     login_password: "{{ mysql_root_password }}"
  37.     name: test
  38.     state: absent
  39. - name: Configure MySQL server
  40.   template:
  41.     src: my.cnf.server.j2
  42.     dest: /etc/my.cnf
  43.   notify: Restart MySQL
  44. - name: Create replication user
  45.   mysql_user:
  46.     login_user: root
  47.     login_password: "{{ mysql_root_password }}"
  48.     name: "{{ mysql_replication_user }}"
  49.     password: "{{ mysql_replication_password }}"
  50.     priv: "*.*:REPLICATION SLAVE"
  51.     host: "%"
  52.     state: present
  53.   when: "'mysql_master' in group_names"
  54. - name: Get master binlog position
  55.   mysql_replication:
  56.     login_user: root
  57.     login_password: "{{ mysql_root_password }}"
  58.     mode: getmaster
  59.   register: master
  60.   when: "'mysql_master' in group_names"
  61. - name: Configure replication on slaves
  62.   mysql_replication:
  63.     login_user: root
  64.     login_password: "{{ mysql_root_password }}"
  65.     mode: changemaster
  66.     master_host: "{{ hostvars[groups['mysql_master'][0]]['ansible_host'] }}"
  67.     master_user: "{{ mysql_replication_user }}"
  68.     master_password: "{{ mysql_replication_password }}"
  69.     master_log_file: "{{ master.File }}"
  70.     master_log_pos: "{{ master.Position }}"
  71.   when: "'mysql_slaves' in group_names"
  72. - name: Start replication on slaves
  73.   mysql_replication:
  74.     login_user: root
  75.     login_password: "{{ mysql_root_password }}"
  76.     mode: startslave
  77.   when: "'mysql_slaves' in group_names"
复制代码

roles/mysql/vars/main.yml:
  1. ---
  2. mysql_package: "mariadb-server"
  3. mysql_service: "mariadb"
复制代码

roles/mysql/templates/my.cnf.j2:
  1. [client]
  2. user=root
  3. password={{ mysql_root_password }}
复制代码

roles/mysql/templates/my.cnf.server.j2:
  1. [mysqld]
  2. datadir=/var/lib/mysql
  3. socket=/var/lib/mysql/mysql.sock
  4. symbolic-links=0
  5. server-id={{ mysql_server_id }}
  6. {% if 'mysql_master' in group_names %}
  7. log-bin=mysql-bin
  8. binlog_format=ROW
  9. {% endif %}
  10. [mysqld_safe]
  11. log-error=/var/log/mariadb/mariadb.log
  12. pid-file=/var/run/mariadb/mariadb.pid
  13. !includedir /etc/my.cnf.d
复制代码
  1. ---
  2. - name: Configure MySQL master
  3.   hosts: mysql_master
  4.   become: yes
  5.   roles:
  6.     - common
  7.     - mysql
  8. - name: Configure MySQL slaves
  9.   hosts: mysql_slaves
  10.   become: yes
  11.   roles:
  12.     - common
  13.     - mysql
复制代码

运行这个Playbook:
  1. ansible-playbook -i inventory site.yml
复制代码

高级应用

动态清单

动态清单允许您从外部源(如云服务API、CMDB等)动态获取主机信息。以下是一个使用AWS EC2作为动态清单的示例:
  1. pip install boto3
复制代码
  1. mkdir -p ~/.aws
  2. cat > ~/.aws/credentials << EOF
  3. [default]
  4. aws_access_key_id = YOUR_ACCESS_KEY
  5. aws_secret_access_key = YOUR_SECRET_KEY
  6. EOF
复制代码
  1. #!/usr/bin/env python3
  2. import boto3
  3. import json
  4. def get_ec2_instances():
  5.     ec2 = boto3.client('ec2')
  6.     response = ec2.describe_instances()
  7.    
  8.     inventory = {
  9.         '_meta': {
  10.             'hostvars': {}
  11.         }
  12.     }
  13.    
  14.     for reservation in response['Reservations']:
  15.         for instance in reservation['Instances']:
  16.             if instance['State']['Name'] != 'running':
  17.                 continue
  18.                
  19.             instance_id = instance['InstanceId']
  20.             private_ip = instance.get('PrivateIpAddress', '')
  21.             public_ip = instance.get('PublicIpAddress', '')
  22.             
  23.             # Get tags
  24.             tags = {}
  25.             for tag in instance.get('Tags', []):
  26.                 tags[tag['Key']] = tag['Value']
  27.             
  28.             # Add to inventory
  29.             inventory['_meta']['hostvars'][instance_id] = {
  30.                 'ansible_host': public_ip if public_ip else private_ip,
  31.                 'private_ip': private_ip,
  32.                 'public_ip': public_ip,
  33.                 'instance_type': instance['InstanceType'],
  34.                 'tags': tags
  35.             }
  36.             
  37.             # Add to groups based on tags
  38.             if 'Name' in tags:
  39.                 group_name = tags['Name']
  40.                 if group_name not in inventory:
  41.                     inventory[group_name] = []
  42.                 inventory[group_name].append(instance_id)
  43.             
  44.             if 'Environment' in tags:
  45.                 group_name = tags['Environment']
  46.                 if group_name not in inventory:
  47.                     inventory[group_name] = []
  48.                 inventory[group_name].append(instance_id)
  49.    
  50.     return inventory
  51. if __name__ == '__main__':
  52.     print(json.dumps(get_ec2_instances(), indent=2))
复制代码
  1. # 使脚本可执行
  2. chmod +x aws_ec2.py
  3. # 测试清单
  4. ./aws_ec2.py
  5. # 使用动态清单运行Ansible命令
  6. ansible -i ./aws_ec2.py all -m ping
  7. # 使用动态清单运行Playbook
  8. ansible-playbook -i ./aws_ec2.py site.yml
复制代码

使用Ansible Vault加密敏感数据

Ansible Vault允许您加密敏感数据,如密码、API密钥等。
  1. ansible-vault create secret.yml
复制代码
  1. ansible-vault edit secret.yml
复制代码
  1. ---
  2. - name: Example with vault
  3.   hosts: all
  4.   become: yes
  5.   vars_files:
  6.     - secret.yml
  7.   
  8.   tasks:
  9.     - name: Create database user
  10.       mysql_user:
  11.         login_user: root
  12.         login_password: "{{ mysql_root_password }}"
  13.         name: "{{ db_user }}"
  14.         password: "{{ db_password }}"
  15.         priv: "{{ db_name }}.*:ALL"
  16.         state: present
复制代码
  1. ansible-playbook --ask-vault-pass site.yml
复制代码

或者使用密码文件:
  1. echo "MyVaultPassword" > vault_pass.txt
  2. ansible-playbook --vault-password-file vault_pass.txt site.yml
复制代码

使用Ansible Tower/AWX

Ansible Tower(或其开源版本AWX)是一个Web界面和REST API,用于Ansible的集中管理、控制和监控。
  1. # 安装Docker
  2. yum install -y docker
  3. # 启动Docker服务
  4. systemctl start docker
  5. systemctl enable docker
  6. # 克隆AWX仓库
  7. git clone https://github.com/ansible/awx.git
  8. cd awx/installer
  9. # 编辑inventory文件,配置密码等参数
  10. vim inventory
  11. # 运行安装 playbook
  12. ansible-playbook -i inventory install.yml
复制代码

1. 通过Web界面访问AWX(默认端口80)。
2. 创建组织和项目。
3. 添加清单(可以是静态或动态的)。
4. 创建凭证,用于连接到受管节点。
5. 创建模板,定义要运行的Playbook。
6. 启动作业,查看执行结果。

自定义模块开发

当Ansible的现有模块无法满足您的需求时,您可以开发自定义模块。

以下是一个简单的自定义模块,用于检查文件是否存在:
  1. #!/usr/bin/python
  2. from ansible.module_utils.basic import AnsibleModule
  3. def main():
  4.     module = AnsibleModule(
  5.         argument_spec=dict(
  6.             path=dict(type='str', required=True),
  7.         ),
  8.         supports_check_mode=True
  9.     )
  10.    
  11.     path = module.params['path']
  12.    
  13.     try:
  14.         with open(path, 'r') as f:
  15.             content = f.read()
  16.         module.exit_json(changed=False, exists=True, content=content)
  17.     except IOError as e:
  18.         module.exit_json(changed=False, exists=False, msg=str(e))
  19. if __name__ == '__main__':
  20.     main()
复制代码

1. 将模块放在library目录下:
  1. project/
  2. ├── library/
  3. │   └── file_exists.py
  4. └── site.yml
复制代码

1. 在Playbook中使用自定义模块:
  1. ---
  2. - name: Use custom module
  3.   hosts: all
  4.   tasks:
  5.     - name: Check if file exists
  6.       file_exists:
  7.         path: /etc/hosts
  8.       register: result
  9.    
  10.     - name: Print result
  11.       debug:
  12.         msg: "File exists: {{ result.exists }}"
复制代码

性能优化和故障排除

性能优化

对于长时间运行的任务,可以使用异步执行:
  1. ---
  2. - name: Run long task asynchronously
  3.   hosts: all
  4.   tasks:
  5.     - name: Run system update
  6.       yum:
  7.         name: "*"
  8.         state: latest
  9.       async: 3600
  10.       poll: 0
  11.       register: yum_result
  12.    
  13.     - name: Wait for update to complete
  14.       async_status:
  15.         jid: "{{ yum_result.ansible_job_id }}"
  16.       register: job_result
  17.       until: job_result.finished
  18.       retries: 300
  19.       delay: 10
复制代码

Ansible提供了不同的策略插件来控制Playbook的执行方式:
  1. ---
  2. - name: Use free strategy
  3.   hosts: all
  4.   strategy: free
  5.   tasks:
  6.     - name: Task that can run independently
  7.       command: echo "This task runs independently on all hosts"
复制代码

在ansible.cfg中启用pipelining可以提高SSH连接的效率:
  1. [ssh_connection]
  2. pipelining = True
复制代码

缓存Facts可以减少Playbook的执行时间:
  1. [defaults]
  2. gathering = smart
  3. fact_caching = jsonfile
  4. fact_caching_connection = /tmp/ansible_facts_cache
  5. fact_caching_timeout = 86400
复制代码

故障排除

使用-v(verbose)标志来获取更详细的输出:
  1. ansible-playbook -v site.yml
复制代码

使用-vvv或-vvvv获取更详细的调试信息:
  1. ansible-playbook -vvvv site.yml
复制代码

使用--check标志来模拟Playbook的执行,而不实际更改系统:
  1. ansible-playbook --check site.yml
复制代码

使用--diff标志来显示文件更改的差异:
  1. ansible-playbook --diff site.yml
复制代码

使用--step标志来逐步执行Playbook,在每个任务前确认:
  1. ansible-playbook --step site.yml
复制代码

1. SSH连接问题:
  1. # 测试SSH连接
  2. ansible all -m ping
  3. # 检查SSH配置
  4. ansible all -m debug -a "var=ansible_ssh_host"
复制代码

1. 权限问题:
  1. ---
  2. - name: Example with become
  3.   hosts: all
  4.   become: yes
  5.   become_user: root
  6.   tasks:
  7.     - name: Task that requires root privileges
  8.       command: echo "This task runs as root"
复制代码

1. 模块路径问题:
  1. # 检查模块路径
  2. ansible-doc -l | grep module_name
  3. # 指定模块路径
  4. ansible-playbook --module-path /path/to/modules site.yml
复制代码

1. 变量问题:
  1. ---
  2. - name: Debug variables
  3.   hosts: all
  4.   tasks:
  5.     - name: Print all variables
  6.       debug:
  7.         var: hostvars[inventory_hostname]
复制代码

总结和展望

通过本文的学习,您已经从Ansible的基础概念开始,逐步掌握了Ansible集群管理脚本编写的各个方面。从简单的Ad-hoc命令到复杂的Playbook编写,从变量和模板的使用到角色和动态清单的应用,再到自定义模块开发和性能优化,您现在具备了使用Ansible管理大规模服务器集群的能力。

Ansible作为一款强大的自动化工具,正在不断发展和完善。未来,我们可以期待Ansible在以下方面的进一步发展:

1. 更多的云服务集成:随着云计算的普及,Ansible将继续增强与各种云服务的集成能力。
2. 更强大的API和UI:Ansible Tower/AWX将提供更丰富的API和用户界面,使自动化管理更加便捷。
3. 更好的性能和可扩展性:Ansible将继续优化性能,提高在大规模环境中的执行效率。
4. 更丰富的模块生态系统:Ansible社区将继续贡献更多的模块,覆盖更广泛的应用场景。
5. 更智能的自动化:结合AI和机器学习技术,Ansible可能会提供更智能的自动化决策能力。

更多的云服务集成:随着云计算的普及,Ansible将继续增强与各种云服务的集成能力。

更强大的API和UI:Ansible Tower/AWX将提供更丰富的API和用户界面,使自动化管理更加便捷。

更好的性能和可扩展性:Ansible将继续优化性能,提高在大规模环境中的执行效率。

更丰富的模块生态系统:Ansible社区将继续贡献更多的模块,覆盖更广泛的应用场景。

更智能的自动化:结合AI和机器学习技术,Ansible可能会提供更智能的自动化决策能力。

作为运维工程师,持续学习和实践是掌握Ansible的关键。希望本文能够成为您Ansible学习之旅的有力指南,帮助您在自动化运维的道路上不断前进,轻松应对大规模服务器集群管理的挑战。
「七転び八起き(ななころびやおき)」
回复

使用道具 举报

0

主题

1304

科技点

654

积分

候风辨气

积分
654
候风辨气 发表于 2025-9-19 06:48:12 | 显示全部楼层
感謝分享
温馨提示:看帖回帖是一种美德,您的每一次发帖、回帖都是对论坛最大的支持,谢谢! [这是默认签名,点我更换签名]
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则