ansible 知识点
-
- [1. 剧本](#1. 剧本)
- [2. facts变量](#2. facts变量)
- [3. register变量](#3. register变量)
- [4. include功能](#4. include功能)
- [5. handlers](#5. handlers)
- [6. when 条件](#6. when 条件)
- [7. with_items 循环](#7. with_items 循环)
- [8. Jinja2模板](#8. Jinja2模板)
- [9. group_vars](#9. group_vars)
- [10. roles :star::star::star:](#10. roles :star::star::star:)
看起来字数很多,实际有很多是脚本执行结果,内容不多哦
1. 剧本
剧本很重要的就是,定义演员的信息(其实就是定义主机的信息),演员的具体任务(以及主机要执行的模块,动作)
ansible剧本也是由两个最基本的部分组成
-
hosts
定义的被管理的主机列表信息(演员有哪些) -
tasks
关键词定义的是被管理主机需要执行的动作(演员要做什么事)
剧本格式:
yaml
# 1
---
- name: first task
hosts: db
# gather_facts: no
vars:
var1: a
var2: b
tasks:
- name: task1
command:..
- name: task2
command:..
- name: second task
hosts: web
- name: task1
command:..
...
# 2
---
- hosts: all
vars:
var1: a
var2: b
tasks:
- name: task1
...
[官网内置模块说明](Ansible.Builtin --- Ansible Community Documentation)
安装nfs
sh
[root@localhost ansible]# cat 01.nfs_install.yml
---
- hosts: all
gather_facts: yes
tasks:
- name: backup repo
shell: "if [ -f /etc/yum.repos.d/CentOS-Base.repo ];then mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.bak; fi"
- name: update yum repo
yum_repository:
name: aliyun_repo
description: aliyun linux repository
baseurl: http://mirrors.aliyun.com/repo/Centos-{{ ansible_distribution_major_version }}.repo
enabled: yes
gpgcheck: no
- name: install nfs rpcbind
yum:
name: "{{ item }}"
state: present
with_items:
- rpcbind
- nfs-utils
- name: started server
systemd:
name: "{{ item }}"
state: started
enabled: yes
with_items:
- rpcbind
- nfs-utils
sh
[root@localhost ansible]# ansible-playbook -i hosts 01.nfs_install.yml
PLAY [all] *************************************************************************************************************************************************************
TASK [Gathering Facts] *************************************************************************************************************************************************
ok: [182.92.85.212]
TASK [backup repo] *****************************************************************************************************************************************************
changed: [182.92.85.212]
TASK [update yum repo] *************************************************************************************************************************************************
changed: [182.92.85.212]
TASK [install nfs rpcbind] *********************************************************************************************************************************************
[DEPRECATION WARNING]: Invoking "yum" only once while using a loop via squash_actions is deprecated. Instead of using a loop to supply multiple items and specifying
`name: "{{ item }}"`, please use `name: ['rpcbind', 'nfs-utils']` and remove the loop. This feature will be removed in version 2.11. Deprecation warnings can be
disabled by setting deprecation_warnings=False in ansible.cfg.
ok: [182.92.85.212] => (item=[u'rpcbind', u'nfs-utils'])
TASK [started server] **************************************************************************************************************************************************
ok: [182.92.85.212] => (item=rpcbind)
changed: [182.92.85.212] => (item=nfs-utils)
PLAY RECAP *************************************************************************************************************************************************************
182.92.85.212 : ok=5 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
笔者发现新版本的ansible,yum已经被dnf取代了,不过目前yum仍可用
2.9及以前版本还能搜到yum的说明,以后的版本就只能搜dnf喽
2. facts变量
在Ansible中,事实变量(facts)是由Ansible自动从受管主机收集的系统信息。这些事实变量包含了与主机相关的各类信息,并且可以在playbook中用于条件判断、循环等场景。
每次运行playbook中的每个play时,Ansible会自动运行一个名为setup
的模块来收集受管主机的事实信息。这些信息包含如下内容:
- 主机名称
- 内核版本
- 网络接口
- IP地址
- 操作系统版本
- 各种环境变量
- CPU数量
- 提供的或可用的内存
- 可用磁盘空间
查看详细信息
sh
[root@localhost ansible]# ansible-playbook -i hosts 02.facts.yml
PLAY [db] **************************************************************************************************************************************************************
TASK [Gathering Facts] *************************************************************************************************************************************************
ok: [182.92.85.212]
TASK [print host msg] **************************************************************************************************************************************************
ok: [182.92.85.212] => {
"msg": {
"all_ipv4_addresses": [
"172.19.91.7"
],
"all_ipv6_addresses": [
"fe80::216:3eff:fe34:19c2"
],
"ansible_local": {},
"apparmor": {
"status": "disabled"
},
"architecture": "x86_64",
"bios_date": "04/01/2014",
"bios_version": "449e491",
"cmdline": {
"BOOT_IMAGE": "/boot/vmlinuz-3.10.0-1160.119.1.el7.x86_64",
"console": "ttyS0,115200n8",
"crashkernel": "auto",
"net.ifnames": "0",
"noibrs": true,
"nvme_core.admin_timeout": "4294967295",
"nvme_core.io_timeout": "4294967295",
"quiet": true,
"rhgb": true,
"ro": true,
"root": "UUID=c8b5b2da-5565-4dc1-b002-2a8b07573e22",
"spectre_v2": "retpoline"
},
"date_time": {
"date": "2025-01-08",
"day": "08",
"epoch": "1736304161",
"hour": "10",
"iso8601": "2025-01-08T02:42:41Z",
"iso8601_basic": "20250108T104241255861",
"iso8601_basic_short": "20250108T104241",
"iso8601_micro": "2025-01-08T02:42:41.255861Z",
"minute": "42",
"month": "01",
"second": "41",
"time": "10:42:41",
"tz": "CST",
"tz_offset": "+0800",
"weekday": "Wednesday",
"weekday_number": "3",
"weeknumber": "01",
"year": "2025"
},
"default_ipv4": {
"address": "172.19.91.7",
"alias": "eth0",
"broadcast": "172.19.95.255",
"gateway": "172.19.95.253",
"interface": "eth0",
"macaddress": "00:16:3e:34:19:c2",
"mtu": 1500,
"netmask": "255.255.240.0",
"network": "172.19.80.0",
"type": "ether"
},
"default_ipv6": {},
"device_links": {
"ids": {
"vda": [
"virtio-2zea4qo6616yh2wqh6ia"
],
"vda1": [
"virtio-2zea4qo6616yh2wqh6ia-part1"
]
},
"labels": {},
"masters": {},
"uuids": {
"vda1": [
"c8b5b2da-5565-4dc1-b002-2a8b07573e22"
]
}
},
"devices": {
"vda": {
"holders": [],
"host": "SCSI storage controller: Red Hat, Inc. Virtio block device",
"links": {
"ids": [
"virtio-2zea4qo6616yh2wqh6ia"
],
"labels": [],
"masters": [],
"uuids": []
},
"model": null,
"partitions": {
"vda1": {
"holders": [],
"links": {
"ids": [
"virtio-2zea4qo6616yh2wqh6ia-part1"
],
"labels": [],
"masters": [],
"uuids": [
"c8b5b2da-5565-4dc1-b002-2a8b07573e22"
]
},
"sectors": "83883999",
"sectorsize": 512,
"size": "40.00 GB",
"start": "2048",
"uuid": "c8b5b2da-5565-4dc1-b002-2a8b07573e22"
}
},
"removable": "0",
"rotational": "1",
"sas_address": null,
"sas_device_handle": null,
"scheduler_mode": "mq-deadline",
"sectors": "83886080",
"sectorsize": "512",
"size": "40.00 GB",
"support_discard": "0",
"vendor": "0x1af4",
"virtual": 1
}
},
"discovered_interpreter_python": "/usr/bin/python",
"distribution": "CentOS",
"distribution_file_parsed": true,
"distribution_file_path": "/etc/redhat-release",
"distribution_file_variety": "RedHat",
"distribution_major_version": "7",
"distribution_release": "Core",
"distribution_version": "7.9",
"dns": {
"nameservers": [
"100.100.2.136",
"100.100.2.138"
],
"options": {
"attempts": "3",
"rotate": true,
"single-request-reopen": true,
"timeout": "2"
}
},
"domain": "",
"effective_group_id": 0,
"effective_user_id": 0,
"env": {
"HOME": "/root",
"LANG": "en_US.UTF-8",
"LESSOPEN": "||/usr/bin/lesspipe.sh %s",
"LOGNAME": "root",
"LS_COLORS": "rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36:",
"MAIL": "/var/mail/root",
"PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin",
"PWD": "/root",
"SHELL": "/bin/bash",
"SHLVL": "2",
"SSH_CLIENT": "175.168.185.6 55563 22",
"SSH_CONNECTION": "175.168.185.6 55563 172.19.91.7 22",
"SSH_TTY": "/dev/pts/2",
"TERM": "xterm",
"USER": "root",
"XDG_RUNTIME_DIR": "/run/user/0",
"XDG_SESSION_ID": "7482",
"_": "/usr/bin/python"
},
"eth0": {
"active": true,
"device": "eth0",
"features": {
"busy_poll": "off [fixed]",
"fcoe_mtu": "off [fixed]",
"generic_receive_offload": "on",
"generic_segmentation_offload": "on",
"highdma": "on [fixed]",
"hw_tc_offload": "off [fixed]",
"l2_fwd_offload": "off [fixed]",
"large_receive_offload": "off [fixed]",
"loopback": "off [fixed]",
"netns_local": "off [fixed]",
"ntuple_filters": "off [fixed]",
"receive_hashing": "off [fixed]",
"rx_all": "off [fixed]",
"rx_checksumming": "on [fixed]",
"rx_fcs": "off [fixed]",
"rx_gro_hw": "off [fixed]",
"rx_udp_tunnel_port_offload": "off [fixed]",
"rx_vlan_filter": "off [fixed]",
"rx_vlan_offload": "off [fixed]",
"rx_vlan_stag_filter": "off [fixed]",
"rx_vlan_stag_hw_parse": "off [fixed]",
"scatter_gather": "on",
"tcp_segmentation_offload": "on",
"tx_checksum_fcoe_crc": "off [fixed]",
"tx_checksum_ip_generic": "on",
"tx_checksum_ipv4": "off [fixed]",
"tx_checksum_ipv6": "off [fixed]",
"tx_checksum_sctp": "off [fixed]",
"tx_checksumming": "on",
"tx_fcoe_segmentation": "off [fixed]",
"tx_gre_csum_segmentation": "off [fixed]",
"tx_gre_segmentation": "off [fixed]",
"tx_gso_partial": "off [fixed]",
"tx_gso_robust": "off [fixed]",
"tx_ipip_segmentation": "off [fixed]",
"tx_lockless": "off [fixed]",
"tx_nocache_copy": "off",
"tx_scatter_gather": "on",
"tx_scatter_gather_fraglist": "off [fixed]",
"tx_sctp_segmentation": "off [fixed]",
"tx_sit_segmentation": "off [fixed]",
"tx_tcp6_segmentation": "on",
"tx_tcp_ecn_segmentation": "on",
"tx_tcp_mangleid_segmentation": "off",
"tx_tcp_segmentation": "on",
"tx_udp_tnl_csum_segmentation": "off [fixed]",
"tx_udp_tnl_segmentation": "off [fixed]",
"tx_vlan_offload": "off [fixed]",
"tx_vlan_stag_hw_insert": "off [fixed]",
"udp_fragmentation_offload": "on",
"vlan_challenged": "off [fixed]"
},
"hw_timestamp_filters": [],
"ipv4": {
"address": "172.19.91.7",
"broadcast": "172.19.95.255",
"netmask": "255.255.240.0",
"network": "172.19.80.0"
},
"ipv6": [
{
"address": "fe80::216:3eff:fe34:19c2",
"prefix": "64",
"scope": "link"
}
],
"macaddress": "00:16:3e:34:19:c2",
"module": "virtio_net",
"mtu": 1500,
"pciid": "virtio2",
"promisc": false,
"timestamping": [
"rx_software",
"software"
],
"type": "ether"
},
"fibre_channel_wwn": [],
"fips": false,
"form_factor": "Other",
"fqdn": "ali01",
"gather_subset": [
"all"
],
"hostname": "ali01",
"hostnqn": "",
"interfaces": [
"lo",
"eth0"
],
"is_chroot": false,
"iscsi_iqn": "",
"kernel": "3.10.0-1160.119.1.el7.x86_64",
"kernel_version": "#1 SMP Tue Jun 4 14:43:51 UTC 2024",
"lo": {
"active": true,
"device": "lo",
"features": {
"busy_poll": "off [fixed]",
"fcoe_mtu": "off [fixed]",
"generic_receive_offload": "on",
"generic_segmentation_offload": "on",
"highdma": "on [fixed]",
"hw_tc_offload": "off [fixed]",
"l2_fwd_offload": "off [fixed]",
"large_receive_offload": "off [fixed]",
"loopback": "on [fixed]",
"netns_local": "on [fixed]",
"ntuple_filters": "off [fixed]",
"receive_hashing": "off [fixed]",
"rx_all": "off [fixed]",
"rx_checksumming": "on [fixed]",
"rx_fcs": "off [fixed]",
"rx_gro_hw": "off [fixed]",
"rx_udp_tunnel_port_offload": "off [fixed]",
"rx_vlan_filter": "off [fixed]",
"rx_vlan_offload": "off [fixed]",
"rx_vlan_stag_filter": "off [fixed]",
"rx_vlan_stag_hw_parse": "off [fixed]",
"scatter_gather": "on",
"tcp_segmentation_offload": "on",
"tx_checksum_fcoe_crc": "off [fixed]",
"tx_checksum_ip_generic": "on [fixed]",
"tx_checksum_ipv4": "off [fixed]",
"tx_checksum_ipv6": "off [fixed]",
"tx_checksum_sctp": "on [fixed]",
"tx_checksumming": "on",
"tx_fcoe_segmentation": "off [fixed]",
"tx_gre_csum_segmentation": "off [fixed]",
"tx_gre_segmentation": "off [fixed]",
"tx_gso_partial": "off [fixed]",
"tx_gso_robust": "off [fixed]",
"tx_ipip_segmentation": "off [fixed]",
"tx_lockless": "on [fixed]",
"tx_nocache_copy": "off [fixed]",
"tx_scatter_gather": "on [fixed]",
"tx_scatter_gather_fraglist": "on [fixed]",
"tx_sctp_segmentation": "on",
"tx_sit_segmentation": "off [fixed]",
"tx_tcp6_segmentation": "on",
"tx_tcp_ecn_segmentation": "on",
"tx_tcp_mangleid_segmentation": "on",
"tx_tcp_segmentation": "on",
"tx_udp_tnl_csum_segmentation": "off [fixed]",
"tx_udp_tnl_segmentation": "off [fixed]",
"tx_vlan_offload": "off [fixed]",
"tx_vlan_stag_hw_insert": "off [fixed]",
"udp_fragmentation_offload": "on",
"vlan_challenged": "on [fixed]"
},
"hw_timestamp_filters": [],
"ipv4": {
"address": "127.0.0.1",
"broadcast": "",
"netmask": "255.0.0.0",
"network": "127.0.0.0"
},
"ipv6": [
{
"address": "::1",
"prefix": "128",
"scope": "host"
}
],
"mtu": 65536,
"promisc": false,
"timestamping": [
"rx_software",
"software"
],
"type": "loopback"
},
"lsb": {
"codename": "Core",
"description": "CentOS Linux release 7.9.2009 (Core)",
"id": "CentOS",
"major_release": "7",
"release": "7.9.2009"
},
"machine": "x86_64",
"machine_id": "88b247814be64fbf8fa045566b89ce3e",
"memfree_mb": 259,
"memory_mb": {
"nocache": {
"free": 1512,
"used": 244
},
"real": {
"free": 259,
"total": 1756,
"used": 1497
},
"swap": {
"cached": 0,
"free": 0,
"total": 0,
"used": 0
}
},
"memtotal_mb": 1756,
"module_setup": true,
"mounts": [
{
"block_available": 8998392,
"block_size": 4096,
"block_total": 10288203,
"block_used": 1289811,
"device": "/dev/vda1",
"fstype": "ext4",
"inode_available": 2556564,
"inode_total": 2621440,
"inode_used": 64876,
"mount": "/",
"options": "rw,relatime,data=ordered",
"size_available": 36857413632,
"size_total": 42140479488,
"uuid": "c8b5b2da-5565-4dc1-b002-2a8b07573e22"
}
],
"nodename": "ali01",
"os_family": "RedHat",
"pkg_mgr": "yum",
"proc_cmdline": {
"BOOT_IMAGE": "/boot/vmlinuz-3.10.0-1160.119.1.el7.x86_64",
"console": [
"tty0",
"ttyS0,115200n8"
],
"crashkernel": "auto",
"net.ifnames": "0",
"noibrs": true,
"nvme_core.admin_timeout": "4294967295",
"nvme_core.io_timeout": "4294967295",
"quiet": true,
"rhgb": true,
"ro": true,
"root": "UUID=c8b5b2da-5565-4dc1-b002-2a8b07573e22",
"spectre_v2": "retpoline"
},
"processor": [
"0",
"GenuineIntel",
"Intel(R) Xeon(R) Platinum",
"1",
"GenuineIntel",
"Intel(R) Xeon(R) Platinum"
],
"processor_cores": 1,
"processor_count": 1,
"processor_threads_per_core": 2,
"processor_vcpus": 2,
"product_name": "Alibaba Cloud ECS",
"product_serial": "33a7cfe4-534e-418a-adbe-783fb05884e8",
"product_uuid": "33A7CFE4-534E-418A-ADBE-783FB05884E8",
"product_version": "pc-i440fx-2.1",
"python": {
"executable": "/usr/bin/python",
"has_sslcontext": true,
"type": "CPython",
"version": {
"major": 2,
"micro": 5,
"minor": 7,
"releaselevel": "final",
"serial": 0
},
"version_info": [
2,
7,
5,
"final",
0
]
},
"python_version": "2.7.5",
"real_group_id": 0,
"real_user_id": 0,
"selinux": {
"status": "disabled"
},
"selinux_python_present": true,
"service_mgr": "systemd",
"ssh_host_key_dsa_public": "AAAAB3NzaC1kc3MAAACBAPoheUF1Sp83cZqdmAbfPqAEkBCLnvAB0b06r8wJE7y9nck2s4BLhChHPK+DYPlpmJOFJzhfA3TDiQqGBw6f3tmtWwtaej65Cnb1jg03EldfzXUZjOWaSBAAv20uWjjHLLB9epezwgpYfXI6lH8J5kcHBQAJr6ReQjVnid4H4T4pAAAAFQDBuMSFQWXhqlqLhdRzdd1WbMbrUQAAAIEA0BdoMMTrcc9QdqI0N2RevOrsiSUCaAcs2BwXGIvN1bCA/D/Juvy7L8YKN7TqD2wHxOEe6bd7YtQlg4mm9XxKnaGpO9/DRRDfjv/ZePrxU2bONHlYTG3yIiuhrlbTkp8Apl6fJpEPeGP/tqOv0T9Yx8BPhRgEuCkmmQ+S7An2hFAAAACBAN0QTG1gltjcqWjVW8OK+u1ih9YkLiciD873rG7LVfpN3X7DgiuxFUmcFBqBbKOObMU1vsqbkfHmGDseWeTvOZlQfjmffU56bRWEHMt1JAvwwkwGFKwGjYzBCy8vsqlzGik559yIQxPF6xijqXDrtH4zSgtvgZE+QRhmZl3tPp7E",
"ssh_host_key_ecdsa_public": "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBE9BHIH3QSoFRbL7br23p3N7rz5FRq19rKEqqucK21bD8bQn4a7O5slXleeGjZQtHMUaTNF4MqyGzFCrcdxw9mQ=",
"ssh_host_key_ed25519_public": "AAAAC3NzaC1lZDI1NTE5AAAAIHnPv/S9xAofLvaR7cs1hpSXVg8rP36LED54L5m96kH5",
"ssh_host_key_rsa_public": "AAAAB3NzaC1yc2EAAAADAQABAAABAQC+pOYVVQ5JR7F4i2DM7Lu3CkQDuyJ4OMDA40V8vAFdMKQonrCb/TTUdkBXjwhSet8ucpPIj3UcRrYn0znPFhyCVfPZTCRDREy8pbF+mV9Tby4fTjvk2RDXHf2OihmUIeCKjZmYsNe2zV1fBWp/7Sb+9qP2U5znM3DfmGbrkUfordQEPiyfunQPIUkLGJuJhuWJl6KygE1ZOWPYaZtlR4jK4rvCKmayVUsWXHePVSGXuC5+Fn9D8vXgALb5GENNok45xjkEDyHfmyIm6MCf13r4+hnhPNEJJVfhbv//63R6R/l4al+G7AduZBP91+f1b41p2pVQ5cfqdX1Fow+ZO5Cp",
"swapfree_mb": 0,
"swaptotal_mb": 0,
"system": "Linux",
"system_capabilities": [
"cap_chown",
"cap_dac_override",
"cap_dac_read_search",
"cap_fowner",
"cap_fsetid",
"cap_kill",
"cap_setgid",
"cap_setuid",
"cap_setpcap",
"cap_linux_immutable",
"cap_net_bind_service",
"cap_net_broadcast",
"cap_net_admin",
"cap_net_raw",
"cap_ipc_lock",
"cap_ipc_owner",
"cap_sys_module",
"cap_sys_rawio",
"cap_sys_chroot",
"cap_sys_ptrace",
"cap_sys_pacct",
"cap_sys_admin",
"cap_sys_boot",
"cap_sys_nice",
"cap_sys_resource",
"cap_sys_time",
"cap_sys_tty_config",
"cap_mknod",
"cap_lease",
"cap_audit_write",
"cap_audit_control",
"cap_setfcap",
"cap_mac_override",
"cap_mac_admin",
"cap_syslog",
"35",
"36+ep"
],
"system_capabilities_enforced": "True",
"system_vendor": "Alibaba Cloud",
"uptime_seconds": 3786285,
"user_dir": "/root",
"user_gecos": "root",
"user_gid": 0,
"user_id": "root",
"user_shell": "/bin/bash",
"user_uid": 0,
"userspace_architecture": "x86_64",
"userspace_bits": "64",
"virtualization_role": "guest",
"virtualization_type": "kvm"
}
}
PLAY RECAP *************************************************************************************************************************************************************
182.92.85.212 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
实际上,我们大概率只会选取经常使用的变量,如下表
事实 | 方式1 | 方式2 | 方式3 |
---|---|---|---|
短主机名 | ansible_facts.hostname | ansible_facts['hostname'] | ansible_hostname |
完全限定域名 | ansible_facts.fqdn | ansible_facts['fqdn'] | ansible_fqdn |
IPv4地址 | ansible_facts.default_ipv4.address | ansible_facts['default_ipv4']['address'] | ansible_default_ipv4 |
所有网络接口的名称列表 | ansible_facts.interfaces | ansible_facts['interfaces '] | ansible_interfaces |
DNS服务器列表 | ansible_facts.dns | ansible_facts['dns'] | ansible_dns |
当前运行的内核版本 | ansible_facts.kernel | ansible_facts['kernel'] | ansible_kernel |
三种格式都可以使用,看自己喜好
sh
[root@localhost ansible]# cat 02.facts.yml
---
- hosts: db
tasks:
- name: print ipv4 1
debug:
msg: "{{ ansible_facts.default_ipv4.address }}"
- name: print ipv4 2
debug:
msg: "{{ ansible_facts['default_ipv4']['address'] }}"
- name: print ipv4 3
debug:
msg: "{{ ansible_default_ipv4.address }}"
[root@localhost ansible]# ansible-playbook -i hosts 02.facts.yml
PLAY [db] **************************************************************************************************************************************************************
TASK [Gathering Facts] *************************************************************************************************************************************************
ok: [182.92.85.212]
TASK [print ipv4 1] ****************************************************************************************************************************************************
ok: [182.92.85.212] => {
"msg": "172.19.91.7"
}
TASK [print ipv4 2] ****************************************************************************************************************************************************
ok: [182.92.85.212] => {
"msg": "172.19.91.7"
}
TASK [print ipv4 3] ****************************************************************************************************************************************************
ok: [182.92.85.212] => {
"msg": "172.19.91.7"
}
PLAY RECAP *************************************************************************************************************************************************************
182.92.85.212 : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
3. register变量
在Ansible中,可以通过register
关键字将任务的输出结果注册为变量,以便在后续任务中使用。
- 注册变量的基本用法
在Ansible playbook中,可以使用register
关键字来捕获任务的输出并将其保存为一个变量。例如:
sh
[root@localhost ansible]# cat 03.register.yml
---
- hosts: db
tasks:
- name: define a var1
shell: "whoami"
register: whoami
- debug: "msg={{ whoami }}"
- debug: "msg={{ whoami.stdout }}"
[root@localhost ansible]# ansible-playbook -i hosts 03.register.yml
PLAY [db] **************************************************************************************************************************************************************
TASK [Gathering Facts] *************************************************************************************************************************************************
ok: [182.92.85.212]
TASK [define a var1] ***************************************************************************************************************************************************
changed: [182.92.85.212]
TASK [debug] ***********************************************************************************************************************************************************
ok: [182.92.85.212] => {
"msg": {
"changed": true,
"cmd": "whoami",
"delta": "0:00:00.046106",
"end": "2025-01-09 10:37:55.151360",
"failed": false,
"rc": 0,
"start": "2025-01-09 10:37:55.105254",
"stderr": "",
"stderr_lines": [],
"stdout": "root",
"stdout_lines": [
"root"
]
}
}
TASK [debug] ***********************************************************************************************************************************************************
ok: [182.92.85.212] => {
"msg": "root"
}
PLAY RECAP *************************************************************************************************************************************************************
182.92.85.212 : ok=4 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
4. include功能
Ansible的include
功能主要用于在Ansible playbook中提取和重用 公共的逻辑代码段,使结构更加清晰,方便阅读和维护。通过使用include
,可以将重复的任务、变量或handlers等代码片段提取到一个单独的文件中,然后在主playbook中通过include
指令引入这些代码片段。
sh
[root@localhost ansible]# cat 04.useradd.yml
---
- name: add user
user:
name: "{{ username }}"
state: present
create_home: no
[root@localhost ansible]# cat 04.include.yml
---
- hosts: db
vars:
username: lisi
tasks:
- include: 04.useradd.yml
- shell: "tail /etc/passwd"
register: content
- debug: "msg={{content}}"
注意:提取的代码片段yml只配任务内容,不需要配置hosts
sh
[root@localhost ansible]# ansible-playbook -i hosts 04.include.yml
PLAY [db] **************************************************************************************************************************************************************
TASK [Gathering Facts] *************************************************************************************************************************************************
ok: [182.92.85.212]
TASK [add user] ********************************************************************************************************************************************************
ok: [182.92.85.212]
TASK [shell] ***********************************************************************************************************************************************************
changed: [182.92.85.212]
TASK [debug] ***********************************************************************************************************************************************************
ok: [182.92.85.212] => {
"msg": {
"changed": true,
"cmd": "tail /etc/passwd",
"delta": "0:00:00.041112",
"end": "2025-01-09 10:58:22.351314",
"failed": false,
"rc": 0,
"start": "2025-01-09 10:58:22.310202",
"stderr": "",
"stderr_lines": [],
"stdout": "postfix:x:89:89::/var/spool/postfix:/sbin/nologin\nchrony:x:998:996::/var/lib/chrony:/sbin/nologin\nnscd:x:28:28:NSCD Daemon:/:/sbin/nologin\ntcpdump:x:72:72::/:/sbin/nologin\nrpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin\nrpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin\nnfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin\necs-assist-user:x:1000:1000::/home/ecs-assist-user:/sbin/nologin\nnginx:x:997:995:Nginx web server:/var/lib/nginx:/sbin/nologin\nlisi:x:1001:1001::/home/lisi:/bin/bash",
"stdout_lines": [
"postfix:x:89:89::/var/spool/postfix:/sbin/nologin",
"chrony:x:998:996::/var/lib/chrony:/sbin/nologin",
"nscd:x:28:28:NSCD Daemon:/:/sbin/nologin",
"tcpdump:x:72:72::/:/sbin/nologin",
"rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin",
"rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin",
"nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin",
"ecs-assist-user:x:1000:1000::/home/ecs-assist-user:/sbin/nologin",
"nginx:x:997:995:Nginx web server:/var/lib/nginx:/sbin/nologin",
"lisi:x:1001:1001::/home/lisi:/bin/bash"
]
}
}
PLAY RECAP *************************************************************************************************************************************************************
182.92.85.212 : ok=4 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
5. handlers
Handlers是Ansible Playbooks中的一种特殊任务类型。它们类似于事件处理程序,用于在特定条件下触发和执行任务。Handlers通常与任务关联,当任务的状态发生变化时,Handlers会被触发执行。Handlers可以用于执行各种操作,如重启服务、重新加载配置文件等。
sh
[root@localhost ansible]# cat 05.handlers.yml
---
- hosts: db
tasks:
- copy:
src: ./exports
dest: /etc/exports
notify: restart nfs
handlers:
- name: restart nfs
systemd:
name: nfs
state: restarted
[root@localhost ansible]# ansible-playbook -i hosts 05.handlers.yml
PLAY [db] **************************************************************************************************************************************************************
TASK [Gathering Facts] *************************************************************************************************************************************************
ok: [182.92.85.212]
TASK [copy] ************************************************************************************************************************************************************
changed: [182.92.85.212]
RUNNING HANDLER [restart nfs] ******************************************************************************************************************************************
changed: [182.92.85.212]
PLAY RECAP *************************************************************************************************************************************************************
182.92.85.212 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
当我们未对文件进行修改,再次执行,handlers不会被触发
sh
[root@localhost ansible]# ansible-playbook -i hosts 05.handlers.yml
PLAY [db] **************************************************************************************************************************************************************
TASK [Gathering Facts] *************************************************************************************************************************************************
ok: [182.92.85.212]
TASK [copy] ************************************************************************************************************************************************************
ok: [182.92.85.212]
PLAY RECAP *************************************************************************************************************************************************************
182.92.85.212 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
6. when 条件
Ansible中的when
语句用于条件判断,根据特定的条件来决定是否执行某个任务。当条件为真时,任务将会执行;当条件为假时,任务将被跳过。when
语句的使用非常灵活,可以基于变量、事实、先前任务的输出或其他表达式的结果来决定是否执行某个任务
sh
[root@localhost ansible]# cat 06.when.yml
---
- hosts: db
tasks:
- name: CentOS Install httpd
yum: name=httpd state=present
when: (ansible_distribution=="CentOS")
- name: Ubuntu Install httpd
yum: name=httpd state=present
when: (ansible_distribution=="Ubuntu")
- name: start httpd
systemd:
name: httpd
state: started
enabled: no
- shell: "systemctl status httpd"
register: state_httpd
- debug: "msg={{state_httpd}}"
sh
[root@localhost ansible]# ansible-playbook -i hosts 06.when.yml
PLAY [db] **************************************************************************************************************************************************************
TASK [Gathering Facts] *************************************************************************************************************************************************
ok: [182.92.85.212]
TASK [CentOS Install httpd] ********************************************************************************************************************************************
ok: [182.92.85.212]
TASK [Ubuntu Install httpd] ********************************************************************************************************************************************
skipping: [182.92.85.212]
TASK [start httpd] *****************************************************************************************************************************************************
ok: [182.92.85.212]
TASK [shell] ***********************************************************************************************************************************************************
changed: [182.92.85.212]
TASK [debug] ***********************************************************************************************************************************************************
ok: [182.92.85.212] => {
"msg": {
"changed": true,
"cmd": "systemctl status httpd",
"delta": "0:00:00.044066",
"end": "2025-01-09 12:34:02.429361",
"failed": false,
"rc": 0,
"start": "2025-01-09 12:34:02.385295",
"stderr": "",
"stderr_lines": [],
"stdout": "● httpd.service - The Apache HTTP Server\n Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled)\n Active: active (running) since Thu 2025-01-09 12:32:34 CST; 1min 27s ago\n Docs: man:httpd(8)\n man:apachectl(8)\n Main PID: 8474 (httpd)\n Status: \"Total requests: 0; Current requests/sec: 0; Current traffic: 0 B/sec\"\n CGroup: /system.slice/httpd.service\n ├─8474 /usr/sbin/httpd -DFOREGROUND\n ├─8475 /usr/sbin/httpd -DFOREGROUND\n ├─8476 /usr/sbin/httpd -DFOREGROUND\n ├─8477 /usr/sbin/httpd -DFOREGROUND\n ├─8478 /usr/sbin/httpd -DFOREGROUND\n └─8479 /usr/sbin/httpd -DFOREGROUND\n\nJan 09 12:32:34 ali01 systemd[1]: Starting The Apache HTTP Server...\nJan 09 12:32:34 ali01 httpd[8474]: AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using fe80::216:3eff:fe34:19c2. Set the 'ServerName' directive globally to suppress this message\nJan 09 12:32:34 ali01 systemd[1]: Started The Apache HTTP Server.",
"stdout_lines": [
"● httpd.service - The Apache HTTP Server",
" Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled)",
" Active: active (running) since Thu 2025-01-09 12:32:34 CST; 1min 27s ago",
" Docs: man:httpd(8)",
" man:apachectl(8)",
" Main PID: 8474 (httpd)",
" Status: \"Total requests: 0; Current requests/sec: 0; Current traffic: 0 B/sec\"",
" CGroup: /system.slice/httpd.service",
" ├─8474 /usr/sbin/httpd -DFOREGROUND",
" ├─8475 /usr/sbin/httpd -DFOREGROUND",
" ├─8476 /usr/sbin/httpd -DFOREGROUND",
" ├─8477 /usr/sbin/httpd -DFOREGROUND",
" ├─8478 /usr/sbin/httpd -DFOREGROUND",
" └─8479 /usr/sbin/httpd -DFOREGROUND",
"",
"Jan 09 12:32:34 ali01 systemd[1]: Starting The Apache HTTP Server...",
"Jan 09 12:32:34 ali01 httpd[8474]: AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using fe80::216:3eff:fe34:19c2. Set the 'ServerName' directive globally to suppress this message",
"Jan 09 12:32:34 ali01 systemd[1]: Started The Apache HTTP Server."
]
}
}
PLAY RECAP *************************************************************************************************************************************************************
182.92.85.212 : ok=5 changed=1 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
语法和逻辑运算符
when
语句的语法与Python的语法非常相似,支持多种条件表达式和逻辑运算符:
- 比较运算符 :
==、!=、>、<、>=、<=
- 逻辑运算符 :
and、or、not
- 组合条件 :可以使用括号
()
来组合多个条件,改变运算的优先级
7. with_items 循环
在Ansible Playbook中,with_items
用于遍历列表或字典,并对每个元素执行任务。其基本语法如下:
sh
tasks:
- command: some_command "{{ item }}"
with_items:
- item1
- item2
- item3
使用场景包括:创建多个用户,安装多个软件包,启动多个服务,拷贝多个文件等等
sh
[root@localhost ansible]# cat 07.with_items.yml
---
- hosts: db
gather_facts: no
tasks:
- name: useradd
user:
name: "{{item}}"
state: present
create_home: no
with_items:
- yurq1
- yurq2
- yurq3
sh
[root@localhost ansible]# ansible-playbook -i hosts 07.with_items.yml
PLAY [db] **************************************************************************************************************************************************************
TASK [useradd] *********************************************************************************************************************************************************
changed: [182.92.85.212] => (item=yurq1)
changed: [182.92.85.212] => (item=yurq2)
changed: [182.92.85.212] => (item=yurq3)
PLAY RECAP *************************************************************************************************************************************************************
182.92.85.212 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@localhost ansible]# ansible -i hosts db -m shell -a "tail -3 /etc/passwd"
182.92.85.212 | CHANGED | rc=0 >>
yurq1:x:1002:1002::/home/yurq1:/bin/bash
yurq2:x:1003:1003::/home/yurq2:/bin/bash
yurq3:x:1004:1004::/home/yurq3:/bin/bash
8. Jinja2模板
Jinja2 是 Python 的全功能模板引擎
Ansible 需要使用 Jinja2 模板来修改被管理主机的配置文件。
ansible 使用 jinja2 模板需要借助 template 模块实现,那 template 模块是用来做什么的?
template 模块和 copy 模块完全一样,都是拷贝文件至远程主机,区别在于template 模块会解析要拷贝的文件中变量的值,而 copy 则是原封不动的将文件拷贝至被控端。
sh
[root@localhost ansible]# cat exports.j2
#{{ansible_hostname}}
/data/ *(rw,sync,all_squash)
[root@localhost ansible]# cat 08.jinja2.yml
---
- hosts: db
tasks:
- template:
src: ./exports.j2
dest: /etc/exports
notify: restart nfs
- shell: "cat /etc/exports"
register: content
- debug: "msg={{content}}"
handlers:
- name: restart nfs
systemd:
name: nfs
state: restarted
[root@localhost ansible]# ansible-playbook -i hosts 08.jinja2.yml
PLAY [db] **************************************************************************************************************************************************************
TASK [Gathering Facts] *************************************************************************************************************************************************
ok: [182.92.84.211]
TASK [template] ********************************************************************************************************************************************************
changed: [182.92.84.211]
TASK [shell] ***********************************************************************************************************************************************************
changed: [182.92.84.211]
TASK [debug] ***********************************************************************************************************************************************************
ok: [182.92.84.211] => {
"msg": {
"changed": true,
"cmd": "cat /etc/exports",
"delta": "0:00:00.039831",
"end": "2025-01-09 13:03:56.418589",
"failed": false,
"rc": 0,
"start": "2025-01-09 13:03:56.378758",
"stderr": "",
"stderr_lines": [],
"stdout": "#ali01\n/data/ *(rw,sync,all_squash) ",
"stdout_lines": [
"#ali01",
"/data/ *(rw,sync,all_squash) "
]
}
}
RUNNING HANDLER [restart nfs] ******************************************************************************************************************************************
changed: [182.92.84.211]
PLAY RECAP *************************************************************************************************************************************************************
182.92.84.211 : ok=5 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
9. group_vars
ansible中变量有很多种,包括:
- 资产变量,即我们配置在hosts文件中的变量
- facts变量,即ansible为我们收集的主机信息变量
- 注册变量,即register注册的变量,在脚本内为后续使用
- 剧本变量,如vars定义在文件前部,供后续使用
- 全局变量,一般是ansible命令行使用的
group_vars
下的文件名应该与 Ansible inventory 中定义的组名匹配,文件名无需添加任何扩展名,内容为该组下所有主机共有的变量。一般用于定义剧本变量。
例如,假设你有一个名为 webservers
的组,group_vars/webservers
文件内容可能是:
json
http_port: 80
max_connections: 1024
不过,一般我们都只定义一个all的文件,供所有组使用
sh
[root@localhost ansible]# tree
.
├── 01.nfs_install.yml
├── 02.facts.yml
├── 03.register.yml
├── 04.include.yml
├── 04.useradd.yml
├── 05.handlers.yml
├── 06.when.yml
├── 07.with_items.yml
├── 08.jinja2.yml
├── 09.group_vars.yml
├── exports
├── exports.j2
├── group_vars
│ └── all
└── hosts
1 directory, 14 files
[root@localhost ansible]# cat group_vars/all
user4: yurq4
sh
[root@localhost ansible]# ansible-playbook -i hosts 09.group_vars.yml
PLAY [db] **************************************************************************************************************************************************************
TASK [Gathering Facts] *************************************************************************************************************************************************
ok: [182.92.84.211]
TASK [useradd 2] *******************************************************************************************************************************************************
changed: [182.92.84.211]
PLAY RECAP *************************************************************************************************************************************************************
182.92.84.211 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@localhost ansible]# ansible -i hosts all -m shell -a "tail -1 /etc/passwd"
182.92.84.211 | CHANGED | rc=0 >>
yurq4:x:1005:1005::/home/yurq4:/bin/bash
看到了吗?我们未做任何导入工作,就可以直接调用user4
,非常方便
10. roles ⭐️⭐️⭐️
Ansible roles是Ansible的一个组织结构,它允许你将配置任务封装为可重用的单元,这样你可以在多个playbook中使用它们。
一个Ansible role通常包含以下目录结构:
defaults/
:设定变量的默认值。files/
:存放由copy或script模块等调用的文件。handlers/
:包含处理器的定义,处理器可以在特定的条件下触发。meta/
:定义role的依赖关系。tasks/
:包含主要的任务集。templates/
:包含Jinja2模板文件,这些模板文件可以根据变量渲染内容。vars/
:定义变量,这些变量会覆盖defaults中的同名变量。
文件:
-
README.md
:对role的简要说明。 -
meta/main.yml
:定义role的特定行为。 -
tasks/main.yml
:列出role要执行的任务。 -
handlers/main.yml
:列出可由任务触发的处理器。 -
vars/main.yml
:定义role使用的变量。
上面的目录并不是每个项目都需要的,一般常用的有:
-
files/
-
handlers/
-
tasks/
-
templates/
-
vars/
我们把08.jinja2.yml
拆分为roles格式,帮助大家理解
sh
[root@localhost ansible]# cat 08.jinja2.yml
---
- hosts: db
tasks:
- template:
src: ./exports.j2
dest: /etc/exports
notify: restart nfs
- shell: "cat /etc/exports"
register: content
- debug: "msg={{content}}"
handlers:
- name: restart nfs
systemd:
name: nfs
state: restarted
如下:
sh
[root@localhost roles]# tree
.
├── 10.roles.yml
├── db
│ ├── handlers
│ │ └── main.yml
│ ├── tasks
│ │ └── main.yml
│ └── templates
│ └── exports.j2
└── hosts
4 directories, 5 files
tasks/
sh
[root@localhost roles]# cat db/tasks/main.yml
- template:
src: ./exports.j2
dest: /etc/exports
notify: restart nfs
- shell: "cat /etc/exports"
register: content
- debug: "msg={{content}}"
handlers/
sh
[root@localhost roles]# cat db/handlers/main.yml
- name: restart nfs
systemd:
name: nfs
state: restarted
templates/
sh
[root@localhost roles]# cat db/templates/exports.j2
#{{ansible_hostname}}
/data/ *(rw,sync,all_squash)
10.roles.yml
sh
[root@localhost roles]# cat 10.roles.yml
---
- hosts: db
roles:
- db
执行
sh
[root@localhost roles]# ansible-playbook -i hosts 10.roles.yml
PLAY [db] **************************************************************************************************************************************************************
TASK [Gathering Facts] *************************************************************************************************************************************************
ok: [182.92.84.211]
TASK [db : template] ***************************************************************************************************************************************************
ok: [182.92.84.211]
TASK [db : shell] ******************************************************************************************************************************************************
changed: [182.92.84.211]
TASK [db : debug] ******************************************************************************************************************************************************
ok: [182.92.84.211] => {
"msg": {
"changed": true,
"cmd": "cat /etc/exports",
"delta": "0:00:00.039530",
"end": "2025-01-09 13:35:27.995178",
"failed": false,
"rc": 0,
"start": "2025-01-09 13:35:27.955648",
"stderr": "",
"stderr_lines": [],
"stdout": "#ali01\n/data/ *(rw,sync,all_squash) ",
"stdout_lines": [
"#ali01",
"/data/ *(rw,sync,all_squash) "
]
}
}
PLAY RECAP *************************************************************************************************************************************************************
182.92.84.211 : ok=4 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
其实执行起来和08的剧本本质是一样的,不过改变了目录结构,方便管理