Ansible – In and Out | Playbooks | Setup Module | Part 4

Playbooks are the files where the Ansible code is written. Playbooks are written in YAML format. YAML stands for Yet Another Markup Language. Playbooks are one of the core features of Ansible and tell Ansible what to execute. They are like a to-do list for Ansible that contains a list of tasks. 

Playbooks are a completely different way to use Ansible than in ad-hoc task execution mode and thus are particularly powerful. That was enough for the introduction, let’s do some practical stuff and write our first Playbook. 

Under our project named “superman”, I have created a folder named playbook exercise and we are going to create a file named web.yml which is the name of the playbook with the below command.

vim web.yml 

In playbooks (yml is the extension for YAML file) where:
“-” represent a list in Yaml
A list can have another list or can have a dictionary.
Here is example we have 2 plays

Let’s create a web.yml as discussed above

#################web.yml#######################
---
- hosts: websrvgrp
  become: yes
  tasks:
    - name: Install apache http SVC
      yum:
        name: httpd
        state: present


    - name: Start and enable Apache http SVC
      service:
        name: httpd
        state: started
        enabled: yes

Let’s understand what it is doing

Till now as we were using 2 centOS machines as web servers. Let’s now add another webserver which is an Ubuntu web server.
So above in this playbook we have one play (play starts with -hosts). This is going to install apache service on all the webservers as we have given the web servers group in hosts and then will start and enable the service on all web servers. So it contains 2 tasks. 

  • Playbooks are pretty much self-explanatory.
  • To execute playbook, we use the below command  
ansible-playbook web.yml

We will notice that httpd service is up and running on websrv01 and websrv02 but not on websrv03(commenting it now) as it is a ubuntu operating system. Later we will see how to tackle this scenario when we will jump to conditions.

Let’s execute the command again and see what happens:

On websrv01 we can see that we have executed 2 tasks:

  1. Installing httpd service
  2. Enabling it

However, there are 3 tasks shown in the response available.

Ansible setup module and fact variables

In the above screenshot, we can see the default task/first is being executed for all the web servers and that task is called Gathering Facts. Gathering facts is a default task and it generates fact variables.

Before ansible executes any task on the target machine it executes a module called setup module and this module collects all information about the target machine. We can also run the setup module directly on any server. Suppose for web server 01 we can run the setup module with the below command:

ansible -m setup websrv01

Response

ubuntu@ip-172-31-20-76:~/superman$ ansible -m setup websrv01
websrv01 | SUCCESS => {
    "ansible_facts": {
        "ansible_all_ipv4_addresses": [
            "172.31.34.188"
        ],
        "ansible_all_ipv6_addresses": [
            "fe80::803:edff:fea6:5756"
        ],
        "ansible_apparmor": {
            "status": "disabled"
        },
        "ansible_architecture": "x86_64",
        "ansible_bios_date": "08/24/2006",
        "ansible_bios_version": "4.2.amazon",
        "ansible_cmdline": {
            "BOOT_IMAGE": "/boot/vmlinuz-3.10.0-957.1.3.el7.x86_64",
            "LANG": "en_US.UTF-8",
            "console": "ttyS0,115200",
            "crashkernel": "auto",
            "ro": true,
            "root": "UUID=f41e390f-835b-4223-a9bb-9b45984ddf8d"
        },
        "ansible_date_time": {
            "date": "2020-02-09",
            "day": "09",
            "epoch": "1581276123",
            "hour": "19",
            "iso8601": "2020-02-09T19:22:03Z",
            "iso8601_basic": "20200209T192203762837",
            "iso8601_basic_short": "20200209T192203",
            "iso8601_micro": "2020-02-09T19:22:03.762919Z",
            "minute": "22",
            "month": "02",
            "second": "03",
            "time": "19:22:03",
            "tz": "UTC",
            "tz_offset": "+0000",
            "weekday": "Sunday",
            "weekday_number": "0",
            "weeknumber": "05",
            "year": "2020"
        },
        "ansible_default_ipv4": {
            "address": "172.31.34.188",
            "alias": "eth0",
            "broadcast": "172.31.47.255",
            "gateway": "172.31.32.1",
            "interface": "eth0",
            "macaddress": "0a:03:ed:a6:57:56",
            "mtu": 9001,
            "netmask": "255.255.240.0",
            "network": "172.31.32.0",
            "type": "ether"
        },
        "ansible_default_ipv6": {},
        "ansible_device_links": {
            "ids": {},
            "labels": {},
            "masters": {},
            "uuids": {
                "xvda1": [
                    "f41e390f-835b-4223-a9bb-9b45984ddf8d"
                ]
            }
        },
        "ansible_devices": {
            "xvda": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": null,
                "partitions": {
                    "xvda1": {
                        "holders": [],
                        "links": {
                            "ids": [],
                            "labels": [],
                            "masters": [],
                            "uuids": [
                                "f41e390f-835b-4223-a9bb-9b45984ddf8d"
                            ]
                        },
                        "sectors": "16775168",
                        "sectorsize": 512,
                        "size": "8.00 GB",
                        "start": "2048",
                        "uuid": "f41e390f-835b-4223-a9bb-9b45984ddf8d"
                    }
                },
                "removable": "0",
                "rotational": "0",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "deadline",
                "sectors": "16777216",
                "sectorsize": "512",
                "size": "8.00 GB",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            }
        },
        "ansible_distribution": "CentOS",
        "ansible_distribution_file_parsed": true,
        "ansible_distribution_file_path": "/etc/redhat-release",
        "ansible_distribution_file_variety": "RedHat",
        "ansible_distribution_major_version": "7",
        "ansible_distribution_release": "Core",
        "ansible_distribution_version": "7.6",
        "ansible_dns": {
            "nameservers": [
                "172.31.0.2"
            ],
            "search": [
                "us-east-2.compute.internal"
            ]
        },
        "ansible_domain": "us-east-2.compute.internal",
        "ansible_effective_group_id": 0,
        "ansible_effective_user_id": 0,
        "ansible_env": {
            "HOME": "/root",
            "LANG": "C",
            "LC_ALL": "C",
            "LC_MESSAGES": "C",
            "LOGNAME": "root",
            "LS_COLORS": "rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36:",
            "MAIL": "/var/mail/devops",
            "PATH": "/sbin:/bin:/usr/sbin:/usr/bin",
            "PWD": "/home/devops",
            "SHELL": "/bin/bash",
            "SHLVL": "1",
            "SUDO_COMMAND": "/bin/sh -c echo BECOME-SUCCESS-kqwxxiryqpmggrtiiknmyptaijajuzxf ; /usr/bin/python /home/devops/.ansible/tmp/ansible-tmp-1581276122.5-11152747352541/AnsiballZ_setup.py",
            "SUDO_GID": "1001",
            "SUDO_UID": "1001",
            "SUDO_USER": "devops",
            "TERM": "xterm",
            "USER": "root",
            "USERNAME": "root",
            "XDG_SESSION_ID": "8",
            "_": "/usr/bin/python"
        },
        "ansible_eth0": {
            "active": true,
            "device": "eth0",
            "features": {
                "busy_poll": "off [fixed]",
                "fcoe_mtu": "off [fixed]",
                "generic_receive_offload": "on",
                "generic_segmentation_offload": "on",
                "highdma": "off [fixed]",
                "hw_tc_offload": "off [fixed]",
                "l2_fwd_offload": "off [fixed]",
                "large_receive_offload": "off [fixed]",
                "loopback": "off [fixed]",
                "netns_local": "off [fixed]",
                "ntuple_filters": "off [fixed]",
                "receive_hashing": "off [fixed]",
                "rx_all": "off [fixed]",
                "rx_checksumming": "on [fixed]",
                "rx_fcs": "off [fixed]",
                "rx_gro_hw": "off [fixed]",
                "rx_udp_tunnel_port_offload": "off [fixed]",
                "rx_vlan_filter": "off [fixed]",
                "rx_vlan_offload": "off [fixed]",
                "rx_vlan_stag_filter": "off [fixed]",
                "rx_vlan_stag_hw_parse": "off [fixed]",
                "scatter_gather": "on",
                "tcp_segmentation_offload": "on",
                "tx_checksum_fcoe_crc": "off [fixed]",
                "tx_checksum_ip_generic": "off [fixed]",
                "tx_checksum_ipv4": "on [fixed]",
                "tx_checksum_ipv6": "off [requested on]",
                "tx_checksum_sctp": "off [fixed]",
                "tx_checksumming": "on",
                "tx_fcoe_segmentation": "off [fixed]",
                "tx_gre_csum_segmentation": "off [fixed]",
                "tx_gre_segmentation": "off [fixed]",
                "tx_gso_partial": "off [fixed]",
                "tx_gso_robust": "on [fixed]",
                "tx_ipip_segmentation": "off [fixed]",
                "tx_lockless": "off [fixed]",
                "tx_nocache_copy": "off",
                "tx_scatter_gather": "on",
                "tx_scatter_gather_fraglist": "off [fixed]",
                "tx_sctp_segmentation": "off [fixed]",
                "tx_sit_segmentation": "off [fixed]",
                "tx_tcp6_segmentation": "off [requested on]",
                "tx_tcp_ecn_segmentation": "off [fixed]",
                "tx_tcp_mangleid_segmentation": "off",
                "tx_tcp_segmentation": "on",
                "tx_udp_tnl_csum_segmentation": "off [fixed]",
                "tx_udp_tnl_segmentation": "off [fixed]",
                "tx_vlan_offload": "off [fixed]",
                "tx_vlan_stag_hw_insert": "off [fixed]",
                "udp_fragmentation_offload": "off [fixed]",
                "vlan_challenged": "off [fixed]"
            },
            "hw_timestamp_filters": [],
            "ipv4": {
                "address": "172.31.34.188",
                "broadcast": "172.31.47.255",
                "netmask": "255.255.240.0",
                "network": "172.31.32.0"
            },
            "ipv6": [
                {
                    "address": "fe80::803:edff:fea6:5756",
                    "prefix": "64",
                    "scope": "link"
                }
            ],
            "macaddress": "0a:03:ed:a6:57:56",
            "module": "xen_netfront",
            "mtu": 9001,
            "pciid": "vif-0",
            "promisc": false,
            "timestamping": [
                "rx_software",
                "software"
            ],
            "type": "ether"
        },
        "ansible_fibre_channel_wwn": [],
        "ansible_fips": false,
        "ansible_form_factor": "Other",
        "ansible_fqdn": "ip-172-31-34-188.us-east-2.compute.internal",
        "ansible_hostname": "ip-172-31-34-188",
        "ansible_hostnqn": "",
        "ansible_interfaces": [
            "lo",
            "eth0"
        ],
        "ansible_is_chroot": false,
        "ansible_iscsi_iqn": "",
        "ansible_kernel": "3.10.0-957.1.3.el7.x86_64",
        "ansible_kernel_version": "#1 SMP Thu Nov 29 14:49:43 UTC 2018",
        "ansible_lo": {
            "active": true,
            "device": "lo",
            "features": {
                "busy_poll": "off [fixed]",
                "fcoe_mtu": "off [fixed]",
                "generic_receive_offload": "on",
                "generic_segmentation_offload": "on",
                "highdma": "on [fixed]",
                "hw_tc_offload": "off [fixed]",
                "l2_fwd_offload": "off [fixed]",
                "large_receive_offload": "off [fixed]",
                "loopback": "on [fixed]",
                "netns_local": "on [fixed]",
                "ntuple_filters": "off [fixed]",
                "receive_hashing": "off [fixed]",
                "rx_all": "off [fixed]",
                "rx_checksumming": "on [fixed]",
                "rx_fcs": "off [fixed]",
                "rx_gro_hw": "off [fixed]",
                "rx_udp_tunnel_port_offload": "off [fixed]",
                "rx_vlan_filter": "off [fixed]",
                "rx_vlan_offload": "off [fixed]",
                "rx_vlan_stag_filter": "off [fixed]",
                "rx_vlan_stag_hw_parse": "off [fixed]",
                "scatter_gather": "on",
                "tcp_segmentation_offload": "on",
                "tx_checksum_fcoe_crc": "off [fixed]",
                "tx_checksum_ip_generic": "on [fixed]",
                "tx_checksum_ipv4": "off [fixed]",
                "tx_checksum_ipv6": "off [fixed]",
                "tx_checksum_sctp": "on [fixed]",
                "tx_checksumming": "on",
                "tx_fcoe_segmentation": "off [fixed]",
                "tx_gre_csum_segmentation": "off [fixed]",
                "tx_gre_segmentation": "off [fixed]",
                "tx_gso_partial": "off [fixed]",
                "tx_gso_robust": "off [fixed]",
                "tx_ipip_segmentation": "off [fixed]",
                "tx_lockless": "on [fixed]",
                "tx_nocache_copy": "off [fixed]",
                "tx_scatter_gather": "on [fixed]",
                "tx_scatter_gather_fraglist": "on [fixed]",
                "tx_sctp_segmentation": "on",
                "tx_sit_segmentation": "off [fixed]",
                "tx_tcp6_segmentation": "on",
                "tx_tcp_ecn_segmentation": "on",
                "tx_tcp_mangleid_segmentation": "on",
                "tx_tcp_segmentation": "on",
                "tx_udp_tnl_csum_segmentation": "off [fixed]",
                "tx_udp_tnl_segmentation": "off [fixed]",
                "tx_vlan_offload": "off [fixed]",
                "tx_vlan_stag_hw_insert": "off [fixed]",
                "udp_fragmentation_offload": "on",
                "vlan_challenged": "on [fixed]"
            },
            "hw_timestamp_filters": [],
            "ipv4": {
                "address": "127.0.0.1",
                "broadcast": "host",
                "netmask": "255.0.0.0",
                "network": "127.0.0.0"
            },
            "ipv6": [
                {
                    "address": "::1",
                    "prefix": "128",
                    "scope": "host"
                }
            ],
            "mtu": 65536,
            "promisc": false,
            "timestamping": [
                "rx_software",
                "software"
            ],
            "type": "loopback"
        },
        "ansible_local": {},
        "ansible_lsb": {},
        "ansible_machine": "x86_64",
        "ansible_machine_id": "05cb8c7b39fe0f70e3ce97e5beab809d",
        "ansible_memfree_mb": 658,
        "ansible_memory_mb": {
            "nocache": {
                "free": 847,
                "used": 142
            },
            "real": {
                "free": 658,
                "total": 989,
                "used": 331
            },
            "swap": {
                "cached": 0,
                "free": 0,
                "total": 0,
                "used": 0
            }
        },
        "ansible_memtotal_mb": 989,
        "ansible_mounts": [
            {
                "block_available": 1817589,
                "block_size": 4096,
                "block_total": 2094336,
                "block_used": 276747,
                "device": "/dev/xvda1",
                "fstype": "xfs",
                "inode_available": 4167226,
                "inode_total": 4193792,
                "inode_used": 26566,
                "mount": "/",
                "options": "rw,seclabel,relatime,attr2,inode64,noquota",
                "size_available": 7444844544,
                "size_total": 8578400256,
                "uuid": "f41e390f-835b-4223-a9bb-9b45984ddf8d"
            }
        ],
        "ansible_nodename": "ip-172-31-34-188.us-east-2.compute.internal",
        "ansible_os_family": "RedHat",
        "ansible_pkg_mgr": "yum",
        "ansible_proc_cmdline": {
            "BOOT_IMAGE": "/boot/vmlinuz-3.10.0-957.1.3.el7.x86_64",
            "LANG": "en_US.UTF-8",
            "console": [
                "tty0",
                "ttyS0,115200n8",
                "ttyS0,115200"
            ],
            "crashkernel": "auto",
            "ro": true,
            "root": "UUID=f41e390f-835b-4223-a9bb-9b45984ddf8d"
        },
        "ansible_processor": [
            "0",
            "GenuineIntel",
            "Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz"
        ],
        "ansible_processor_cores": 1,
        "ansible_processor_count": 1,
        "ansible_processor_threads_per_core": 1,
        "ansible_processor_vcpus": 1,
        "ansible_product_name": "HVM domU",
        "ansible_product_serial": "ec2b0d2a-f66f-0f3d-80ce-f42b61c10ba2",
        "ansible_product_uuid": "EC2B0D2A-F66F-0F3D-80CE-F42B61C10BA2",
        "ansible_product_version": "4.2.amazon",
        "ansible_python": {
            "executable": "/usr/bin/python",
            "has_sslcontext": true,
            "type": "CPython",
            "version": {
                "major": 2,
                "micro": 5,
                "minor": 7,
                "releaselevel": "final",
                "serial": 0
            },
            "version_info": [
                2,
                7,
                5,
                "final",
                0
            ]
        },
        "ansible_python_version": "2.7.5",
        "ansible_real_group_id": 0,
        "ansible_real_user_id": 0,
        "ansible_selinux": {
            "config_mode": "enforcing",
            "mode": "enforcing",
            "policyvers": 31,
            "status": "enabled",
            "type": "targeted"
        },
        "ansible_selinux_python_present": true,
        "ansible_service_mgr": "systemd",
        "ansible_ssh_host_key_ecdsa_public": "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOhlDSZYvcL5I+TmxCLoj/k3cg+Euy88gzXkQtMVQA58NSwKUx9MSUFv3B+HTMrfGVtnBSCIdIuON45PmlMoqGo=",
        "ansible_ssh_host_key_ed25519_public": "AAAAC3NzaC1lZDI1NTE5AAAAIIhFv3zJkEgmJyCSlhUodOtLrPbDaBWvtGkj3pBuw9Dq",
        "ansible_ssh_host_key_rsa_public": "AAAAB3NzaC1yc2EAAAADAQABAAABAQClle+xrS0le1qzL5xjQ1ZgXZTiydFe9wrReyJPAW3oZzjpLiIqrj8l6rDMwIJtBLvm0JCOQxjgGCtWCtaZaSchmqQDSCymBGK04tmeylgvYOcz7G2MYTC6w0mdqE20szqhRxXnzaKhLgZTZ4NRJJnQvV8f/zlFLprWN0o/wjgidmczxMZX/UnR67lwtL4NAwNBQwVRJK6bhhfX7KfglkoEmX/Dks5MH8Z1SCIhzVoNkfZWidKsUi1Ptc/nTSz5tGSH9sr9xXcuj3TGFoBIsrvk4obLfYiEDIqSsAYlpBnrrl6hv9vasKr+nNzUoRy0sLoZxJj5e9unSRrxKB+qKJAl",
        "ansible_swapfree_mb": 0,
        "ansible_swaptotal_mb": 0,
        "ansible_system": "Linux",
        "ansible_system_capabilities": [
            "cap_chown",
            "cap_dac_override",
            "cap_dac_read_search",
            "cap_fowner",
            "cap_fsetid",
            "cap_kill",
            "cap_setgid",
            "cap_setuid",
            "cap_setpcap",
            "cap_linux_immutable",
            "cap_net_bind_service",
            "cap_net_broadcast",
            "cap_net_admin",
            "cap_net_raw",
            "cap_ipc_lock",
            "cap_ipc_owner",
            "cap_sys_module",
            "cap_sys_rawio",
            "cap_sys_chroot",
            "cap_sys_ptrace",
            "cap_sys_pacct",
            "cap_sys_admin",
            "cap_sys_boot",
            "cap_sys_nice",
            "cap_sys_resource",
            "cap_sys_time",
            "cap_sys_tty_config",
            "cap_mknod",
            "cap_lease",
            "cap_audit_write",
            "cap_audit_control",
            "cap_setfcap",
            "cap_mac_override",
            "cap_mac_admin",
            "cap_syslog",
            "35",
            "36+ep"
        ],
        "ansible_system_capabilities_enforced": "True",
        "ansible_system_vendor": "Xen",
        "ansible_uptime_seconds": 4261,
        "ansible_user_dir": "/root",
        "ansible_user_gecos": "root",
        "ansible_user_gid": 0,
        "ansible_user_id": "root",
        "ansible_user_shell": "/bin/bash",
        "ansible_user_uid": 0,
        "ansible_userspace_architecture": "x86_64",
        "ansible_userspace_bits": "64",
        "ansible_virtualization_role": "guest",
        "ansible_virtualization_type": "xen",
        "discovered_interpreter_python": "/usr/bin/python",
        "gather_subset": [
            "all"
        ],
        "module_setup": true
    },
    "changed": false
}

We can see that it generates a json output with all the variables that contains lots of information about the target machine. This json output contains lots of variables and these are called Fact Variables.

Thus, based on the values of fact variables we can take decisions inside playbook while writing different tasks.

So we can make use of ansible_os_family variable and depending on its value we can decide which module we can use to install the package on different types of target machines. Now, let’s write one more play for the database server (Centos7) as well. In this play, we are going to install MySQL service, start and enable this service. The package name for MySQL is maria-db. 

Below is the updated playbook.

---
- hosts: websrvgrp
  become: yes
  tasks:
    - name: Install apache http SVC
      yum:
        name: httpd
        state: present

    - name: Start and enable Apache http SVC
      service:
         name: httpd
         state: started
         enabled: yes

- hosts: dbsrvgrp
  become: yes
  tasks:
    - name: Install mariadb SVC
      package:
        name: mariadb-server
        state: present

    - name: Start and enable mariadb SVC
      service:
         name: mariadb
         state: started
         enabled: yes

Let’s execute this playbook.

ansible-playbook playbook-exercise/web.yml

Maria db svc should be installed and enabled successfully.

Question: How to catch issues in the playbooks

1.ansible-playbook {{playbook name}} --syntax-check

2.ansible-playbook {{playbook name}} -C  ### where -C stands for Dry run

However, dry run is not a guarantee that it will catch an error, it may or may not catch error

3. Increase the verbosity. There are max 4 level of verbosity

ansible-playbook -vvvv {{playbook name}}

About the author

Deepak Sood

Deepak Sood is Lead Consultant in an IT firm holding expertise in Devops and QA Architecture with 8 years of experience.

His expertise is in building highly scalable frameworks. His skills include Java, Configuration Management, Containers, and Kubernetes.

Reach out to him using contact form.

View all posts