Ansible:简易高效的自动化配置管理
第5章:Ansible:简易高效的自动化配置管理
在众多自动化配置管理工具中,Ansible以其简洁的架构、易用的语法和强大的功能脱颖而出,成为现代IT运维领域最受欢迎的工具之一。作为Red Hat旗下的开源项目,Ansible凭借其无代理架构、声明式配置和丰富的模块生态系统,为组织提供了简易高效的自动化配置管理解决方案。
Ansible概述
Ansible是一个开源的自动化引擎,可用于配置管理、应用部署、任务自动化和IT编排。它由Michael DeHaan于2012年创建,2015年被Red Hat收购,现已成为业界领先的自动化工具之一。
核心特性
1. 无代理架构(Agentless)
Ansible采用无代理架构,这是其最重要的特性之一:
# 无代理架构的优势
## 传统有代理架构[管理节点] <---> [代理1] <---> [被管节点1]
[管理节点] <---> [代理2] <---> [被管节点2]
[管理节点] <---> [代理3] <---> [被管节点3]
## Ansible无代理架构[Ansible控制节点] <---> [被管节点1] (SSH)
[Ansible控制节点] <---> [被管节点2] (SSH)
[Ansible控制节点] <---> [被管节点3] (SSH)
无代理架构的优势:
- 简化部署:无需在被管节点安装额外软件
- 降低资源消耗:被管节点无需运行代理进程
- 减少维护成本:无需管理代理软件的更新和维护
- 提高安全性:减少潜在的安全攻击面
2. 声明式配置
Ansible使用声明式配置方式,用户描述期望的系统状态:
# 声明式配置示例
---
- name: Configure Web Server
hosts: webservers
tasks:
- name: Ensure Apache is installed
yum:
name: httpd
state: present
- name: Ensure Apache service is running
service:
name: httpd
state: started
enabled: yes
- name: Deploy configuration file
template:
src: httpd.conf.j2
dest: /etc/httpd/conf/httpd.conf
notify: restart apache3. 幂等性
Ansible的操作具有幂等性,同一配置可以多次执行而不会产生副作用:
# 幂等性示例
def ensure_package_installed(package_name):
"""确保软件包已安装(幂等操作)"""
# Ansible会自动检查包是否已安装
# 如果已安装,则不执行任何操作
# 如果未安装,则执行安装操作
pass架构组件
Ansible的架构相对简单,主要包括以下组件:
1. 控制节点(Control Node)
控制节点是运行Ansible命令的机器:
# 控制节点上运行的Ansible命令
ansible --version
ansible-playbook site.yml
ansible-vault encrypt secret.yml2. 被管节点(Managed Nodes)
被管节点是Ansible管理的目标机器:
# Inventory文件示例
[webservers]
web01.example.com
web02.example.com
[databases]
db01.example.com
db02.example.com
[all:vars]
ansible_user=ansible
ansible_ssh_private_key_file=~/.ssh/ansible_key3. Inventory
Inventory定义了Ansible管理的主机和组:
# YAML格式的Inventory示例
all:
children:
webservers:
hosts:
web01.example.com:
ansible_host: 192.168.1.10
web02.example.com:
ansible_host: 192.168.1.11
vars:
http_port: 80
https_port: 443
databases:
hosts:
db01.example.com:
ansible_host: 192.168.1.20
db02.example.com:
ansible_host: 192.168.1.21
vars:
mysql_port: 33064. Modules
Modules是Ansible执行具体任务的组件:
# Ansible模块示例
def main():
module = AnsibleModule(
argument_spec=dict(
name=dict(required=True, type='str'),
state=dict(default='present', choices=['present', 'absent']),
)
)
name = module.params['name']
state = module.params['state']
# 执行具体操作
if state == 'present':
# 安装软件包
pass
elif state == 'absent':
# 卸载软件包
pass5. Plugins
Plugins扩展Ansible的功能:
# Connection Plugin示例
class Connection:
def __init__(self, play_context, new_stdin):
self.play_context = play_context
self.new_stdin = new_stdin
def connect(self):
# 建立连接
pass
def exec_command(self, cmd):
# 执行命令
pass
def put_file(self, in_path, out_path):
# 传输文件
passAnsible的核心概念
1. Playbooks
Playbooks是Ansible的配置、部署和编排语言:
# 完整的Playbook示例
---
- name: Deploy and configure web application
hosts: webservers
become: yes
vars:
app_name: myapp
app_version: 1.2.3
http_port: 80
pre_tasks:
- name: Update package cache
yum:
name: "*"
state: latest
when: ansible_os_family == "RedHat"
roles:
- common
- webserver
- application
tasks:
- name: Ensure application is running
service:
name: "{{ app_name }}"
state: started
enabled: yes
- name: Wait for application to start
wait_for:
port: "{{ http_port }}"
delay: 10
timeout: 300
post_tasks:
- name: Send notification
mail:
host: localhost
port: 25
to: admin@example.com
subject: "Deployment completed"
body: "Application {{ app_name }} deployed successfully"2. Roles
Roles提供了一种组织Playbook的方式:
# Role结构
roles/
├── common/
│ ├── tasks/
│ │ └── main.yml
│ ├── handlers/
│ │ └── main.yml
│ ├── templates/
│ │ └── ntp.conf.j2
│ ├── files/
│ │ └── banner.txt
│ ├── vars/
│ │ └── main.yml
│ ├── defaults/
│ │ └── main.yml
│ └── meta/
│ └── main.yml# roles/common/tasks/main.yml
---
- name: Install NTP
package:
name: ntp
state: present
- name: Configure NTP
template:
src: ntp.conf.j2
dest: /etc/ntp.conf
notify: restart ntp
- name: Start NTP service
service:
name: ntpd
state: started
enabled: yes3. Variables
Variables提供了一种灵活配置的方式:
# 变量定义和使用
---
- name: Demonstrate variable usage
hosts: all
vars:
# 直接定义变量
app_port: 8080
app_name: "myapp"
vars_files:
# 从文件加载变量
- vars/common.yml
- vars/{{ ansible_os_family }}.yml
vars_prompt:
# 交互式变量输入
- name: "db_password"
prompt: "Enter database password"
private: yes
tasks:
- name: Use variables in tasks
template:
src: app.conf.j2
dest: "/etc/{{ app_name }}/app.conf"
vars:
# 任务级别变量
config_file: "/etc/{{ app_name }}/app.conf"4. Templates
Templates使用Jinja2模板引擎:
{# templates/app.conf.j2 #}
# Application Configuration
application.name={{ app_name }}
application.port={{ app_port }}
application.debug={{ debug_mode | default(false) }}
# Database Configuration
database.host={{ db_host | default('localhost') }}
database.port={{ db_port | default(3306) }}
database.username={{ db_user }}
database.password={{ db_password }}
# Logging Configuration
logging.level={{ log_level | default('INFO') }}
logging.file={{ log_file | default('/var/log/' + app_name + '.log') }}
# Environment-specific settings
{% if ansible_env.DEPLOY_ENV == 'production' %}
performance.cache.enabled=true
performance.cache.ttl=3600
{% else %}
performance.cache.enabled=false
{% endif %}Ansible的生态系统
1. Ansible Galaxy
Ansible Galaxy是官方的Role仓库:
# 使用Ansible Galaxy
# 搜索Role
ansible-galaxy search nginx
# 安装Role
ansible-galaxy install geerlingguy.nginx
# 列出已安装的Role
ansible-galaxy list
# 创建Role框架
ansible-galaxy init myrole2. Ansible Collections
Collections是Ansible 2.9引入的新概念:
# requirements.yml
collections:
- name: community.general
version: ">=1.0.0"
- name: ansible.posix
version: ">=1.1.0"
- name: amazon.aws
version: ">=1.4.0"# 安装Collections
ansible-galaxy collection install -r requirements.yml3. Ansible Tower/AWX
Ansible Tower是Ansible的企业版,提供Web界面和API:
# Ansible Tower API示例
import requests
def launch_job_template(template_id, tower_url, auth_token):
"""启动Job Template"""
url = f"{tower_url}/api/v2/job_templates/{template_id}/launch/"
headers = {
"Authorization": f"Bearer {auth_token}",
"Content-Type": "application/json"
}
response = requests.post(url, headers=headers)
return response.json()Ansible的最佳实践
1. 目录结构
# 推荐的Ansible项目结构
ansible-project/
├── ansible.cfg
├── inventory/
│ ├── production
│ ├── staging
│ └── development
├── group_vars/
│ ├── all.yml
│ ├── webservers.yml
│ └── databases.yml
├── host_vars/
│ └── web01.example.com.yml
├── roles/
│ ├── common/
│ ├── webserver/
│ └── database/
├── playbooks/
│ ├── site.yml
│ ├── webservers.yml
│ └── databases.yml
├── files/
├── templates/
├── vars/
└── README.md2. 配置管理
# ansible.cfg示例
[defaults]
inventory = ./inventory
host_key_checking = False
retry_files_enabled = False
stdout_callback = yaml
bin_ansible_callbacks = True
[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=60s
pipelining = True3. 安全实践
# 使用Ansible Vault保护敏感数据
---
- name: Secure configuration management
hosts: all
vars:
# 加密的变量
db_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
66386439653...
tasks:
- name: Configure database with encrypted password
template:
src: database.conf.j2
dest: /etc/myapp/database.conf
mode: '0600'Ansible的应用场景
1. 基础设施配置
# 基础设施配置示例
---
- name: Configure network infrastructure
hosts: network_devices
connection: network_cli
tasks:
- name: Configure VLANs
ios_vlan:
vlan_id: "{{ item.id }}"
name: "{{ item.name }}"
state: present
loop:
- { id: 10, name: "Web VLAN" }
- { id: 20, name: "DB VLAN" }
- { id: 30, name: "App VLAN" }
- name: Configure interfaces
ios_interface:
name: "{{ item.interface }}"
description: "{{ item.description }}"
enabled: yes
loop:
- { interface: "GigabitEthernet0/1", description: "Web Server Connection" }
- { interface: "GigabitEthernet0/2", description: "Database Connection" }2. 应用部署
# 应用部署示例
---
- name: Deploy web application
hosts: webservers
become: yes
vars:
app_name: myapp
app_version: 1.2.3
deploy_path: /opt/{{ app_name }}
tasks:
- name: Create deployment directory
file:
path: "{{ deploy_path }}"
state: directory
owner: www-data
group: www-data
- name: Download application package
get_url:
url: "https://example.com/{{ app_name }}-{{ app_version }}.tar.gz"
dest: "/tmp/{{ app_name }}-{{ app_version }}.tar.gz"
mode: '0644'
- name: Extract application
unarchive:
src: "/tmp/{{ app_name }}-{{ app_version }}.tar.gz"
dest: "{{ deploy_path }}"
owner: www-data
group: www-data
remote_src: yes
- name: Create symbolic link
file:
src: "{{ deploy_path }}/{{ app_name }}-{{ app_version }}"
dest: "{{ deploy_path }}/current"
state: link
- name: Restart application service
service:
name: "{{ app_name }}"
state: restarted3. 安全加固
# 安全加固示例
---
- name: Security hardening
hosts: all
become: yes
tasks:
- name: Configure SSH security
lineinfile:
path: /etc/ssh/sshd_config
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
backup: yes
loop:
- { regexp: '^#?PermitRootLogin', line: 'PermitRootLogin no' }
- { regexp: '^#?PasswordAuthentication', line: 'PasswordAuthentication no' }
- { regexp: '^#?PubkeyAuthentication', line: 'PubkeyAuthentication yes' }
- { regexp: '^#?Port', line: 'Port 2222' }
notify: restart ssh
- name: Configure firewall
ufw:
rule: allow
port: "{{ item }}"
proto: tcp
loop:
- 2222
- 80
- 443
- name: Enable firewall
ufw:
state: enabled
policy: deny
- name: Install and configure fail2ban
package:
name: fail2ban
state: present
- name: Configure fail2ban
template:
src: jail.local.j2
dest: /etc/fail2ban/jail.local
notify: restart fail2ban
handlers:
- name: restart ssh
service:
name: ssh
state: restarted
- name: restart fail2ban
service:
name: fail2ban
state: restarted本章小结
Ansible以其简洁的架构、易用的语法和强大的功能,成为自动化配置管理领域的佼佼者。其无代理架构、声明式配置、丰富的模块生态系统以及活跃的社区支持,使其在各种规模的组织中都得到了广泛应用。
通过本章的介绍,我们了解了Ansible的核心特性、架构组件、核心概念、生态系统以及最佳实践。在接下来的章节中,我们将深入探讨Ansible的基本概念与架构,帮助您更好地理解和使用这一强大的自动化工具。
