引言:虚拟化环境管理的挑战与机遇
在现代IT基础设施管理中,VMware作为企业级虚拟化平台的领导者,承载着大量关键业务系统。然而,传统的手动虚拟机配置方式正面临着严峻挑战:配置过程繁琐耗时、环境一致性难以保证、人为错误频发、运维效率低下。这些问题不仅增加了运营成本,还严重影响了业务的敏捷性和可靠性。
Ansible作为一款强大的自动化工具,以其无代理(Agentless)、简单易用、功能丰富的特点,成为解决这些痛点的理想选择。通过Ansible与VMware的深度集成,我们可以实现从虚拟机创建、配置到应用部署的全流程自动化,彻底解决配置繁琐和环境不一致的问题。
一、Ansible与VMware集成基础
1.1 核心概念与工作原理
Ansible通过VMware的vSphere API与ESXi主机或vCenter Server进行通信,实现对虚拟机的全生命周期管理。其工作原理基于以下核心组件:
Inventory(清单)
:定义目标VMware环境中的主机和虚拟机
Modules(模块)
:封装具体操作的代码单元,如
vmware_guest
用于虚拟机管理
Playbook(剧本)
:YAML格式的任务编排文件,定义自动化流程
Connection Plugin(连接插件)
:处理与VMware API的通信细节
1.2 环境准备与依赖安装
在开始之前,需要确保满足以下前提条件:
# 1. 安装Ansible(推荐使用Python虚拟环境)
python3 -m venv ansible-vmware
source ansible-vmware/bin/activate
pip install ansible
# 2. 安装VMware集成依赖包
pip install pyvmomi # VMware vSphere Python SDK
pip install requests # HTTP请求库
# 3. 验证Ansible版本
ansible –version
# 预期输出:ansible 2.9+ 或 ansible-core 2.11+
# 4. 安装社区VMware集合(Ansible 2.9+)
ansible-galaxy collection install community.vmware
1.3 VMware连接配置
建立与VMware环境的安全连接是自动化成功的关键:
# 文件:ansible.cfg
[defaults]
inventory = ./inventory
host_key_checking = False
private_key_file = ~/.ssh/id_rsa
[privilege_escalation]
become = True
become_method = sudo
becorme_user = root
# VMware连接参数配置
[vmware]
vcenter_hostname = vcenter.company.com
vcenter_username = administrator@vsphere.local
vcenter_password = YourSecurePassword
validate_certs = False # 生产环境应设为True并配置证书
二、构建VMware清单(Inventory)
2.1 静态清单配置
对于小型环境,可以使用静态清单文件:
# 文件:inventory/hosts.yml
all:
children:
vmware_vcenter:
hosts:
vcenter.company.com:
ansible_user: root
ansible_ssh_private_key_file: ~/.ssh/id_rsa
vmware_esxi:
hosts:
esxi01.company.com:
ansible_user: root
ansible_ssh_private_key_file: ~/.ssh/id_rsa
esxi02.company.com:
ansible_user: root
ansible_community_datastore: True
2.2 动态清单配置(推荐)
对于大规模环境,使用动态清单自动发现VMware资源:
# 文件:inventory/vmware_inventory.py
#!/usr/bin/env python3
# 需要安装:pip install pyvmomi
import json
import argparse
from pyVim.connect import SmartConnect, Disconnect
from pyVmomi import vim
def get_vmware_inventory(vcenter, username, password):
# 连接vCenter
si = SmartConnect(host=vcenter, user=username, pwd=password, disableSslCertValidation=True)
content = si.RetrieveContent()
inventory = {‘_meta’: {‘hostvars’: {}}}
vms = []
# 遍历所有虚拟机
for child in content.rootFolder.childEntity:
if isinstance(child, vim.VirtualApp):
for vm in child.vm:
vms.append(vm)
elif hasattr(child, ‘vmFolder’):
for vm in child.vmFolder.childEntity:
if isinstance(vm, vim.VirtualMachine):
vms.append(vm)
# 构建清单
for vm in vms:
vm_name = vm.summary.config.name
vms.append(vm_name)
inventory[‘_meta’][‘hostvars’][vm_name] = {
‘ansible_host’: vm_name,
‘vmware_guest_id’: vm.summary.config.instanceUuid,
‘vmware_datastore’: vm.summary.config.datastoreUrl[0],
‘vmware_tools_version’: vm.summary.guest.toolsVersion
}
inventory[‘vmware_vms’] = {‘hosts’: vms}
return inventory
if __name__ == ‘__main__’:
parser = argparse.ArgumentParser()
parser.add_argument(‘–vcenter’, required=True)
parser.add_argument(‘–username’, required=True)
parser.add_argument(‘–password’, required=True)
args = parser.parse_args()
inventory = get_vmware_inventory(args.vcenter, args.username, args.password)
print(json.dumps(inventory, indent=2))
# 使用动态清单
chmod +x inventory/vmware_inventory.py
ansible-inventory -i inventory/vmware_inventory.py –list
三、虚拟机生命周期管理自动化
3.1 创建虚拟机(vmware_guest模块)
使用
vmware_guest
模块实现虚拟机创建的标准化:
# 文件:playbooks/create_vm.yml
—
– name: 创建标准化虚拟机
hosts: localhost
gather_facts: false
vars:
vcenter_hostname: “vcenter.company.com”
vcenter_username: “administrator@vsphere.local”
vcenter_password: “YourSecurePassword”
validate_certs: false
tasks:
– name: 创建基础虚拟机
community.vmware.vmware_guest:
hostname: “{{ vcenter_hostname }}”
username: “{{ vcenter_username }}”
password: “{{ vcenter_password }}”
validate_certs: “{{ validate_certs }}”
name: “{{ vm_name }}”
guest_id: “ubuntu64Guest”
datacenter: “DC01”
folder: “/DC01/vm/Production”
cluster: “Cluster01”
resource_pool: “RP01”
hardware:
memory_mb: 4096
num_cpus: 4
scsi: “paravirtual”
disk:
– size_gb: 50
type: “thin”
datastore: “DS01”
networks:
– name: “VM Network”
type: “dhcp”
state: poweredon
wait_for_ip_address: true
register: vm_creation_result
– name: 等待虚拟机就绪
wait_for:
host: “{{ vm_creation_result.instance.ipv4 }}”
port: 22
delay: 30
timeout: 600
when: vm_creation_result.instance.ipv4 is defined
– name: 输出虚拟机信息
debug:
msg: “虚拟机 {{ vm_name }} 创建成功,IP: {{ vm_creation_result.instance.ipv4 }}”
执行命令:
ansible-playbook playbooks/create_vm.yml -e “vm_name=web-server-01”
3.2 虚拟机配置管理
创建完成后,使用Ansible进行精细化配置:
# 文件:playbooks/configure_vm.yml
—
– name: 配置虚拟机基础环境
hosts: “{{ target_vm }}”
gather_facts: true
vars:
# 通过变量注入目标VM信息
ansible_host: “{{ vm_ip }}”
ansible_user: root
ansible_ssh_private_key_file: ~/.ssh/id_rsa
tasks:
– name: 更新系统包
apt:
update_cache: yes
upgrade: dist
when: ansible_os_family == “Debian”
– name: 安装基础工具
package:
name:
– vim
– curl
– wget
– net-tools
– htop
state: present
– name: 配置静态IP(可选)
template:
src: templates/netplan.yaml.j2
dest: /etc/netplan/01-netcfg.yaml
mode: ‘0644’
when: ansible_os_family == “Debian”
notify: apply_netplan
– name: 配置主机名
hostname:
name: “{{ vm_name }}”
– name: 配置NTP服务
package:
name: chrony
state: present
– name: 启动并启用NTP
systemd:
name: chronyd
enabled: yes
state: started
– name: 配置防火墙
ufw:
rule: allow
port: “{{ item }}”
loop:
– 22
– 80
– 443
handlers:
– name: apply_netplan
command: netplan apply
3.3 快照管理
# 文件:playbooks/snapshot_management.yml
—
– name: 虚拟机快照管理
hosts: localhost
gather_facts: false
vars:
vcenter_hostname: “vcenter.company.com”
vcenter_username: “administrator@vsphere.local”
vcenter_password: “YourSecurePassword”
tasks:
– name: 创建快照(应用更新前)
community.vmware.vmware_guest_snapshot:
hostname: “{{ vcenter_hostname }}”
username: “{{ vcenter_username }}”
password: “{{ vcenter_password }}”
name: “{{ vm_name }}”
state: present
snapshot_name: “pre-update-{{ ansible_date_time.date }}”
description: “应用更新前的快照”
memory: yes
quiesce: yes
when: snapshot_action == “create”
– name: 恢复到快照
community.vmware.vmware_guest_snapshot:
hostname: “{{ vcenter_hostname }}”
username: “{{ vcenter_username }}”
password: “{{ vcenter_password }}”
name: “{{ vm_name }}”
state: revert
snapshot_name: “{{ snapshot_name }}”
when: snapshot_action == “revert”
– name: 删除旧快照(保留最近5个)
community.vmware.vmware_guest_snapshot:
hostname: “{{ vcenter_hostname }}”
username: “{{ vcenter_username }}”
password: “{{ vcenter_password }}”
name: “{{ vm_name }}”
state: absent
snapshot_name: “{{ item }}”
loop: “{{ existing_snapshots | sort | reverse | list[5:] }}”
when: snapshot_action == “cleanup”
四、解决环境不一致问题
4.1 基础镜像标准化(Golden Image)
创建标准化的虚拟机模板是解决环境不一致的关键:
# 文件:playbooks/create_template.yml
—
– name: 创建标准化模板
hosts: localhost
gather_facts: false
vars:
vcenter_hostname: “vcenter.company.com”
vcenter_username: “administrator@vsphere.local”
vcenter_password: “YourSecurePassword”
template_name: “ubuntu-20.04-template-v1.2”
tasks:
# 步骤1:创建临时虚拟机
– name: 创建临时虚拟机用于模板制作
community.vmware.vmware_guest:
hostname: “{{ vcenter_hostname }}”
username: “{{ vcenter_username }}”
password: “{{ vcenter_password }}”
name: “temp-template-vm”
guest_id: “ubuntu64Guest”
datacenter: “DC01”
folder: “/DC01/vm/Templates”
cluster: “Cluster01”
hardware:
memory_mb: 2048
num_cpus: 2
disk:
– size_gb: 40
type: “thin”
datastore: “DS01”
networks:
– name: “VM Network”
type: “dhcp”
state: poweredon
wait_for_ip_address: true
register: temp_vm
# 步骤2:配置临时虚拟机
– name: 等待虚拟机就绪
wait_for:
host: “{{ temp_vm.instance.ipv4 }}”
port: 22
delay: 30
timeout: 600
– name: 配置临时虚拟机(安装基础软件)
hosts: “{{ temp_vm.instance.ipv4 }}”
gather_facts: true
vars:
ansible_host: “{{ temp_vm.instance.ipv4 }}”
ansible_user: root
ansible_ssh_private_key_file: ~/.ssh/id_rsa
tasks:
– name: 更新系统
apt:
update_cache: yes
upgrade: dist
– name: 安装基础软件
package:
name:
– openssh-server
– python3
– cloud-init
– vim
– curl
– net-tools
state: present
– name: 清理临时文件
shell: |
apt-get clean
rm -rf /var/lib/apt/lists/*
rm -rf /tmp/*
rm -rf /var/tmp/*
– name: 清理SSH主机密钥
shell: rm -f /etc/ssh/ssh_host_*_key*
– name: 停止虚拟机
command: shutdown -h now
async: 0
poll: 0
ignore_errors: yes
# 步骤3:转换为模板
– name: 将虚拟机转换为模板
community.vmware.vmware_guest:
hostname: “{{ vcenter_hostname }}”
username: “{{ vcenter_username }}”
password: “{{ vcenter_password }}”
name: “temp-template-vm”
state: poweredoff
convert_to_template: true
when: temp_vm.changed
– name: 重命名模板
community.vmware.vmware_guest:
hostname: “{{ vcenter_hostname }}”
username: “{{ vcenter_username }}”
password: “{{ vcenter_password }}”
name: “temp-template-vm”
new_name: “{{ template_name }}”
when: temp_vm.changed
– name: 清理临时虚拟机(如果转换失败)
community.vmware.vmware_guest:
hostname: “{{ vcenter_hostname }}”
username: “{{ vcenter_username }}”
password: “{{ vcenter_password }}”
name: “temp-template-vm”
state: absent
force: true
when: not temp_vm.changed
4.2 使用模板批量部署
# 文件:playbooks/deploy_from_template.yml
—
– name: 从模板批量部署虚拟机
hosts: localhost
gather_facts: false
vars:
vcenter_hostname: “vcenter.company.com”
vcenter_username: “administrator@vsphere.local”
vcenter_password: “YourSecurePassword”
template_name: “ubuntu-20.04-template-v1.2”
deployment_plan:
– name: web-01
ip: 192.168.1.101
cpu: 4
memory: 8192
– name: web-02
ip: 192.168.1.102
cpu: 4
memory: 8192
– name: db-01
ip: 192.168.1.201
cpu: 8
memory: 16384
tasks:
– name: 从模板部署虚拟机
community.vmware.vmware_guest:
hostname: “{{ vcenter_hostname }}”
username: “{{ vcenter_username }}”
password: “{{ vcenter_password }}”
name: “{{ item.name }}”
template: “{{ template_name }}”
datacenter: “DC01”
folder: “/DC01/vm/Production”
cluster: “Cluster01”
hardware:
memory_mb: “{{ item.memory }}”
num_cpus: “{{ item.cpu }}”
networks:
– name: “VM Network”
ip: “{{ item.ip }}”
netmask: “255.255.255.0”
gateway: “192.168.1.1”
dns_servers:
– “8.8.8.8”
– “8.8.4.4”
state: poweredon
wait_for_ip_address: true
loop: “{{ deployment_plan }}”
register: deployment_results
– name: 等待所有虚拟机SSH就绪
wait_for:
host: “{{ item.instance.ipv4 }}”
port: 22
delay: 30
timeout: 600
loop: “{{ deployment_results.results }}”
when: item.instance.ipv4 is defined
– name: 执行后续配置
include_tasks: configure_vm.yml
vars:
target_vm: “{{ item.item.name }}”
vm_ip: “{{ item.instance.ipv4 }}”
loop: “{{ deployment_results.results }}”
when: item.instance.ipv4 is defined
4.3 配置漂移检测与修复
# 文件:playbooks/config_drift_detection.yml
—
– name: 检测和修复配置漂移
hosts: all
gather_facts: true
vars:
# 定义期望的配置状态
expected_packages:
– openssh-server
– vim
– curl
expected_services:
– sshd
– chronyd
expected_files:
– path: /etc/ssh/sshd_config
mode: “0600”
owner: root
group: root
– path: /etc/hosts
content: |
127.0.0.1 localhost
192.168.1.100 {{ inventory_hostname }}
tasks:
– name: 检测缺失的软件包
package:
name: “{{ item }}”
state: present
loop: “{{ expected_packages }}”
register: package_check
– name: 检测并修复服务状态
systemd:
name: “{{ item }}”
enabled: yes
state: started
loop: “{{ expected_services }}”
register: service_check
– name: 检测并修复文件配置
copy:
src: “files/{{ item.path | basename }}”
dest: “{{ item.path }}”
mode: “{{ item.mode }}”
owner: “{{ item.owner }}”
group: “{{ item.group }}”
loop: “{{ expected_files }}”
when: item.content is not defined
register: file_check
– name: 检测文件内容
copy:
content: “{{ item.content }}”
dest: “{{ item.path }}”
mode: “{{ item.mode }}”
owner: “{{ item.owner }}”
group: “{{ item.group }}”
loop: “{{ expected_files }}”
when: item.content is defined
register: content_check
– name: 生成配置漂移报告
copy:
content: |
配置漂移检测报告
==================
检测时间: {{ ansible_date_time.iso8601 }}
主机: {{ inventory_hostname }}
修复的软件包: {{ package_check.results | selectattr(‘changed’, ‘equalto’, true) | map(attribute=’item’) | list }}
修复的服务: {{ service_check.results | selectattr(‘changed’, ‘equalto’, true) | map(attribute=’item’) | list }}
修复的文件: {{ file_check.results | selectattr(‘changed’, ‘equalto’, true) | map(attribute=’item’) | list }}
修复的内容: {{ content_check.results | selectattr(‘changed’, ‘equalto’, true) | map(attribute=’item’) | list }}
总修复项: {{ (package_check.results | selectattr(‘changed’, ‘equalto’, true) | list + service_check.results | selectattr(‘changed’, ‘equalto’, true) | list + file_check.results | selectattr(‘changed’, ‘equalto’, true) | list + content_check.results | selectattr(‘changed’, ‘equalto’, true) | list) | length }}
dest: “/var/log/config-drift-report-{{ ansible_date_time.date }}.log”
mode: ‘0644’
delegate_to: localhost
五、高级自动化场景
5.1 网络配置自动化
# 文件:playbooks/network_configuration.yml
—
– name: 自动化网络配置
hosts: localhost
gather_facts: false
vars:
vcenter_hostname: “vcenter.company.com”
vcenter_username: “administrator@vsphere.local”
vcenter_password: “YourSecurePassword”
network_plan:
– name: “VM Network”
type: “standard”
vswitch: “vSwitch0”
vlan: 0
– name: “VM Network VLAN10”
type: “standard”
vswitch: “vSwitch0”
vlan: 10
– name: “VM Network VLAN20”
type: “standard”
vswitch: “vSwitch0”
vlan: 20
tasks:
– name: 创建标准端口组
community.vmware.vmware_portgroup:
hostname: “{{ vcenter_hostname }}”
username: “{{ vcenter_username }}”
password: “{{ vcenter_password }}”
switch_name: “{{ item.vswitch }}”
portgroup_name: “{{ item.name }}”
vlan_id: “{{ item.vlan }}”
security:
promiscuous_mode: false
forged_transmits: false
mac_changes: false
teaming_policy:
load_balance_policy: “loadbalance_srcid”
network_failure_detection: “link_status_only”
loop: “{{ network_plan }}”
delegate_to: localhost
– name: 配置虚拟机网络适配器
community.vmware.vmware_guest_network:
hostname: “{{ vcenter_hostname }}”
username: “{{ vcenter_username }}”
password: “{{ vcenter_password }}”
name: “{{ vm_name }}”
networks:
– name: “{{ network_name }}”
type: “static”
ip: “{{ ip_address }}”
netmask: “255.255.255.0”
gateway: “192.168.1.1”
dns_servers:
– “8.8.8.8”
– “8.8.4.4”
state: present
delegate_to: localhost
5.2 存储配置自动化
# 文件:playbooks/storage_configuration.yml
—
– name: 自动化存储配置
hosts: localhost
gather_facts: false
vars:
vcenter_hostname: “vcenter.company.com”
vcenter_username: “administrator@vsphere.local”
vcenter_password: “YourSecurePassword”
tasks:
– name: 添加NFS数据存储
community.vmware.vmware_datastore_nfs:
hostname: “{{ vcenter_hostname }}”
username: “{{ vcenter_username }}”
password: “{{ vcenter_password }}”
datastore_name: “{{ nfs_datastore_name }}”
nfs_server: “{{ nfs_server_ip }}”
nfs_path: “{{ nfs_export_path }}”
nfs_version: “{{ nfs_version }}”
esxi_hostname: “{{ esxi_host }}”
delegate_to: localhost
– name: 添加iSCSI数据存储
community.vmware.vmware_datastore_iSCSI:
hostname: “{{ vcenter_hostname }}”
username: “{{ vcenter_username }}”
password: “{{ vcenter_password }}”
datastore_name: “{{ iscsi_datastore_name }}”
iscsi_server: “{{ iscsi_server_ip }}”
iscsi_target: “{{ iscsi_target_name }}”
iscsi_port: “{{ iscsi_port }}”
esxi_hostname: “{{ esxi_host }}”
delegate_to: localhost
– name: 扩展虚拟机磁盘
community.vmware.vmware_guest_disk:
hostname: “{{ vcenter_hostname }}”
username: “{{ vcenter_username }}”
password: “{{ vcenter_password }}”
name: “{{ vm_name }}”
disk:
– size: “{{ new_disk_size }}”
type: “thin”
datastore: “{{ datastore_name }}”
state: present
delegate_to: localhost
5.3 集群与资源池管理
# 文件:playbooks/cluster_configuration.yml
—
– name: 自动化集群配置
hosts: localhost
gather_facts: false
vars:
vcenter_hostname: “vcenter.company.com”
vcenter_username: “administrator@vsphere.local”
vcenter_password: “YourSecurePassword”
tasks:
– name: 创建资源池
community.vmware.vmware_resource_pool:
hostname: “{{ vcenter_hostname }}”
username: “{{ vcenter_username }}”
password: “{{ vcenter_password }}”
datacenter: “DC01”
cluster: “Cluster01”
resource_pool: “Production-RP”
cpu_shares: “high”
cpu_limit: -1
cpu_reservation: 0
mem_shares: “high”
mem_limit: -1
mem_reservation: 0
state: present
delegate_to: localhost
– name: 配置DRS规则
community.vmware.vmware_cluster_drs:
hostname: “{{ vcenter_hostname }}”
username: “{{ vcenter_username }}”
password: “{{ vcenter_password }}”
datacenter: “DC01”
cluster: “Cluster01”
drs_enabled: true
drs_default_vm_behavior: “fullyAutomated”
drs_vmotion_rate: 3
advanced_settings:
“TryBalanceVmsPerHost”: “1”
delegate_to: localhost
– name: 配置HA设置
community.vmware.vmware_cluster_ha:
hostname: “{{ vcenter_hostname }}”
username: “{{ vcenter_username }}”
password: “{{ vcenter_password }}”
datacenter: “DC01”
cluster: “Cluster01”
ha_enabled: true
ha_host_failure_response: “restart”
ha_vm_failure_interval: 30
ha_vm_min_up_time: 120
ha_vm_max_failures: 3
advanced_settings:
“das.failuredetectiontime”: “30000”
delegate_to: localhost
六、角色与最佳实践
6.1 创建可重用角色
# 创建角色目录结构
ansible-galaxy init roles/vmware_base_config
# 文件:roles/vmware_base_config/defaults/main.yml
—
# 默认变量
vmware_vcenter: “vcenter.company.com”
vmware_username: “administrator@vsphere.local”
vmware_password: “YourSecurePassword”
vmware_datacenter: “DC01”
vmware_cluster: “Cluster01”
vmware_folder: “/DC01/vm/Production”
# 虚拟机配置默认值
vm_memory: 4096
vm_cpu: 2
vm_disk_size: 50
vm_guest_id: “ubuntu64Guest”
vm_network: “VM Network”
vm_datastore: “DS01”
# 文件:roles/vmware_base_config/tasks/main.yml
—
– name: 确保虚拟机存在
community.vmware.vmware_guest:
hostname: “{{ vmware_vcenter }}”
username: “{{ vmware_username }}”
password: “{{ vmware_password }}”
name: “{{ vm_name }}”
guest_id: “{{ vm_guest_id }}”
datacenter: “{{ vmware_datacenter }}”
folder: “{{ vmware_folder }}”
cluster: “{{ vmware_cluster }}”
hardware:
memory_mb: “{{ vm_memory }}”
num_cpus: “{{ vm_cpu }}”
disk:
– size_gb: “{{ vm_disk_size }}”
type: “thin”
datastore: “{{ vm_datastore }}”
networks:
– name: “{{ vm_network }}”
type: “dhcp”
state: present
register: vm_result
– name: 等待虚拟机就绪
wait_for:
host: “{{ vm_result.instance.ipv4 }}”
port: 22
delay: 30
timeout: 600
when: vm_result.instance.ipv4 is defined
– name: 应用基础配置
include_tasks: base_config.yml
vars:
target_host: “{{ vm_result.instance.ipv4 }}”
when: vm_result.instance.ipv4 is defined
# 文件:roles/vmware_base_config/tasks/base_config.yml
—
– name: 更新系统
apt:
update_cache: yes
upgrade: dist
delegate_to: “{{ target_host }}”
– name: 安装基础软件
package:
name:
– openssh-server
– python3
– vim
– curl
state: present
delegate_to: “{{ target_host }}”
– name: 配置SSH
template:
src: sshd_config.j2
dest: /etc/ssh/sshd_config
mode: ‘0644’
delegate_to: “{{ target_host }}”
notify: restart_ssh
handlers:
– name: restart_ssh
systemd:
name: sshd
state: restarted
delegate_to: “{{ target_host }}”
6.2 使用Ansible Vault保护敏感数据
# 创建加密文件
ansible-vault create group_vars/vmware_secrets.yml
# 文件:group_vars/vmware_secrets.yml(加密后内容)
vmware_password: “YourSecurePassword”
vmware_api_token: “your-api-token”
ssh_private_key: |
—–BEGIN RSA PRIVATE KEY—–
…
—–END RSA PRIVATE KEY—–
6.3 完整的部署工作流
# 文件:playbooks/full_deployment_workflow.yml
—
– name: 完整的VMware自动化部署工作流
hosts: localhost
gather_facts: false
vars_files:
– group_vars/vmware_secrets.yml
vars:
deployment_name: “web-cluster-01”
vm_count: 3
vm_prefix: “web”
vm_template: “ubuntu-20.04-template-v1.2”
tasks:
# 阶段1:环境验证
– name: 验证vCenter连接
community.vmware.vmware_about_info:
hostname: “{{ vcenter_hostname }}”
username: “{{ vcenter_username }}”
password: “{{ vmware_password }}”
register: vcenter_info
delegate_to: localhost
– name: 验证模板存在
community.vmware.vmware_guest_facts:
hostname: “{{ vcenter_hostname }}”
username: “{{ vcenter_username }}”
password: “{{ vmware_password }}”
datacenter: “{{ vmware_datacenter }}”
name: “{{ vm_template }}”
register: template_facts
delegate_to: localhost
– name: 失败如果模板不存在
fail:
msg: “模板 {{ vm_template }} 不存在”
when: not template_facts.instance
# 阶段2:批量创建虚拟机
– name: 批量创建虚拟机
community.vmware.vmware_guest:
hostname: “{{ vcenter_hostname }}”
username: “{{ vcenter_username }}”
password: “{{ vmware_password }}”
name: “{{ vm_prefix }}-{{ ‘%02d’ | format(item) }}”
template: “{{ vm_template }}”
datacenter: “{{ vmware_datacenter }}”
folder: “{{ vmware_folder }}”
cluster: “{{ vmware_cluster }}”
hardware:
memory_mb: “{{ vm_memory }}”
num_cpus: “{{ vm_cpu }}”
disk:
– size_gb: “{{ vm_disk_size }}”
type: “thin”
datastore: “{{ vm_datastore }}”
networks:
– name: “{{ vm_network }}”
type: “dhcp”
state: poweredon
wait_for_ip_address: true
loop: “{{ range(1, vm_count + 1) | list }}”
register: vm_creation_results
delegate_to: localhost
# 阶段3:等待所有虚拟机就绪
– name: 等待所有虚拟机SSH就绪
wait_for:
host: “{{ item.instance.ipv4 }}”
port: 22
delay: 30
timeout: 600
loop: “{{ vm_creation_results.results }}”
when: item.instance.ipv4 is defined
delegate_to: localhost
# 阶段4:应用配置
– name: 应用基础配置
include_role:
name: vmware_base_config
vars:
vm_name: “{{ item.item.name }}”
target_host: “{{ item.instance.ipv4 }}”
loop: “{{ vm_creation_results.results }}”
when: item.instance.ipv4 is defined
delegate_to: localhost
# 阶段5:应用特定角色
– name: 应用Web服务器配置
include_role:
name: web_server_config
vars:
target_host: “{{ item.instance.ipv4 }}”
loop: “{{ vm_creation_results.results }}”
when:
– item.instance.ipv4 is defined
– “‘web’ in item.item.name”
– name: 应用数据库配置
include_role:
name: db_server_config
vars:
target_host: “{{ item.instance.ipv4 }}”
loop: “{{ vm_creation_results.results }}”
when:
– item.instance.ipv4 is defined
– “‘db’ in item.item.name”
# 阶段6:验证与报告
– name: 生成部署报告
copy:
content: |
VMware Deployment Report
========================
Deployment Name: {{ deployment_name }}
Date: {{ ansible_date_time.iso8601 }}
Created VMs:
{% for result in vm_creation_results.results %}
– {{ result.item.name }}: {{ result.instance.ipv4 | default(‘N/A’) }}
{% endfor %}
Status: {{ ‘SUCCESS’ if vm_creation_results.results | selectattr(‘changed’, ‘equalto’, true) | list | length == vm_count else ‘PARTIAL’ }}
dest: “reports/{{ deployment_name }}-{{ ansible_date_time.date }}.log”
mode: ‘0644’
delegate_to: localhost
七、监控与日志
7.1 集成监控系统
# 文件:playbooks/monitoring_integration.yml
—
– name: 集成监控系统
hosts: all
gather_facts: true
vars:
monitoring_server: “monitoring.company.com”
monitoring_api_key: “{{ vault_monitoring_api_key }}”
tasks:
– name: 安装Prometheus节点导出器
package:
name: prometheus-node-exporter
state: present
delegate_to: “{{ target_host }}”
– name: 配置节点导出器
template:
src: node_exporter.service.j2
dest: /etc/systemd/system/node_exporter.service
mode: ‘0644’
delegate_to: “{{ target_host }}”
notify: restart_node_exporter
– name: 启动节点导出器
systemd:
name: node_exporter
enabled: yes
state: started
delegate_to: “{{ target_host }}”
– name: 注册到监控系统
uri:
url: “http://{{ monitoring_server }}/api/v1/register”
method: POST
headers:
Authorization: “Bearer {{ monitoring_api_key }}”
body_format: json
body:
hostname: “{{ inventory_hostname }}”
ip: “{{ ansible_host }}”
labels:
environment: “{{ env }}”
role: “{{ role }}”
delegate_to: localhost
ignore_errors: yes
handlers:
– name: restart_node_exporter
systemd:
name: node_exporter
state: restarted
delegate_to: “{{ target_host }}”
7.2 日志收集配置
# 文件:playbooks/logging_configuration.yml
—
– name: 配置日志收集
hosts: all
gather_facts: true
vars:
logstash_server: “logstash.company.com:5044”
tasks:
– name: 安装Filebeat
package:
name: filebeat
state: present
– name: 配置Filebeat
template:
src: filebeat.yml.j2
dest: /etc/filebeat/filebeat.yml
mode: ‘0644’
notify: restart_filebeat
– name: 启用Filebeat系统模块
command: filebeat modules enable system
notify: restart_filebeat
– name: 启动Filebeat
systemd:
name: filebeat
enabled: yes
state: started
handlers:
– name: restart_filebeat
systemd:
name: filebeat
state: restarted
八、故障排查与最佳实践
8.1 常见问题解决方案
问题1:连接超时
# 检查网络连通性
ping vcenter.company.com
telnet vcenter.company.com 443
# 增加超时时间
ansible-playbook playbook.yml -e “ansible_timeout=600”
问题2:权限不足
# 在playbook中明确指定become
– name: 需要root权限的任务
become: yes
become_method: sudo
become_user: root
command: whoami
问题3:证书验证失败
# 临时禁用证书验证(仅开发环境)
community.vmware.vmware_guest:
validate_certs: false
8.2 性能优化建议
使用异步任务
:对于长时间运行的操作
– name: 异步创建虚拟机
community.vmware.vmware_guest:
# … 参数
async: 1800 # 30分钟超时
poll: 0
register: async_job
– name: 等待异步任务完成
async_status:
jid: “{{ async_job.ansible_job_id }}”
register: job_result
until: job_result.finished
retries: 30
delay: 10
并行执行
:使用
forks
参数
ansible-playbook playbook.yml –forks 10
缓存事实
:减少重复收集
[defaults]
fact_caching = jsonfile
fact_caching_connection = /tmp/ansible_facts
fact_caching_timeout = 86400
8.3 安全最佳实践
使用Vault加密敏感数据
限制API权限
:使用最小权限原则
审计日志
:记录所有自动化操作
定期轮换凭证
:使用临时令牌
# 使用临时令牌的示例
– name: 获取临时API令牌
uri:
url: “https://{{ vcenter_hostname }}/rest/com/vmware/cis/session”
method: POST
user: “{{ vcenter_username }}”
password: “{{ vcenter_password }}”
force_basic_auth: yes
register: session_result
delegate_to: localhost
– name: 使用令牌执行操作
community.vmware.vmware_guest:
hostname: “{{ vcenter_hostname }}”
username: “{{ vcenter_username }}”
password: “{{ vcenter_password }}”
# … 其他参数
delegate_to: localhost
– name: 销毁临时令牌
uri:
url: “https://{{ vcenter_hostname }}/rest/com/vmware/cis/session”
method: DELETE
headers:
vmware-api-session-id: “{{ session_result.json.value }}”
delegate_to: localhost
when: session_result.changed
ignore_errors: yes
九、总结与展望
通过Ansible与VMware的深度集成,我们能够:
彻底解决配置繁琐问题
:从手动操作转向代码定义,配置过程标准化、可重复
保证环境一致性
:通过模板和角色,确保所有环境配置一致
提升运维效率
:批量操作、自动化流程大幅减少人工干预
降低错误率
:消除人为因素,提高操作准确性
实现可追溯性
:所有变更通过版本控制管理,便于审计和回滚
未来,随着基础设施即代码(IaC)理念的深入,Ansible与VMware的结合将更加紧密。建议持续关注:
Ansible Collections
:社区持续更新的VMware模块
Terraform集成
:与Ansible形成互补,实现更完整的IaC方案
GitOps实践
:将Ansible Playbook纳入CI/CD流水线
AI辅助运维
:利用机器学习优化自动化策略
通过本文的实战指南,您应该已经掌握了使用Ansible解决VMware虚拟机配置繁琐和环境不一致问题的核心方法。立即开始实践,将自动化引入您的VMware环境,体验效率和质量的双重提升!