|
|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
1. Ansible Playbook基础介绍
Ansible Playbook是Ansible的核心组件,它是一种使用YAML语言编写的配置、部署和编排文件。Playbook允许您描述IT应用基础设施的自动化策略,使复杂的配置管理任务变得简单易行。
Playbook的优势在于:
• 人类可读:使用YAML格式,语法简洁明了
• 幂等性:多次执行相同任务不会改变结果(除非需要改变)
• 高效性:可以并行执行多个任务
• 可扩展性:支持模块化设计,可以通过角色和包含来组织复杂任务
2. YAML语法基础
Ansible Playbook使用YAML(YAML Ain’t Markup Language)语言编写。了解YAML的基本语法对于编写Playbook至关重要。
2.1 基本语法规则
- # 键值对
- key: value
- # 列表(使用连字符开头)
- - item1
- - item2
- - item3
- # 嵌套结构
- key:
- nested_key1: value1
- nested_key2: value2
- # 列表中的字典
- - name: item1
- value: value1
- - name: item2
- value: value2
复制代码
2.2 YAML中的数据类型
- # 字符串
- string_var: "This is a string"
- another_string: 'This is also a string'
- # 数字
- integer_var: 42
- float_var: 3.14
- # 布尔值
- boolean_true: yes
- boolean_false: no
- # null值
- null_var: null
复制代码
2.3 YAML中的注释
在YAML中,使用#符号表示注释:
- # 这是一个注释
- key: value # 这也是一个行内注释
复制代码
3. Playbook基本结构
一个基本的Ansible Playbook由一个或多个”play”组成,每个play定义了一组要在特定主机或主机组上执行的任务。
3.1 最简单的Playbook结构
- ---
- - name: Playbook名称
- hosts: 目标主机或主机组
- tasks:
- - name: 任务1名称
- module_name:
- parameter1: value1
- parameter2: value2
-
- - name: 任务2名称
- module_name:
- parameter1: value1
复制代码
3.2 完整的Playbook结构
- ---
- - name: 第一个play
- hosts: webservers
- become: yes
- vars:
- http_port: 80
- max_clients: 200
-
- vars_files:
- - vars/external_vars.yml
-
- pre_tasks:
- - name: 预任务1
- debug:
- msg: "开始执行预任务"
-
- roles:
- - common
- - webserver
-
- tasks:
- - name: 安装Apache
- yum:
- name: httpd
- state: present
-
- - name: 启动Apache服务
- service:
- name: httpd
- state: started
- enabled: yes
-
- post_tasks:
- - name: 后任务1
- debug:
- msg: "所有任务执行完成"
-
- handlers:
- - name: 重启Apache
- service:
- name: httpd
- state: restarted
复制代码
4. 常用模块详解
Ansible提供了大量模块来执行各种任务。以下是一些最常用的模块及其用法。
4.1 文件和目录操作模块
- - name: 复制文件到远程主机
- copy:
- src: /path/to/local/file
- dest: /path/to/remote/file
- owner: root
- group: root
- mode: '0644'
- backup: yes
复制代码- - name: 创建目录
- file:
- path: /path/to/directory
- state: directory
- owner: root
- group: root
- mode: '0755'
- - name: 创建符号链接
- file:
- src: /path/to/source
- dest: /path/to/link
- state: link
- - name: 删除文件
- file:
- path: /path/to/file
- state: absent
复制代码- - name: 检查文件状态
- stat:
- path: /path/to/file
- register: file_stat
- - name: 显示文件信息
- debug:
- msg: "文件大小: {{ file_stat.stat.size }} 字节"
- when: file_stat.stat.exists
复制代码
4.2 软件包管理模块
- - name: 安装最新版本的Apache
- yum:
- name: httpd
- state: latest
- - name: 安装多个软件包
- yum:
- name:
- - httpd
- - httpd-tools
- - mod_ssl
- state: present
- - name: 移除软件包
- yum:
- name: httpd
- state: absent
复制代码- - name: 更新apt缓存并安装Nginx
- apt:
- name: nginx
- state: latest
- update_cache: yes
- - name: 安装特定版本的软件包
- apt:
- name: nginx=1.18.0-0ubuntu1
- state: present
- - name: 卸载软件包并删除配置文件
- apt:
- name: nginx
- state: absent
- purge: yes
复制代码
4.3 服务管理模块
- - name: 启动并启用Apache服务
- service:
- name: httpd
- state: started
- enabled: yes
- - name: 重启服务
- service:
- name: httpd
- state: restarted
- - name: 停止服务
- service:
- name: httpd
- state: stopped
复制代码
4.4 用户和组管理模块
- - name: 创建用户
- user:
- name: johndoe
- comment: "John Doe"
- uid: 1040
- group: users
- shell: /bin/bash
- password: "{{ 'password' | password_hash('sha512') }}"
- - name: 创建组
- group:
- name: developers
- state: present
- gid: 1050
- - name: 生成SSH密钥
- user:
- name: johndoe
- generate_ssh_key: yes
- ssh_key_bits: 2048
- ssh_key_file: .ssh/id_rsa
复制代码
4.5 系统信息模块
- - name: 收集系统信息
- setup:
- register: system_info
- - name: 显示操作系统信息
- debug:
- msg: "系统: {{ system_info.ansible_distribution }} {{ system_info.ansible_distribution_version }}"
复制代码
4.6 命令和脚本执行模块
- - name: 检查磁盘空间
- command: df -h
- register: disk_space
- - name: 显示磁盘使用情况
- debug:
- msg: "{{ disk_space.stdout_lines }}"
复制代码- - name: 执行带有管道的命令
- shell: ps aux | grep httpd
- register: httpd_processes
- - name: 显示Apache进程
- debug:
- msg: "{{ httpd_processes.stdout_lines }}"
复制代码- - name: 在远程主机上执行本地脚本
- script: /path/to/local/script.sh --parameter1 value1
复制代码
5. 变量使用
变量是Ansible Playbook中的重要组成部分,它们使Playbook更加灵活和可重用。
5.1 定义变量
- ---
- - name: 使用变量示例
- hosts: webservers
- vars:
- package_name: httpd
- service_name: httpd
- config_file: /etc/httpd/conf/httpd.conf
-
- tasks:
- - name: 安装{{ package_name }}
- yum:
- name: "{{ package_name }}"
- state: present
-
- - name: 启动{{ service_name }}服务
- service:
- name: "{{ service_name }}"
- state: started
复制代码- # vars/webserver.yml
- package_name: httpd
- service_name: httpd
- config_file: /etc/httpd/conf/httpd.conf
复制代码
然后在Playbook中引用:
- ---
- - name: 使用外部变量文件
- hosts: webservers
- vars_files:
- - vars/webserver.yml
-
- tasks:
- - name: 安装{{ package_name }}
- yum:
- name: "{{ package_name }}"
- state: present
复制代码
5.2 变量类型
- vars:
- app_name: "my_web_app"
- app_version: "1.2.3"
复制代码- vars:
- http_port: 80
- https_port: 443
- max_connections: 1000
复制代码- vars:
- required_packages:
- - httpd
- - php
- - mysql
- - php-mysql
复制代码- vars:
- database_config:
- host: localhost
- port: 3306
- name: webapp_db
- user: webapp_user
- password: secure_password
复制代码
5.3 使用变量
- tasks:
- - name: 创建目录
- file:
- path: "/var/www/{{ app_name }}"
- state: directory
复制代码- tasks:
- - name: 创建配置文件
- template:
- src: config.j2
- dest: "/etc/app/config.ini"
- vars:
- db_host: "{{ database_config.host }}"
- db_port: "{{ database_config.port }}"
复制代码- tasks:
- - name: 安装多个软件包
- yum:
- name: "{{ required_packages }}"
- state: present
复制代码
5.4 变量优先级
Ansible中变量的优先级顺序(从高到低):
1. 命令行中通过-e或--extra-vars指定的变量
2. 在inventory中定义的连接变量
3. 在play中定义的vars
4. 在play中通过vars_files包含的变量
5. 在role中定义的vars
6. 在inventory中定义的变量
7. 通过set_fact模块设置的变量
8. 角色默认值(defaults/main.yml)
5.5 注册变量
使用register关键字可以将任务的输出保存到变量中,以便在后续任务中使用。
- - name: 检查服务状态
- command: systemctl status nginx
- register: nginx_status
- ignore_errors: yes
- - name: 显示服务状态
- debug:
- msg: "Nginx服务状态: {{ nginx_status.rc }}"
- when: nginx_status.rc is defined
- - name: 重启服务(如果失败)
- service:
- name: nginx
- state: restarted
- when: nginx_status.rc != 0
复制代码
6. 条件判断和循环
条件判断和循环是Ansible Playbook中控制任务执行流程的重要机制。
6.1 条件判断
- - name: 安装Apache(仅适用于CentOS系统)
- yum:
- name: httpd
- state: present
- when: ansible_distribution == "CentOS"
- - name: 安装Nginx(仅适用于Ubuntu系统)
- apt:
- name: nginx
- state: present
- when: ansible_distribution == "Ubuntu"
复制代码- - name: 安装特定版本的软件包(仅适用于CentOS 7)
- yum:
- name: httpd-2.4.6
- state: present
- when:
- - ansible_distribution == "CentOS"
- - ansible_distribution_major_version == "7"
复制代码- - name: 安装开发工具
- yum:
- name: "@Development tools"
- state: present
- when:
- - (ansible_distribution == "CentOS" or ansible_distribution == "Red Hat Enterprise Linux")
- - ansible_distribution_major_version|int >= 7
复制代码- - name: 使用自定义配置文件(如果存在)
- copy:
- src: "{{ custom_config_file | default('/etc/app/default.conf') }}"
- dest: /etc/app/config.conf
复制代码
6.2 循环
- - name: 创建多个用户
- user:
- name: "{{ item }}"
- state: present
- loop:
- - alice
- - bob
- - charlie
复制代码- - name: 创建多个用户并设置属性
- user:
- name: "{{ item.name }}"
- uid: "{{ item.uid }}"
- group: "{{ item.group }}"
- shell: "{{ item.shell }}"
- loop:
- - { name: 'alice', uid: 1001, group: 'users', shell: '/bin/bash' }
- - { name: 'bob', uid: 1002, group: 'developers', shell: '/bin/zsh' }
- - { name: 'charlie', uid: 1003, group: 'admins', shell: '/bin/bash' }
复制代码- - name: 安装多个软件包
- yum:
- name: "{{ item }}"
- state: present
- with_items:
- - httpd
- - php
- - php-mysql
- - php-gd
复制代码- - name: 打印字典键值对
- debug:
- msg: "Key: {{ item.key }}, Value: {{ item.value }}"
- with_dict:
- - { key: 'name', value: 'John' }
- - { key: 'age', value: 30 }
- - { key: 'city', value: 'New York' }
复制代码- - name: 复制所有配置文件
- copy:
- src: "{{ item }}"
- dest: "/etc/app/{{ item | basename }}"
- with_fileglob:
- - "files/*.conf"
复制代码- - name: 创建多个目录
- file:
- path: "/tmp/dir{{ item }}"
- state: directory
- with_sequence: start=1 end=5
复制代码- - name: 等待服务启动
- command: systemctl status nginx
- register: nginx_status
- until: nginx_status.rc == 0
- retries: 5
- delay: 10
复制代码
7. 模板和文件操作
7.1 使用template模块
template模块允许您使用Jinja2模板引擎生成动态配置文件。
- - name: 生成Apache配置文件
- template:
- src: templates/httpd.conf.j2
- dest: /etc/httpd/conf/httpd.conf
- owner: root
- group: root
- mode: '0644'
- backup: yes
- notify: 重启Apache
复制代码- # {{ ansible_managed }}
- ServerRoot "/etc/httpd"
- Listen {{ http_port }}
- User apache
- Group apache
- ServerAdmin {{ server_admin }}
- ServerName {{ server_name }}
- DocumentRoot "/var/www/html"
- <Directory "/var/www/html">
- Options Indexes FollowSymLinks
- AllowOverride None
- Require all granted
- </Directory>
- {% if enable_ssl %}
- LoadModule ssl_module modules/mod_ssl.so
- Listen {{ https_port }}
- <VirtualHost *:{{ https_port }}>
- SSLEngine on
- SSLCertificateFile {{ ssl_cert_file }}
- SSLCertificateKeyFile {{ ssl_key_file }}
- </VirtualHost>
- {% endif %}
复制代码
7.2 Jinja2模板高级用法
- {% if ansible_distribution == "CentOS" %}
- # CentOS specific configuration
- SyslogFacility AUTHPRIV
- {% elif ansible_distribution == "Ubuntu" %}
- # Ubuntu specific configuration
- SyslogFacility AUTH
- {% else %}
- # Default configuration
- SyslogFacility AUTH
- {% endif %}
复制代码- # Virtual hosts configuration
- {% for vhost in virtual_hosts %}
- <VirtualHost *:{{ vhost.port }}>
- ServerName {{ vhost.server_name }}
- DocumentRoot {{ vhost.document_root }}
-
- {% if vhost.custom_log is defined %}
- CustomLog {{ vhost.custom_log }} combined
- {% endif %}
-
- {% if vhost.error_log is defined %}
- ErrorLog {{ vhost.error_log }}
- {% endif %}
- </VirtualHost>
- {% endfor %}
复制代码- # 使用过滤器
- ServerAdmin {{ admin_email | default("admin@example.com") }}
- MaxClients {{ max_clients | int }}
- ServerName {{ server_name | lower }}
- DocumentRoot "{{ document_root | quote }}"
复制代码
7.3 行内文件内容
- - name: 在配置文件中添加块
- blockinfile:
- path: /etc/ssh/sshd_config
- block: |
- # Custom SSH settings
- PermitRootLogin no
- PasswordAuthentication no
- AllowUsers {{ allowed_users }}
- marker: "# {mark} ANSIBLE MANAGED BLOCK"
- backup: yes
- notify: 重启SSH服务
复制代码- - name: 确保特定行存在于文件中
- lineinfile:
- path: /etc/selinux/config
- regexp: '^SELINUX='
- line: 'SELINUX=disabled'
- backup: yes
- notify: 重启系统
- - name: 删除文件中的特定行
- lineinfile:
- path: /etc/hosts
- regexp: '^192\.168\.1\.100'
- state: absent
复制代码
8. 错误处理
8.1 忽略错误
- - name: 尝试删除可能不存在的文件
- file:
- path: /tmp/old_config.conf
- state: absent
- ignore_errors: yes
复制代码
8.2 错误处理与恢复
- - name: 尝试执行可能失败的任务
- command: /usr/bin/might_fail
- register: result
- ignore_errors: yes
- - name: 执行失败时的恢复操作
- command: /usr/bin/recover_from_failure
- when: result is failed
复制代码
8.3 使用failed_when控制失败条件
- - name: 检查磁盘空间
- shell: df / | tail -1 | awk '{print $5}' | sed 's/%//'
- register: disk_usage
- failed_when: disk_usage.stdout|int > 90
- changed_when: false
- - name: 显示磁盘使用情况
- debug:
- msg: "磁盘使用率: {{ disk_usage.stdout }}%"
复制代码
8.4 使用rescue和block进行错误处理
- - name: 尝试执行一系列任务,并在失败时执行恢复操作
- block:
- - name: 安装软件包
- yum:
- name: "{{ item }}"
- state: present
- loop:
- - package1
- - package2
- - package3
-
- - name: 配置服务
- template:
- src: service.conf.j2
- dest: /etc/service/service.conf
-
- - name: 启动服务
- service:
- name: myservice
- state: started
- enabled: yes
-
- rescue:
- - name: 记录错误
- debug:
- msg: "安装或配置过程中出现错误,执行回滚操作"
-
- - name: 停止服务(如果已启动)
- service:
- name: myservice
- state: stopped
- ignore_errors: yes
-
- - name: 删除配置文件
- file:
- path: /etc/service/service.conf
- state: absent
- ignore_errors: yes
-
- - name: 卸载软件包
- yum:
- name: "{{ item }}"
- state: absent
- loop:
- - package1
- - package2
- - package3
- ignore_errors: yes
-
- always:
- - name: 发送通知
- debug:
- msg: "任务执行完成,无论成功或失败"
复制代码
9. 角色和包含
9.1 使用include和import
- - name: 包含任务列表
- include_tasks: tasks/setup.yml
- vars:
- package_name: httpd
- - name: 条件包含任务
- include_tasks: "tasks/{{ ansible_os_family }}.yml"
复制代码- - name: 导入任务列表
- import_tasks: tasks/common.yml
- - name: 条件导入任务(在解析时评估)
- import_tasks: tasks/firewall.yml
- when: enable_firewall | bool
复制代码- - name: 包含角色
- include_role:
- name: common
- tasks_from: main.yml
- vars_from: main.yml
- defaults_from: main.yml
- - name: 导入角色
- import_role:
- name: webserver
复制代码
9.2 创建和使用角色
- site.yml
- webservers.yml
- fooservers.yml
- roles/
- common/
- tasks/
- handlers/
- files/
- templates/
- vars/
- defaults/
- meta/
- webservers/
- tasks/
- defaults/
- meta/
复制代码- ---
- - name: 安装Web服务器软件包
- package:
- name: "{{ web_server_package }}"
- state: present
- - name: 创建Web服务器配置目录
- file:
- path: "{{ web_server_config_dir }}"
- state: directory
- owner: root
- group: root
- mode: '0755'
- - name: 生成Web服务器配置文件
- template:
- src: webserver.conf.j2
- dest: "{{ web_server_config_path }}"
- owner: root
- group: root
- mode: '0644'
- notify: 重启Web服务器
- - name: 确保Web服务器正在运行
- service:
- name: "{{ web_server_service }}"
- state: started
- enabled: yes
复制代码- ---
- # 默认变量
- web_server_package: apache2
- web_server_service: apache2
- web_server_config_dir: /etc/apache2
- web_server_config_path: /etc/apache2/apache2.conf
- web_server_port: 80
- web_server_user: www-data
- web_server_group: www-data
复制代码- ---
- - name: 重启Web服务器
- service:
- name: "{{ web_server_service }}"
- state: restarted
- - name: 重新加载Web服务器
- service:
- name: "{{ web_server_service }}"
- state: reloaded
复制代码- ---
- - name: 配置Web服务器
- hosts: webservers
- become: yes
-
- roles:
- - common
- - { role: webservers, web_server_port: 8080 }
- - { role: firewall, when: enable_firewall | bool }
复制代码
10. 最佳实践
10.1 Playbook结构最佳实践
- # 始终在Playbook顶部添加注释,说明用途和作者
- ---
- # 作者: John Doe
- # 描述: 配置Web服务器和数据库服务器
- # 版本: 1.0
- - name: 配置Web服务器
- hosts: webservers
- # ... 其余内容 ...
复制代码- # 不好的做法
- - name: 安装包
- yum:
- name: httpd
- state: present
- # 好的做法
- - name: 安装Apache Web服务器
- yum:
- name: httpd
- state: present
复制代码- ---
- - name: 配置Web服务器
- hosts: webservers
- become: yes
-
- pre_tasks:
- - name: 预检查系统状态
- include_tasks: tasks/pre_check.yml
-
- roles:
- - common
- - webserver
-
- tasks:
- - name: 部署应用程序
- include_tasks: tasks/deploy_app.yml
-
- post_tasks:
- - name: 验证部署
- include_tasks: tasks/verify_deployment.yml
复制代码
10.2 变量管理最佳实践
- # 不好的做法
- - name: 配置数据库连接
- template:
- src: database.conf.j2
- dest: /etc/app/database.conf
- # 好的做法
- - name: 配置数据库连接
- template:
- src: database.conf.j2
- dest: /etc/app/database.conf
- vars:
- db_host: "{{ database_host }}"
- db_port: "{{ database_port }}"
- db_name: "{{ database_name }}"
- db_user: "{{ database_user }}"
- db_pass: "{{ database_password }}"
复制代码- ---
- - name: 配置应用程序
- hosts: app_servers
- vars:
- # 全局变量
- app_version: "2.3.1"
-
- tasks:
- - name: 设置应用程序特定变量
- set_fact:
- app_config_dir: "/etc/app-{{ app_version }}"
-
- - name: 创建配置目录
- file:
- path: "{{ app_config_dir }}"
- state: directory
-
- - name: 生成配置文件
- template:
- src: app.conf.j2
- dest: "{{ app_config_dir }}/app.conf"
- vars:
- # 任务级别变量
- debug_mode: "{{ debug_mode_enabled | default(false) }}"
复制代码
10.3 安全最佳实践
- # 创建加密的变量文件
- ansible-vault create secrets.yml
复制代码- # 在Playbook中使用加密的变量文件
- ---
- - name: 安全部署应用程序
- hosts: app_servers
- vars_files:
- - secrets.yml
-
- tasks:
- - name: 配置数据库连接
- template:
- src: database.conf.j2
- dest: /etc/app/database.conf
- vars:
- db_host: "{{ database_host }}"
- db_port: "{{ database_port }}"
- db_name: "{{ database_name }}"
- db_user: "{{ database_user }}"
- db_pass: "{{ database_password }}" # 此值来自加密的secrets.yml
复制代码- # 不好的做法
- ansible-playbook deploy.yml --extra-vars "db_password=secret123"
- # 好的做法
- ansible-playbook deploy.yml --ask-vault-pass
复制代码
10.4 性能优化最佳实践
- # ansible.cfg
- [defaults]
- gathering = smart
- fact_caching = jsonfile
- fact_caching_connection = /tmp/ansible_facts_cache
- fact_caching_timeout = 86400
复制代码- - name: 执行长时间运行的任务
- command: /usr/bin/long_running_operation
- async: 3600
- poll: 0
- register: long_operation_result
- - name: 等待长时间运行的任务完成
- async_status:
- jid: "{{ long_operation_result.ansible_job_id }}"
- register: job_result
- until: job_result.finished
- retries: 300
- delay: 10
复制代码- ---
- - name: 在多台主机上并行执行任务
- hosts: webservers
- strategy: free
-
- tasks:
- - name: 更新所有软件包
- yum:
- name: "*"
- state: latest
复制代码
10.5 调试和测试最佳实践
- ansible-playbook deploy.yml --check
复制代码- ansible-playbook deploy.yml --check --diff
复制代码- - name: 调试变量值
- debug:
- msg: "数据库主机: {{ database_host }}, 端口: {{ database_port }}"
- - name: 调试复杂变量结构
- debug:
- var: database_config
复制代码- - name: 验证服务是否正在运行
- assert:
- that:
- - "'running' in service_status.status"
- success_msg: "服务正在运行"
- fail_msg: "服务未运行"
复制代码
结论
Ansible Playbook是自动化配置管理的强大工具,掌握其语法和核心技巧对于构建高效、可维护的自动化解决方案至关重要。通过本速查表,您可以快速了解和参考Ansible Playbook的主要语法元素和使用方法,从基础结构到高级技巧,包括变量使用、条件判断、循环、模板、错误处理、角色和最佳实践等方面。
随着您对Ansible的深入了解,您将能够构建更加复杂和强大的自动化解决方案,提高IT基础设施的效率和可靠性。记住,实践是掌握Ansible Playbook的最佳方式,不断尝试和应用这些技巧将帮助您成为Ansible自动化专家。 |
|