From 7ef99d3a3b39ae130eb4385932a59a9a00777f94 Mon Sep 17 00:00:00 2001 From: diandian Date: Thu, 1 Jun 2023 10:53:37 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E6=96=87=E4=BB=B6=E8=87=B3?= =?UTF-8?q?=20'ansible'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ansible/Ansible-jinja2模板.md | 142 ++++ ansible/Ansible之Setup模块.md | 740 ++++++++++++++++++++ ansible/Ansible自动化运维基础.md | 1097 ++++++++++++++++++++++++++++++ ansible/Yaml语法格式.md | 172 +++++ 4 files changed, 2151 insertions(+) create mode 100644 ansible/Ansible-jinja2模板.md create mode 100644 ansible/Ansible之Setup模块.md create mode 100644 ansible/Ansible自动化运维基础.md create mode 100644 ansible/Yaml语法格式.md diff --git a/ansible/Ansible-jinja2模板.md b/ansible/Ansible-jinja2模板.md new file mode 100644 index 0000000..692539c --- /dev/null +++ b/ansible/Ansible-jinja2模板.md @@ -0,0 +1,142 @@ +

Ansible-jinja2模板

+ +------ + +**作者:行癫(盗版必究)** + +## 一:简介 + +​ ansible通常使用jinja2模板来修改被管理主机的配置文件 + +​ 使用ansible的jinja2模板,也就是template模块,该模块和copy模块一样,都是将文件复制到远端主机上;区别在于template模块可以获取要复制的文件中变量的值;而copy则是原封不动的把文件内容复制过去,比如针对不同的主机定义不同的变量,template会在将配置文件分发出去之前读取变量到jinja2模板,然后分发到不通的被管理主机上 + +​ ansible允许jinja2模板中使用条件判断和循环,但是jinja2判断循环语法不允许在playbook中使用 + +​ jinja2 文件件以 .j2 为后缀, 也可以不写后缀 + +## 二:基本使用 + +#### 1.模板基本语法 + +​ 要在配置文件中使用jinja2,playbook中的tasks必须使用template模块 + +​ 模板配置文件里面使用变量,比如{{ port }}或者使用{{ facts变量 }} + +#### 2.模板逻辑关系 + +```jinja +{% for i in EXPR %}...{% endfor %}作为循环表达式 + +{% if EXPR %}...{% elif EXPR %}...{% endif %}作为条件判断 + +{# COMMENT #}表示注释 +``` + +## 三:使用案例 + +#### 1.案例一 + +​ 使用facts变量 + +```yaml +[root@db2 memcache]# cat jinja1.yaml +- hosts: all + tasks: + - name: copy template file /etc/motd + template: src=./motd.j2 dest=/etc/motd backup=yes + +[root@db2 memcache]# cat motd.j2 +Welcome to qingcheng service!! +This System Hostname: {{ ansible_hostname }} +This System total memory is: {{ ansible_memtotal_mb }} MB +This System free memory is: {{ ansible_memfree_mb }} MB +``` + +#### 2.案例二 + +​ nginx负载均衡变量 + +```yaml +[root@db2 memcache]# cat kod_proxy.conf.j2 +upstream {{ server_name }} { + {% for i in range(1,10) %} + server 192.168.10.{{ i }}; + {% endfor %} +} +server { + listen {{ http_port }}; + server_name {{ server_name }}; + location / { + proxy_pass http://{{ server_name }}; + include proxy_params; + } +} +[root@db2 memcache]# cat jinja2.yaml +- hosts: webserver + vars: + - http_port: 80 + - server_name: kod_qingchen.com + tasks: + - name: install nginx server + yum: name=nginx state=latest + - name: configure nginx virt + template: src=./kod_proxy.conf.j2 dest=/etc/nginx/conf.d/proxy_kod.conf + notify: Restart Nginx Server + - name: start nginx server + service: name=nginx state=started enabled=yes + handlers: + - name: Restart Nginx Server + service: name=nginx state=restarted +``` + +#### 3.案例三 + +​ keepalive主从 + +```shell +inventory中的host_vars根据不同主机设定不同的变量 +在playbook中是when判断主机名称,然后分发不同的配置文件 +使用jinja2的方式渲染出不同的配置文件 +``` + +```jinja2 +[root@db2 memcache]# cat keepalived.yaml +- hosts: all + tasks: + - name: copy template keepalived configure + template: src=keepalived.j2 dest=/etc/keepalived/keepalived.conf + notify: Restart keepalived service + handler: + - name: Restart keepalived service + service: name=keepalived state=restarted + +[root@db2 memcache]# cat keepalived.j2 +global_defs { + router_id {{ ansible_fqdn }} +} + +vrrp_instance VI_1 { +{% if ansible_fqdn == "web01" %} + state MASTER + priority 150 +{% elif ansible_fqdn == "web02" %} + state BACKUP + priority 100 +{% endif %} + interface eth0 + virtual_router_id 50 + advert_int 1 + authentication { + auth_type PASS + auth_pass 1111 + } + virtual_ipaddress { + 10.0.0.3 + } +} +``` + + + + + diff --git a/ansible/Ansible之Setup模块.md b/ansible/Ansible之Setup模块.md new file mode 100644 index 0000000..791d340 --- /dev/null +++ b/ansible/Ansible之Setup模块.md @@ -0,0 +1,740 @@ +

Ansible之Setup模块

+ +------ + +**作者:行癫(盗版必究)** + +## 一:所有参数 + +```yml +10.0.0.111 | SUCCESS => { + "ansible_facts": { + "ansible_all_ipv4_addresses": [ + "10.0.0.111" + ], + "ansible_all_ipv6_addresses": [ + "fe80::a1d7:aadb:3ae3:bbb9" + ], + "ansible_apparmor": { + "status": "disabled" + }, + "ansible_architecture": "x86_64", + "ansible_bios_date": "11/12/2020", + "ansible_bios_version": "6.00", + "ansible_cmdline": { + "BOOT_IMAGE": "/vmlinuz-3.10.0-693.el7.x86_64", + "LANG": "en_US.UTF-8", + "quiet": true, + "rd.lvm.lv": "centos/root", + "rhgb": true, + "ro": true, + "root": "/dev/mapper/centos-root" + }, + "ansible_date_time": { + "date": "2023-03-02", + "day": "02", + "epoch": "1677768313", + "hour": "22", + "iso8601": "2023-03-02T14:45:13Z", + "iso8601_basic": "20230302T224513178165", + "iso8601_basic_short": "20230302T224513", + "iso8601_micro": "2023-03-02T14:45:13.178165Z", + "minute": "45", + "month": "03", + "second": "13", + "time": "22:45:13", + "tz": "CST", + "tz_offset": "+0800", + "weekday": "Thursday", + "weekday_number": "4", + "weeknumber": "09", + "year": "2023" + }, + "ansible_default_ipv4": { + "address": "10.0.0.111", + "alias": "ens33", + "broadcast": "10.0.0.255", + "gateway": "10.0.0.2", + "interface": "ens33", + "macaddress": "00:0c:29:0d:1c:29", + "mtu": 1500, + "netmask": "255.255.255.0", + "network": "10.0.0.0", + "type": "ether" + }, + "ansible_default_ipv6": {}, + "ansible_device_links": { + "ids": { + "dm-0": [ + "dm-name-centos-root", + "dm-uuid-LVM-jtnKDeIbgg03hClVGR4QFsF0xdtxSolvn3Yfi9VBej4wXITukpJCMpFT914kP7cH" + ], + "sda2": [ + "lvm-pv-uuid-vWNEKk-udkQ-vl1K-YJck-9KMY-D13P-eAoAnR" + ], + "sr0": [ + "ata-VMware_Virtual_IDE_CDROM_Drive_10000000000000000001" + ] + }, + "labels": { + "sr0": [ + "CentOS\\x207\\x20x86_64" + ] + }, + "masters": { + "sda2": [ + "dm-0" + ] + }, + "uuids": { + "dm-0": [ + "d0261be2-3486-4ff1-8563-8360393cfeb4" + ], + "sda1": [ + "bdfa051f-b5a8-4713-9bee-440b49233372" + ], + "sr0": [ + "2017-09-05-14-14-50-00" + ] + } + }, + "ansible_devices": { + "dm-0": { + "holders": [], + "host": "", + "links": { + "ids": [ + "dm-name-centos-root", + "dm-uuid-LVM-jtnKDeIbgg03hClVGR4QFsF0xdtxSolvn3Yfi9VBej4wXITukpJCMpFT914kP7cH" + ], + "labels": [], + "masters": [], + "uuids": [ + "d0261be2-3486-4ff1-8563-8360393cfeb4" + ] + }, + "model": null, + "partitions": {}, + "removable": "0", + "rotational": "1", + "sas_address": null, + "sas_device_handle": null, + "scheduler_mode": "", + "sectors": "82853888", + "sectorsize": "512", + "size": "39.51 GB", + "support_discard": "0", + "vendor": null, + "virtual": 1 + }, + "sda": { + "holders": [], + "host": "", + "links": { + "ids": [], + "labels": [], + "masters": [], + "uuids": [] + }, + "model": "VMware Virtual S", + "partitions": { + "sda1": { + "holders": [], + "links": { + "ids": [], + "labels": [], + "masters": [], + "uuids": [ + "bdfa051f-b5a8-4713-9bee-440b49233372" + ] + }, + "sectors": "1024000", + "sectorsize": 512, + "size": "500.00 MB", + "start": "2048", + "uuid": "bdfa051f-b5a8-4713-9bee-440b49233372" + }, + "sda2": { + "holders": [ + "centos-root" + ], + "links": { + "ids": [ + "lvm-pv-uuid-vWNEKk-udkQ-vl1K-YJck-9KMY-D13P-eAoAnR" + ], + "labels": [], + "masters": [ + "dm-0" + ], + "uuids": [] + }, + "sectors": "82860032", + "sectorsize": 512, + "size": "39.51 GB", + "start": "1026048", + "uuid": null + } + }, + "removable": "0", + "rotational": "1", + "sas_address": null, + "sas_device_handle": null, + "scheduler_mode": "deadline", + "sectors": "83886080", + "sectorsize": "512", + "size": "40.00 GB", + "support_discard": "0", + "vendor": "VMware,", + "virtual": 1 + }, + "sr0": { + "holders": [], + "host": "", + "links": { + "ids": [ + "ata-VMware_Virtual_IDE_CDROM_Drive_10000000000000000001" + ], + "labels": [ + "CentOS\\x207\\x20x86_64" + ], + "masters": [], + "uuids": [ + "2017-09-05-14-14-50-00" + ] + }, + "model": "VMware IDE CDR10", + "partitions": {}, + "removable": "1", + "rotational": "1", + "sas_address": null, + "sas_device_handle": null, + "scheduler_mode": "cfq", + "sectors": "1622016", + "sectorsize": "2048", + "size": "792.00 MB", + "support_discard": "0", + "vendor": "NECVMWar", + "virtual": 1 + } + }, + "ansible_distribution": "CentOS", + "ansible_distribution_file_parsed": true, + "ansible_distribution_file_path": "/etc/redhat-release", + "ansible_distribution_file_variety": "RedHat", + "ansible_distribution_major_version": "7", + "ansible_distribution_release": "Core", + "ansible_distribution_version": "7.4", + "ansible_dns": { + "nameservers": [ + "10.0.0.2" + ], + "search": [ + "localdomain" + ] + }, + "ansible_domain": "", + "ansible_effective_group_id": 0, + "ansible_effective_user_id": 0, + "ansible_ens33": { + "active": true, + "device": "ens33", + "features": { + "busy_poll": "off [fixed]", + "fcoe_mtu": "off [fixed]", + "generic_receive_offload": "on", + "generic_segmentation_offload": "on", + "highdma": "off [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", + "rx_checksumming": "off", + "rx_fcs": "off", + "rx_vlan_filter": "on [fixed]", + "rx_vlan_offload": "on", + "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_mpls_segmentation": "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": "off [fixed]", + "tx_tcp_ecn_segmentation": "off [fixed]", + "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": "on [fixed]", + "tx_vlan_stag_hw_insert": "off [fixed]", + "udp_fragmentation_offload": "off [fixed]", + "vlan_challenged": "off [fixed]" + }, + "hw_timestamp_filters": [], + "ipv4": { + "address": "10.0.0.111", + "broadcast": "10.0.0.255", + "netmask": "255.255.255.0", + "network": "10.0.0.0" + }, + "ipv6": [ + { + "address": "fe80::a1d7:aadb:3ae3:bbb9", + "prefix": "64", + "scope": "link" + } + ], + "macaddress": "00:0c:29:0d:1c:29", + "module": "e1000", + "mtu": 1500, + "pciid": "0000:02:01.0", + "promisc": false, + "speed": 1000, + "timestamping": [ + "tx_software", + "rx_software", + "software" + ], + "type": "ether" + }, + "ansible_env": { + "HOME": "/root", + "LANG": "en_US.UTF-8", + "LESSOPEN": "||/usr/bin/lesspipe.sh %s", + "LOGNAME": "root", + "LS_COLORS": "rs=0:di=38;5;27:ln=38;5;51:mh=44;38;5;15:pi=40;38;5;11:so=38;5;13:do=38;5;5:bd=48;5;232;38;5;11:cd=48;5;232;38;5;3:or=48;5;232;38;5;9:mi=05;48;5;232;38;5;15:su=48;5;196;38;5;15:sg=48;5;11;38;5;16:ca=48;5;196;38;5;226:tw=48;5;10;38;5;16:ow=48;5;10;38;5;21:st=48;5;21;38;5;15:ex=38;5;34:*.tar=38;5;9:*.tgz=38;5;9:*.arc=38;5;9:*.arj=38;5;9:*.taz=38;5;9:*.lha=38;5;9:*.lz4=38;5;9:*.lzh=38;5;9:*.lzma=38;5;9:*.tlz=38;5;9:*.txz=38;5;9:*.tzo=38;5;9:*.t7z=38;5;9:*.zip=38;5;9:*.z=38;5;9:*.Z=38;5;9:*.dz=38;5;9:*.gz=38;5;9:*.lrz=38;5;9:*.lz=38;5;9:*.lzo=38;5;9:*.xz=38;5;9:*.bz2=38;5;9:*.bz=38;5;9:*.tbz=38;5;9:*.tbz2=38;5;9:*.tz=38;5;9:*.deb=38;5;9:*.rpm=38;5;9:*.jar=38;5;9:*.war=38;5;9:*.ear=38;5;9:*.sar=38;5;9:*.rar=38;5;9:*.alz=38;5;9:*.ace=38;5;9:*.zoo=38;5;9:*.cpio=38;5;9:*.7z=38;5;9:*.rz=38;5;9:*.cab=38;5;9:*.jpg=38;5;13:*.jpeg=38;5;13:*.gif=38;5;13:*.bmp=38;5;13:*.pbm=38;5;13:*.pgm=38;5;13:*.ppm=38;5;13:*.tga=38;5;13:*.xbm=38;5;13:*.xpm=38;5;13:*.tif=38;5;13:*.tiff=38;5;13:*.png=38;5;13:*.svg=38;5;13:*.svgz=38;5;13:*.mng=38;5;13:*.pcx=38;5;13:*.mov=38;5;13:*.mpg=38;5;13:*.mpeg=38;5;13:*.m2v=38;5;13:*.mkv=38;5;13:*.webm=38;5;13:*.ogm=38;5;13:*.mp4=38;5;13:*.m4v=38;5;13:*.mp4v=38;5;13:*.vob=38;5;13:*.qt=38;5;13:*.nuv=38;5;13:*.wmv=38;5;13:*.asf=38;5;13:*.rm=38;5;13:*.rmvb=38;5;13:*.flc=38;5;13:*.avi=38;5;13:*.fli=38;5;13:*.flv=38;5;13:*.gl=38;5;13:*.dl=38;5;13:*.xcf=38;5;13:*.xwd=38;5;13:*.yuv=38;5;13:*.cgm=38;5;13:*.emf=38;5;13:*.axv=38;5;13:*.anx=38;5;13:*.ogv=38;5;13:*.ogx=38;5;13:*.aac=38;5;45:*.au=38;5;45:*.flac=38;5;45:*.mid=38;5;45:*.midi=38;5;45:*.mka=38;5;45:*.mp3=38;5;45:*.mpc=38;5;45:*.ogg=38;5;45:*.ra=38;5;45:*.wav=38;5;45:*.axa=38;5;45:*.oga=38;5;45:*.spx=38;5;45:*.xspf=38;5;45:", + "MAIL": "/var/mail/root", + "PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin", + "PWD": "/root", + "SHELL": "/bin/bash", + "SHLVL": "2", + "SSH_CLIENT": "10.0.0.110 51406 22", + "SSH_CONNECTION": "10.0.0.110 51406 10.0.0.111 22", + "SSH_TTY": "/dev/pts/1", + "TERM": "xterm-256color", + "USER": "root", + "XDG_RUNTIME_DIR": "/run/user/0", + "XDG_SESSION_ID": "15", + "_": "/usr/bin/python" + }, + "ansible_fibre_channel_wwn": [], + "ansible_fips": false, + "ansible_form_factor": "Other", + "ansible_fqdn": "xingdian", + "ansible_hostname": "xingdian", + "ansible_hostnqn": "", + "ansible_interfaces": [ + "lo", + "ens33" + ], + "ansible_is_chroot": false, + "ansible_iscsi_iqn": "", + "ansible_kernel": "3.10.0-693.el7.x86_64", + "ansible_kernel_version": "#1 SMP Tue Aug 22 21:09:27 UTC 2017", + "ansible_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_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_mpls_segmentation": "off [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" + }, + "ansible_local": {}, + "ansible_lsb": {}, + "ansible_lvm": { + "lvs": { + "root": { + "size_g": "39.51", + "vg": "centos" + } + }, + "pvs": { + "/dev/sda2": { + "free_g": "0", + "size_g": "39.51", + "vg": "centos" + } + }, + "vgs": { + "centos": { + "free_g": "0", + "num_lvs": "1", + "num_pvs": "1", + "size_g": "39.51" + } + } + }, + "ansible_machine": "x86_64", + "ansible_machine_id": "b2553b2f1ad64a88a81a775b55de0eb3", + "ansible_memfree_mb": 1754, + "ansible_memory_mb": { + "nocache": { + "free": 1833, + "used": 151 + }, + "real": { + "free": 1754, + "total": 1984, + "used": 230 + }, + "swap": { + "cached": 0, + "free": 0, + "total": 0, + "used": 0 + } + }, + "ansible_memtotal_mb": 1984, + "ansible_mounts": [ + { + "block_available": 97092, + "block_size": 4096, + "block_total": 127145, + "block_used": 30053, + "device": "/dev/sda1", + "fstype": "xfs", + "inode_available": 255673, + "inode_total": 256000, + "inode_used": 327, + "mount": "/boot", + "options": "rw,relatime,attr2,inode64,noquota", + "size_available": 397688832, + "size_total": 520785920, + "uuid": "bdfa051f-b5a8-4713-9bee-440b49233372" + }, + { + "block_available": 9998628, + "block_size": 4096, + "block_total": 10351679, + "block_used": 353051, + "device": "/dev/mapper/centos-root", + "fstype": "xfs", + "inode_available": 20687486, + "inode_total": 20713472, + "inode_used": 25986, + "mount": "/", + "options": "rw,relatime,attr2,inode64,noquota", + "size_available": 40954380288, + "size_total": 42400477184, + "uuid": "d0261be2-3486-4ff1-8563-8360393cfeb4" + } + ], + "ansible_nodename": "xingdian", + "ansible_os_family": "RedHat", + "ansible_pkg_mgr": "yum", + "ansible_proc_cmdline": { + "BOOT_IMAGE": "/vmlinuz-3.10.0-693.el7.x86_64", + "LANG": "en_US.UTF-8", + "quiet": true, + "rd.lvm.lv": "centos/root", + "rhgb": true, + "ro": true, + "root": "/dev/mapper/centos-root" + }, + "ansible_processor": [ + "0", + "GenuineIntel", + "11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz" + ], + "ansible_processor_cores": 1, + "ansible_processor_count": 1, + "ansible_processor_threads_per_core": 1, + "ansible_processor_vcpus": 1, + "ansible_product_name": "VMware Virtual Platform", + "ansible_product_serial": "VMware-56 4d 77 c3 38 eb b5 44-f9 c5 f5 a9 0c 0d 1c 29", + "ansible_product_uuid": "C3774D56-EB38-44B5-F9C5-F5A90C0D1C29", + "ansible_product_version": "None", + "ansible_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 + ] + }, + "ansible_python_version": "2.7.5", + "ansible_real_group_id": 0, + "ansible_real_user_id": 0, + "ansible_selinux": { + "status": "disabled" + }, + "ansible_selinux_python_present": true, + "ansible_service_mgr": "systemd", + "ansible_ssh_host_key_ecdsa_public": "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFWlYnYAyylfiZr2C9xiHsT8i2ao+RY8CY+z6wJEBQxdtg+/VHmxYOejdPKrq94IjLU00x5Iu096aQ5XdNyDUs4=", + "ansible_ssh_host_key_ed25519_public": "AAAAC3NzaC1lZDI1NTE5AAAAIPHn7/QapryKV1IenlFdQngIQed+y9YyziwtVYnBflG9", + "ansible_ssh_host_key_rsa_public": "AAAAB3NzaC1yc2EAAAADAQABAAABAQCso6OpQ9TsQ/2ihnVLtUpqK4y1hjR9WyHqKQFcqH7TN9TDxuyB+gPfN1IzC25IoUb8mp9zIiLNqg8epsNbKFj9l3WQUtx3fcSXqIcZdWeTWkltxz0DxSr0xQd+odYwQ+ppH5gFjvTnJNcVJhqfMLAdQjLFjSrZfvF28qUyTGj8HJC7qGneM9ECLQwQ+ZQ6qvjaXMpgUR4p9JsOdSeicGD3mZwIsvScfhHq011V/2ZCQAgCuUlO/Z6+Xbzc27ZPyu4wkZYWM+DyZEXi0cvO5WYV+tst8uwdBQhSaQi8T5Vu7eUitdoFBC9vTFjZiR39dxEHy2nlkTnJWZ9ChLY08iLf", + "ansible_swapfree_mb": 0, + "ansible_swaptotal_mb": 0, + "ansible_system": "Linux", + "ansible_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" + ], + "ansible_system_capabilities_enforced": "True", + "ansible_system_vendor": "VMware, Inc.", + "ansible_uptime_seconds": 3024, + "ansible_user_dir": "/root", + "ansible_user_gecos": "root", + "ansible_user_gid": 0, + "ansible_user_id": "root", + "ansible_user_shell": "/bin/bash", + "ansible_user_uid": 0, + "ansible_userspace_architecture": "x86_64", + "ansible_userspace_bits": "64", + "ansible_virtualization_role": "guest", + "ansible_virtualization_type": "VMware", + "discovered_interpreter_python": "/usr/bin/python", + "gather_subset": [ + "all" + ], + "module_setup": true + }, + "changed": false +} +``` + +## 二:使用Setup + +#### 1.案例一 + +​ 使用“ansible_fqdn”获取主机名称和域名 + +```yml +[root@xingdian ansible]# cat test.yml +- name: test a playbook + hosts: web + tasks: + - name: hostname + debug: + msg: "{{ ansible_fqdn }}" +``` + +​ 运行剧本 + +```yaml +[root@xingdian ansible]# ansible-playbook test.yml +[WARNING]: Could not match supplied host pattern, ignoring: node1 + +PLAY [test a playbook] **************************************************************************************************************************************** +skipping: no hosts matched + +PLAY RECAP **************************************************************************************************************************************************** + +[root@xingdian ansible]# vim test.yml +[root@xingdian ansible]# ansible-playbook test.yml + +PLAY [test a playbook] **************************************************************************************************************************************** + +TASK [Gathering Facts] **************************************************************************************************************************************** +ok: [10.0.0.111] + +TASK [hostname] *********************************************************************************************************************************************** +ok: [10.0.0.111] => { + "msg": "xingdian" +} + +PLAY RECAP **************************************************************************************************************************************************** +10.0.0.111 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 +``` + +#### 2.案例二 + +​ 使用“ansible_ens33.ipv4.address”获取指定网卡IP地址 + +```yaml +[root@xingdian ansible]# cat test.yml +- name: test a playbook + hosts: web + tasks: + - name: hostname + debug: + msg: "{{ ansible_ens33.ipv4.address }}" +``` + +​ 运行剧本 + +```yaml +[root@xingdian ansible]# ansible-playbook test.yml + +PLAY [test a playbook] **************************************************************************************************************************************** + +TASK [Gathering Facts] **************************************************************************************************************************************** +ok: [10.0.0.111] + +TASK [hostname] *********************************************************************************************************************************************** +ok: [10.0.0.111] => { + "msg": "10.0.0.111" +} + +PLAY RECAP **************************************************************************************************************************************************** +10.0.0.111 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 +``` + +#### 3.案例三 + +​ 使用“ansible_devices.sda.partitions.sda2.size”获取磁盘容量 + +```yaml +[root@xingdian ansible]# cat test.yml +- name: test a playbook + hosts: web + tasks: + - name: hostname + debug: + msg: "{{ ansible_devices.sda.partitions.sda2.size }}" +``` + +​ 运行剧本 + +```yaml +[root@xingdian ansible]# ansible-playbook test.yml + +PLAY [test a playbook] **************************************************************************************************************************************** + +TASK [Gathering Facts] **************************************************************************************************************************************** +ok: [10.0.0.111] + +TASK [hostname] *********************************************************************************************************************************************** +ok: [10.0.0.111] => { + "msg": "39.51 GB" +} + +PLAY RECAP **************************************************************************************************************************************************** +10.0.0.111 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 +``` + diff --git a/ansible/Ansible自动化运维基础.md b/ansible/Ansible自动化运维基础.md new file mode 100644 index 0000000..47346de --- /dev/null +++ b/ansible/Ansible自动化运维基础.md @@ -0,0 +1,1097 @@ +

Ansible自动化运维基础

+ +------ + +**作者:行癫(盗版必究)** + +## 一:简介 + +#### 1.自动化运维工具对比 + +​ Puppet:基于 Ruby 开发,采用 C/S 架构,扩展性强,基于 SSL,远程命令执行相对较弱 + +​ SaltStack:基于 Python 开发,采用 C/S 架构,YAML使得配置脚本更简单.需要配置客户端及服务器端;每台被控制节点需要安装agent + +​ Ansible:基于 Python开发,分布式,无需客户端,轻量级,配置语法使用YAML语言,更强的远程命令执行操作 + +#### 2.Ansible简介 + +​ ansible是新出现的自动化运维工具,基于Python开发,分布式,无需客户端,轻量级,实现了批量系统配置、批量程序部署、批量运行命令等功能,ansible是基于模块工作的,本身没有批量部署的能力。真正具有批量部署的是ansible所运行的模块,ansible只是提供一种框架 + +特性: + +​ no agents:不需要在被管控主机上安装任何客户端,更新时,只需在操作机上进行一次更新即可(不用安装客户端。分布式的) + +​ no server:无服务器端,使用时直接运行命令即可 + +​ modules in any languages:基于模块工作,可使用任意语言开发模块 + +​ yaml,not code:使用yaml语言定制剧本playbook + +​ ssh by default:基于SSH工作 + +​ strong multi-tier solution:可实现多级指挥 + +特点: + +image-20230228225234537 + +​ connection plugins:连接插件,负责和被监控端实现通信,默认使用SSH连接 + +​ host inventory:主机清单,是一个配置文件里面定义监控的主机 + +​ modules : 模块,核心模块、command模块、自定义模块等 + +​ plugins : modules功能的补充,包括连接插件,邮件插件等 + +​ playbook:编排,定义 Ansible 多任务配置文件,非必需 + +#### 3.部署Ansible + +环境准备: + +```shell +环境: +主机:4台 一个控制节点 3个被控制节点 +解析:本地互相解析(所有机器) +# vim /etc/hosts +192.168.1.10 ansible-web1 +192.168.1.11 ansible-web2 +192.168.1.12 ansible-web3 +192.168.1.9 ansible-server (控制节点服务器端) +配置ssh公钥认证:控制节点需要发送ssh公钥给所有非被控制节点 +[root@ansible-server ~]# ssh-keygen +[root@ansible-server ~]# ssh-copy-id -i 192.168.1.10 #所有机器 + +所有机器: +systemctl stop firewalld && setenforce 0 +``` + +安装ansible: + +```shell +安装:控制节点 + 1. 配置EPEL网络yum源 + [root@ansible-server ~]# yum install -y epel-release + 2. 安装ansible + [root@ansible-server ~]# yum install -y ansible + 3.查看版本 + [root@ansiable-server ~]# ansible --version +ansible 2.9.2 + config file = /etc/ansible/ansible.cfg + configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules'] + ansible python module location = /usr/lib/python2.7/site-packages/ansible + executable location = /usr/bin/ansible + python version = 2.7.5 (default, Oct 30 2018, 23:45:53) [GCC 4.8.5 20150623 (Red Hat 4.8.5-36)] + + 4.看帮助 + [root@ansible-server ~]# ansible --help +``` + +## 二:主机清单inventory + +​ inventory文件通常用于定义要管理主机及其认证信息,例如ssh登录用户名、密码以及key相关信息 + +#### 1.配置文件 + +```shell +vim /etc/ansible/hosts + web1 //单独指定主机,可以使用主机名称或IP地址 + web2 + web3 + #----------------------------------------------------------------- + [webservers] //使用[]标签指定主机组 + 192.168.10.128 + bar.example.com + up.example.com:5309 //指定 SSH 端口 5309 + web5 ansible_ssh_host=web2 //设置主机web2的别名为 web5 + web1 ansible_ssh_pass='123' //设置ssh密码,使用-k参数之后提示的密码可以不写,直接回车 + www[01:50].example.com //支持通配符匹配www01,www02,...,www50 + db-[a:f].example.com //通配符匹配db-a,db-b,...,db-f + #----------------------------------------------------------------- + 为每个主机单独指定变量,这些变量随后可以在 playbooks 中使用:内置变量 + [atlanta] + host1 http_port=80 maxRequestsPerChild=808 + host2 http_port=303 maxRequestsPerChild=909 + #------------------------------------------------------------------ + 为一个组指定变量,组内每个主机都可以使用该变量: + [atlanta] + host1 + host2 + [atlanta:vars] + ansible_ssh_pass='123' + ntp_server=ntp.atlanta.example.com + proxy=proxy.atlanta.example.com + #----------------------------------------------------------------- + 组可以包含其他组: + [atlanta] + host1 + host2 + [raleigh] + host3 + host4 + [southeast:children] //southeast包括两个子组 + atlanta + raleigh + [southeast:vars] + some_server=foo.southeast.example.com + halon_system_timeout=30 +``` + +​ ansible基于ssh连接inventory中指定的远程主机时,还可以通过参数指定其交互方式 + +```shell + ansible_ssh_host # 远程主机 + ansible_ssh_port # 指定远程主机ssh端口 + ansible_ssh_user # ssh连接远程主机的用户,默认root + ansible_ssh_pass # 连接远程主机使用的密码,在文件中明文,建议使用--ask-pass或者使用SSH keys + ansible_sudo_pass # sudo密码, 建议使用--ask-sudo-pass + ansible_connection # 指定连接类型: local, ssh, paramiko + ansible_ssh_private_key_file # ssh 连接使用的私钥 + ansible_shell_type # 指定连接对端的shell类型, 默认sh,支持csh,fish + ansible_python_interpreter # 指定对端使用的python编译器的路径 +``` + +#### 2.使用 + +​ 查看组内主机列表 + +``` +语法:ansible 组名 --list-hosts +[root@xingdian ~]# ansible web --list-hosts + hosts (2): + 172.17.0.2 + 172.17.0.3 +``` + +​ 自定义主机列表 + +```shell +vim /home/ansible/hostlist +[all:vars] +ansible_ssh_port=22 +ansible_ssh_user=root +#ansible_ssh_private_key_file=/root/.ssh/id_rsa +ansible_ssh_pass=1 +[all] +ansible-web1 +ansible-web2 +``` + +​ 案例 + +```shell +[root@ansible-server ~]# ansible -i /opt/hostlist all -m ping -o +-i:指定清单文件 +``` + +注意: + +```shell +一个典型的例子就是 shell 和 command 模块. 这两个模块在很多情况下都能完成同样的工作, 以下是两个模块之前的区别: +command 模块命令将不会使用 shell 执行. 因此, 像 $HOME 这样的变量是不可用的。还有像 |,& 都将不可用 +shell 模块通过shell程序执行, 默认是/bin/sh, <, >, |, ;, & 可用 +``` + +## 三:点对点Ad-Hoc + +​ ad hoc 临时的,在ansible中是指需要快速执行,并且不需要保存的命令 + +​ 简单的命令——一条命令;对于复杂的命令则为 playbook + +#### 1.ansible模块 + +​ 列出ansible支持的模块: + +```shell +-l:获取列表 +-s module_name:获取指定模块的使用信息 +获取模块列表 +[root@ansible-server ~]# ansible-doc -l +模块使用格式: +[root@ansible-server ~]# ansible-doc -s yum +``` + +​ 模块官方文档:https://docs.ansible.com/ansible/2.9/modules/list_of_files_modules.html + +常用模块 + +**用户管理模块:user** + +​ 添加用户并设置密码: + +```shell +[root@ansible-server ~]# ansible webservers1 -m user -a "name=liudehua password=`echo 1234 | openssl passwd -1 -stdin`" -o +"name= " #如:指定的用户名,要安装的软件 +-1 MD5加密算法 +``` + +​ 删除用户: + +```shell +[root@ansible-server ~]# ansible webservers1 -m user -a "name=liudehua state=absent" -o +adsent #删除用户,但是不会删除家目录 +``` + +**组管理模块:group** + +​ 参数: + +```shell +gid:为组设置的可选GID +name:要管理的组的名称 +state:该组是否应该存在于远程主机上;absent不在/默认是present在 +system:如果是,表示创建的组是系统组;默认时no +``` + +​ 案例: + +```shell +[root@ansible-server ~]# ansible all -m group -a 'name=somegroup state=present' +``` + +**软件包管理模块:yum** + +​ 参数: + +```shell +config_file:yum的配置文件 +disable_gpg_check:关闭gpg_check +disablerepo:不启用某个源 +enablerepo:启用某个源 +name:要进行操作的软件包的名字,也可以传递一个url或者一个本地的rpm包的路径 +state:状态(present,absent,latest) +``` + +​ 安装apache: + +```shell +[root@ansible-server ~]# ansible webservers1 -m yum -a "name=httpd state=latest" -o +state= #状态是什么,干什么 +state=absent 用于remove安装包 +state=latest 表示最新的 +state=removed 表示卸载 +``` + +​ 卸载软件: + +```shell +[root@ansible-server ~]# ansible webservers1 -m yum -a "name=httpd state=removed" -o +``` + +**服务管理模块:service** + +​ 参数: + +```shell +arguments:给命令行提供一些选项 +enabled:是否开机启动 yes|no +name:必选项,服务名称 +pattern:定义一个模式,如果通过status指令来查看服务的状态时,没有响应,就会通过ps指令在进程中根据该模式进行查找,如果匹配到,则认为该服务依然在运行 +runlevel:运行级别 +sleep:如果执行了restarted,在则stop和start之间沉睡几秒钟 +state:对当前服务执行启动,停止、重启、重新加载等操作(started,stopped,restarted,reloaded) +``` + +​ 案例: + +```shell +[root@ansible-server ~]# ansible webservers1 -m service -a "name=httpd state=started" #启动 +[root@ansible-server ~]# ansible webservers1 -m service -a "name=httpd state=stopped" #停止 +[root@ansible-server ~]# ansible webservers1 -m service -a "name=httpd state=restarted" #重启 +[root@ansible-server ~]# ansible webservers1 -m service -a "name=httpd state=started enabled=yes" #开机启动 +[root@ansible-server ~]# ansible webservers1 -m service -a "name=httpd state=started enabled=no" #开机关闭 +``` + +**文件模块:file** + +​ 参数: + +```shell +owner:修改属主 +group:修改属组 +mode:修改权限 +path=:要修改文件的路径 +recurse:递归的设置文件的属性,只对目录有效 + yes:表示使用递归设置 +state: +touch:创建一个新的空文件 +directory:当目录存在时不会进行修改 +``` + +​ 案例: + +```shell +[root@ansible-server ~]# ansible webservers1 -m file -a 'path=/tmp/88.txt mode=777 state=touch' #创建一个文件 +[root@ansible-server ~]# ansible webservers1 -m file -a 'path=/tmp/99 mode=777 state=directory' #创建一个目录 +``` + +**收集信息模块:setup** + +```shell +[root@ansible-server ~]# ansible webservers1 -m setup #收集所有信息 +[root@ansible-server ~]# ansible webservers1 -m setup -a 'filter=ansible_all_ipv4_addresses' #只查询ipv4的地址 +filter:过滤 +[root@ansible-server ~]# ansible webservers1 -m setup -a 'filter=ansible_*_mb' +[root@ansible-server ~]# ansible -i /home/ansible/hostlist web -m setup -a 'filter=ansible_processor_cores' +[root@ansible-server ~]# ansible all -m setup --tree /tmp/facts +``` + +**文件复制模块:copy** + +​ 参数: + +```shell +backup:在覆盖之前,将源文件备份,备份文件包含时间信息。有两个选项:yes|no +content:用于替代“src”,可以直接设定指定文件的值 +dest:必选项。要将源文件复制到的远程主机的绝对路径,如果源文件是一个目录,那么该路径也必须是个目录 +directory_mode:递归设定目录的权限,默认为系统默认权限 +force:如果目标主机包含该文件,但内容不同,如果设置为yes,则强制覆盖,如果为no,默认为yes +others:所有的file模块里的选项都可以在这里使用 +src:被复制到远程主机的本地文件,可以是绝对路径,也可以是相对路径。如果路径是一个目录,它将递归复制。在这种情况下,如果路径使用“/”来结尾,则只复制目录里的内容,如果没有使用“/”来结尾,则包含目录在内的整个内容全部复制 +``` + +​ 案例: + +```shell +[root@ansible-server ~]# ansible test -m copy -a "src=/srv/myfiles/foo.conf dest=/etc/foo.conf owner=foo group=foo mode=0644" +[root@ansible-server ~]# ansible test -m copy -a "src=/mine/ntp.conf dest=/etc/ntp.conf owner=root group=root mode=644 backup=yes" +``` + +**计划任务模块:cron** + +​ 参数: + +```shell +backup:对远程主机上的原任务计划内容修改之前做备份 +cron_file:如果指定该选项,则用该文件替换远程主机上的cron.d目录下的用户的任务计划 +day:日(1-31,*,*/2,……) +hour:小时(0-23,*,*/2,……) +minute:分钟(0-59,*,*/2,……) +month:月(1-12,*,*/2,……) +weekday:周(0-7,*,……) +job:要执行的任务,依赖于state=present +name:该任务的描述 +special_time:指定什么时候执行,参数:reboot,yearly,annually,monthly,weekly,daily,hourly +state:确认该任务计划是创建还是删除 +user:以哪个用户的身份执行 +``` + +​ 案例: + +```shell +[root@ansible-server ~]# ansible test -m cron -a 'name="a job for reboot" special_time=reboot job="/some/job.sh"' +[root@ansible-server ~]# ansible test -m cron -a 'name="yum autoupdate" weekday="2" minute=0 hour=12 user="root +[root@ansible-server ~]# ansible test -m cron  -a 'backup="True" name="test" minute="0" hour="5,2" job="ls -alh > /dev/null"' +[root@ansible-server ~]# ansilbe test -m cron -a 'cron_file=ansible_yum-autoupdate state=absent' +``` + +#### 2.实战案例 + +​ 获取每台主机的IP地址 + +```shell +[root@xingdian ~]# ansible -i /home/ansible/hostlist web -m shell -a "ip a | grep eth0| awk 'NR==2{print $2}'" -o > a.txt && cat a.txt |awk '{print $9,$NF}' +``` + +​ 获取每台主机的内存 + +```shell +[root@xingdian ~]# ansible -i /home/ansible/hostlist web -m shell -a "free -m | awk 'NR==2'" > b.txt -o && cat b.txt | awk '{print $10}' +``` + +## 四:剧本Playbook + +#### 1.介绍 + +​ playbook是ansible用于配置,部署,和管理被控节点的剧本。通过playbook的详细描述,执行其中的tasks,可以让远端主机达到预期的状态。playbook是由一个或多个”play”组成的列表。 当对一台机器做环境初始化的时候往往需要不止做一件事情,这时使用playbook会更加适合。通过playbook你可以一次在多台机器执行多个指令。通过这种预先设计的配置保持了机器的配置统一,并很简单的执行日常任务 + +#### 2.格式 + +​ playbook由YMAL语言编写。YMAL格式是类似于JSON的文件格式,便于人理解和阅读,同时便于书写 + +​ yaml介绍见另一章 + +#### 3.核心元素 + +​ Variables #变量元素,可传递给Tasks/Templates使用 + +​ Tasks #任务元素,由模块定义的操作的列表,即调用模块完成任务 + +​ Templates #模板元素,使用了模板语法的文本文件,可根据变量动态生成配置文件 + +​ Handlers #处理器元素,通常指在某事件满足时触发的操作 + +​ Roles #角色元素 + +注意: + +​ 一个剧本里面可以有多个play,每个play只能有一个tasks,每个tasks可以有多个name + +#### 4.基础组件 + +name: + +​ 定义playbook或者task的名称(描述信息),每一个play都可以完成一个任务 + +hosts: + +​ playbook中的每一个paly的目的都是为了让某个或某些以某个指定用户的身份执行任务;与命令模式下的ansible匹配规则一样 + +user: + +​ remote_user则用于指定远程主机上的执行任务的用户,也可以使用user(基本上是root) + +tasks: + +​ 任务列表play的主体部分是task list. task list中的各任务按次序逐个在hosts中指定的所有主机上执行 + +vars: + +​ 定义变量(如果不使用内部变量需要提前定义) + +vars_files: + +​ 调用定义变量文件 + +notify: + +​ 任务执行结果如果是发生更改了的则触发定义在handler的任务执行 + +handlers: + +​ 用于当前关注的资源发生变化时采取一定指定的操作 + +include: + +​ 能包含的包括task,handler和playbook;可以在include的时候传递变量 + +## 五:剧本案例 + +#### 1.案例一 + +``` +[root@ansible-server ~]# cd /etc/ansible/ +[root@ansible-server ansible]# vim test.yml #创建文件必须以.yml结尾 +--- + - hosts: webservers1 + user: root + tasks: + - name: playbook_test + file: state=touch path=/tpm/playbook.txt +``` + +参数解释 + +​ hosts:参数指定了对哪些主机进行操作 + +​ user:参数指定了使用什么用户登录远程主机操作 + +​ tasks:指定了一个任务 + +​ name:参数同样是对任务的描述,在执行过程中会打印出 + +检测语法 + +```shell +[root@ansible-server ansible]# ansible-playbook --syntax-check test.yml +playbook: test.yml +``` + +运行Playbook + +```shell +[root@ansible-server ansible]# ansible-playbook test.yml +``` + +#### 2.案例二 + +​ handlers:由特定条件触发的Tasks + +语法 + +```yaml +tasks: +- name: TASK_NAME + module: arguments #1.上面任务执行成功,然后 + notify: HANDLER_NAME #2.通知他 +handlers: +- name: HANDLER_NAME #3.一一对应,这里的描述与notify定义的必须一样 + module: arguments #4.执行这个命令 +``` + +案例 + +```yaml +[root@ansible-server ansible]# vim handlers.yml +- hosts: webservers1 + user: root + tasks: + - name: test copy + copy: src=/root/a.txt dest=/mnt + notify: test handlers + handlers: + - name: test handlers + shell: echo "abcd" >> /mnt/a.txt +``` + +注意: + +​ 只有 copy 模块真正执行后,才会去调用下面的 handlers 相关的操作,追加内容。所以这种比较适合配置文件发生更改后,需要重启服务的操作 + +检测语法 + +```shell +[root@ansible-server ansible]# ansible-playbook --syntax-check handlers.yml +playbook: handlers.yml +``` + +运行剧本 + +```shell +[root@ansible-server ansible]# ansible-playbook handlers.yml +``` + +#### 3.案例三 + +安装nginx并启动服务 + +``` +[root@ansible-server ansible]# vim /home/ansible/yum.yml +--- + - hosts: web + user: root + tasks: + - name: install nginx + yum: name=nginx state=latest + notify: diandian + handlers: + - name: diandian + service: name=nginx state=started +``` + +检测语法 + +```shell +[root@ansible-server ansible]# ansible-playbook --syntax-check /home/ansible/yum.yml +playbook: handlers.yml +``` + +运行剧本 + +```shell +[root@ansible-server ansible]# ansible-playbook /home/ansible/yum.yml +``` + +4.案例四 + +​ 循环:迭代,需要重复执行的任务 + +​ 对迭代项的引用,固定变量名为”item”,使用with_items属性给定要迭代的元素 + +​ 元素:1.列表 2.字符串 3.字典 + +**基于字符串列表元素实战** + +```yaml +[root@ansible-server ansible]# vim list.yml +- hosts: websrvs + remote_user: root + tasks: + - name: install packages + yum: name={{ item }} state=latest #相当于for循环里面的i + with_items: #取值 。但是不支持通配符 + - httpd + - php + - php-mysql + - php-mbstring + - php-gd +``` + +语法检测 + +```shell +[root@ansible-server ansible]# ansible-playbook --syntax-check list.yml +playbook: list.yml +``` + +运行剧本 + +```shell +[root@ansible-server ansible]# ansible-playbook list.yml +``` + +**基于字典列表给元素示例** + +``` +[root@ansible-server ansible]# vim zidian.yml +- hosts: all + user: root + tasks: + - name: create groups + group: name={{ item }} state=present + with_items: + - groupx1 + - groupx2 + - groupx3 + - name: create users + user: name={{ item.name }} group={{ item.group }} state=present + with_items: #这里使用的是字典 + - {name: 'userx1', group: 'groupx1'} + - {name: 'userx2', group: 'groupx2'} + - {name: 'userx3', group: 'groupx3'} +``` + +语法检测 + +```shell +[root@ansible-server ansible]# ansible-playbook --syntax-check zidian.yml +playbook: zidian.yml +``` + +运行剧本 + +```shell +[root@ansible-server ansible]# ansible-playbook zidian.yml +``` + +#### 4.案例四 + +tags使用 + +​ 给指定的任务定义一个调用标识,形式如下;只运行指定标记的任务:-t tags + +```shell +[root@ansible ansible]# ansible-playbook -t 标记名称 test.yml +``` + +​ 跳过某一个被标记的任务:--skip-tags=SKIP_TAGS + +```shell +[root@ansible ansible]# ansible-playbook --skip-tags=标记名称 test.yml +``` + +​ 从某一个任务开始往下运行:--start-at-task 任务名称 + +```shell +[root@ansible ansible]# ansible-playbook --start-at-task "start httpd service" test.yml +``` + +案例 + +```yaml +[root@xingdian /]# vim /home/ansible/tag.yml +--- + - hosts: web + user: root + tasks: + - name: touch file + file: path=/root/nihao.txt state=touch + tags: nihao + - name: mkdir file + file: path=/root/xingdian state=directory + tags: xingdian + - name: touch file1 + file: path=/root/file1.txt state=touch + tags: file1 +``` + +#### 5.案例五 + +​ 批量安装apache服务,并使用浏览器访问到对应的项目 + +```yaml +[root@xingdian /]# vim /home/ansible/apache.yml +--- + - hosts: web + user: root + tasks: + - name: apache install + yum: name=httpd state=latest + - name: mkdir file + file: path=/web1 state=directory mode=777 + - name: copy index + copy: src=/index.html dest=/web1 + - name: Listen + shell: echo "Listen 81" >> /etc/httpd/conf/httpd.conf + - name: copy conf + copy: src=/wordpress.conf dest=/etc/httpd/conf.d/ + notify: start httpd + handlers: + - name: start httpd + service: name=httpd state=restarted +``` + +检测语法 + +```shell +[root@ansible-server ansible]# ansible-playbook --syntax-check apache.yml +playbook: list.yml +``` + +运行剧本 + +```shell +[root@xingdian /]# ansible-playbook /home/ansible/apache.yml +``` + +## 六:变量使用 + +#### 1.语法格式 + +```shell +变量调用语法: +{{ var_name }} +``` + +#### 2.案例一 + +​ 通过命令行传递变量:(通过--extra-vars或-e选项来传递key=value变量) + +```shell +[root@xingdian /]# ansible-playbook release.yml -e "user=starbuck" +``` + +​ 传递字典 + +```shell +[root@xingdian ansible]# ansible-playbook conf.yml -e '{"conf81":"/root/81.conf","conf82":"/root/conf82"}' +``` + +#### 3.案例二 + +​ 创建变量目录 + +```shell +[root@ansible-server ~]# mkdir /etc/ansible/vars +[root@ansible-server ~]# cd /etc/ansible/vars/ +``` + +​ 创建变量文件 + +```shell +[root@ansible-server vars]# vim file.yml +src_path: /root/test/a.txt +dest_path: /opt/test/ +``` + +​ 创建一个测试文件 + +```shell +[root@ansible-server vars]# mkdir /root/test +[root@ansible-server vars]# echo 123 >/root/test/a.txt +``` + +​ 创建playbook引用变量文件 + +```yaml +[root@ansible-server vars]# cd /etc/ansible/ +[root@ansible-server ansible]# vim vars.yml +- hosts: ansible-web1 + user: root + vars_files: + - /etc/ansible/vars/file.yml + tasks: + - name: create directory + file: path={{ dest_path }} mode=755 state=directory + - name: copy file + copy: src={{ src_path }} dest={{ dest_path }} +``` + +​ 检测语法 + +```shell +[root@ansible-server ansible]# ansible-playbook --syntax-check vars.yml +playbook: vars.yml +``` + +​ 运行剧本 + +```shell +[root@ansible-server ansible]# ansible-playbook vars.yml +``` + +#### 4.案例三 + +​ 文件中包含变量 + +```yaml +[root@xingdian ansible]# vim conf.yml +- hosts: web + remote_user: root + vars: + httpd: + conf80: /root/80.conf + conf8080: /root/8080.conf + tasks: + - name: task1 + file: + path: "{{httpd.conf80}}" + state: touch + - name: task2 + file: + path: "{{httpd.conf8080}}" + state: touch +``` + +​ 检测语法 + +```shell +[root@xingdian ansible]# ansible-playbook --syntax-check conf.yml +``` + +​ 运行剧本 + +```shell +[root@xingdian ansible]# ansible-playbook conf.yml +``` + +#### 5.案例四 + +​ 在主机清单中定义变量 + +```shell +[root@xingdian ansible]# tail -5 /etc/ansible/hosts +[web] +10.0.0.111 +[web:vars] +conf81=ppp +conf82=ooo +``` + +​ 创建剧本 + +```yml +[root@xingdian ansible]# cat conf.yml +- hosts: web + remote_user: root + tasks: + - name: task1 + file: + path: "{{ conf81 }}" + state: touch + - name: task2 + file: + path: "{{ conf82 }}" + state: touch +``` + +​ 语法检测 + +```shell +[root@xingdian ansible]# ansible-playbook --syntax-check conf.yml +``` + +​ 运行剧本 + +```shell +[root@xingdian ansible]# ansible-playbook conf.yml +``` + +#### 6.案例五 + +​ set_fact自定义facts变量 + +​ set_fact模块可以自定义facts,这些自定义的facts可以通过template或者变量的方式在playbook中使用。如果你想要获取一 个进程使用的内存的百分比,则必须通过set_fact来进行计算之后得出其值,并将其值在playbook中引用 + +​ 配置mysql innodb buffer size的示例 + +```yaml + - name: Configure MySQL + hosts: web + tasks: + - name: Calculate InnoDB buffer pool size + set_fact: innodb_buffer_pool_size_mb="{{ ansible_swapfree_mb / 2 }}" + - name: nihao + template: src=/my.cnf dest=/etc/my.cnf owner=root group=root mode=0644 +``` + +​ 参数说明 + +```shell +set_fact: innodb_buffer_pool_size_mb="{{ ansible_memtotal_mb / 2 }}" + 通过sey_fact去定义,而不是直接执行 +template: src=templates/my.cnf dest=/etc/my.cnf owner=root group=root mode=0644 + template:这个是一个模板 可以传变量 +``` + +​ my.cnf文件 + +```shell +[mysqld] +datadir=/var/lib/mysql +socket=/var/lib/mysql/mysql.sock +# Disabling symbolic-links is recommended to prevent assorted +security risks +symbolic-links=0 + +# Configure the buffer pool +innodb_buffer_pool_size = {{ innodb_buffer_pool_size_mb|int }}M +[mysqld_safe] +log-error=/var/log/mysqld.log +pid-file=/var/run/mysqld/mysqld.pid +``` + +## 七:Role角色 + +#### 1.介绍 + +​ Roles是在ansible中,playbook的目录组织结构 + +​ 每一个角色是有名字的 ,他是一个目录 ,可以包含子目录 + +​ 以特定的层级目录结构进行组织的tasks、variables、handlers、templates、files等 + +#### 2.目录作用 + +role_name:这个是角色的名称 + +files:存储由copy或script等模块调用的文件 + +tasks:专门存储任务的目录,一个角色可以定义多个任务;此目录中至少应该有一个名为main.yml的文件,用于定义各task;其它的文件需要由main.yml进行“包含”调用 + +handlers:条件 前一个任务执行成功去执行下面的,处理特定事物的文件,此目录中至少应该有一个名为main.yml的文件,用于定义各handler;其它的文件需要由main.yml进行“包含”调用 + +vars:变量 ,定义变量的文件;此目录中至少应该有一个名为main.yml的文件,用于定义各variable;其它的文件需要由main.yml进行“包含”调用 + +templates:模板 使用变量的文件存储由template模块调用的模板文本 + +meta:此目录中至少应该有一个名为main.yml的文件,定义当前角色的特殊设定及其依赖关系;其它的文件需要由main.yml进行“包含”调用 + +default:此目录中至少应该有一个名为main.yml的文件,用于设定默认变量 + +#### 3.目录案例 + +​ nginx是一个角色的名字,角色里用到文件放在files中,通过创建playbook来调用这些角色 + +image-20230303004925730 + +#### 4.项目案例 + +​ 准备目录结构 + +```shell +[root@ansible-server ~]# cd /etc/ansible/roles/ #role位自带目录,如果不存在可以创建 +[root@ansible-server roles]# mkdir nginx/{files,handlers,tasks,templates,vars} -p +``` + +​ 创建文件 + +```shell +[root@ansible-server roles]# touch site.yml nginx/{handlers,tasks,vars}/main.yml +[root@ansible-server roles]# yum install -y tree +[root@xingdian roles]# tree nginx/ +nginx/ +├── files +├── handlers +│   └── main.yml +├── tasks +│   └── main.yml +├── templates +└── vars + └── main.yml + +5 directories, 3 files +``` + +​ 创建nginx的测试文件 + +```shell +[root@ansible-server roles]# echo 1234 > nginx/files/index.html +``` + +​ 安装nginx并配置模板 + +```shell +[root@ansible-server roles]# yum install -y nginx && cp /etc/nginx/nginx.conf nginx/templates/nginx.conf.j2 +``` + +​ 编写任务 + +```yml +[root@ansible-server roles]# vim nginx/tasks/main.yml +--- +- name: install epel + yum: name=epel-release state=latest +- name: install nginx + yum: name=nginx state=latest +- name: copy nginx.conf templte + template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf +- name: copy index.html + copy: src=index.html dest=/usr/share/nginx/html/index.html + notify: start nginx +``` + +​ templates模板 + +```shell +[root@ansible-server roles]# vim nginx/templates/nginx.conf.j2 +``` + +​ 自定义变量 + +![image-20230303005728244](https://xingdian-image.oss-cn-beijing.aliyuncs.com/xingdian-image/image-20230303005728244.png) + +​ 编写变量 + +```shell +[root@ansible-server roles]# vim nginx/vars/main.yml #添加如下内容 +worker_connections: 2 +``` + +​ 编写handlers + +```yaml +[root@ansible-server roles]# vim nginx/handlers/main.yml #编写如下内容 +--- +- name: start nginx + service: name=nginx state=started +``` + +​ 编写剧本 + +```yml +[root@ansible-server roles]# vim site.yml +--- +- hosts: webservers4 + user: root + roles: + - nginx +``` + +​ 检测语法 + +```shell +[root@ansible-server roles]# ansible-playbook site.yml --syntax-check +playbook: site.yml +``` + +​ 执行剧本 + +```shell +[root@ansible-server roles]# ansible-playbook site.yml +``` + +​ 查看 + +```shell +[root@ansible-web4 ~]# netstat -lntp +[root@ansible-web4 ~]# cat /etc/nginx/nginx.conf | grep pro +#worker_processes auto; +worker_processes 2; +``` + +​ 访问 + +```shell +[root@ansible-web4 ~]# http://172.17.0.2 +``` + +注意:(了解) + +​ ansible会使用jinja2模板来修改被管理主机的配置文件;使用ansible的jinja2模板,也就是template模块,该模块和copy模块一样,都是将文件复制到远端主机上;区别在于template模块可以获取要复制的文件中变量的值;而copy则是原封不动的把文件内容复制过去,比如针对不同的主机定义不同的变量,template会在将配置文件分发出去之前读取变量到jinja2模板,然后分发到不通的被管理主机上;ansible允许jinja2模板中使用条件判断和循环,但是jinja2判断循环语法不允许在playbook中使用;jinja2 文件件以 .j2 为后缀, 也可以不写后缀 + + + + + diff --git a/ansible/Yaml语法格式.md b/ansible/Yaml语法格式.md new file mode 100644 index 0000000..2ae0931 --- /dev/null +++ b/ansible/Yaml语法格式.md @@ -0,0 +1,172 @@ +

Yaml语法格式

+ +------ + +**作者:行癫(盗版必究)** + +## 一:Yaml介绍 + +​ YAML 是 "YAML Ain't a Markup Language"(YAML 不是一种标记语言)的递归缩写。在开发的这种语言时,YAML 的意思其实是:"Yet Another Markup Language"(仍是一种标记语言);YAML 的语法和其他高级语言类似,并且可以简单表达清单、散列表,标量等数据形态。它使用空白符号缩进和大量依赖外观的特色,特别适合用来表达或编辑数据结构、各种配置文件等;YAML 的配置文件后缀为 .yml,如:runoob.yml* + +#### 1.基本语法 + +​ 大小写敏感 + +​ 使用缩进表示层级关系 + +​ 缩进不允许使用tab,只允许空格 + +​ 缩进的空格数不重要,只要相同层级的元素左对齐即可 + +​ '#'表示注释 + +#### 2.数据类型 + +​ 对象:键值对的集合,又称为映射(mapping)/ 哈希(hashes) / 字典(dictionary) + +​ 数组:一组按次序排列的值,又称为序列(sequence) / 列表(list) + +​ 纯量(scalars):单个的、不可再分的值 + +#### 3.Yaml对象 + +​ 对象键值对使用冒号结构表示 key: value,冒号后面要加一个空格 + +​ 也可以使用 key:{key1: value1, key2: value2, ...} + +```yaml +key: + child-key: value + child-key2: value2 +``` + +#### 4.Yaml数组 + +​ 以 **-** 开头的行表示构成一个数组 + +```yaml +- A +- B +- C +``` + +​ YAML 支持多维数组,可以使用行内表示 + +```shell +key: [value1, value2, ...] +``` + +​ 数据结构的子成员是一个数组,则可以在该项下面缩进一个空格 + +```shell +- + - A + - B + - C +``` + +​ 案例:companies 属性是一个数组,每一个数组元素又是由 id、name、price 三个属性构成 + +```yaml +companies: + - + id: 1 + name: company1 + price: 200W + - + id: 2 + name: company2 + price: 500W +``` + +#### 5.复合结构 + +​ 数组和对象可以构成复合结构 + +```yaml +languages: + - Ruby + - Perl + - Python +websites: + YAML: yaml.org + Ruby: ruby-lang.org + Python: python.org + Perl: use.perl.org +``` + +​ 转换为 json 为: + +``` +{"languages": ["Ruby", "Perl", "Python"], "websites": {"YAML": "yaml.org", "Ruby": "ruby-lang.org", "Python": "python.org", "Perl": "use.perl.org"}} + + +{ + languages: [ 'Ruby', 'Perl', 'Python'], + websites: { + YAML: 'yaml.org', + Ruby: 'ruby-lang.org', + Python: 'python.org', + Perl: 'use.perl.org' + } +} +``` + +#### 6.纯量 + +​ 纯量是最基本的,不可再分的值,包括: + +​ 字符串 + +​ 布尔值 + +​ 整数 + +​ 浮点数 + +​ Null + +​ 时间 + +​ 日期 + +```yaml +boolean: + - TRUE #true,True都可以 + - FALSE #false,False都可以 +float: + - 3.14 + - 6.8523015e+5 #可以使用科学计数法 +int: + - 123 + - 0b1010_0111_0100_1010_1110 #二进制表示 +null: + nodeName: 'node' + parent: ~ #使用~表示null +string: + - 哈哈 + - 'Hello world' #可以使用双引号或者单引号包裹特殊字符 + - newline + newline2 #字符串可以拆成多行,每一行会被转化成一个空格 +date: + - 2018-02-17 #日期必须使用ISO 8601格式,即yyyy-MM-dd +datetime: + - 2018-02-17T15:02:31+08:00 #时间使用ISO 8601格式,时间和日期之间使用T连接,最后使用+代表时区 +``` + + + + + + + + + + + + + + + + +