[K8S Deploy] #2μ£Όμ°¨ Ansible (2)

26년도 K8S Deploy 정리 κΈ€μž…λ‹ˆλ‹€.

 

Facts

Ansible FactsλŠ” λŒ€μƒ 호슀트의 μ‹œμŠ€ν…œ 정보λ₯Ό μžλ™μœΌλ‘œ μˆ˜μ§‘ν•œ 데이터이닀. Ansible은 ν”Œλ ˆμ΄ μ‹€ν–‰ μ‹œ λŒ€μƒ λ…Έλ“œμ— μ ‘μ†ν•˜μ—¬ 운영체제, λ„€νŠΈμ›Œν¬, ν•˜λ“œμ›¨μ–΄, 컀널 λ“±μ˜ 정보λ₯Ό μˆ˜μ§‘ν•˜κ³  이λ₯Ό λ³€μˆ˜ ν˜•νƒœλ‘œ μ €μž₯ν•œλ‹€.

이 정보듀은 ν”Œλ ˆμ΄λΆμ—μ„œ 쑰건 λΆ„κΈ°, ν…œν”Œλ¦Ώ λ Œλ”λ§, 동적 섀정에 ν™œμš©λœλ‹€.

 

λͺ¨λ“  facts μΆ”μΆœ

- hosts: db

  tasks:
  - name: Print all facts
    ansible.builtin.debug:
      var: ansible_facts
oot@server:~/my-ansible# ansible-playbook facts.yml

PLAY [db] *************************************************************************************************************************************************

TASK [Gathering Facts] ************************************************************************************************************************************
ok: [tnode3]

TASK [Print all facts] ************************************************************************************************************************************
ok: [tnode3] => {
    "ansible_facts": {
        "all_ipv4_addresses": [
            "10.10.1.13",
            "10.0.2.15"
        ],
        "all_ipv6_addresses": [
            "fe80::a00:27ff:fe89:9ec1",
            "fd17:625c:f037:2:a00:27ff:fe1f:ae8b",
            "fe80::a00:27ff:fe1f:ae8b"
        ],
        "ansible_local": {},
        "apparmor": {
            "status": "disabled"
        },
        "architecture": "aarch64",
        "bios_date": "NA",
        "bios_vendor": "NA",
        "bios_version": "NA",
        "board_asset_tag": "NA",
        "board_name": "NA",
        "board_serial": "NA",
        "board_vendor": "NA",
        "board_version": "NA",
        "chassis_asset_tag": "NA",
        "chassis_serial": "NA",
        "chassis_vendor": "NA",
        "chassis_version": "NA",
        "cmdline": {
            "BOOT_IMAGE": "(hd0,gpt3)/boot/vmlinuz-5.14.0-570.52.1.el9_6.aarch64",
            "console": "ttyS0,115200n8",
            "no_timer_check": true,
            "ro": true,
            "root": "UUID=858fc44c-7093-420e-8ecd-aad817736634"
        },
        "date_time": {
            "date": "2026-01-18",
            "day": "18",
            "epoch": "1768673479",
            "epoch_int": "1768673479",
            "hour": "03",
            "iso8601": "2026-01-17T18:11:19Z",
            "iso8601_basic": "20260118T031119989925",
            "iso8601_basic_short": "20260118T031119",
            "iso8601_micro": "2026-01-17T18:11:19.989925Z",
            "minute": "11",
            "month": "01",
            "second": "19",
            "time": "03:11:19",
            "tz": "KST",
            "tz_dst": "KST",
            "tz_offset": "+0900",
            "weekday": "Sunday",
            "weekday_number": "0",
            "weeknumber": "02",
            "year": "2026"
        },
        "default_ipv4": {
            "address": "10.0.2.15",
            "alias": "enp0s8",
            "broadcast": "10.0.2.255",
            "gateway": "10.0.2.2",
            "interface": "enp0s8",
            "macaddress": "08:00:27:1f:ae:8b",
            "mtu": 1500,
            "netmask": "255.255.255.0",
            "network": "10.0.2.0",
            "prefix": "24",
            "type": "ether"
        },
        "default_ipv6": {
            "address": "fd17:625c:f037:2:a00:27ff:fe1f:ae8b",
            "gateway": "fe80::2",
            "interface": "enp0s8",
            "macaddress": "08:00:27:1f:ae:8b",
            "mtu": 1500,
            "prefix": "64",
            "scope": "global",
            "type": "ether"
        },
        "device_links": {
            "ids": {},
            "labels": {},
            "masters": {},
            "uuids": {
                "sda1": [
                    "19AA-5BCD"
                ],
                "sda2": [
                    "170ab8d6-f3c1-4df4-a6c8-f5ca12bf7724"
                ],
                "sda3": [
                    "858fc44c-7093-420e-8ecd-aad817736634"
                ]
            }
        },
        "devices": {
            "sda": {
                "holders": [],
                "host": "SCSI storage controller: Red Hat, Inc. Virtio 1.0 SCSI (rev 01)",
                "links": {
                    "ids": [],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": "HARDDISK",
                "partitions": {
                    "sda1": {
                        "holders": [],
                        "links": {
                            "ids": [],
                            "labels": [],
                            "masters": [],
                            "uuids": [
                                "19AA-5BCD"
                            ]
                        },
                        "sectors": 1228800,
                        "sectorsize": 512,
                        "size": "600.00 MB",
                        "start": "2048",
                        "uuid": "19AA-5BCD"
                    },
                    "sda2": {
                        "holders": [],
                        "links": {
                            "ids": [],
                            "labels": [],
                            "masters": [],
                            "uuids": [
                                "170ab8d6-f3c1-4df4-a6c8-f5ca12bf7724"
                            ]
                        },
                        "sectors": 7993344,
                        "sectorsize": 512,
                        "size": "3.81 GB",
                        "start": "1230848",
                        "uuid": "170ab8d6-f3c1-4df4-a6c8-f5ca12bf7724"
                    },
                    "sda3": {
                        "holders": [],
                        "links": {
                            "ids": [],
                            "labels": [],
                            "masters": [],
                            "uuids": [
                                "858fc44c-7093-420e-8ecd-aad817736634"
                            ]
                        },
                        "sectors": 124991488,
                        "sectorsize": 512,
                        "size": "59.60 GB",
                        "start": "9224192",
                        "uuid": "858fc44c-7093-420e-8ecd-aad817736634"
                    }
                },
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "none",
                "sectors": 134217728,
                "sectorsize": "512",
                "size": "64.00 GB",
                "support_discard": "0",
                "vendor": "VBOX",
                "virtual": 1
            }
        },
        "distribution": "Rocky",
        "distribution_file_parsed": true,
        "distribution_file_path": "/etc/redhat-release",
        "distribution_file_variety": "RedHat",
        "distribution_major_version": "9",
        "distribution_release": "Blue Onyx",
        "distribution_version": "9.6",
        "dns": {
            "nameservers": [
                "168.126.63.1",
                "168.126.63.2"
            ],
            "search": [
                "lan"
            ]
        },
        "domain": "",
        "effective_group_id": 0,
        "effective_user_id": 0,
        "enp0s8": {
            "active": true,
            "device": "enp0s8",
            "features": {
                "esp_hw_offload": "off [fixed]",
                "esp_tx_csum_hw_offload": "off [fixed]",
                "generic_receive_offload": "on",
                "generic_segmentation_offload": "on",
                "highdma": "off [fixed]",
                "hsr_dup_offload": "off [fixed]",
                "hsr_fwd_offload": "off [fixed]",
                "hsr_tag_ins_offload": "off [fixed]",
                "hsr_tag_rm_offload": "off [fixed]",
                "hw_tc_offload": "off [fixed]",
                "l2_fwd_offload": "off [fixed]",
                "large_receive_offload": "off [fixed]",
                "loopback": "off [fixed]",
                "macsec_hw_offload": "off [fixed]",
                "ntuple_filters": "off [fixed]",
                "receive_hashing": "off [fixed]",
                "rx_all": "off",
                "rx_checksumming": "off",
                "rx_fcs": "off",
                "rx_gro_hw": "off [fixed]",
                "rx_gro_list": "off",
                "rx_udp_gro_forwarding": "off",
                "rx_udp_tunnel_port_offload": "off [fixed]",
                "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",
                "tls_hw_record": "off [fixed]",
                "tls_hw_rx_offload": "off [fixed]",
                "tls_hw_tx_offload": "off [fixed]",
                "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_esp_segmentation": "off [fixed]",
                "tx_fcoe_segmentation": "off [fixed]",
                "tx_gre_csum_segmentation": "off [fixed]",
                "tx_gre_segmentation": "off [fixed]",
                "tx_gso_list": "off [fixed]",
                "tx_gso_partial": "off [fixed]",
                "tx_gso_robust": "off [fixed]",
                "tx_ipxip4_segmentation": "off [fixed]",
                "tx_ipxip6_segmentation": "off [fixed]",
                "tx_nocache_copy": "off",
                "tx_scatter_gather": "on",
                "tx_scatter_gather_fraglist": "off [fixed]",
                "tx_sctp_segmentation": "off [fixed]",
                "tx_tcp6_segmentation": "off [fixed]",
                "tx_tcp_ecn_segmentation": "off [fixed]",
                "tx_tcp_mangleid_segmentation": "off",
                "tx_tcp_segmentation": "on",
                "tx_tunnel_remcsum_segmentation": "off [fixed]",
                "tx_udp_segmentation": "off [fixed]",
                "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]",
                "vlan_challenged": "off [fixed]"
            },
            "hw_timestamp_filters": [],
            "ipv4": {
                "address": "10.0.2.15",
                "broadcast": "10.0.2.255",
                "netmask": "255.255.255.0",
                "network": "10.0.2.0",
                "prefix": "24"
            },
            "ipv6": [
                {
                    "address": "fd17:625c:f037:2:a00:27ff:fe1f:ae8b",
                    "prefix": "64",
                    "scope": "global"
                },
                {
                    "address": "fe80::a00:27ff:fe1f:ae8b",
                    "prefix": "64",
                    "scope": "link"
                }
            ],
            "macaddress": "08:00:27:1f:ae:8b",
            "module": "e1000",
            "mtu": 1500,
            "pciid": "0000:00:08.0",
            "promisc": false,
            "speed": 1000,
            "timestamping": [],
            "type": "ether"
        },
        "enp0s9": {
            "active": true,
            "device": "enp0s9",
            "features": {
                "esp_hw_offload": "off [fixed]",
                "esp_tx_csum_hw_offload": "off [fixed]",
                "generic_receive_offload": "on",
                "generic_segmentation_offload": "on",
                "highdma": "off [fixed]",
                "hsr_dup_offload": "off [fixed]",
                "hsr_fwd_offload": "off [fixed]",
                "hsr_tag_ins_offload": "off [fixed]",
                "hsr_tag_rm_offload": "off [fixed]",
                "hw_tc_offload": "off [fixed]",
                "l2_fwd_offload": "off [fixed]",
                "large_receive_offload": "off [fixed]",
                "loopback": "off [fixed]",
                "macsec_hw_offload": "off [fixed]",
                "ntuple_filters": "off [fixed]",
                "receive_hashing": "off [fixed]",
                "rx_all": "off",
                "rx_checksumming": "off",
                "rx_fcs": "off",
                "rx_gro_hw": "off [fixed]",
                "rx_gro_list": "off",
                "rx_udp_gro_forwarding": "off",
                "rx_udp_tunnel_port_offload": "off [fixed]",
                "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",
                "tls_hw_record": "off [fixed]",
                "tls_hw_rx_offload": "off [fixed]",
                "tls_hw_tx_offload": "off [fixed]",
                "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_esp_segmentation": "off [fixed]",
                "tx_fcoe_segmentation": "off [fixed]",
                "tx_gre_csum_segmentation": "off [fixed]",
                "tx_gre_segmentation": "off [fixed]",
                "tx_gso_list": "off [fixed]",
                "tx_gso_partial": "off [fixed]",
                "tx_gso_robust": "off [fixed]",
                "tx_ipxip4_segmentation": "off [fixed]",
                "tx_ipxip6_segmentation": "off [fixed]",
                "tx_nocache_copy": "off",
                "tx_scatter_gather": "on",
                "tx_scatter_gather_fraglist": "off [fixed]",
                "tx_sctp_segmentation": "off [fixed]",
                "tx_tcp6_segmentation": "off [fixed]",
                "tx_tcp_ecn_segmentation": "off [fixed]",
                "tx_tcp_mangleid_segmentation": "off",
                "tx_tcp_segmentation": "on",
                "tx_tunnel_remcsum_segmentation": "off [fixed]",
                "tx_udp_segmentation": "off [fixed]",
                "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]",
                "vlan_challenged": "off [fixed]"
            },
            "hw_timestamp_filters": [],
            "ipv4": {
                "address": "10.10.1.13",
                "broadcast": "10.10.1.255",
                "netmask": "255.255.255.0",
                "network": "10.10.1.0",
                "prefix": "24"
            },
            "ipv6": [
                {
                    "address": "fe80::a00:27ff:fe89:9ec1",
                    "prefix": "64",
                    "scope": "link"
                }
            ],
            "macaddress": "08:00:27:89:9e:c1",
            "module": "e1000",
            "mtu": 1500,
            "pciid": "0000:00:09.0",
            "promisc": false,
            "speed": 1000,
            "timestamping": [],
            "type": "ether"
        },
        "env": {
            "BASH_FUNC_which%%": "() {  ( alias;\n eval ${which_declare} ) | /usr/bin/which --tty-only --read-alias --read-functions --show-tilde --show-dot $@\n}",
            "DBUS_SESSION_BUS_ADDRESS": "unix:path=/run/user/0/bus",
            "DEBUGINFOD_IMA_CERT_PATH": "/etc/keys/ima:",
            "DEBUGINFOD_URLS": "https://debuginfod.rockylinux.org/ ",
            "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;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:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=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:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=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:*.webp=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:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.m4a=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:*.oga=01;36:*.opus=01;36:*.spx=01;36:*.xspf=01;36:",
            "MOTD_SHOWN": "pam",
            "PATH": "/root/.local/bin:/root/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin",
            "PWD": "/root",
            "SELINUX_LEVEL_REQUESTED": "",
            "SELINUX_ROLE_REQUESTED": "",
            "SELINUX_USE_CURRENT_RANGE": "",
            "SHELL": "/bin/bash",
            "SHLVL": "1",
            "SSH_CLIENT": "10.10.1.10 35396 22",
            "SSH_CONNECTION": "10.10.1.10 35396 10.10.1.13 22",
            "SSH_TTY": "/dev/pts/0",
            "TERM": "xterm-256color",
            "USER": "root",
            "XDG_RUNTIME_DIR": "/run/user/0",
            "XDG_SESSION_CLASS": "user",
            "XDG_SESSION_ID": "46",
            "XDG_SESSION_TYPE": "tty",
            "_": "/usr/bin/python3",
            "which_declare": "declare -f"
        },
        "fibre_channel_wwn": [],
        "fips": false,
        "form_factor": "NA",
        "fqdn": "tnode3",
        "gather_subset": [
            "all"
        ],
        "hostname": "tnode3",
        "hostnqn": "nqn.2014-08.org.nvmexpress:uuid:b4201204-1135-498b-8536-3a8fe83e7131",
        "interfaces": [
            "enp0s8",
            "lo",
            "enp0s9"
        ],
        "is_chroot": false,
        "iscsi_iqn": "",
        "kernel": "5.14.0-570.52.1.el9_6.aarch64",
        "kernel_version": "#1 SMP PREEMPT_DYNAMIC Wed Oct 15 14:48:33 UTC 2025",
        "lo": {
            "active": true,
            "device": "lo",
            "features": {
                "esp_hw_offload": "off [fixed]",
                "esp_tx_csum_hw_offload": "off [fixed]",
                "generic_receive_offload": "on",
                "generic_segmentation_offload": "on",
                "highdma": "on [fixed]",
                "hsr_dup_offload": "off [fixed]",
                "hsr_fwd_offload": "off [fixed]",
                "hsr_tag_ins_offload": "off [fixed]",
                "hsr_tag_rm_offload": "off [fixed]",
                "hw_tc_offload": "off [fixed]",
                "l2_fwd_offload": "off [fixed]",
                "large_receive_offload": "off [fixed]",
                "loopback": "on [fixed]",
                "macsec_hw_offload": "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_gro_list": "off",
                "rx_udp_gro_forwarding": "off",
                "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",
                "tls_hw_record": "off [fixed]",
                "tls_hw_rx_offload": "off [fixed]",
                "tls_hw_tx_offload": "off [fixed]",
                "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_esp_segmentation": "off [fixed]",
                "tx_fcoe_segmentation": "off [fixed]",
                "tx_gre_csum_segmentation": "off [fixed]",
                "tx_gre_segmentation": "off [fixed]",
                "tx_gso_list": "on",
                "tx_gso_partial": "off [fixed]",
                "tx_gso_robust": "off [fixed]",
                "tx_ipxip4_segmentation": "off [fixed]",
                "tx_ipxip6_segmentation": "off [fixed]",
                "tx_nocache_copy": "off [fixed]",
                "tx_scatter_gather": "on [fixed]",
                "tx_scatter_gather_fraglist": "on [fixed]",
                "tx_sctp_segmentation": "on",
                "tx_tcp6_segmentation": "on",
                "tx_tcp_ecn_segmentation": "on",
                "tx_tcp_mangleid_segmentation": "on",
                "tx_tcp_segmentation": "on",
                "tx_tunnel_remcsum_segmentation": "off [fixed]",
                "tx_udp_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]",
                "vlan_challenged": "on [fixed]"
            },
            "hw_timestamp_filters": [],
            "ipv4": {
                "address": "127.0.0.1",
                "broadcast": "",
                "netmask": "255.0.0.0",
                "network": "127.0.0.0",
                "prefix": "8"
            },
            "ipv6": [
                {
                    "address": "::1",
                    "prefix": "128",
                    "scope": "host"
                }
            ],
            "mtu": 65536,
            "promisc": false,
            "timestamping": [],
            "type": "loopback"
        },
        "loadavg": {
            "15m": 0.0,
            "1m": 0.0,
            "5m": 0.0
        },
        "locally_reachable_ips": {
            "ipv4": [
                "10.0.2.15",
                "10.10.1.13",
                "127.0.0.0/8",
                "127.0.0.1"
            ],
            "ipv6": [
                "::1",
                "fd17:625c:f037:2:a00:27ff:fe1f:ae8b",
                "fe80::a00:27ff:fe1f:ae8b",
                "fe80::a00:27ff:fe89:9ec1"
            ]
        },
        "lsb": {},
        "lvm": {
            "lvs": {},
            "pvs": {},
            "vgs": {}
        },
        "machine": "aarch64",
        "machine_id": "2ed554c3a90b423da25e15ea84029767",
        "memfree_mb": 783,
        "memory_mb": {
            "nocache": {
                "free": 1102,
                "used": 222
            },
            "real": {
                "free": 783,
                "total": 1324,
                "used": 541
            },
            "swap": {
                "cached": 0,
                "free": 3902,
                "total": 3902,
                "used": 0
            }
        },
        "memtotal_mb": 1324,
        "module_setup": true,
        "mounts": [
            {
                "block_available": 15092148,
                "block_size": 4096,
                "block_total": 15607552,
                "block_used": 515404,
                "device": "/dev/sda3",
                "dump": 0,
                "fstype": "xfs",
                "inode_available": 31209737,
                "inode_total": 31247872,
                "inode_used": 38135,
                "mount": "/",
                "options": "rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota",
                "passno": 0,
                "size_available": 61817438208,
                "size_total": 63928532992,
                "uuid": "858fc44c-7093-420e-8ecd-aad817736634"
            },
            {
                "block_available": 151423,
                "block_size": 4096,
                "block_total": 153290,
                "block_used": 1867,
                "device": "/dev/sda1",
                "dump": 0,
                "fstype": "vfat",
                "inode_available": 0,
                "inode_total": 0,
                "inode_used": 0,
                "mount": "/boot/efi",
                "options": "rw,relatime,fmask=0077,dmask=0077,codepage=437,iocharset=ascii,shortname=winnt,errors=remount-ro",
                "passno": 0,
                "size_available": 620228608,
                "size_total": 627875840,
                "uuid": "19AA-5BCD"
            }
        ],
        "nodename": "tnode3",
        "os_family": "RedHat",
        "pkg_mgr": "dnf",
        "proc_cmdline": {
            "BOOT_IMAGE": "(hd0,gpt3)/boot/vmlinuz-5.14.0-570.52.1.el9_6.aarch64",
            "console": [
                "tty0",
                "ttyS0,115200n8"
            ],
            "no_timer_check": true,
            "ro": true,
            "root": "UUID=858fc44c-7093-420e-8ecd-aad817736634"
        },
        "processor": [
            "0",
            "1"
        ],
        "processor_cores": 1,
        "processor_count": 2,
        "processor_nproc": 2,
        "processor_threads_per_core": 1,
        "processor_vcpus": 2,
        "product_name": "NA",
        "product_serial": "NA",
        "product_uuid": "NA",
        "product_version": "NA",
        "python": {
            "executable": "/usr/bin/python3",
            "has_sslcontext": true,
            "type": "cpython",
            "version": {
                "major": 3,
                "micro": 21,
                "minor": 9,
                "releaselevel": "final",
                "serial": 0
            },
            "version_info": [
                3,
                9,
                21,
                "final",
                0
            ]
        },
        "python_version": "3.9.21",
        "real_group_id": 0,
        "real_user_id": 0,
        "selinux": {
            "config_mode": "permissive",
            "mode": "permissive",
            "policyvers": 33,
            "status": "enabled",
            "type": "targeted"
        },
        "selinux_python_present": true,
        "service_mgr": "systemd",
        "ssh_host_key_ecdsa_public": "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBA3NDADxITYCQ+Yzl24Rv5+HTMqHFo1A1i6bGwRXfIvZ5ZPFQYMrR2CAi0vU69QVLwdWCJoLoQP8He+NBfrlrV8=",
        "ssh_host_key_ecdsa_public_keytype": "ecdsa-sha2-nistp256",
        "ssh_host_key_ed25519_public": "AAAAC3NzaC1lZDI1NTE5AAAAIKcCJWNOyGZ6SW350FH+dihyL+qJBcvRb7NIvkyes3Lt",
        "ssh_host_key_ed25519_public_keytype": "ssh-ed25519",
        "ssh_host_key_rsa_public": "AAAAB3NzaC1yc2EAAAADAQABAAABgQCQOhfEeFMicbWK5uXUAbgkFqTQRQGptB4FLBmiMIrpVVC0J9PFfBTJL2UIvDg1TCdwQ+DkJhtjffLDjWM/OU75gsYs9Ih0aGgE1zHf+93Wt0tM5+I8z0fTact/+4GaBAuSO4o7rjlebOC5XpgGT7aglCbuUn7UIefvf4m1OIdrWL8szWb6jZLGNH6AOn7itpri2cXWp9pnffr8FHYWIsKyHJWnRGtPXSOlU7/2wc7j0b8M1+H2FpBS8d4Y9+0Jdf0T9wq3tK7UkcW5hOGv09X1h42xMLzaCqivdvP2dxMz5xcvUWrC6g2wQgzg7IkA+hVszF6Nfazu2GYrNOTNyy3Pf+Krb8SthldVg4/Skw7sMkmGQ6TGCO5yTY0ul13sPiEx4SHBbtebJXk075W2+dB1yx6/6lxziUkUeW9jBJf2IVUpSMTf6PGLOefce1pLu/bSdD0pxR6CpukDfUhHaNGJCZpaiOEbk5FK2f9B+9TJ0y+w6ZaXzcfNmPj2hzzhN+8=",
        "ssh_host_key_rsa_public_keytype": "ssh-rsa",
        "swapfree_mb": 3902,
        "swaptotal_mb": 3902,
        "system": "Linux",
        "system_capabilities": [],
        "system_capabilities_enforced": "False",
        "system_vendor": "NA",
        "systemd": {
            "features": "+PAM +AUDIT +SELINUX -APPARMOR +IMA +SMACK +SECCOMP +GCRYPT +GNUTLS +OPENSSL +ACL +BLKID +CURL +ELFUTILS +FIDO2 +IDN2 -IDN -IPTC +KMOD +LIBCRYPTSETUP +LIBFDISK +PCRE2 -PWQUALITY +P11KIT -QRENCODE +TPM2 +BZIP2 +LZ4 +XZ +ZLIB +ZSTD -BPF_FRAMEWORK +XKBCOMMON +UTMP +SYSVINIT default-hierarchy=unified",
            "version": 252
        },
        "uptime_seconds": 11376,
        "user_dir": "/root",
        "user_gecos": "root",
        "user_gid": 0,
        "user_id": "root",
        "user_shell": "/bin/bash",
        "user_uid": 0,
        "userspace_bits": "64",
        "virtualization_role": "NA",
        "virtualization_tech_guest": [],
        "virtualization_tech_host": [],
        "virtualization_type": "NA"
    }
}

PLAY RECAP ************************************************************************************************************************************************
tnode3                     : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

 

νŠΉμ • κ°’  μΆ”μΆœ

- hosts: db

  tasks:
  - name: Print all facts
    ansible.builtin.debug:
      msg: >
        The default IPv4 address of {{ ansible_facts.hostname }}
        is {{ ansible_facts.default_ipv4.address }}
root@server:~/my-ansible# ansible-playbook facts1.yml

PLAY [db] *************************************************************************************************************************************************

TASK [Gathering Facts] ************************************************************************************************************************************
ok: [tnode3]

TASK [Print all facts] ************************************************************************************************************************************
ok: [tnode3] => {
    "msg": "The default IPv4 address of tnode3 is 10.0.2.15"
}

PLAY RECAP ************************************************************************************************************************************************
tnode3                     : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

 

fact μˆ˜μ§‘μ„ λΉ„ν™œμ„±ν™”

- hosts: db
  gather_facts: no

  tasks:
  - name: Print all facts
    ansible.builtin.debug:
      msg: >
        The default IPv4 address of {{ ansible_facts.hostname }}
        is {{ ansible_facts.default_ipv4.address }}
root@server:~/my-ansible# ansible-playbook facts1.yml

PLAY [db] *************************************************************************************************************************************************

TASK [Print all facts] ************************************************************************************************************************************
[ERROR]: Task failed: Finalization of task args for 'ansible.builtin.debug' failed: Error while resolving value for 'msg': object of type 'dict' has no attribute 'hostname'

Task failed.
Origin: /root/my-ansible/facts1.yml:5:5

3
4   tasks:
5   - name: Print all facts
      ^ column 5

<<< caused by >>>

Finalization of task args for 'ansible.builtin.debug' failed.
Origin: /root/my-ansible/facts1.yml:6:5

4   tasks:
5   - name: Print all facts
6     ansible.builtin.debug:
      ^ column 5

<<< caused by >>>

Error while resolving value for 'msg': object of type 'dict' has no attribute 'hostname'
Origin: /root/my-ansible/facts1.yml:7:12

5   - name: Print all facts
6     ansible.builtin.debug:
7       msg: >
             ^ column 12

fatal: [tnode3]: FAILED! => {"msg": "Task failed: Finalization of task args for 'ansible.builtin.debug' failed: Error while resolving value for 'msg': object of type 'dict' has no attribute 'hostname'"}

PLAY RECAP ************************************************************************************************************************************************
tnode3                     : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0

 

팩트 μˆ˜μ§‘μ΄ μ•ˆλ˜λ―€λ‘œ μ—λŸ¬κ°€ λ°œμƒν•˜κ²Œ λœλ‹€.

λ§Œμ•½ 팩트 μˆ˜μ§‘μ΄ ν•„μš”μ—†λŠ” ν”Œλ ˆμ΄λΆμ˜ 경우 였λ₯˜ 없이 μˆ˜ν–‰λœλ‹€.

 

- hosts: db
  gather_facts: no

  tasks:
  - name: Print message
    debug:
      msg: Hello Ansible World

root@server:~/my-ansible# ansible-playbook facts1.yml

PLAY [db] *************************************************************************************************************************************************

TASK [Print message] **************************************************************************************************************************************
ok: [tnode3] => {
    "msg": "Hello Ansible World"
}

PLAY RECAP ************************************************************************************************************************************************
tnode3                     : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

 

- hosts: db
  gather_facts: no

  tasks:
  - name: Manually gather facts
    ansible.builtin.setup:

  - name: Print all facts
    ansible.builtin.debug:
      msg: >
        The default IPv4 address of {{ ansible_facts.hostname }}
        is {{ ansible_facts.default_ipv4.address }}
        
 
 root@server:~/my-ansible# ansible-playbook facts1.yml

PLAY [db] *************************************************************************************************************************************************

TASK [Print message] **************************************************************************************************************************************
ok: [tnode3] => {
    "msg": "Hello Ansible World"
}

PLAY RECAP ************************************************************************************************************************************************
tnode3                     : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

root@server:~/my-ansible# ansible-playbook facts1.yml

PLAY [db] *************************************************************************************************************************************************

TASK [Manually gather facts] ******************************************************************************************************************************
ok: [tnode3]

TASK [Print all facts] ************************************************************************************************************************************
ok: [tnode3] => {
    "msg": "The default IPv4 address of tnode3 is 10.0.2.15"
}

PLAY RECAP ************************************************************************************************************************************************
tnode3                     : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

 

팩트 캐싱

μˆ˜μ§‘λœ κ²°κ³Όλ₯Ό μž¬μ‚¬μš©ν•˜κΈ° μœ„ν•΄ μ €μž₯ν•˜λŠ” κΈ°λŠ₯을 Facts Caching이라고 ν•œλ‹€.

Facts μΊμ‹œλŠ” μΊμ‹œκ°€ μ‘΄μž¬ν•˜μ§€ μ•Šμ„ λ•Œ, --flush-cache μ˜΅μ…˜μ„ μ‚¬μš©ν–ˆμ„ λ•Œ setup λͺ¨λ“ˆμ„ λͺ…μ‹œμ μœΌλ‘œ μ‹€ν–‰ν–ˆμ„ λ•Œ κ°±μ‹ λ˜κ²Œ λœλ‹€.

 

ν•˜μ§€λ§Œ λ³€κ²½λœ μ‹œμŠ€ν…œ 정보가 μ¦‰μ‹œ λ°˜μ˜λ˜μ§€ μ•Šμ„ 수 있으며, 동적 ν™˜κ²½μ—μ„œλŠ” μΊμ‹œ 정책을 μ‹ μ€‘νžˆ κ³ λ €ν•΄μ•Όν•œλ‹€.

# ansible.cfg
[defaults]
inventory = ./inventory
remote_user = root
ask_pass = false
gathering = smart
fact_caching = jsonfile
fact_caching_connection = myfacts

[privilege_escalation]
become = true
become_method = sudo
become_user = root
become_ask_pass = false

 

μ‚¬μš©μž μ§€μ • 팩트 생성

root@server:~/my-ansible# mkdir /etc/ansible/facts.d
root@server:~/my-ansible# cat <<EOT > /etc/ansible/facts.d/my-custom.fact
[packages]
web_package = httpd
db_package = mariadb-server

[users]
user1 = ansible
user2 = gasida
EOT

root@server:~/my-ansible# cat /etc/ansible/facts.d/my-custom.fact
[packages]
web_package = httpd
db_package = mariadb-server

[users]
user1 = ansible
user2 = gasida
- hosts: localhost

  tasks:
  - name: Print all facts
    ansible.builtin.debug:
      var: ansible_local

root@server:~/my-ansible# ansible-playbook facts.yml

PLAY [localhost] ******************************************************************************************************************************************

TASK [Gathering Facts] ************************************************************************************************************************************
ok: [localhost]

TASK [Print all facts] ************************************************************************************************************************************
ok: [localhost] => {
    "ansible_local": {
        "my-custom": {
            "packages": {
                "db_package": "mariadb-server",
                "web_package": "httpd"
            },
            "users": {
                "user1": "ansible",
                "user2": "gasida"
            }
        }
    }
}

PLAY RECAP ************************************************************************************************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

 

 

반볡문

---
- hosts: all
  tasks:
  - name: Check sshd and rsyslog state
    ansible.builtin.service:
      name: "{{ item }}"
      state: started
    loop:
      - vboxadd-service  # ssh
      - rsyslog
- hosts: all
  vars:
    services:
      - vboxadd-service  # ssh
      - rsyslog

  tasks:
  - name: Check sshd and rsyslog state
    ansible.builtin.service:
      name: "{{ item }}"
      state: started
    loop: "{{ services }}"
root@server:~/my-ansible# ansible-playbook check-services.yml 

PLAY [all] ************************************************************************************************************************************************

TASK [Check sshd and rsyslog state] ***********************************************************************************************************************
ok: [tnode3] => (item=vboxadd-service)
ok: [tnode1] => (item=vboxadd-service)
ok: [tnode2] => (item=vboxadd-service)
ok: [tnode3] => (item=rsyslog)
ok: [tnode1] => (item=rsyslog)
ok: [tnode2] => (item=rsyslog)

PLAY RECAP ************************************************************************************************************************************************
tnode1                     : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
tnode2                     : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
tnode3                     : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

사전 λͺ©λ‘ 반볡문

- hosts: all

  tasks:
    - name: Create files
      ansible.builtin.file:
        path: "{{ item['log-path'] }}"
        mode: "{{ item['log-mode'] }}"
        state: touch
      loop:
        - log-path: /var/log/test1.log
          log-mode: '0644'
        - log-path: /var/log/test2.log
          log-mode: '0600'

 

loopλŠ” λ™μΌν•œ νƒœμŠ€ν¬λ₯Ό μ—¬λŸ¬ μž…λ ₯ κ°’μœΌλ‘œ 반볡 μ‹€ν–‰ν•˜λ©° 두 개의 파일 μ •μ˜λ₯Ό 리슀트둜 μ „λ‹¬ν•œλ‹€.

각 ν•­λͺ©μ€ log-path와 log-modeλ₯Ό κ°€μ§„ λ”•μ…”λ„ˆλ¦¬μ΄λ‹€.

 

Ansible은 이 νƒœμŠ€ν¬λ₯Ό λ‹€μŒκ³Ό 같이 두 번 μ‹€ν–‰ν•œλ‹€.

  1. /var/log/test1.logλ₯Ό 0644 κΆŒν•œμœΌλ‘œ μƒμ„±ν•œλ‹€.
  2. /var/log/test2.logλ₯Ό 0600 κΆŒν•œμœΌλ‘œ μƒμ„±ν•œλ‹€.

 

root@server:~/my-ansible# ansible-playbook make-file.yml

PLAY [all] ************************************************************************************************************************************************

TASK [Create files] ***************************************************************************************************************************************
changed: [tnode3] => (item={'log-path': '/var/log/test1.log', 'log-mode': '0644'})
changed: [tnode1] => (item={'log-path': '/var/log/test1.log', 'log-mode': '0644'})
changed: [tnode2] => (item={'log-path': '/var/log/test1.log', 'log-mode': '0644'})
changed: [tnode3] => (item={'log-path': '/var/log/test2.log', 'log-mode': '0600'})
changed: [tnode1] => (item={'log-path': '/var/log/test2.log', 'log-mode': '0600'})
changed: [tnode2] => (item={'log-path': '/var/log/test2.log', 'log-mode': '0600'})

PLAY RECAP ************************************************************************************************************************************************
tnode1                     : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
tnode2                     : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
tnode3                     : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

register ν‚€μ›Œλ“œλ₯Ό ν™œμš©ν•œ 반볡문

- hosts: localhost
  tasks:
    - name: Loop echo test
      ansible.builtin.shell: "echo 'I can speak {{ item }}'"
      loop:
        - Korean
        - English
      register: result

    - name: Show result
      ansible.builtin.debug:
        var: result
root@server:~/my-ansible# ansible-playbook loop_register.yml

PLAY [localhost] ******************************************************************************************************************************************

TASK [Loop echo test] *************************************************************************************************************************************
changed: [localhost] => (item=Korean)
changed: [localhost] => (item=English)

TASK [Show result] ****************************************************************************************************************************************
ok: [localhost] => {
    "result": {
        "changed": true,
        "msg": "All items completed",
        "results": [
            {
                "ansible_loop_var": "item",
                "changed": true,
                "cmd": "echo 'I can speak Korean'",
                "delta": "0:00:00.001535",
                "end": "2026-01-18 03:29:11.177087",
                "failed": false,
                "invocation": {
                    "module_args": {
                        "_raw_params": "echo 'I can speak Korean'",
                        "_uses_shell": true,
                        "argv": null,
                        "chdir": null,
                        "cmd": null,
                        "creates": null,
                        "executable": null,
                        "expand_argument_vars": true,
                        "removes": null,
                        "stdin": null,
                        "stdin_add_newline": true,
                        "strip_empty_ends": true
                    }
                },
                "item": "Korean",
                "msg": "",
                "rc": 0,
                "start": "2026-01-18 03:29:11.175552",
                "stderr": "",
                "stderr_lines": [],
                "stdout": "I can speak Korean",
                "stdout_lines": [
                    "I can speak Korean"
                ]
            },
            {
                "ansible_loop_var": "item",
                "changed": true,
                "cmd": "echo 'I can speak English'",
                "delta": "0:00:00.001181",
                "end": "2026-01-18 03:29:11.286112",
                "failed": false,
                "invocation": {
                    "module_args": {
                        "_raw_params": "echo 'I can speak English'",
                        "_uses_shell": true,
                        "argv": null,
                        "chdir": null,
                        "cmd": null,
                        "creates": null,
                        "executable": null,
                        "expand_argument_vars": true,
                        "removes": null,
                        "stdin": null,
                        "stdin_add_newline": true,
                        "strip_empty_ends": true
                    }
                },
                "item": "English",
                "msg": "",
                "rc": 0,
                "start": "2026-01-18 03:29:11.284931",
                "stderr": "",
                "stderr_lines": [],
                "stdout": "I can speak English",
                "stdout_lines": [
                    "I can speak English"
                ]
            }
        ],
        "skipped": false
    }
}

PLAY RECAP ************************************************************************************************************************************************
localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

 

λ“±λ‘λœ κ²°κ³Όλ₯Ό μž¬μ‚¬μš©ν•˜μ—¬ 좜λ ₯

- hosts: localhost
  tasks:
    - name: Loop echo test
      ansible.builtin.shell: "echo 'I can speak {{ item }}'"
      loop:
        - Korean
        - English
      register: result

    - name: Show result
      ansible.builtin.debug:
        msg: "Stdout: {{ item.stdout }}"
      loop: "{{ result.results }}"
      
 root@server:~/my-ansible# ansible-playbook loop_register.yml

PLAY [localhost] ******************************************************************************************************************************************

TASK [Loop echo test] *************************************************************************************************************************************
changed: [localhost] => (item=Korean)
changed: [localhost] => (item=English)

TASK [Show result] ****************************************************************************************************************************************
ok: [localhost] => (item={'changed': True, 'stdout': 'I can speak Korean', 'stderr': '', 'rc': 0, 'cmd': "echo 'I can speak Korean'", 'start': '2026-01-18 03:45:24.632828', 'end': '2026-01-18 03:45:24.634702', 'delta': '0:00:00.001874', 'msg': '', 'invocation': {'module_args': {'_raw_params': "echo 'I can speak Korean'", '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['I can speak Korean'], 'stderr_lines': [], 'failed': False, 'item': 'Korean', 'ansible_loop_var': 'item'}) => {
    "msg": "Stdout: I can speak Korean"
}
ok: [localhost] => (item={'changed': True, 'stdout': 'I can speak English', 'stderr': '', 'rc': 0, 'cmd': "echo 'I can speak English'", 'start': '2026-01-18 03:45:24.742805', 'end': '2026-01-18 03:45:24.744214', 'delta': '0:00:00.001409', 'msg': '', 'invocation': {'module_args': {'_raw_params': "echo 'I can speak English'", '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['I can speak English'], 'stderr_lines': [], 'failed': False, 'item': 'English', 'ansible_loop_var': 'item'}) => {
    "msg": "Stdout: I can speak English"
}

PLAY RECAP ************************************************************************************************************************************************
localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

 

user1~10 생성 ν›„ μ‚­μ œ

---
- name: Create, verify, and delete users user1~user10
  hosts: all
  become: true

  vars:
    users:
      - user1
      - user2
      - user3
      - user4
      - user5
      - user6
      - user7
      - user8
      - user9
      - user10

  tasks:
    - name: Create users user1~user10
      ansible.builtin.user:
        name: "{{ item }}"
        state: present
        shell: /bin/bash
        create_home: true
      loop: "{{ users }}"

    - name: Verify users exist (check /etc/passwd)
      ansible.builtin.shell: "getent passwd {{ item }}"
      loop: "{{ users }}"
      register: user_check
      changed_when: false

    - name: Show verification result
      ansible.builtin.debug:
        msg: "{{ item.stdout }}"
      loop: "{{ user_check.results }}"

    - name: Delete users user1~user10
      ansible.builtin.user:
        name: "{{ item }}"
        state: absent
        remove: true
      loop: "{{ users }}"

    - name: Verify users are deleted
      ansible.builtin.shell: "getent passwd {{ item }} || echo '{{ item }} not found'"
      loop: "{{ users }}"
      register: delete_check
      changed_when: false

    - name: Show delete verification result
      ansible.builtin.debug:
        msg: "{{ item.stdout }}"
      loop: "{{ delete_check.results }}"
root@server:~/my-ansible# ansible-playbook ex1.yml 

PLAY [Create, verify, and delete users user1~user10] ******************************************************************************************************

TASK [Create users user1~user10] **************************************************************************************************************************
changed: [tnode3] => (item=user1)
changed: [tnode1] => (item=user1)
changed: [tnode2] => (item=user1)
changed: [tnode3] => (item=user2)
changed: [tnode1] => (item=user2)
changed: [tnode2] => (item=user2)
changed: [tnode3] => (item=user3)
changed: [tnode1] => (item=user3)
changed: [tnode2] => (item=user3)
changed: [tnode3] => (item=user4)
changed: [tnode1] => (item=user4)
changed: [tnode2] => (item=user4)
changed: [tnode3] => (item=user5)
changed: [tnode2] => (item=user5)
changed: [tnode1] => (item=user5)
changed: [tnode3] => (item=user6)
changed: [tnode2] => (item=user6)
changed: [tnode1] => (item=user6)
changed: [tnode3] => (item=user7)
changed: [tnode2] => (item=user7)
changed: [tnode1] => (item=user7)
changed: [tnode3] => (item=user8)
changed: [tnode2] => (item=user8)
changed: [tnode1] => (item=user8)
changed: [tnode3] => (item=user9)
changed: [tnode2] => (item=user9)
changed: [tnode1] => (item=user9)
changed: [tnode3] => (item=user10)
changed: [tnode2] => (item=user10)
changed: [tnode1] => (item=user10)

TASK [Verify users exist (check /etc/passwd)] *************************************************************************************************************
ok: [tnode1] => (item=user1)
ok: [tnode2] => (item=user1)
ok: [tnode3] => (item=user1)
ok: [tnode1] => (item=user2)
ok: [tnode2] => (item=user2)
ok: [tnode3] => (item=user2)
ok: [tnode1] => (item=user3)
ok: [tnode3] => (item=user3)
ok: [tnode2] => (item=user3)
ok: [tnode1] => (item=user4)
ok: [tnode2] => (item=user4)
ok: [tnode3] => (item=user4)
ok: [tnode1] => (item=user5)
ok: [tnode2] => (item=user5)
ok: [tnode3] => (item=user5)
ok: [tnode1] => (item=user6)
ok: [tnode2] => (item=user6)
ok: [tnode3] => (item=user6)
ok: [tnode1] => (item=user7)
ok: [tnode2] => (item=user7)
ok: [tnode3] => (item=user7)
ok: [tnode1] => (item=user8)
ok: [tnode2] => (item=user8)
ok: [tnode3] => (item=user8)
ok: [tnode1] => (item=user9)
ok: [tnode2] => (item=user9)
ok: [tnode3] => (item=user9)
ok: [tnode1] => (item=user10)
ok: [tnode2] => (item=user10)
ok: [tnode3] => (item=user10)

TASK [Show verification result] ***************************************************************************************************************************
ok: [tnode1] => (item={'changed': False, 'stdout': 'user1:x:1001:1001::/home/user1:/bin/bash', 'stderr': '', 'rc': 0, 'cmd': 'getent passwd user1', 'start': '2026-01-18 03:48:36.141191', 'end': '2026-01-18 03:48:36.144680', 'delta': '0:00:00.003489', 'msg': '', 'invocation': {'module_args': {'_raw_params': 'getent passwd user1', '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user1:x:1001:1001::/home/user1:/bin/bash'], 'stderr_lines': [], 'failed': False, 'item': 'user1', 'ansible_loop_var': 'item'}) => {
    "msg": "user1:x:1001:1001::/home/user1:/bin/bash"
}
ok: [tnode1] => (item={'changed': False, 'stdout': 'user2:x:1002:1002::/home/user2:/bin/bash', 'stderr': '', 'rc': 0, 'cmd': 'getent passwd user2', 'start': '2026-01-18 03:48:36.299108', 'end': '2026-01-18 03:48:36.300470', 'delta': '0:00:00.001362', 'msg': '', 'invocation': {'module_args': {'_raw_params': 'getent passwd user2', '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user2:x:1002:1002::/home/user2:/bin/bash'], 'stderr_lines': [], 'failed': False, 'item': 'user2', 'ansible_loop_var': 'item'}) => {
    "msg": "user2:x:1002:1002::/home/user2:/bin/bash"
}
ok: [tnode1] => (item={'changed': False, 'stdout': 'user3:x:1003:1003::/home/user3:/bin/bash', 'stderr': '', 'rc': 0, 'cmd': 'getent passwd user3', 'start': '2026-01-18 03:48:36.453680', 'end': '2026-01-18 03:48:36.455059', 'delta': '0:00:00.001379', 'msg': '', 'invocation': {'module_args': {'_raw_params': 'getent passwd user3', '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user3:x:1003:1003::/home/user3:/bin/bash'], 'stderr_lines': [], 'failed': False, 'item': 'user3', 'ansible_loop_var': 'item'}) => {
    "msg": "user3:x:1003:1003::/home/user3:/bin/bash"
}
ok: [tnode1] => (item={'changed': False, 'stdout': 'user4:x:1004:1004::/home/user4:/bin/bash', 'stderr': '', 'rc': 0, 'cmd': 'getent passwd user4', 'start': '2026-01-18 03:48:36.611845', 'end': '2026-01-18 03:48:36.613239', 'delta': '0:00:00.001394', 'msg': '', 'invocation': {'module_args': {'_raw_params': 'getent passwd user4', '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user4:x:1004:1004::/home/user4:/bin/bash'], 'stderr_lines': [], 'failed': False, 'item': 'user4', 'ansible_loop_var': 'item'}) => {
    "msg": "user4:x:1004:1004::/home/user4:/bin/bash"
}
ok: [tnode2] => (item={'changed': False, 'stdout': 'user1:x:1001:1001::/home/user1:/bin/bash', 'stderr': '', 'rc': 0, 'cmd': 'getent passwd user1', 'start': '2026-01-18 03:48:36.142723', 'end': '2026-01-18 03:48:36.144862', 'delta': '0:00:00.002139', 'msg': '', 'invocation': {'module_args': {'_raw_params': 'getent passwd user1', '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user1:x:1001:1001::/home/user1:/bin/bash'], 'stderr_lines': [], 'failed': False, 'item': 'user1', 'ansible_loop_var': 'item'}) => {
    "msg": "user1:x:1001:1001::/home/user1:/bin/bash"
}
ok: [tnode3] => (item={'changed': False, 'stdout': 'user1:x:1001:1001::/home/user1:/bin/bash', 'stderr': '', 'rc': 0, 'cmd': 'getent passwd user1', 'start': '2026-01-18 03:48:36.208079', 'end': '2026-01-18 03:48:36.210671', 'delta': '0:00:00.002592', 'msg': '', 'invocation': {'module_args': {'_raw_params': 'getent passwd user1', '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user1:x:1001:1001::/home/user1:/bin/bash'], 'stderr_lines': [], 'failed': False, 'item': 'user1', 'ansible_loop_var': 'item'}) => {
    "msg": "user1:x:1001:1001::/home/user1:/bin/bash"
}
ok: [tnode1] => (item={'changed': False, 'stdout': 'user5:x:1005:1005::/home/user5:/bin/bash', 'stderr': '', 'rc': 0, 'cmd': 'getent passwd user5', 'start': '2026-01-18 03:48:36.763410', 'end': '2026-01-18 03:48:36.764802', 'delta': '0:00:00.001392', 'msg': '', 'invocation': {'module_args': {'_raw_params': 'getent passwd user5', '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user5:x:1005:1005::/home/user5:/bin/bash'], 'stderr_lines': [], 'failed': False, 'item': 'user5', 'ansible_loop_var': 'item'}) => {
    "msg": "user5:x:1005:1005::/home/user5:/bin/bash"
}
ok: [tnode3] => (item={'changed': False, 'stdout': 'user2:x:1002:1002::/home/user2:/bin/bash', 'stderr': '', 'rc': 0, 'cmd': 'getent passwd user2', 'start': '2026-01-18 03:48:36.374164', 'end': '2026-01-18 03:48:36.375985', 'delta': '0:00:00.001821', 'msg': '', 'invocation': {'module_args': {'_raw_params': 'getent passwd user2', '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user2:x:1002:1002::/home/user2:/bin/bash'], 'stderr_lines': [], 'failed': False, 'item': 'user2', 'ansible_loop_var': 'item'}) => {
    "msg": "user2:x:1002:1002::/home/user2:/bin/bash"
}
ok: [tnode3] => (item={'changed': False, 'stdout': 'user3:x:1003:1003::/home/user3:/bin/bash', 'stderr': '', 'rc': 0, 'cmd': 'getent passwd user3', 'start': '2026-01-18 03:48:36.542495', 'end': '2026-01-18 03:48:36.544266', 'delta': '0:00:00.001771', 'msg': '', 'invocation': {'module_args': {'_raw_params': 'getent passwd user3', '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user3:x:1003:1003::/home/user3:/bin/bash'], 'stderr_lines': [], 'failed': False, 'item': 'user3', 'ansible_loop_var': 'item'}) => {
    "msg": "user3:x:1003:1003::/home/user3:/bin/bash"
}
ok: [tnode1] => (item={'changed': False, 'stdout': 'user6:x:1006:1006::/home/user6:/bin/bash', 'stderr': '', 'rc': 0, 'cmd': 'getent passwd user6', 'start': '2026-01-18 03:48:36.916250', 'end': '2026-01-18 03:48:36.917624', 'delta': '0:00:00.001374', 'msg': '', 'invocation': {'module_args': {'_raw_params': 'getent passwd user6', '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user6:x:1006:1006::/home/user6:/bin/bash'], 'stderr_lines': [], 'failed': False, 'item': 'user6', 'ansible_loop_var': 'item'}) => {
    "msg": "user6:x:1006:1006::/home/user6:/bin/bash"
}
ok: [tnode3] => (item={'changed': False, 'stdout': 'user4:x:1004:1004::/home/user4:/bin/bash', 'stderr': '', 'rc': 0, 'cmd': 'getent passwd user4', 'start': '2026-01-18 03:48:36.714032', 'end': '2026-01-18 03:48:36.715952', 'delta': '0:00:00.001920', 'msg': '', 'invocation': {'module_args': {'_raw_params': 'getent passwd user4', '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user4:x:1004:1004::/home/user4:/bin/bash'], 'stderr_lines': [], 'failed': False, 'item': 'user4', 'ansible_loop_var': 'item'}) => {
    "msg": "user4:x:1004:1004::/home/user4:/bin/bash"
}
ok: [tnode2] => (item={'changed': False, 'stdout': 'user2:x:1002:1002::/home/user2:/bin/bash', 'stderr': '', 'rc': 0, 'cmd': 'getent passwd user2', 'start': '2026-01-18 03:48:36.307091', 'end': '2026-01-18 03:48:36.308940', 'delta': '0:00:00.001849', 'msg': '', 'invocation': {'module_args': {'_raw_params': 'getent passwd user2', '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user2:x:1002:1002::/home/user2:/bin/bash'], 'stderr_lines': [], 'failed': False, 'item': 'user2', 'ansible_loop_var': 'item'}) => {
    "msg": "user2:x:1002:1002::/home/user2:/bin/bash"
}
ok: [tnode3] => (item={'changed': False, 'stdout': 'user5:x:1005:1005::/home/user5:/bin/bash', 'stderr': '', 'rc': 0, 'cmd': 'getent passwd user5', 'start': '2026-01-18 03:48:36.876295', 'end': '2026-01-18 03:48:36.878049', 'delta': '0:00:00.001754', 'msg': '', 'invocation': {'module_args': {'_raw_params': 'getent passwd user5', '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user5:x:1005:1005::/home/user5:/bin/bash'], 'stderr_lines': [], 'failed': False, 'item': 'user5', 'ansible_loop_var': 'item'}) => {
    "msg": "user5:x:1005:1005::/home/user5:/bin/bash"
}
ok: [tnode3] => (item={'changed': False, 'stdout': 'user6:x:1006:1006::/home/user6:/bin/bash', 'stderr': '', 'rc': 0, 'cmd': 'getent passwd user6', 'start': '2026-01-18 03:48:37.041497', 'end': '2026-01-18 03:48:37.043357', 'delta': '0:00:00.001860', 'msg': '', 'invocation': {'module_args': {'_raw_params': 'getent passwd user6', '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user6:x:1006:1006::/home/user6:/bin/bash'], 'stderr_lines': [], 'failed': False, 'item': 'user6', 'ansible_loop_var': 'item'}) => {
    "msg": "user6:x:1006:1006::/home/user6:/bin/bash"
}
ok: [tnode3] => (item={'changed': False, 'stdout': 'user7:x:1007:1007::/home/user7:/bin/bash', 'stderr': '', 'rc': 0, 'cmd': 'getent passwd user7', 'start': '2026-01-18 03:48:37.204297', 'end': '2026-01-18 03:48:37.206120', 'delta': '0:00:00.001823', 'msg': '', 'invocation': {'module_args': {'_raw_params': 'getent passwd user7', '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user7:x:1007:1007::/home/user7:/bin/bash'], 'stderr_lines': [], 'failed': False, 'item': 'user7', 'ansible_loop_var': 'item'}) => {
    "msg": "user7:x:1007:1007::/home/user7:/bin/bash"
}
ok: [tnode2] => (item={'changed': False, 'stdout': 'user3:x:1003:1003::/home/user3:/bin/bash', 'stderr': '', 'rc': 0, 'cmd': 'getent passwd user3', 'start': '2026-01-18 03:48:36.486925', 'end': '2026-01-18 03:48:36.489055', 'delta': '0:00:00.002130', 'msg': '', 'invocation': {'module_args': {'_raw_params': 'getent passwd user3', '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user3:x:1003:1003::/home/user3:/bin/bash'], 'stderr_lines': [], 'failed': False, 'item': 'user3', 'ansible_loop_var': 'item'}) => {
    "msg": "user3:x:1003:1003::/home/user3:/bin/bash"
}
ok: [tnode3] => (item={'changed': False, 'stdout': 'user8:x:1008:1008::/home/user8:/bin/bash', 'stderr': '', 'rc': 0, 'cmd': 'getent passwd user8', 'start': '2026-01-18 03:48:37.366901', 'end': '2026-01-18 03:48:37.368667', 'delta': '0:00:00.001766', 'msg': '', 'invocation': {'module_args': {'_raw_params': 'getent passwd user8', '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user8:x:1008:1008::/home/user8:/bin/bash'], 'stderr_lines': [], 'failed': False, 'item': 'user8', 'ansible_loop_var': 'item'}) => {
    "msg": "user8:x:1008:1008::/home/user8:/bin/bash"
}
ok: [tnode1] => (item={'changed': False, 'stdout': 'user7:x:1007:1007::/home/user7:/bin/bash', 'stderr': '', 'rc': 0, 'cmd': 'getent passwd user7', 'start': '2026-01-18 03:48:37.066146', 'end': '2026-01-18 03:48:37.067501', 'delta': '0:00:00.001355', 'msg': '', 'invocation': {'module_args': {'_raw_params': 'getent passwd user7', '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user7:x:1007:1007::/home/user7:/bin/bash'], 'stderr_lines': [], 'failed': False, 'item': 'user7', 'ansible_loop_var': 'item'}) => {
    "msg": "user7:x:1007:1007::/home/user7:/bin/bash"
}
ok: [tnode3] => (item={'changed': False, 'stdout': 'user9:x:1009:1009::/home/user9:/bin/bash', 'stderr': '', 'rc': 0, 'cmd': 'getent passwd user9', 'start': '2026-01-18 03:48:37.532661', 'end': '2026-01-18 03:48:37.534402', 'delta': '0:00:00.001741', 'msg': '', 'invocation': {'module_args': {'_raw_params': 'getent passwd user9', '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user9:x:1009:1009::/home/user9:/bin/bash'], 'stderr_lines': [], 'failed': False, 'item': 'user9', 'ansible_loop_var': 'item'}) => {
    "msg": "user9:x:1009:1009::/home/user9:/bin/bash"
}
ok: [tnode3] => (item={'changed': False, 'stdout': 'user10:x:1010:1010::/home/user10:/bin/bash', 'stderr': '', 'rc': 0, 'cmd': 'getent passwd user10', 'start': '2026-01-18 03:48:37.688668', 'end': '2026-01-18 03:48:37.690181', 'delta': '0:00:00.001513', 'msg': '', 'invocation': {'module_args': {'_raw_params': 'getent passwd user10', '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user10:x:1010:1010::/home/user10:/bin/bash'], 'stderr_lines': [], 'failed': False, 'item': 'user10', 'ansible_loop_var': 'item'}) => {
    "msg": "user10:x:1010:1010::/home/user10:/bin/bash"
}
ok: [tnode2] => (item={'changed': False, 'stdout': 'user4:x:1004:1004::/home/user4:/bin/bash', 'stderr': '', 'rc': 0, 'cmd': 'getent passwd user4', 'start': '2026-01-18 03:48:36.646360', 'end': '2026-01-18 03:48:36.647715', 'delta': '0:00:00.001355', 'msg': '', 'invocation': {'module_args': {'_raw_params': 'getent passwd user4', '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user4:x:1004:1004::/home/user4:/bin/bash'], 'stderr_lines': [], 'failed': False, 'item': 'user4', 'ansible_loop_var': 'item'}) => {
    "msg": "user4:x:1004:1004::/home/user4:/bin/bash"
}
ok: [tnode1] => (item={'changed': False, 'stdout': 'user8:x:1008:1008::/home/user8:/bin/bash', 'stderr': '', 'rc': 0, 'cmd': 'getent passwd user8', 'start': '2026-01-18 03:48:37.217502', 'end': '2026-01-18 03:48:37.218909', 'delta': '0:00:00.001407', 'msg': '', 'invocation': {'module_args': {'_raw_params': 'getent passwd user8', '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user8:x:1008:1008::/home/user8:/bin/bash'], 'stderr_lines': [], 'failed': False, 'item': 'user8', 'ansible_loop_var': 'item'}) => {
    "msg": "user8:x:1008:1008::/home/user8:/bin/bash"
}
ok: [tnode2] => (item={'changed': False, 'stdout': 'user5:x:1005:1005::/home/user5:/bin/bash', 'stderr': '', 'rc': 0, 'cmd': 'getent passwd user5', 'start': '2026-01-18 03:48:36.797363', 'end': '2026-01-18 03:48:36.798773', 'delta': '0:00:00.001410', 'msg': '', 'invocation': {'module_args': {'_raw_params': 'getent passwd user5', '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user5:x:1005:1005::/home/user5:/bin/bash'], 'stderr_lines': [], 'failed': False, 'item': 'user5', 'ansible_loop_var': 'item'}) => {
    "msg": "user5:x:1005:1005::/home/user5:/bin/bash"
}
ok: [tnode2] => (item={'changed': False, 'stdout': 'user6:x:1006:1006::/home/user6:/bin/bash', 'stderr': '', 'rc': 0, 'cmd': 'getent passwd user6', 'start': '2026-01-18 03:48:36.947390', 'end': '2026-01-18 03:48:36.948816', 'delta': '0:00:00.001426', 'msg': '', 'invocation': {'module_args': {'_raw_params': 'getent passwd user6', '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user6:x:1006:1006::/home/user6:/bin/bash'], 'stderr_lines': [], 'failed': False, 'item': 'user6', 'ansible_loop_var': 'item'}) => {
    "msg": "user6:x:1006:1006::/home/user6:/bin/bash"
}
ok: [tnode1] => (item={'changed': False, 'stdout': 'user9:x:1009:1009::/home/user9:/bin/bash', 'stderr': '', 'rc': 0, 'cmd': 'getent passwd user9', 'start': '2026-01-18 03:48:37.367900', 'end': '2026-01-18 03:48:37.369476', 'delta': '0:00:00.001576', 'msg': '', 'invocation': {'module_args': {'_raw_params': 'getent passwd user9', '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user9:x:1009:1009::/home/user9:/bin/bash'], 'stderr_lines': [], 'failed': False, 'item': 'user9', 'ansible_loop_var': 'item'}) => {
    "msg": "user9:x:1009:1009::/home/user9:/bin/bash"
}
ok: [tnode1] => (item={'changed': False, 'stdout': 'user10:x:1010:1010::/home/user10:/bin/bash', 'stderr': '', 'rc': 0, 'cmd': 'getent passwd user10', 'start': '2026-01-18 03:48:37.519474', 'end': '2026-01-18 03:48:37.520967', 'delta': '0:00:00.001493', 'msg': '', 'invocation': {'module_args': {'_raw_params': 'getent passwd user10', '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user10:x:1010:1010::/home/user10:/bin/bash'], 'stderr_lines': [], 'failed': False, 'item': 'user10', 'ansible_loop_var': 'item'}) => {
    "msg": "user10:x:1010:1010::/home/user10:/bin/bash"
}
ok: [tnode2] => (item={'changed': False, 'stdout': 'user7:x:1007:1007::/home/user7:/bin/bash', 'stderr': '', 'rc': 0, 'cmd': 'getent passwd user7', 'start': '2026-01-18 03:48:37.098905', 'end': '2026-01-18 03:48:37.100474', 'delta': '0:00:00.001569', 'msg': '', 'invocation': {'module_args': {'_raw_params': 'getent passwd user7', '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user7:x:1007:1007::/home/user7:/bin/bash'], 'stderr_lines': [], 'failed': False, 'item': 'user7', 'ansible_loop_var': 'item'}) => {
    "msg": "user7:x:1007:1007::/home/user7:/bin/bash"
}
ok: [tnode2] => (item={'changed': False, 'stdout': 'user8:x:1008:1008::/home/user8:/bin/bash', 'stderr': '', 'rc': 0, 'cmd': 'getent passwd user8', 'start': '2026-01-18 03:48:37.250130', 'end': '2026-01-18 03:48:37.251635', 'delta': '0:00:00.001505', 'msg': '', 'invocation': {'module_args': {'_raw_params': 'getent passwd user8', '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user8:x:1008:1008::/home/user8:/bin/bash'], 'stderr_lines': [], 'failed': False, 'item': 'user8', 'ansible_loop_var': 'item'}) => {
    "msg": "user8:x:1008:1008::/home/user8:/bin/bash"
}
ok: [tnode2] => (item={'changed': False, 'stdout': 'user9:x:1009:1009::/home/user9:/bin/bash', 'stderr': '', 'rc': 0, 'cmd': 'getent passwd user9', 'start': '2026-01-18 03:48:37.401937', 'end': '2026-01-18 03:48:37.403499', 'delta': '0:00:00.001562', 'msg': '', 'invocation': {'module_args': {'_raw_params': 'getent passwd user9', '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user9:x:1009:1009::/home/user9:/bin/bash'], 'stderr_lines': [], 'failed': False, 'item': 'user9', 'ansible_loop_var': 'item'}) => {
    "msg": "user9:x:1009:1009::/home/user9:/bin/bash"
}
ok: [tnode2] => (item={'changed': False, 'stdout': 'user10:x:1010:1010::/home/user10:/bin/bash', 'stderr': '', 'rc': 0, 'cmd': 'getent passwd user10', 'start': '2026-01-18 03:48:37.554541', 'end': '2026-01-18 03:48:37.555928', 'delta': '0:00:00.001387', 'msg': '', 'invocation': {'module_args': {'_raw_params': 'getent passwd user10', '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user10:x:1010:1010::/home/user10:/bin/bash'], 'stderr_lines': [], 'failed': False, 'item': 'user10', 'ansible_loop_var': 'item'}) => {
    "msg": "user10:x:1010:1010::/home/user10:/bin/bash"
}

TASK [Delete users user1~user10] **************************************************************************************************************************
changed: [tnode1] => (item=user1)
changed: [tnode2] => (item=user1)
changed: [tnode3] => (item=user1)
changed: [tnode1] => (item=user2)
changed: [tnode2] => (item=user2)
changed: [tnode3] => (item=user2)
changed: [tnode1] => (item=user3)
changed: [tnode2] => (item=user3)
changed: [tnode3] => (item=user3)
changed: [tnode2] => (item=user4)
changed: [tnode1] => (item=user4)
changed: [tnode3] => (item=user4)
changed: [tnode2] => (item=user5)
changed: [tnode1] => (item=user5)
changed: [tnode3] => (item=user5)
changed: [tnode2] => (item=user6)
changed: [tnode1] => (item=user6)
changed: [tnode3] => (item=user6)
changed: [tnode2] => (item=user7)
changed: [tnode1] => (item=user7)
changed: [tnode3] => (item=user7)
changed: [tnode2] => (item=user8)
changed: [tnode1] => (item=user8)
changed: [tnode3] => (item=user8)
changed: [tnode2] => (item=user9)
changed: [tnode1] => (item=user9)
changed: [tnode3] => (item=user9)
changed: [tnode2] => (item=user10)
changed: [tnode1] => (item=user10)
changed: [tnode3] => (item=user10)

TASK [Verify users are deleted] ***************************************************************************************************************************
ok: [tnode2] => (item=user1)
ok: [tnode1] => (item=user1)
ok: [tnode3] => (item=user1)
ok: [tnode2] => (item=user2)
ok: [tnode1] => (item=user2)
ok: [tnode3] => (item=user2)
ok: [tnode2] => (item=user3)
ok: [tnode1] => (item=user3)
ok: [tnode3] => (item=user3)
ok: [tnode2] => (item=user4)
ok: [tnode1] => (item=user4)
ok: [tnode3] => (item=user4)
ok: [tnode2] => (item=user5)
ok: [tnode1] => (item=user5)
ok: [tnode3] => (item=user5)
ok: [tnode2] => (item=user6)
ok: [tnode1] => (item=user6)
ok: [tnode3] => (item=user6)
ok: [tnode2] => (item=user7)
ok: [tnode1] => (item=user7)
ok: [tnode3] => (item=user7)
ok: [tnode2] => (item=user8)
ok: [tnode1] => (item=user8)
ok: [tnode3] => (item=user8)
ok: [tnode2] => (item=user9)
ok: [tnode1] => (item=user9)
ok: [tnode3] => (item=user9)
ok: [tnode2] => (item=user10)
ok: [tnode1] => (item=user10)
ok: [tnode3] => (item=user10)

TASK [Show delete verification result] ********************************************************************************************************************
ok: [tnode1] => (item={'changed': False, 'stdout': 'user1 not found', 'stderr': '', 'rc': 0, 'cmd': "getent passwd user1 || echo 'user1 not found'", 'start': '2026-01-18 03:48:39.925085', 'end': '2026-01-18 03:48:39.926931', 'delta': '0:00:00.001846', 'msg': '', 'invocation': {'module_args': {'_raw_params': "getent passwd user1 || echo 'user1 not found'", '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user1 not found'], 'stderr_lines': [], 'failed': False, 'item': 'user1', 'ansible_loop_var': 'item'}) => {
    "msg": "user1 not found"
}
ok: [tnode1] => (item={'changed': False, 'stdout': 'user2 not found', 'stderr': '', 'rc': 0, 'cmd': "getent passwd user2 || echo 'user2 not found'", 'start': '2026-01-18 03:48:40.079699', 'end': '2026-01-18 03:48:40.081338', 'delta': '0:00:00.001639', 'msg': '', 'invocation': {'module_args': {'_raw_params': "getent passwd user2 || echo 'user2 not found'", '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user2 not found'], 'stderr_lines': [], 'failed': False, 'item': 'user2', 'ansible_loop_var': 'item'}) => {
    "msg": "user2 not found"
}
ok: [tnode1] => (item={'changed': False, 'stdout': 'user3 not found', 'stderr': '', 'rc': 0, 'cmd': "getent passwd user3 || echo 'user3 not found'", 'start': '2026-01-18 03:48:40.230493', 'end': '2026-01-18 03:48:40.232099', 'delta': '0:00:00.001606', 'msg': '', 'invocation': {'module_args': {'_raw_params': "getent passwd user3 || echo 'user3 not found'", '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user3 not found'], 'stderr_lines': [], 'failed': False, 'item': 'user3', 'ansible_loop_var': 'item'}) => {
    "msg": "user3 not found"
}
ok: [tnode1] => (item={'changed': False, 'stdout': 'user4 not found', 'stderr': '', 'rc': 0, 'cmd': "getent passwd user4 || echo 'user4 not found'", 'start': '2026-01-18 03:48:40.381210', 'end': '2026-01-18 03:48:40.382905', 'delta': '0:00:00.001695', 'msg': '', 'invocation': {'module_args': {'_raw_params': "getent passwd user4 || echo 'user4 not found'", '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user4 not found'], 'stderr_lines': [], 'failed': False, 'item': 'user4', 'ansible_loop_var': 'item'}) => {
    "msg": "user4 not found"
}
ok: [tnode1] => (item={'changed': False, 'stdout': 'user5 not found', 'stderr': '', 'rc': 0, 'cmd': "getent passwd user5 || echo 'user5 not found'", 'start': '2026-01-18 03:48:40.532973', 'end': '2026-01-18 03:48:40.534616', 'delta': '0:00:00.001643', 'msg': '', 'invocation': {'module_args': {'_raw_params': "getent passwd user5 || echo 'user5 not found'", '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user5 not found'], 'stderr_lines': [], 'failed': False, 'item': 'user5', 'ansible_loop_var': 'item'}) => {
    "msg": "user5 not found"
}
ok: [tnode1] => (item={'changed': False, 'stdout': 'user6 not found', 'stderr': '', 'rc': 0, 'cmd': "getent passwd user6 || echo 'user6 not found'", 'start': '2026-01-18 03:48:40.682370', 'end': '2026-01-18 03:48:40.684145', 'delta': '0:00:00.001775', 'msg': '', 'invocation': {'module_args': {'_raw_params': "getent passwd user6 || echo 'user6 not found'", '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user6 not found'], 'stderr_lines': [], 'failed': False, 'item': 'user6', 'ansible_loop_var': 'item'}) => {
    "msg": "user6 not found"
}
ok: [tnode1] => (item={'changed': False, 'stdout': 'user7 not found', 'stderr': '', 'rc': 0, 'cmd': "getent passwd user7 || echo 'user7 not found'", 'start': '2026-01-18 03:48:40.833742', 'end': '2026-01-18 03:48:40.835433', 'delta': '0:00:00.001691', 'msg': '', 'invocation': {'module_args': {'_raw_params': "getent passwd user7 || echo 'user7 not found'", '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user7 not found'], 'stderr_lines': [], 'failed': False, 'item': 'user7', 'ansible_loop_var': 'item'}) => {
    "msg": "user7 not found"
}
ok: [tnode2] => (item={'changed': False, 'stdout': 'user1 not found', 'stderr': '', 'rc': 0, 'cmd': "getent passwd user1 || echo 'user1 not found'", 'start': '2026-01-18 03:48:39.906050', 'end': '2026-01-18 03:48:39.907626', 'delta': '0:00:00.001576', 'msg': '', 'invocation': {'module_args': {'_raw_params': "getent passwd user1 || echo 'user1 not found'", '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user1 not found'], 'stderr_lines': [], 'failed': False, 'item': 'user1', 'ansible_loop_var': 'item'}) => {
    "msg": "user1 not found"
}
ok: [tnode1] => (item={'changed': False, 'stdout': 'user8 not found', 'stderr': '', 'rc': 0, 'cmd': "getent passwd user8 || echo 'user8 not found'", 'start': '2026-01-18 03:48:40.985759', 'end': '2026-01-18 03:48:40.987601', 'delta': '0:00:00.001842', 'msg': '', 'invocation': {'module_args': {'_raw_params': "getent passwd user8 || echo 'user8 not found'", '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user8 not found'], 'stderr_lines': [], 'failed': False, 'item': 'user8', 'ansible_loop_var': 'item'}) => {
    "msg": "user8 not found"
}
ok: [tnode3] => (item={'changed': False, 'stdout': 'user1 not found', 'stderr': '', 'rc': 0, 'cmd': "getent passwd user1 || echo 'user1 not found'", 'start': '2026-01-18 03:48:39.988492', 'end': '2026-01-18 03:48:39.991136', 'delta': '0:00:00.002644', 'msg': '', 'invocation': {'module_args': {'_raw_params': "getent passwd user1 || echo 'user1 not found'", '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user1 not found'], 'stderr_lines': [], 'failed': False, 'item': 'user1', 'ansible_loop_var': 'item'}) => {
    "msg": "user1 not found"
}
ok: [tnode1] => (item={'changed': False, 'stdout': 'user9 not found', 'stderr': '', 'rc': 0, 'cmd': "getent passwd user9 || echo 'user9 not found'", 'start': '2026-01-18 03:48:41.135716', 'end': '2026-01-18 03:48:41.137477', 'delta': '0:00:00.001761', 'msg': '', 'invocation': {'module_args': {'_raw_params': "getent passwd user9 || echo 'user9 not found'", '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user9 not found'], 'stderr_lines': [], 'failed': False, 'item': 'user9', 'ansible_loop_var': 'item'}) => {
    "msg": "user9 not found"
}
ok: [tnode2] => (item={'changed': False, 'stdout': 'user2 not found', 'stderr': '', 'rc': 0, 'cmd': "getent passwd user2 || echo 'user2 not found'", 'start': '2026-01-18 03:48:40.059948', 'end': '2026-01-18 03:48:40.061626', 'delta': '0:00:00.001678', 'msg': '', 'invocation': {'module_args': {'_raw_params': "getent passwd user2 || echo 'user2 not found'", '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user2 not found'], 'stderr_lines': [], 'failed': False, 'item': 'user2', 'ansible_loop_var': 'item'}) => {
    "msg": "user2 not found"
}
ok: [tnode1] => (item={'changed': False, 'stdout': 'user10 not found', 'stderr': '', 'rc': 0, 'cmd': "getent passwd user10 || echo 'user10 not found'", 'start': '2026-01-18 03:48:41.286882', 'end': '2026-01-18 03:48:41.288676', 'delta': '0:00:00.001794', 'msg': '', 'invocation': {'module_args': {'_raw_params': "getent passwd user10 || echo 'user10 not found'", '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user10 not found'], 'stderr_lines': [], 'failed': False, 'item': 'user10', 'ansible_loop_var': 'item'}) => {
    "msg": "user10 not found"
}
ok: [tnode3] => (item={'changed': False, 'stdout': 'user2 not found', 'stderr': '', 'rc': 0, 'cmd': "getent passwd user2 || echo 'user2 not found'", 'start': '2026-01-18 03:48:40.158799', 'end': '2026-01-18 03:48:40.161390', 'delta': '0:00:00.002591', 'msg': '', 'invocation': {'module_args': {'_raw_params': "getent passwd user2 || echo 'user2 not found'", '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user2 not found'], 'stderr_lines': [], 'failed': False, 'item': 'user2', 'ansible_loop_var': 'item'}) => {
    "msg": "user2 not found"
}
ok: [tnode2] => (item={'changed': False, 'stdout': 'user3 not found', 'stderr': '', 'rc': 0, 'cmd': "getent passwd user3 || echo 'user3 not found'", 'start': '2026-01-18 03:48:40.210623', 'end': '2026-01-18 03:48:40.212414', 'delta': '0:00:00.001791', 'msg': '', 'invocation': {'module_args': {'_raw_params': "getent passwd user3 || echo 'user3 not found'", '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user3 not found'], 'stderr_lines': [], 'failed': False, 'item': 'user3', 'ansible_loop_var': 'item'}) => {
    "msg": "user3 not found"
}
ok: [tnode3] => (item={'changed': False, 'stdout': 'user3 not found', 'stderr': '', 'rc': 0, 'cmd': "getent passwd user3 || echo 'user3 not found'", 'start': '2026-01-18 03:48:40.325941', 'end': '2026-01-18 03:48:40.328560', 'delta': '0:00:00.002619', 'msg': '', 'invocation': {'module_args': {'_raw_params': "getent passwd user3 || echo 'user3 not found'", '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user3 not found'], 'stderr_lines': [], 'failed': False, 'item': 'user3', 'ansible_loop_var': 'item'}) => {
    "msg": "user3 not found"
}
ok: [tnode2] => (item={'changed': False, 'stdout': 'user4 not found', 'stderr': '', 'rc': 0, 'cmd': "getent passwd user4 || echo 'user4 not found'", 'start': '2026-01-18 03:48:40.363933', 'end': '2026-01-18 03:48:40.365640', 'delta': '0:00:00.001707', 'msg': '', 'invocation': {'module_args': {'_raw_params': "getent passwd user4 || echo 'user4 not found'", '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user4 not found'], 'stderr_lines': [], 'failed': False, 'item': 'user4', 'ansible_loop_var': 'item'}) => {
    "msg": "user4 not found"
}
ok: [tnode3] => (item={'changed': False, 'stdout': 'user4 not found', 'stderr': '', 'rc': 0, 'cmd': "getent passwd user4 || echo 'user4 not found'", 'start': '2026-01-18 03:48:40.491115', 'end': '2026-01-18 03:48:40.493713', 'delta': '0:00:00.002598', 'msg': '', 'invocation': {'module_args': {'_raw_params': "getent passwd user4 || echo 'user4 not found'", '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user4 not found'], 'stderr_lines': [], 'failed': False, 'item': 'user4', 'ansible_loop_var': 'item'}) => {
    "msg": "user4 not found"
}
ok: [tnode2] => (item={'changed': False, 'stdout': 'user5 not found', 'stderr': '', 'rc': 0, 'cmd': "getent passwd user5 || echo 'user5 not found'", 'start': '2026-01-18 03:48:40.515119', 'end': '2026-01-18 03:48:40.516887', 'delta': '0:00:00.001768', 'msg': '', 'invocation': {'module_args': {'_raw_params': "getent passwd user5 || echo 'user5 not found'", '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user5 not found'], 'stderr_lines': [], 'failed': False, 'item': 'user5', 'ansible_loop_var': 'item'}) => {
    "msg": "user5 not found"
}
ok: [tnode3] => (item={'changed': False, 'stdout': 'user5 not found', 'stderr': '', 'rc': 0, 'cmd': "getent passwd user5 || echo 'user5 not found'", 'start': '2026-01-18 03:48:40.657509', 'end': '2026-01-18 03:48:40.660023', 'delta': '0:00:00.002514', 'msg': '', 'invocation': {'module_args': {'_raw_params': "getent passwd user5 || echo 'user5 not found'", '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user5 not found'], 'stderr_lines': [], 'failed': False, 'item': 'user5', 'ansible_loop_var': 'item'}) => {
    "msg": "user5 not found"
}
ok: [tnode2] => (item={'changed': False, 'stdout': 'user6 not found', 'stderr': '', 'rc': 0, 'cmd': "getent passwd user6 || echo 'user6 not found'", 'start': '2026-01-18 03:48:40.667675', 'end': '2026-01-18 03:48:40.669460', 'delta': '0:00:00.001785', 'msg': '', 'invocation': {'module_args': {'_raw_params': "getent passwd user6 || echo 'user6 not found'", '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user6 not found'], 'stderr_lines': [], 'failed': False, 'item': 'user6', 'ansible_loop_var': 'item'}) => {
    "msg": "user6 not found"
}
ok: [tnode3] => (item={'changed': False, 'stdout': 'user6 not found', 'stderr': '', 'rc': 0, 'cmd': "getent passwd user6 || echo 'user6 not found'", 'start': '2026-01-18 03:48:40.821378', 'end': '2026-01-18 03:48:40.823888', 'delta': '0:00:00.002510', 'msg': '', 'invocation': {'module_args': {'_raw_params': "getent passwd user6 || echo 'user6 not found'", '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user6 not found'], 'stderr_lines': [], 'failed': False, 'item': 'user6', 'ansible_loop_var': 'item'}) => {
    "msg": "user6 not found"
}
ok: [tnode2] => (item={'changed': False, 'stdout': 'user7 not found', 'stderr': '', 'rc': 0, 'cmd': "getent passwd user7 || echo 'user7 not found'", 'start': '2026-01-18 03:48:40.818673', 'end': '2026-01-18 03:48:40.820623', 'delta': '0:00:00.001950', 'msg': '', 'invocation': {'module_args': {'_raw_params': "getent passwd user7 || echo 'user7 not found'", '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user7 not found'], 'stderr_lines': [], 'failed': False, 'item': 'user7', 'ansible_loop_var': 'item'}) => {
    "msg": "user7 not found"
}
ok: [tnode3] => (item={'changed': False, 'stdout': 'user7 not found', 'stderr': '', 'rc': 0, 'cmd': "getent passwd user7 || echo 'user7 not found'", 'start': '2026-01-18 03:48:40.985865', 'end': '2026-01-18 03:48:40.988338', 'delta': '0:00:00.002473', 'msg': '', 'invocation': {'module_args': {'_raw_params': "getent passwd user7 || echo 'user7 not found'", '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user7 not found'], 'stderr_lines': [], 'failed': False, 'item': 'user7', 'ansible_loop_var': 'item'}) => {
    "msg": "user7 not found"
}
ok: [tnode3] => (item={'changed': False, 'stdout': 'user8 not found', 'stderr': '', 'rc': 0, 'cmd': "getent passwd user8 || echo 'user8 not found'", 'start': '2026-01-18 03:48:41.149146', 'end': '2026-01-18 03:48:41.151610', 'delta': '0:00:00.002464', 'msg': '', 'invocation': {'module_args': {'_raw_params': "getent passwd user8 || echo 'user8 not found'", '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user8 not found'], 'stderr_lines': [], 'failed': False, 'item': 'user8', 'ansible_loop_var': 'item'}) => {
    "msg": "user8 not found"
}
ok: [tnode2] => (item={'changed': False, 'stdout': 'user8 not found', 'stderr': '', 'rc': 0, 'cmd': "getent passwd user8 || echo 'user8 not found'", 'start': '2026-01-18 03:48:40.972592', 'end': '2026-01-18 03:48:40.974593', 'delta': '0:00:00.002001', 'msg': '', 'invocation': {'module_args': {'_raw_params': "getent passwd user8 || echo 'user8 not found'", '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user8 not found'], 'stderr_lines': [], 'failed': False, 'item': 'user8', 'ansible_loop_var': 'item'}) => {
    "msg": "user8 not found"
}
ok: [tnode3] => (item={'changed': False, 'stdout': 'user9 not found', 'stderr': '', 'rc': 0, 'cmd': "getent passwd user9 || echo 'user9 not found'", 'start': '2026-01-18 03:48:41.313806', 'end': '2026-01-18 03:48:41.316194', 'delta': '0:00:00.002388', 'msg': '', 'invocation': {'module_args': {'_raw_params': "getent passwd user9 || echo 'user9 not found'", '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user9 not found'], 'stderr_lines': [], 'failed': False, 'item': 'user9', 'ansible_loop_var': 'item'}) => {
    "msg": "user9 not found"
}
ok: [tnode2] => (item={'changed': False, 'stdout': 'user9 not found', 'stderr': '', 'rc': 0, 'cmd': "getent passwd user9 || echo 'user9 not found'", 'start': '2026-01-18 03:48:41.123024', 'end': '2026-01-18 03:48:41.124990', 'delta': '0:00:00.001966', 'msg': '', 'invocation': {'module_args': {'_raw_params': "getent passwd user9 || echo 'user9 not found'", '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user9 not found'], 'stderr_lines': [], 'failed': False, 'item': 'user9', 'ansible_loop_var': 'item'}) => {
    "msg": "user9 not found"
}
ok: [tnode2] => (item={'changed': False, 'stdout': 'user10 not found', 'stderr': '', 'rc': 0, 'cmd': "getent passwd user10 || echo 'user10 not found'", 'start': '2026-01-18 03:48:41.277144', 'end': '2026-01-18 03:48:41.279074', 'delta': '0:00:00.001930', 'msg': '', 'invocation': {'module_args': {'_raw_params': "getent passwd user10 || echo 'user10 not found'", '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user10 not found'], 'stderr_lines': [], 'failed': False, 'item': 'user10', 'ansible_loop_var': 'item'}) => {
    "msg": "user10 not found"
}
ok: [tnode3] => (item={'changed': False, 'stdout': 'user10 not found', 'stderr': '', 'rc': 0, 'cmd': "getent passwd user10 || echo 'user10 not found'", 'start': '2026-01-18 03:48:41.470070', 'end': '2026-01-18 03:48:41.472197', 'delta': '0:00:00.002127', 'msg': '', 'invocation': {'module_args': {'_raw_params': "getent passwd user10 || echo 'user10 not found'", '_uses_shell': True, 'expand_argument_vars': True, 'stdin_add_newline': True, 'strip_empty_ends': True, 'cmd': None, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['user10 not found'], 'stderr_lines': [], 'failed': False, 'item': 'user10', 'ansible_loop_var': 'item'}) => {
    "msg": "user10 not found"
}

PLAY RECAP ************************************************************************************************************************************************
tnode1                     : ok=6    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
tnode2                     : ok=6    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
tnode3                     : ok=6    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

 

쑰건문

run_my_task : true

- hosts: localhost
  vars:
    run_my_task: true

  tasks:
  - name: echo message
    ansible.builtin.shell: "echo test"
    when: run_my_task
    register: result

  - name: Show result
    ansible.builtin.debug:
      var: result
root@server:~/my-ansible# ansible-playbook when_task.yml 

PLAY [localhost] ******************************************************************************************************************************************

TASK [echo message] ***************************************************************************************************************************************
changed: [localhost]

TASK [Show result] ****************************************************************************************************************************************
ok: [localhost] => {
    "result": {
        "changed": true,
        "cmd": "echo test",
        "delta": "0:00:00.001565",
        "end": "2026-01-18 03:49:25.113933",
        "failed": false,
        "msg": "",
        "rc": 0,
        "start": "2026-01-18 03:49:25.112368",
        "stderr": "",
        "stderr_lines": [],
        "stdout": "test",
        "stdout_lines": [
            "test"
        ]
    }
}

PLAY RECAP ************************************************************************************************************************************************
localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

 

run_my_task: false

- hosts: localhost
  vars:
    run_my_task: false

  tasks:
  - name: echo message
    ansible.builtin.shell: "echo test"
    when: run_my_task
    register: result

  - name: Show result
    ansible.builtin.debug:
      var: result
root@server:~/my-ansible# ansible-playbook when_task.yml 

PLAY [localhost] ******************************************************************************************************************************************

TASK [echo message] ***************************************************************************************************************************************
skipping: [localhost]

TASK [Show result] ****************************************************************************************************************************************
ok: [localhost] => {
    "result": {
        "changed": false,
        "false_condition": "run_my_task",
        "skip_reason": "Conditional result was False",
        "skipped": true
    }
}

PLAY RECAP ************************************************************************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0

 

쑰건 μ—°μ‚°μž

- hosts: all
  vars:
    supported_distros:
      - Ubuntu
      - CentOS

  tasks:
    - name: Print supported os
      ansible.builtin.debug:
        msg: "This {{ ansible_facts['distribution'] }} need to use apt"
      when: ansible_facts['distribution'] in supported_distros
root@server:~/my-ansible# ansible-playbook check_os.yml 

PLAY [all] ************************************************************************************************************************************************

TASK [Print supported os] *********************************************************************************************************************************
skipping: [tnode3]
ok: [tnode1] => {
    "msg": "This Ubuntu need to use apt"
}
ok: [tnode2] => {
    "msg": "This Ubuntu need to use apt"
}

PLAY RECAP ************************************************************************************************************************************************
tnode1                     : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
tnode2                     : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
tnode3                     : ok=0    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0

 

볡수 쑰건문

- hosts: all

  tasks:
    - name: Print os type
      ansible.builtin.debug:
        msg: "OS Type {{ ansible_facts['distribution'] }}"
      when: ansible_facts['distribution'] == "CentOS" or ansible_facts['distribution'] == "Ubuntu"
root@server:~/my-ansible# ansible-playbook check_os.yml 

PLAY [all] ************************************************************************************************************************************************

TASK [Print os type] **************************************************************************************************************************************
skipping: [tnode3]
ok: [tnode1] => {
    "msg": "OS Type Ubuntu"
}
ok: [tnode2] => {
    "msg": "OS Type Ubuntu"
}

PLAY RECAP ************************************************************************************************************************************************
tnode1                     : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
tnode2                     : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
tnode3                     : ok=0    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0

 

and μ—°μ‚°μž μ‚¬μš©ν•˜κΈ°

- hosts: all

  tasks:
    - name: Print os type
      ansible.builtin.debug:
        msg: >-
             OS Type: {{ ansible_facts['distribution'] }}
             OS Version: {{ ansible_facts['distribution_version'] }}
      when: ansible_facts['distribution'] == "Ubuntu" and ansible_facts['distribution_version'] == "24.04"
root@server:~/my-ansible# ansible-playbook check_os.yml 

PLAY [all] ************************************************************************************************************************************************

TASK [Print os type] **************************************************************************************************************************************
skipping: [tnode3]
ok: [tnode1] => {
    "msg": "OS Type: Ubuntu OS Version: 24.04"
}
ok: [tnode2] => {
    "msg": "OS Type: Ubuntu OS Version: 24.04"
}

PLAY RECAP ************************************************************************************************************************************************
tnode1                     : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
tnode2                     : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
tnode3                     : ok=0    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0

 

- hosts: all

  tasks:
    - name: Print os type
      ansible.builtin.debug:
        msg: >-
             OS Type: {{ ansible_facts['distribution'] }}
             OS Version: {{ ansible_facts['distribution_version'] }}
      when: > 
          ( ansible_facts['distribution'] == "Rocky" and
            ansible_facts['distribution_version'] == "9.6" )
          or
          ( ansible_facts['distribution'] == "Ubuntu" and
            ansible_facts['distribution_version'] == "24.04" )
root@server:~/my-ansible# ansible-playbook check_os.yml 

PLAY [all] ************************************************************************************************************************************************

TASK [Print os type] **************************************************************************************************************************************
ok: [tnode1] => {
    "msg": "OS Type: Ubuntu OS Version: 24.04"
}
ok: [tnode2] => {
    "msg": "OS Type: Ubuntu OS Version: 24.04"
}
ok: [tnode3] => {
    "msg": "OS Type: Rocky OS Version: 9.6"
}

PLAY RECAP ************************************************************************************************************************************************
tnode1                     : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
tnode2                     : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
tnode3                     : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

 

fqdn 좜λ ₯

- name: Debug OS and FQDN only for Ubuntu tnode1
  hosts: all
  gather_facts: true

  tasks:
    - name: Show OS and FQDN information
      ansible.builtin.debug:
        msg:
          - "OS Distribution : {{ ansible_distribution }}"
          - "OS Version      : {{ ansible_distribution_version }}"
          - "OS Family       : {{ ansible_os_family }}"
          - "FQDN            : {{ ansible_fqdn }}"
      when:
        - ansible_distribution == "Ubuntu"
        - ansible_fqdn == "tnode1"
root@server:~/my-ansible# ansible-playbook check_os.yml 

PLAY [Debug OS and FQDN only for Ubuntu tnode1] ***********************************************************************************************************

TASK [Show OS and FQDN information] ***********************************************************************************************************************
skipping: [tnode2]
ok: [tnode1] => {
    "msg": [
        "OS Distribution : Ubuntu",
        "OS Version      : 24.04",
        "OS Family       : Debian",
        "FQDN            : tnode1"
    ]
}
skipping: [tnode3]

PLAY RECAP ************************************************************************************************************************************************
tnode1                     : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
tnode2                     : ok=0    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
tnode3                     : ok=0    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0

 

builtin.command λͺ¨λ“ˆ

- hosts: db
  tasks:
    - name: Print Root Directory Size
      ansible.builtin.debug:
        msg: "Directory {{ item.mount }} size is {{ item.size_available }}"
      loop: "{{ ansible_facts['mounts'] }}"
      when: item['mount'] == "/" and item['size_available'] > 300000000
root@server:~/my-ansible# ansible-playbook check_mount.yml --flush-cache

PLAY [db] *************************************************************************************************************************************************

TASK [Gathering Facts] ************************************************************************************************************************************
ok: [tnode3]

TASK [Print Root Directory Size] **************************************************************************************************************************
ok: [tnode3] => (item={'mount': '/', 'device': '/dev/sda3', 'fstype': 'xfs', 'options': 'rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota', 'dump': 0, 'passno': 0, 'size_total': 63928532992, 'size_available': 61816799232, 'block_size': 4096, 'block_total': 15607552, 'block_available': 15091992, 'block_used': 515560, 'inode_total': 31247872, 'inode_available': 31209735, 'inode_used': 38137, 'uuid': '858fc44c-7093-420e-8ecd-aad817736634'}) => {
    "msg": "Directory / size is 61816799232"
}
skipping: [tnode3] => (item={'mount': '/boot/efi', 'device': '/dev/sda1', 'fstype': 'vfat', 'options': 'rw,relatime,fmask=0077,dmask=0077,codepage=437,iocharset=ascii,shortname=winnt,errors=remount-ro', 'dump': 0, 'passno': 0, 'size_total': 627875840, 'size_available': 620228608, 'block_size': 4096, 'block_total': 153290, 'block_available': 151423, 'block_used': 1867, 'inode_total': 0, 'inode_available': 0, 'inode_used': 0, 'uuid': '19AA-5BCD'}) 

PLAY RECAP ************************************************************************************************************************************************
tnode3                     : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

 

register ν‚€μ›Œλ“œ

- hosts: all

  tasks:
    - name: Get rsyslog service status
      ansible.builtin.command: systemctl is-active rsyslog
      register: result

    - name: Print rsyslog status
      ansible.builtin.debug:
        msg: "Rsyslog status is {{ result.stdout }}"
      when: result.stdout == "active"
root@server:~/my-ansible# ansible-playbook register-when.yml 

PLAY [all] ************************************************************************************************************************************************

TASK [Gathering Facts] ************************************************************************************************************************************
ok: [tnode2]
ok: [tnode1]

TASK [Get rsyslog service status] *************************************************************************************************************************
changed: [tnode2]
changed: [tnode1]
changed: [tnode3]

TASK [Print rsyslog status] *******************************************************************************************************************************
ok: [tnode1] => {
    "msg": "Rsyslog status is active"
}
ok: [tnode2] => {
    "msg": "Rsyslog status is active"
}
ok: [tnode3] => {
    "msg": "Rsyslog status is active"
}

PLAY RECAP ************************************************************************************************************************************************
tnode1                     : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
tnode2                     : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
tnode3                     : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

ν•Έλ“€λŸ¬ 및 μž‘μ—… μ‹€νŒ¨ 처리

- hosts: tnode2
  tasks:
    - name: restart rsyslog
      ansible.builtin.service:
        name: "rsyslog"
        state: restarted
      notify:
        - print msg

  handlers:
    - name: print msg
      ansible.builtin.debug:
        msg: "rsyslog is restarted"
root@server:~/my-ansible# ansible-playbook handler.yml 

PLAY [tnode2] *********************************************************************************************************************************************

TASK [restart rsyslog] ************************************************************************************************************************************
changed: [tnode2]

RUNNING HANDLER [print msg] *******************************************************************************************************************************
ok: [tnode2] => {
    "msg": "rsyslog is restarted"
}

PLAY RECAP ************************************************************************************************************************************************
tnode2                     : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

 

apache2 λͺ¨λ“ˆ μ„€μΉ˜ / μž¬μ‹œμž‘ ν”Œλ ˆμ΄λΆ

- name: Install Apache Web Server on Ubuntu and Rocky Linux
  hosts: all
  become: true
  gather_facts: true

  vars:
    web_package: "{{ 'apache2' if ansible_os_family == 'Debian' else 'httpd' }}"
    web_service: "{{ 'apache2' if ansible_os_family == 'Debian' else 'httpd' }}"

  tasks:
    - name: Install web server package
      ansible.builtin.package:
        name: "{{ web_package }}"
        state: present
      notify: Restart web service

  handlers:
    - name: Restart web service
      ansible.builtin.service:
        name: "{{ web_service }}"
        state: restarted
root@server:~/my-ansible# ansible-playbook apache.yml 

PLAY [Install Apache Web Server on Ubuntu and Rocky Linux] ************************************************************************************************

TASK [Install web server package] *************************************************************************************************************************
ok: [tnode1]
ok: [tnode2]
changed: [tnode3]

RUNNING HANDLER [Restart web service] *********************************************************************************************************************
changed: [tnode3]

PLAY RECAP ************************************************************************************************************************************************
tnode1                     : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
tnode2                     : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
tnode3                     : ok=2    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

 

 

μ²˜μŒμ— apt λͺ¨λ“ˆλ‘œ μ„€μΉ˜λ₯Ό ν•΄μ„œ tnode1,2만 λ¨Όμ € μ„€μΉ˜κ°€ λ˜μ–΄λ²„λ Έλ‹€.

os λ³€μˆ˜λ‘œ λ°›μ•„μ™€μ„œ μ„€μΉ˜λ₯Ό μ§„ν–‰ν•˜μ—¬ rocky도 μ•ˆμ „ν•˜κ²Œ μ„€μΉ˜ν•œλ‹€

 

μž‘μ—… μ‹€νŒ¨ λ¬΄μ‹œ

- hosts : tnode1

  tasks:
    - name: Install apache3
      ansible.builtin.apt:
        name: apache3
        state: latest

    - name: Print msg
      ansible.builtin.debug:
        msg: "Before task is ignored"

root@server:~/my-ansible# ansible-playbook ignore.yml 

PLAY [tnode1] *********************************************************************************************************************************************

TASK [Install apache3] ************************************************************************************************************************************
[ERROR]: Task failed: Module failed: No package matching 'apache3' is available
Origin: /root/my-ansible/ignore.yml:4:7

2
3   tasks:
4     - name: Install apache3
        ^ column 7

fatal: [tnode1]: FAILED! => {"changed": false, "msg": "No package matching 'apache3' is available"}

PLAY RECAP ************************************************************************************************************************************************
tnode1                     : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0
- hosts : tnode1

  tasks:
    - name: Install apache3
      ansible.builtin.apt:
        name: apache3
        state: latest
      ignore_errors: yes

    - name: Print msg
      ansible.builtin.debug:
        msg: "Before task is ignored"
        
        
 root@server:~/my-ansible# ansible-playbook ignore.yml 

PLAY [tnode1] *********************************************************************************************************************************************

TASK [Install apache3] ************************************************************************************************************************************
[ERROR]: Task failed: Module failed: No package matching 'apache3' is available
Origin: /root/my-ansible/ignore.yml:4:7

2
3   tasks:
4     - name: Install apache3
        ^ column 7

fatal: [tnode1]: FAILED! => {"changed": false, "msg": "No package matching 'apache3' is available"}
...ignoring

TASK [Print msg] ******************************************************************************************************************************************
ok: [tnode1] => {
    "msg": "Before task is ignored"
}

PLAY RECAP ************************************************************************************************************************************************
tnode1                     : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=1

 

μž‘μ—… μ‹€νŒ¨ ν›„ ν•Έλ“€λŸ¬ μ‹€ν–‰

- hosts: tnode2

  tasks:
    - name: restart rsyslog
      ansible.builtin.service:
        name: "rsyslog"
        state: restarted
      notify:
        - print msg

    - name: install apache3
      ansible.builtin.apt:
        name: "apache3"
        state: latest

  handlers:
    - name: print msg
      ansible.builtin.debug:
        msg: "rsyslog is restarted"
        
        
root@server:~/my-ansible# ansible-playbook ignore.yml 

PLAY [tnode2] *********************************************************************************************************************************************

TASK [restart rsyslog] ************************************************************************************************************************************
changed: [tnode2]

TASK [install apache3] ************************************************************************************************************************************
[ERROR]: Task failed: Module failed: No package matching 'apache3' is available
Origin: /root/my-ansible/ignore.yml:11:7

 9         - print msg
10
11     - name: install apache3
         ^ column 7

fatal: [tnode2]: FAILED! => {"changed": false, "msg": "No package matching 'apache3' is available"}

PLAY RECAP ************************************************************************************************************************************************
tnode2                     : ok=1    changed=1    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0
- hosts: tnode2
  force_handlers: yes

  tasks:
    - name: restart rsyslog
      ansible.builtin.service:
        name: "rsyslog"
        state: restarted
      notify:
        - print msg

    - name: install apache3
      ansible.builtin.apt:
        name: "apache3"
        state: latest

  handlers:
    - name: print msg
      ansible.builtin.debug:
        msg: "rsyslog is restarted"
        
        
 root@server:~/my-ansible# ansible-playbook ignore.yml 

PLAY [tnode2] *********************************************************************************************************************************************

TASK [restart rsyslog] ************************************************************************************************************************************
changed: [tnode2]

TASK [install apache3] ************************************************************************************************************************************
[ERROR]: Task failed: Module failed: No package matching 'apache3' is available
Origin: /root/my-ansible/ignore.yml:13:7

11         - print msg
12
13     - name: install apache3
         ^ column 7

fatal: [tnode2]: FAILED! => {"changed": false, "msg": "No package matching 'apache3' is available"}

RUNNING HANDLER [print msg] *******************************************************************************************************************************
ok: [tnode2] => {
    "msg": "rsyslog is restarted"
}

PLAY RECAP ************************************************************************************************************************************************
tnode2                     : ok=2    changed=1    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0

 

였λ₯˜ 처리

- hosts: tnode2
  vars:
    logdir: /var/log/daily_log
    logfile: todays.log

  tasks:
    - name: Configure Log Env
      block:
        - name: Find Directory
          ansible.builtin.find:
            paths: "{{ logdir }}"
          register: result
          failed_when: "'Not all paths' in result.msg"

      rescue:
        - name: Make Directory when Not found Directory
          ansible.builtin.file:
            path: "{{ logdir }}"
            state: directory
            mode: '0755'

      always:
        - name: Create File
          ansible.builtin.file:
            path: "{{ logdir }}/{{ logfile }}"
            state: touch
            mode: '0644'
root@server:~/my-ansible# ansible-playbook block-example.yml 

PLAY [tnode2] *********************************************************************************************************************************************

TASK [Find Directory] *************************************************************************************************************************************
[WARNING]: Skipped '/var/log/daily_log' path due to this access issue: '/var/log/daily_log' is not a directory
[ERROR]: Task failed: Action failed: Not all paths examined, check warnings for details
Origin: /root/my-ansible/block-example.yml:9:11

7     - name: Configure Log Env
8       block:
9         - name: Find Directory
            ^ column 11

fatal: [tnode2]: FAILED! => {"changed": false, "examined": 0, "failed_when_result": true, "files": [], "matched": 0, "msg": "Not all paths examined, check warnings for details", "skipped_paths": {"/var/log/daily_log": "'/var/log/daily_log' is not a directory"}}

TASK [Make Directory when Not found Directory] ************************************************************************************************************
changed: [tnode2]

TASK [Create File] ****************************************************************************************************************************************
changed: [tnode2]

PLAY RECAP ************************************************************************************************************************************************
tnode2                     : ok=2    changed=2    unreachable=0    failed=0    skipped=0    rescued=1    ignored=0

 

μ˜λ„μ μœΌλ‘œ μ‹€νŒ¨λ₯Ό λ°œμƒν•˜μ—¬ block이 μ‹€νŒ¨ μƒνƒœλ‘œ μ „ν™˜λ˜κ²Œ ν•œλ‹€.

 

root@server:~/my-ansible# ansible-playbook block-example.yml 

PLAY [tnode2] *********************************************************************************************************************************************

TASK [Find Directory] *************************************************************************************************************************************
ok: [tnode2]

TASK [Create File] ****************************************************************************************************************************************
changed: [tnode2]

PLAY RECAP ************************************************************************************************************************************************
tnode2                     : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

 

λ‹€μ‹œ μ‹€ν–‰ν•˜κ²Œ 되면 디렉터리가 방금 μƒμ„±λ˜μ—ˆμœΌλ―€λ‘œ 파일 생성이 μ΄λ²ˆμ—λŠ” μ„±κ³΅ν•˜κ²Œ λœλ‹€.

 

 

block rescue μ˜ˆμ‹œ

- name: Test block rescue always behavior
  hosts: all
  become: true

  vars:
    test_dir: /var/log/block_test
    test_file: result.log

  tasks:
    - name: Block / Rescue / Always test
      block:
        - name: Try to find directory (will fail if not exists)
          ansible.builtin.find:
            paths: "{{ test_dir }}"
          register: find_result
          failed_when: "'Not all paths' in find_result.msg"

      rescue:
        - name: Create directory when find failed
          ansible.builtin.file:
            path: "{{ test_dir }}"
            state: directory
            mode: '0755'

      always:
        - name: Create log file (always runs)
          ansible.builtin.file:
            path: "{{ test_dir }}/{{ test_file }}"
            state: touch
            mode: '0644'
root@server:~/my-ansible# ansible-playbook block2.yml 

PLAY [Test block rescue always behavior] ******************************************************************************************************************

TASK [Try to find directory (will fail if not exists)] ****************************************************************************************************
[WARNING]: Skipped '/var/log/block_test' path due to this access issue: '/var/log/block_test' is not a directory
[ERROR]: Task failed: Action failed: Not all paths examined, check warnings for details
Origin: /root/my-ansible/block2.yml:12:11

10     - name: Block / Rescue / Always test
11       block:
12         - name: Try to find directory (will fail if not exists)
             ^ column 11

fatal: [tnode3]: FAILED! => {"changed": false, "examined": 0, "failed_when_result": true, "files": [], "matched": 0, "msg": "Not all paths examined, check warnings for details", "skipped_paths": {"/var/log/block_test": "'/var/log/block_test' is not a directory"}}
fatal: [tnode1]: FAILED! => {"changed": false, "examined": 0, "failed_when_result": true, "files": [], "matched": 0, "msg": "Not all paths examined, check warnings for details", "skipped_paths": {"/var/log/block_test": "'/var/log/block_test' is not a directory"}}
fatal: [tnode2]: FAILED! => {"changed": false, "examined": 0, "failed_when_result": true, "files": [], "matched": 0, "msg": "Not all paths examined, check warnings for details", "skipped_paths": {"/var/log/block_test": "'/var/log/block_test' is not a directory"}}

TASK [Create directory when find failed] ******************************************************************************************************************
changed: [tnode2]
changed: [tnode1]
changed: [tnode3]

TASK [Create log file (always runs)] **********************************************************************************************************************
changed: [tnode1]
changed: [tnode2]
changed: [tnode3]

PLAY RECAP ************************************************************************************************************************************************
tnode1                     : ok=2    changed=2    unreachable=0    failed=0    skipped=0    rescued=1    ignored=0   
tnode2                     : ok=2    changed=2    unreachable=0    failed=0    skipped=0    rescued=1    ignored=0   
tnode3                     : ok=2    changed=2    unreachable=0    failed=0    skipped=0    rescued=1    ignored=0

 

ν”Œλ ˆμ΄λΆμ„ 처음 μ‹€ν–‰ν•˜λ©΄ λŒ€μƒ ν˜ΈμŠ€νŠΈμ—λŠ” /var/log/block_test 디렉터리가 μ‘΄μž¬ν•˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ— block μ˜μ—­μ—μ„œ μˆ˜ν–‰λ˜λŠ” 디렉터리 탐색 μž‘μ—…μ΄ μ‹€νŒ¨ν•œλ‹€. ansible.builtin.find λͺ¨λ“ˆμ€ μ§€μ •λœ κ²½λ‘œκ°€ 디렉터리가 아닐 경우 "Not all paths examined" λ©”μ‹œμ§€λ₯Ό λ°˜ν™˜ν•˜λ©°, 이 λ©”μ‹œμ§€λŠ” failed_when 쑰건에 μ˜ν•΄ μ˜λ„μ μœΌλ‘œ μ‹€νŒ¨λ‘œ μ²˜λ¦¬λœλ‹€. 이 μ‹œμ μ—μ„œ block 전체가 μ‹€νŒ¨ μƒνƒœλ‘œ μ „ν™˜λœλ‹€.

 

block이 μ‹€νŒ¨ν–ˆκΈ° λ•Œλ¬Έμ— Ansible은 μ¦‰μ‹œ rescue μ˜μ—­μœΌλ‘œ 흐름을 μ΄λ™ν•œλ‹€. rescue μ˜μ—­μ—μ„œλŠ” μ‹€νŒ¨μ˜ 원인이 λ˜μ—ˆλ˜ /var/log/block_test 디렉터리λ₯Ό μƒμ„±ν•˜λŠ” μž‘μ—…μ΄ μˆ˜ν–‰λœλ‹€. 이 μž‘μ—…μ„ 톡해 μ‹€ν–‰ ν™˜κ²½μ€ 정상 μƒνƒœλ‘œ 볡ꡬ되며, 이후 μž‘μ—…μ΄ μ •μƒμ μœΌλ‘œ 진행될 수 μžˆλŠ” 쑰건이 λ§ˆλ ¨λœλ‹€.

 

rescue μ‹€ν–‰ 여뢀와 관계없이 always μ˜μ—­μ€ λ°˜λ“œμ‹œ μ‹€ν–‰λœλ‹€. always μ˜μ—­μ—μ„œλŠ” μ•žμ„œ μ •μ˜ν•œ 디렉터리 경둜 μ•„λž˜μ— result.log νŒŒμΌμ„ μƒμ„±ν•˜λŠ” μž‘μ—…μ΄ μˆ˜ν–‰λœλ‹€. 이둜 인해 첫 번째 싀행이 μ’…λ£Œλœ μ‹œμ μ—λŠ” 디렉터리와 둜그 파일이 λͺ¨λ‘ μƒμ„±λœ μƒνƒœκ°€ λœλ‹€. μ‹€ν–‰ κ²°κ³Ό μš”μ•½μ—μ„œλŠ” rescueκ°€ ν•œ 번 μ‹€ν–‰λ˜μ—ˆμŒμ„ λ‚˜νƒ€λ‚΄λŠ” rescued=1 값이 좜λ ₯λœλ‹€.

 

root@server:~/my-ansible# ansible-playbook block2.yml 

PLAY [Test block rescue always behavior] ******************************************************************************************************************

TASK [Try to find directory (will fail if not exists)] ****************************************************************************************************
ok: [tnode3]
ok: [tnode1]
ok: [tnode2]

TASK [Create log file (always runs)] **********************************************************************************************************************
changed: [tnode3]
changed: [tnode2]
changed: [tnode1]

PLAY RECAP ************************************************************************************************************************************************
tnode1                     : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
tnode2                     : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
tnode3                     : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

 

같은 ν”Œλ ˆμ΄λΆμ„ 두 번째둜 μ‹€ν–‰ν•˜λ©΄ /var/log/block_test 디렉터리가 μ‘΄μž¬ν•˜λ―€λ‘œ block μ˜μ—­μ˜ 디렉터리 탐색 μž‘μ—…μ€ μ •μƒμ μœΌλ‘œ μ™„λ£Œλœλ‹€. 이 경우 block은 μ‹€νŒ¨ν•˜μ§€ μ•ŠμœΌλ©°, rescue μ˜μ—­μ€ μ‹€ν–‰λ˜μ§€ μ•ŠλŠ”λ‹€. rescue μ‹€ν–‰ νšŸμˆ˜λŠ” 0으둜 κΈ°λ‘λœλ‹€.

 

κ·ΈλŸ¬λ‚˜ always μ˜μ—­μ€ μ—¬μ „νžˆ μ‹€ν–‰λœλ‹€. alwaysμ—μ„œ μ‚¬μš©λœ state: touch 섀정은 파일이 이미 μ‘΄μž¬ν•˜λ”λΌλ„ μˆ˜μ • μ‹œκ°„(mtime)을 κ°±μ‹ ν•˜κΈ° λ•Œλ¬Έμ—, 두 번째 μ‹€ν–‰μ—μ„œλ„ 파일 μž‘μ—…μ€ λ³€κ²½ μ‚¬ν•­μœΌλ‘œ μΈμ‹λœλ‹€. 이둜 인해 μ‹€ν–‰ κ²°κ³Ό μš”μ•½μ—λŠ” changed=1이 κΈ°λ‘λœλ‹€.

 

둀 ꡬ쑰

Ansibleμ—μ„œ Role은 ν”Œλ ˆμ΄λΆμ„ κ΅¬μ„±ν•˜λŠ” μž‘μ—…λ“€μ„ μ—­ν•  λ‹¨μœ„λ‘œ κ΅¬μ‘°ν™”ν•˜κΈ° μœ„ν•œ ν‘œμ€€μ μΈ 방법이닀. 단일 ν”Œλ ˆμ΄λΆμ— λͺ¨λ“  μž‘μ—…μ„ μž‘μ„±ν•˜λŠ” 방식은 규λͺ¨κ°€ 컀질수둝 가독성과 μž¬μ‚¬μš©μ„±μ΄ λ–¨μ–΄μ§„λ‹€. 이λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄ Ansible은 Roleμ΄λΌλŠ” κ°œλ…μ„ λ„μž…ν•˜μ—¬, κ΄€λ ¨λœ μž‘μ—…λ“€μ„ ν•˜λ‚˜μ˜ 논리적인 묢음으둜 관리할 수 μžˆλ„λ‘ ν•œλ‹€.

 

Role은 νŠΉμ • λͺ©μ μ„ μˆ˜ν–‰ν•˜λŠ” 데 ν•„μš”ν•œ μž‘μ—…(tasks), λ³€μˆ˜(vars), ν•Έλ“€λŸ¬(handlers), 파일(files), ν…œν”Œλ¦Ώ(templates) 등을 ν•˜λ‚˜μ˜ 디렉터리 ꡬ쑰둜 κ΅¬μ„±ν•œλ‹€. 예λ₯Ό λ“€μ–΄ μ›Ή μ„œλ²„λ₯Ό μ„€μΉ˜ν•˜κ³  μ„€μ •ν•˜λŠ” μž‘μ—…μ€ webserverλΌλŠ” Role둜 뢄리할 수 있으며, λ°μ΄ν„°λ² μ΄μŠ€ μ„€μΉ˜ μž‘μ—…μ€ database Role둜 뢄리할 수 μžˆλ‹€. μ΄λ ‡κ²Œ κ΅¬μ„±λœ Role은 μ—¬λŸ¬ ν”Œλ ˆμ΄λΆμ—μ„œ μž¬μ‚¬μš©ν•  수 μžˆλ‹€.

 

root@server:~/my-ansible# ansible-galaxy role init my-role
- Role my-role was created successfully
root@server:~/my-ansible# tree ./my-role/
./my-role/
β”œβ”€β”€ defaults
β”‚   └── main.yml
β”œβ”€β”€ files
β”œβ”€β”€ handlers
β”‚   └── main.yml
β”œβ”€β”€ meta
β”‚   └── main.yml
β”œβ”€β”€ README.md
β”œβ”€β”€ tasks
β”‚   └── main.yml
β”œβ”€β”€ templates
β”œβ”€β”€ tests
β”‚   β”œβ”€β”€ inventory
β”‚   └── test.yml
└── vars
    └── main.yml

9 directories, 8 files

 

~/my-ansible/my-role/tasks/main.yml

#SPDX-License-Identifier: MIT-0
---
# tasks file for my-role
- name: install service {{ service_title }}
  ansible.builtin.apt:
    name: "{{ item }}"
    state: latest
  loop: "{{ httpd_packages }}"
  when: ansible_facts.distribution in supported_distros

- name: copy conf file
  ansible.builtin.copy:
    src: "{{ src_file_path }}"
    dest: "{{ dest_file_path }}"
  notify: 
    - restart service

 

~/my-ansible/my-role/files/index.html

root@server:~/my-ansible/my-role# echo "Hello! Ansible" > files/index.html

 

~/my-ansible/my-role/handlers/main.yml

- name: restart service
  ansible.builtin.service:
    name: "{{ service_name }}"
    state: restarted

 

~/my-ansible/my-role/defaults/main.yml

echo 'service_title: "Apache Web Server"' >> defaults/main.yml

 

my-ansible/my-role/vars/main.yml

service_name: apache2
src_file_path: ../files/index.html
dest_file_path: /var/www/html
httpd_packages:
  - apache2
  - apache2-doc

supported_distros:
  - Ubuntu

 

~/my-ansible/role-example.yml

ν”Œλ ˆμ΄λΆμ—μ„œ λ‘€ 싀행을 μœ„ν•΄ 둀을 ν˜ΈμΆœν•˜λŠ” ν”Œλ ˆμ΄λΆ

- hosts: tnode1

  tasks:
    - name: Print start play
      ansible.builtin.debug:
        msg: "Let's start role play"

    - name: Install Service by role
      ansible.builtin.import_role:
        name: my-role
root@server:~/my-ansible# ansible-playbook role-example.yml

PLAY [tnode1] *********************************************************************************************************************************************

TASK [Print start play] ***********************************************************************************************************************************
ok: [tnode1] => {
    "msg": "Let's start role play"
}

TASK [my-role : install service Apache Web Server] ********************************************************************************************************
ok: [tnode1] => (item=apache2)
changed: [tnode1] => (item=apache2-doc)

TASK [my-role : copy conf file] ***************************************************************************************************************************
changed: [tnode1]

RUNNING HANDLER [my-role : restart service] ***************************************************************************************************************
changed: [tnode1]

PLAY RECAP ************************************************************************************************************************************************
tnode1                     : ok=4    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

 

- hosts: tnode1

  tasks:
    - name: Print start play
      ansible.builtin.debug:
        msg: "Let's start role play"

    - name: Install Service by role
      ansible.builtin.import_role:
        name: my-role
      vars:
        service_title: Httpd
root@server:~/my-ansible# ansible-playbook role-example.yml

PLAY [tnode1] *********************************************************************************************************************************************

TASK [Print start play] ***********************************************************************************************************************************
ok: [tnode1] => {
    "msg": "Let's start role play"
}

TASK [my-role : install service Httpd] ********************************************************************************************************************
ok: [tnode1] => (item=apache2)
ok: [tnode1] => (item=apache2-doc)

TASK [my-role : copy conf file] ***************************************************************************************************************************
ok: [tnode1]

PLAY RECAP ************************************************************************************************************************************************
tnode1                     : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
root@server:~/my-ansible# curl tnode1
Hello! Ansible

 

index.html 정적 파일 λ³€κ²½

root@server:~/my-ansible# echo "Hello! CloudNet@" > my-role/files/index.html

root@server:~/my-ansible# ansible-playbook role-example.yml

PLAY [tnode1] *********************************************************************************************************************************************

TASK [Print start play] ***********************************************************************************************************************************
ok: [tnode1] => {
    "msg": "Let's start role play"
}

TASK [my-role : install service Httpd] ********************************************************************************************************************
ok: [tnode1] => (item=apache2)
ok: [tnode1] => (item=apache2-doc)

TASK [my-role : copy conf file] ***************************************************************************************************************************
changed: [tnode1]

RUNNING HANDLER [my-role : restart service] ***************************************************************************************************************
changed: [tnode1]

PLAY RECAP ************************************************************************************************************************************************
tnode1                     : ok=4    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

root@server:~/my-ansible# curl tnode1
Hello! CloudNet@

 

ν”Œλ ˆμ΄λΆμ—μ„œ Roles μ„Ήμ…˜ μ‚¬μš©

# tnode1
apt install firewalld -y
systemctl status firewalld

Hello! CloudNet@
root@server:~/my-ansible# ping -c 1 tnode1
PING tnode1 (10.10.1.11) 56(84) bytes of data.
64 bytes from tnode1 (10.10.1.11): icmp_seq=1 ttl=64 time=1.82 ms

--- tnode1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 1.820/1.820/1.820/0.000 ms
root@server:~/my-ansible# curl tnode1
curl: (7) Failed to connect to tnode1 port 80 after 4 ms: Couldn't connect to server
root@server:~/my-ansible# ansible-galaxy role init my-role2
- Role my-role2 was created successfully
root@server:~/my-ansible# tree my-role2
my-role2
β”œβ”€β”€ defaults
β”‚   └── main.yml
β”œβ”€β”€ files
β”œβ”€β”€ handlers
β”‚   └── main.yml
β”œβ”€β”€ meta
β”‚   └── main.yml
β”œβ”€β”€ README.md
β”œβ”€β”€ tasks
β”‚   └── main.yml
β”œβ”€β”€ templates
β”œβ”€β”€ tests
β”‚   β”œβ”€β”€ inventory
β”‚   └── test.yml
└── vars
    └── main.yml

9 directories, 8 files

 

my-ansible/my-role2/tasks/main.yml

- name: Config firewalld
  ansible.posix.firewalld:
    service: "{{ item }}"
    permanent: true
    state: enabled
  loop: "{{ service_port }}"

- name: Reload firewalld
  ansible.builtin.service:
    name: firewalld
    state: reloaded

 

my-ansible/my-role2/vars/main.yml

---
# defaults file for my-role2

service_port: 
  - http
  - https

 

my-ansible/role-example2.yml

- hosts: tnode1

  roles:
    - my-role
    - my-role2

  tasks:
    - name: Print finish role play
      ansible.builtin.debug:
        msg: "Finish role play"
root@server:~/my-ansible# ansible-playbook role-example2.yml 

PLAY [tnode1] *********************************************************************************************************************************************

TASK [my-role : install service Apache Web Server] ********************************************************************************************************
ok: [tnode1] => (item=apache2)
ok: [tnode1] => (item=apache2-doc)

TASK [my-role : copy conf file] ***************************************************************************************************************************
ok: [tnode1]

TASK [my-role2 : Config firewalld] ************************************************************************************************************************
changed: [tnode1] => (item=http)
changed: [tnode1] => (item=https)

TASK [my-role2 : Reload firewalld] ************************************************************************************************************************
changed: [tnode1]

TASK [Print finish role play] *****************************************************************************************************************************
ok: [tnode1] => {
    "msg": "Finish role play"
}

PLAY RECAP ************************************************************************************************************************************************
tnode1                     : ok=5    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
root@server:~/my-ansible# curl tnode1
Hello! CloudNet@

root@server:~/my-ansible# ansible -m shell -a "firewall-cmd --list-all" tnode1
tnode1 | CHANGED | rc=0 >>
public (default, active)
  target: default
  ingress-priority: 0
  egress-priority: 0
  icmp-block-inversion: no
  interfaces: 
  sources: 
  services: dhcpv6-client http https ssh
  ports: 
  protocols: 
  forward: yes
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules:

 

특수 μž‘μ—… μ„Ήμ…˜

Role μ‹€ν–‰ μ „ν›„ 흐름과 handler λ™μž‘ μˆœμ„œλ₯Ό 확인할 수 μžˆλŠ” ν”Œλ ˆμ΄λΆμ΄λ‹€.

- hosts: tnode1

  pre_tasks:
    - name: Print Start role
      ansible.builtin.debug:
        msg: "Let's start role play"
 
  roles:
    - role: my-role
    - role: my-role2
 
  tasks:
    - name: Curl test
      ansible.builtin.uri:
        url: http://tnode1
        return_content: true
      register: curl_result
      notify: Print result
      changed_when: true

  post_tasks:
    - name: Print Finish role
      ansible.builtin.debug:
        msg: "Finish role play"

  handlers:
    - name: Print result
      ansible.builtin.debug:
        msg: "{{ curl_result.content }}"
root@server:~/my-ansible# ansible-playbook special_role.yml

PLAY [tnode1] *********************************************************************************************************************************************

TASK [Print Start role] ***********************************************************************************************************************************
ok: [tnode1] => {
    "msg": "Let's start role play"
}

TASK [my-role : install service Apache Web Server] ********************************************************************************************************
ok: [tnode1] => (item=apache2)
ok: [tnode1] => (item=apache2-doc)

TASK [my-role : copy conf file] ***************************************************************************************************************************
ok: [tnode1]

TASK [my-role2 : Config firewalld] ************************************************************************************************************************
ok: [tnode1] => (item=http)
ok: [tnode1] => (item=https)

TASK [my-role2 : Reload firewalld] ************************************************************************************************************************
changed: [tnode1]

TASK [Curl test] ******************************************************************************************************************************************
changed: [tnode1]

RUNNING HANDLER [Print result] ****************************************************************************************************************************
ok: [tnode1] => {
    "msg": "Hello! CloudNet@\n"
}

TASK [Print Finish role] **********************************************************************************************************************************
ok: [tnode1] => {
    "msg": "Finish role play"
}

PLAY RECAP ************************************************************************************************************************************************
tnode1                     : ok=8    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

 

ν”Œλ ˆμ΄λΆμ΄ μ‹€ν–‰λ˜λ©΄ λ¨Όμ € pre_tasksμ—μ„œ "Let's start role play" λ©”μ‹œμ§€λ₯Ό 좜λ ₯ν•˜μ—¬ Role μ‹€ν–‰ μ‹œμž‘μ„ μ•Œλ¦°λ‹€. 이후 roles μ˜μ—­μ—μ„œ my-roleκ³Ό my-role2κ°€ μˆœμ„œλŒ€λ‘œ μ‹€ν–‰λ˜λ©°, μ‹€μ œ μ‹œμŠ€ν…œ ꡬ성 μž‘μ—…μ€ 이 Role듀이 λ‹΄λ‹Ήν•œλ‹€.

 

Role 싀행이 λλ‚œ λ’€ tasks λ‹¨κ³„μ—μ„œ uri λͺ¨λ“ˆμ„ μ‚¬μš©ν•΄ tnode1의 μ›Ή μ„œλΉ„μŠ€μ— HTTP μš”μ²­μ„ 보내 정상 λ™μž‘ μ—¬λΆ€λ₯Ό ν™•μΈν•œλ‹€. 이 μž‘μ—…μ€ 항상 λ³€κ²½λœ κ²ƒμœΌλ‘œ μ²˜λ¦¬λ˜μ–΄ handlerλ₯Ό ν˜ΈμΆœν•˜λ©°, handlerμ—μ„œλŠ” HTTP 응닡 λ‚΄μš©μ„ 좜λ ₯ν•œλ‹€.

 

λ§ˆμ§€λ§‰μœΌλ‘œ post_tasksμ—μ„œ "Finish role play" λ©”μ‹œμ§€λ₯Ό 좜λ ₯ν•˜μ—¬ 전체 Role μ‹€ν–‰ 흐름이 μ’…λ£Œλ˜μ—ˆμŒμ„ μ•Œλ¦°λ‹€.
이 ν”Œλ ˆμ΄λΆμ€ pre_tasks → roles → tasks → handlers → post_tasks의 μ‹€ν–‰ μˆœμ„œλ₯Ό 확인할 수 μžˆλ‹€.