第328集Ansible自动化部署架构实战:批量配置管理、Playbook编排与企业级DevOps解决方案
|字数总计:2.8k|阅读时长:13分钟|阅读量:
Ansible自动化部署架构实战:批量配置管理、Playbook编排与企业级DevOps解决方案
一、Ansible基础
1.1 Ansible简介
Ansible是一个自动化IT工具,用于配置管理、应用部署、任务自动化。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| Ansible核心优势: 无Agent: - 无需在目标服务器安装代理 - 基于SSH通信 - 降低运维复杂度 幂等性: - 重复执行结果一致 - 安全的多次运行 - 简化自动化流程 简单易学: - 基于YAML语法 - 人类可读 - 易于版本控制 模块化: - 丰富的内置模块 - 可扩展插件系统 - 社区支持强大
|
1.2 Ansible架构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| Ansible架构组件: Control Node (控制节点): - 运行Ansible命令 - 管理Playbook和Inventory Managed Nodes (被管理节点): - 目标服务器 - 无需安装Agent Inventory (清单): - 定义管理的主机 - 主机分组和组织 Modules (模块): - 执行具体任务 - copy、file、service等 Playbooks (剧本): - YAML格式的任务集 - 定义配置和部署流程
|
1.3 Ansible安装
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
sudo apt update sudo apt install software-properties-common sudo apt-add-repository --yes --update ppa:ansible/ansible sudo apt install ansible
sudo yum install epel-release sudo yum install ansible
pip3 install ansible
ansible --version
|
二、Inventory管理
2.1 基础Inventory配置
静态Inventory
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
|
[web_servers] web1.example.com ansible_host=192.168.1.10 web2.example.com ansible_host=192.168.1.11 web3.example.com ansible_host=192.168.1.12
[db_servers] db1.example.com ansible_host=192.168.1.20 db2.example.com ansible_host=192.168.1.21
[app_servers] app1.example.com ansible_host=192.168.1.30 app2.example.com ansible_host=192.168.1.31
[production:children] web_servers db_servers app_servers
[web_servers:vars] ansible_user=deploy ansible_ssh_private_key_file=~/.ssh/id_rsa
|
2.2 动态Inventory
基于脚本的动态Inventory
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| #!/bin/bash
echo '{ "web_servers": { "hosts": [ "192.168.1.10", "192.168.1.11", "192.168.1.12" ], "vars": { "ansible_user": "deploy" } } }'
|
使用CMDB的Inventory
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
|
import json import requests
def main(): cmdb_url = "http://cmdb.example.com/api/hosts" response = requests.get(cmdb_url) hosts = response.json() inventory = {} for host in hosts: group = host['group'] if group not in inventory: inventory[group] = {'hosts': [], 'vars': {}} host_entry = f"{host['hostname']}" inventory[group]['hosts'].append(host_entry) print(json.dumps(inventory, indent=2))
if __name__ == "__main__": main()
|
三、Ad-hoc命令
3.1 常用Ad-hoc命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| ansible all -i inventory.ini -m ping
ansible web_servers -i inventory.ini -a "uptime"
ansible all -i inventory.ini -m apt -a "name=nginx state=present" --become
ansible web_servers -i inventory.ini -m systemd -a "name=nginx state=started" --become
ansible web_servers -i inventory.ini -m copy -a "src=/local/file dest=/remote/file"
ansible web_servers -i inventory.ini -m file -a "path=/var/www/html owner=www-data group=www-data mode=755" --become
ansible all -i inventory.ini -m user -a "name=deploy shell=/bin/bash" --become
ansible db_servers -i inventory.ini -m shell -a "mysql -u root -p'password' -e 'SHOW DATABASES;'"
|
3.2 Ad-hoc最佳实践
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| ansible all -i inventory.ini --private-key ~/.ssh/id_rsa -m ping
ansible all -i inventory.ini -f 5 -m ping
ansible all -i inventory.ini -v -a "hostname"
ansible all -i inventory.ini -C -a "rm /tmp/test.txt"
ansible all -i inventory.ini --limit "web_servers" -m ping
|
四、Playbook编写
4.1 基础Playbook
简单Playbook示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| ---
- name: 部署Nginx Web服务器 hosts: web_servers become: yes vars: nginx_version: "1.20" server_names: - example.com - www.example.com tasks: - name: 更新apt缓存 apt: update_cache: yes cache_valid_time: 3600 - name: 安装Nginx apt: name: nginx state: present - name: 创建网站目录 file: path: /var/www/html/{{ server_names[0] }} state: directory owner: www-data group: www-data mode: '0755' - name: 复制网站文件 copy: src: /local/www/ dest: /var/www/html/{{ server_names[0] }}/index.html owner: www-data group: www-data mode: '0644' - name: 配置Nginx虚拟主机 template: src: nginx-site.conf.j2 dest: /etc/nginx/sites-available/{{ server_names[0] }} owner: root group: root mode: '0644' notify: restart nginx - name: 启用虚拟主机 file: src: /etc/nginx/sites-available/{{ server_names[0] }} dest: /etc/nginx/sites-enabled/{{ server_names[0] }} state: link - name: 启动Nginx服务 systemd: name: nginx state: started enabled: yes tags: services handlers: - name: restart nginx systemd: name: nginx state: restarted
|
4.2 循环和条件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| --- - name: 使用循环和条件 hosts: all become: yes tasks: - name: 安装多个软件包 apt: name: "{{ item }}" state: present loop: - nginx - mysql-client - curl - git when: ansible_os_family == "Debian" - name: 在不同系统上安装软件包 package: name: nginx state: present when: ansible_os_family == "RedHat" - name: 创建多个用户 user: name: "{{ item.name }}" groups: "{{ item.groups }}" create_home: yes loop: - { name: "dev1", groups: "developers" } - { name: "dev2", groups: "developers" } - { name: "ops1", groups: "operators" }
|
4.3 变量和模板
变量定义
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| ---
app_name: myapp app_version: "1.0.0" database_host: 192.168.1.20 database_port: 3306
---
nginx_workers: 4 nginx_max_connections: 2048
---
nginx_workers: 8
|
模板文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| # nginx-site.conf.j2 server { listen 80; server_name {% for domain in server_names %}{{ domain }} {% endfor %}; root /var/www/html/{{ server_names[0] }}; index index.html index.htm; access_log /var/log/nginx/{{ server_names[0] }}.access.log; error_log /var/log/nginx/{{ server_names[0] }}.error.log; location / { try_files $uri $uri/ /index.html; } location /static { alias /var/www/html/{{ server_names[0] }}/static; expires 30d; } }
|
五、Roles模块化
5.1 Role结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| --- - name: 安装Nginx apt: name: nginx state: present
- name: 创建配置目录 file: path: /etc/nginx/sites-enabled state: directory
- name: 配置Nginx template: src: nginx.conf.j2 dest: /etc/nginx/nginx.conf notify: restart nginx
- name: 启动Nginx systemd: name: nginx state: started enabled: yes
|
完整Role结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| roles/nginx/ ├── defaults/ │ └── main.yml ├── handlers/ │ └── main.yml ├── meta/ │ └── main.yml ├── tasks/ │ └── main.yml ├── templates/ │ └── nginx.conf.j2 ├── vars/ │ └── main.yml └── tests/ ├── inventory └── test.yml
|
5.2 Role使用
1 2 3 4 5 6 7 8 9 10 11 12 13
| --- - name: Web服务器配置 hosts: web_servers become: yes roles: - role: nginx vars: nginx_workers: 4 - role: php-fpm vars: php_version: "7.4" - role: application
|
5.3 创建Role
1 2 3 4 5 6
| ansible-galaxy init my_role
mkdir -p roles/my_role/{defaults,tasks,handlers,vars,meta,templates} touch roles/my_role/{defaults,tasks,handlers,vars,meta}/main.yml
|
六、常用模块
6.1 文件管理模块
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| - copy: src: /local/file dest: /remote/file owner: user group: group mode: '0644'
- synchronize: src: /local/dir/ dest: /remote/dir/ delete: yes
- file: path: /path/to/file state: touch owner: user group: group mode: '0644'
- file: src: /path/to/file dest: /path/to/link state: link
|
6.2 包管理模块
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| - apt: name: - nginx - mysql-server state: present update_cache: yes
- yum: name: - nginx - mysql-server state: present
- package: name: nginx state: present
|
6.3 服务管理模块
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| - systemd: name: nginx state: started enabled: yes
- systemd: name: nginx state: reloaded
- systemd: name: nginx state: restarted
|
6.4 其他常用模块
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| - shell: "cat /etc/hostname" register: hostname_result
- command: uptime register: uptime_result
- user: name: deploy groups: developers shell: /bin/bash create_home: yes
- group: name: developers state: present
- slurp: src: /etc/hostname register: hostname_file
|
七、企业级部署案例
7.1 完整Web应用部署
site.yml主Playbook
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| ---
- name: 部署Web应用 hosts: web_servers become: yes serial: "50%" roles: - role: base tags: [base, common] - role: nginx nginx_workers: 4 tags: [nginx, web] - role: application app_name: myapp app_version: "{{ app_version }}" tags: [app, deploy] - role: monitoring tags: [monitoring]
- name: 部署数据库 hosts: db_servers become: yes roles: - role: mysql mysql_version: "8.0" mysql_root_password: "{{ vault_mysql_root_password }}" tags: [mysql, database]
|
7.2 滚动更新部署
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| --- - name: 滚动更新应用 hosts: app_servers become: yes serial: 1 max_failure_percentage: 0 vars: app_version: "2.0.0" tasks: - name: 备份当前版本 archive: path: /opt/app/current dest: /opt/app/backup-{{ ansible_date_time.epoch }}.tar.gz - name: 停止应用 systemd: name: myapp state: stopped - name: 部署新版本 copy: src: "app-{{ app_version }}.tar.gz" dest: /opt/app/ notify: extract and deploy - name: 启动应用 systemd: name: myapp state: started - name: 健康检查 uri: url: http://localhost:8080/health status_code: 200 register: health_check until: health_check.status == 200 retries: 5 delay: 10 handlers: - name: extract and deploy unarchive: src: /opt/app/app-{{ app_version }}.tar.gz dest: /opt/app/ notify: set permissions - name: set permissions file: path: /opt/app/current owner: appuser group: appuser recurse: yes
|
7.3 配置管理Playbook
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| --- - name: 配置系统基线 hosts: all become: yes tasks: - name: 更新系统 apt: upgrade: dist update_cache: yes when: ansible_os_family == "Debian" - name: 安装基础软件包 apt: name: - curl - git - htop - vim state: present - name: 配置SSH密钥 authorized_key: user: deploy key: "{{ lookup('file', 'keys/deploy.pub') }}" - name: 配置Sudo copy: src: deploy_sudoers dest: /etc/sudoers.d/deploy mode: '0440' - name: 配置防火墙 ufw: rule: allow name: SSH state: enabled - name: 配置时区 timezone: name: Asia/Shanghai
|
八、Ansible Vault加密
8.1 Vault基础
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| ansible-vault create secrets.yml
ansible-vault edit secrets.yml
ansible-vault view secrets.yml
ansible-vault encrypt secrets.yml
ansible-vault decrypt secrets.yml
ansible-vault rekey secrets.yml
|
8.2 使用Vault变量
1 2 3 4 5 6 7 8 9
| --- db_password: !vault | $ANSIBLE_VAULT;1.1;AES256 623463653462663066303039623539663832363036613737396664336637...
api_key: !vault | $ANSIBLE_VAULT;1.1;AES256 393535663466666133303766663532...
|
在Playbook中使用
1 2 3 4 5 6 7 8 9 10 11
| --- - name: 使用加密变量 hosts: db_servers vars_files: - secrets.yml tasks: - name: 配置数据库 mysql_db: login_user: root login_password: "{{ db_password }}"
|
九、最佳实践
9.1 Playbook最佳实践
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| 最佳实践: 1. 使用Roles组织代码: - 提高代码复用性 - 便于维护和测试 2. 使用标签: - 组织任务 - 选择性执行 3. 使用Handlers: - 服务重启 - 幂等性操作 4. 错误处理: - 使用ignore_errors - 添加rescue块 5. 日志记录: - 使用register - debug模块输出
|
9.2 目录结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| project/ ├── inventory/ │ ├── production │ ├── staging │ └── development ├── group_vars/ │ ├── all.yml │ ├── web_servers.yml │ └── db_servers.yml ├── host_vars/ │ ├── host1.yml │ └── host2.yml ├── roles/ │ ├── nginx/ │ ├── mysql/ │ └── application/ ├── playbooks/ │ ├── site.yml │ ├── deploy.yml │ └── configure.yml └── ansible.cfg
|
9.3 ansible.cfg配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| [defaults] inventory = inventory/production remote_user = deploy host_key_checking = False retry_files_enabled = False gathering = smart fact_caching = jsonfile fact_caching_connection = /tmp/ansible_facts timeout = 30 forks = 10
[privilege_escalation] become = True become_method = sudo become_user = root become_ask_pass = False
[ssh_connection] ssh_args = -o ControlMaster=auto -o ControlPersist=300s pipelining = True
|
十、故障排查
10.1 常见问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| ansible all -i inventory.ini -m ping
ansible-playbook --syntax-check playbook.yml
ansible-playbook --check playbook.yml
ansible-playbook -vvv playbook.yml
ansible-playbook --step playbook.yml
ansible-playbook --tags "nginx" playbook.yml
|
10.2 调试技巧
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| - name: 调试变量 debug: var: hostname_result
- name: 调试消息 debug: msg: "主机名是 {{ hostname_result.stdout }}"
- name: 暂停检查 pause: prompt: "请检查配置,按Enter继续"
- name: 验证条件 assert: that: - app_status == "running" fail_msg: "应用未运行" success_msg: "应用运行正常"
|
十一、总结
Ansible是强大的自动化工具。本文涵盖了:
核心要点
- 基础概念:Inventory、Modules、Playbooks、Roles
- Playbook编写:任务定义、循环条件、变量模板
- Roles模块化:代码组织、复用维护
- 企业级实践:滚动更新、配置管理、安全加密
技术要点
- Inventory管理:静态/动态清单配置
- Playbook:任务编排与流程控制
- Roles:模块化与代码组织
- Vault:敏感信息加密
实践建议
- 使用Roles提高代码复用性
- 利用Vault管理敏感信息
- 实施分阶段发布与自动化测试
- 设定明确变量与行内说明
- 通过Git控制版本并跟踪变更
通过Ansible可实现高效、可复用的自动化运维和部署。