Ansible

Ansible:
========

Configuration Management(CM):
-----------------------------
A configuration management is refers to the process of systematically handling the changes to a system.
A configuration management (CM) system is used to keep track of an organizationís hardware, software and related information. 
This includes software versions and updates installed on the organization's computers.

with respect to IT, it covers set of things like below
	@hardware
	@software
	@Network
	@People
	@Process

- it turns your infrastructure as a code.
           - means it not converting your infrastructure as a code, it just defining your infrastructure as a code.
- Why ansible is a infrastructure as a code, because
	       @ is your infrastructure is versionable
	       @ is your infrastructure is repeatable
	       @ is your infrastructure is testable
               if you agree with above 3steps, then ansible is going to act as "infrastructure as a code".

Chef vs Ansible
---------------
Herculean task for Administratiors:
----------------------------------
As a sysadmin we do:(Pain Points)
	Create/delete users                 
	Taking Backups
	Deploying Applications
	Configure servers
	Documenting steps
	keep maintaining systems
	keep repeating ourselves, so boring
	Rely on our memory (what conf we had did on what server)

STATE:
-----
- The undelying problem is STATE of the server (here state can be a backup,user creation or application any thing)
- STATE is a snapshot of your configuration

		  Eg:- for ruby:- file '/home/hello.txt' do
                                          action: create
			                  content:'welcome to chef' --->> this is STATE of file b/n do and end.
			               end.
 

By adopting configuration management tools, you will benefit from:
-----------------------------------------------------------------

* Reduced risk:-  of outages and security breaches through visibility and tracking of the changes to your systems.

* Cost reduction:-  by having detailed knowledge of all the elements of your configuration, avoiding wasteful duplication of your technology assets.

* Strict control:-  of your processes by defining and enforcing formal policies and procedures that govern asset identification, status monitoring, and auditing.

* Greater agility and faster problem resolution:-  enabling you to provide a higher quality of service.

* Quicker restoration of service:-  In an outage, you'll be able to recover quickly as your configuration is documented and automated.

* Increase uptime

* Prevent Errors

* Code re-usability

Alternatives:
-------------
Puppet/Chef/Saltstack...etc

Why Ansible:
-----------
* "Redhat" people developed "Ansible" and now recently "IBM" is taken over "Redhat" (so, it is very compatable to run redhat tools in redhat machines) 
* No need to go with huge configurations and setup compare to chef and puppet.
* pull mechanism(agents has to pull the things from server)
* lot of learning is required for chef and puppet
* yaml code, which is very secure and easy to learn
* workstation less
* Relies on ssh
* it uses Python internally(no need to write python programming/script) 
* Push Mechanism
     @ we have to install ansible in one machine and push the configuration and all to other machines through ssh connections.

What is Ansible:-
-----------------
- Ansible is an automation platform that configures and manages your infrastructure, whether it is on-premises or in the cloud.
      
      - Ansible is a independent
      - you only need to tell to ansible what the desired configuration should be, not how to achieve it.
      - Tell what to do not how to do. (Ansible YAML Code)
                 eg: 1. check whether the package is installe or not
                     2. install git 1.2
                     3. we need to compare whether git 1.2 is compatable to our system
                     4. if not, then install git 1.3 version
                     5. return values
      

Archetecture:
-------------
  Ansible Server                                ssh
     YAML--------------------------------------------------------------------->>Nodes(collect all the info about the system)                           
- note: workspace/station where we going to write code, which describes the state of server                    
- yet another markup language (or) yaml ain't another markup language   

Configurations:
--------------
1. cat /etc/ansible/ansible.cfg
2. cat /etc/ansible/hosts
3. vi /etc/ssh/sshd_config

Ansible Installation in Physical Server:
========================================
1. Need RHEL Above 7.1
2. yum update
3. Install yum repository/server
4. epel enable link :- yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm
5. verify repos :- yum repolist (or) yum makecache 
6. yum install -y https://releases.ansible.com/ansible/rpm/release/epel-7-x86_64/ansible-2.9.1-1.el7.ans.noarch.rpm 
7. ansible --version
8. yum update ansible --> to get latest version

Note:-  on RHEL 7 it is recommended to also enable the optional, extras, and HA repositories since EPEL packages may depend on packages from these repositories.

   Note:- subscription-manager repos --enable "rhel-*-optional-rpms" --enable "rhel-*-extras-rpms"  --enable "rhel-ha-for-rhel-*-server-rpms"

step1:- go to ansibel default configuration file  "/etc/ansible/ansible.cfg" and uncomment the inventory.
	        >> what are the different machines to which ansible has to connect and do some configurations

step2:- enable sudo_user in the same confg file.(/etc/ansible/ansible.cfg)

step3:- create users in both node and server and add sudo privaliges in visudo
       ansible ALL=(ALL) NOPASSWD: ALL

Ansible Installation in EC2 
===========================
1. launch redhat EC2 instance in aws
2. become a root user
     # sudo su - (or) sudo -i    
3. update your EC2 Instance (in Ansible-Server and node)
     # sudo yum update -y 
4. adduser/useradd VmTutes (in Ansible-Server and node)
5. passwd VmTutes  (in master and node)
6. add VmTutes user in "visudo" (or) /etc/sudoers file for sudo permissions (in Ansible-Server and node)
      # vmtutes ALL=(ALL) NOPASSWD: ALL
7. enable password authentication for VmTutes user (in Ansible-Server and node)
      # vi /etc/ssh/sshd_config
      # systemctl restart sshd  (or)  service sshd reload

8. for RHEL-8 and later we need to install python2/3 version which ever latest
     # Note:- yum install python3 -y (you will get old version of python i.e 3.6.8) ---->> optional

     # sudo yum install -y wget libffi-devel  zlib-devel  bzip2-devel  openssl-devel  ncurses-devel  sqlite-devel  readline-devel  tk-devel  gdbm-devel  xz-devel  expat-devel

     # sudo yum groupinstall -y "development tools"

     # cd /opt

     # sudo wget https://www.python.org/ftp/python/3.12.0/Python-3.12.0.tgz
	     
     # sudo tar -xvzf Python-3.12.0.tgz

     # cd Python-3.12.0 (Note: if it is not allowing try with root user)

     # ./configure --enable-optimizations

     # sudo make altinstall
              note:- cd /usr/local/bin and hit ls command, you can see python config files.

     # Defaults    secure_path = /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin (sudo vi /etc/sudoers )

     # python3.12 --version

     # pip3.12 install --upgrade pip (don't give in root user and don't use sudo command also in normal user.)
               note:- python3.12 -m pip install --upgrade pip
               note:- pip is default with python3 installation.
               note:- pip3.12 -V (or) pip3.12 --version
               note:- Pip is a package manager for Python that allows you to install and manage additional Python packages which are not part of the standard python library.

9.  switch to VmTutes user
        Note:- in RHEL-8 and above versions, we should install ansible in normal users.
        Note:- we should not install in root user, bcz it doesn't work as expected.
10.  pip3.12 install ansible --user (--user means, taking vmtutes as a user)
11.  ansible --version
12.  mkdir /etc/ansible
13.  vi /etc/ansible/hosts and add node system ipaddress

Installation Troubleshoot
-------------------------
ansible vmtutes -m ping -vvv
<172.31.19.38> ESTABLISH SSH CONNECTION FOR USER: None

[vmtutes]
172.31.19.38 ansible_user=ec2-user
NOte:- node-machine also required python



Setting Hostname:
-----------------
- hostname/hostnamectl
- hostnamectl set-hostname vmtutes (host/system/server name)
- if you want to give a domain name for your hostname fallow below command
- hostnamectl set-hostname VmTutes.devops.com (Domain/DNS name)

Password less login using SSH keys:
---------------------------------
- ssh-keygen
- ssh-copy-id -i /root/.ssh/id_rsa.pub  192.168.222.130
- ssh-copy-id localhost(configuring on same machine)

Ansible Inventory:
-----------------
- inventory is a place where all the systems present to which ansible is to configure and run.
- default to be saved in the location /etc/ansible/hosts
- we can also specify a different inventory file using -i <path> in command line

Host Patterns:
-------------
- How to identify which machine i need to run specifically
- a pattern can refer to a particular machine or group name
    
     >> ansible all --list-hosts('all' refers all the machines in the inventory)
     >> groupname[0] --> picks the first machine in the group
     >> groupname[1] --> picks the second machine in the group
     >> groupname[-1] --> picks the first last machine in the group
     >> groupname[0:4] --> picks the first five machines in the group(range)
     >> groups sepertes with clolon uses to run hosts on multiple groups 
            > group_name1[0]:group_name2[1]

    		ansible all --list-hosts
    		ansible VmTutes --list-hosts
   		ansible localhost --list-hosts
    		ansible 192.168.9.130 --list-hosts

Ad-Hoc Commands:
----------------
- if you want to run any simple and one time commands we will use ad-hoc commands
          syntax:- ansible [group-name] -m[module] -a[arbitary]

       -a :- to run arbitrary(if you want to run any operating system commands through ansible use option '-a')
                    eg:- ansible VmTutes -a "ls -l"
                         ansible VmTutes -a "ls /root"
                         ansible VmTutes -a "cat /var/log/messages" 
                 	 ansible local -a "touch hello_devops"
       -m :- to run a module(operating system tasks) 
                   eg:- ansible all -m ping 
                	ansible all -m copy -a "src=hello.txt dest=/root/hello.txt"

                   install/remove a packages:
                  	ansible VmTutes -m yum -a "pkg=httpd state=present" (it will install)
	          	ansible all -m yum -a "pkg=httpd state=latest"  (it will update)
                  	ansible VmTutes -m yum -a "pkg=httpd state=absent"  (it will remove)

                   start/stop a services:
                  	ansible -m service -a "name=httpd state=started"
	         	ansible -m service -a "name=httpd state=restarted"
                  	ansible -m service -a "name=httpd state=stopped"

                   create/delete a user account:(instead of creating user with command 'adduser/useradd')
		        ansible VmTutes -m user -a "name=vinodh"
			ansible VmTutes -m user -a "name=vinodh state=absent"
                   
                   Add/Remove a cron job:
                        ansible tek -b -m cron -a "name='name_of_cronjob' minute='10' hour='11' day='19' month='12' weekday='5' job='ls-alh > /opt/null'"
		        ansible VmTutes -m cron -a "name='name_of_cronjob' minute='11' hour='12' job='cat /var/log/messages'"
                                Note:- if you not give cron columns then it will take default as "*"
                        ansible VmTutes  -m cron -a "name='mycron' state='absent'"
                              (OR)
                        cron:
                           name: "my_cron"
                           minute: "2"
                           hour: "20"
                           day: "23"
                           month: "11"
                           weekday: "0"
                           job: "cat /var/mail/spool/vinodh"
                           job: "date > /dev/pts/2"
                           job: "mkdir /root/hello"
                                         
        -b(become) :- To run as a sudo
                   eg:- ansible VmTutes -b -m ping 

     GREEN :- Ansible executes successfully, but it will not do any changes in machine(node)
     YELLOW :- it did some new changes in the machine
     RED :- if ansible is connecting to machine and failing in any step/task the it will show you "RED" colour 
     BLUE :- Warnings
        
Gathering Facts/Convergence/Idempotence:
----------------------------------------
- as soon as ansible connects to node-machine it gathers the information about the machine(node)
 	  and it start comparing the state that what we have defined and what it has gathered,
 	  in case it has diff then based on that it is going to udate/maintaining the state accordingly, if already in same state it is not going to do anything.

       if we want to see what and all modules it is going to gather from machine, we can use
                    ansible all -m setup   
                    ansible VmTutes -m setup -a "filter='ansible_nodename'"
                    ansible all -m setup -a "filter='ansible_dns'"
                    ansible all -m setup -a "filter='*ipv4*" 
                    ansible all -m setup -a "filter='*swap*'" 
       If you want to save output to facts directory
                    ansible all -m setup --tree facts

Playbooks:  
----------
- playbooks are ansible configurations, playbooks defines a policy you want your remote machine to enforce.
or set of steps. playbooks are returened in YAML format
   -->  usr/bin/ansible-playbook is used for running configurations from an playbook
   -->  ansible-playbook <playbook_name.yml>

 # we have 3 section in playbooks       
    1. Target Section:- Defines the hosts against which playbook tasks has to be executed
    2. Variable Section:- values that we were storing while running ansible and re-using whenever we want
    3. Tasks Section:- list of all tasks that we need to run in order

 YAML (yaml ain't another markup language)
 ----
   * every YAML file starts with a list
   * each item in the list is a key/value pairs.
   * all yaml files begin with "---" and end with "..." (optional)
   * all members in a list  should  begins  at the same indentation level starting with "-"
                   --- # a list of courses
                   courses:
                     - devops
                     - aws
                     - digital marketing 
                     - java 
                   ...
   * key: value     
                   ---# a employee details
                   Employee:
                     name: vinodh
                     job: Devops Engineer
                     company: xyz
                   ...

Eg(1):- 

      --- # sample playbook
      - hosts: VmTutes
        become: true
        tasks:
          - name: install ftp package
            action: yum name=ftp state=present
Eg(2):-      
     --- # VmTutes initial YAML playbook
     - hosts: all
       tasks:
         - name: remove ftp package
           action: yum name=ftp state=absent 
Eg(3):-
      --- # variables declaration in playbook       
      - hosts: all
        vars:
         globes: httpd 
        tasks:
         - name: install "{{ globes }}" package
           action: yum name='{{ globes }}' state=present

Eg(4):-
     --- # 2nd method of variables declaration in playbook       
      - hosts: all
        user: ani
        sudo: yes
        connection: ssh
        gather_facts: yes
        vars_files: ( we can declare variables in the form of variable files, in case if we want to use same file to diff playbooks)
          - filename.yml 
        tasks:
        - name: install "{{ variable_name }}" package
          action: yum name='{{ variable_name }}' state=present

Eg(5):- 
      --- # 3rd method of variables declaration in playbook       
      - hosts: all
        user: ani
        sudo: yes
        connection: ssh
        gather_facts: yes
        vars_prompt: (we can delclare variables with prompting)
         - name: globes
           prompt: Please Enter The Package Name to Install. 
        tasks:
        - name: install "{{ globes }}" package
          action: yum name='{{ globes }}' state=present

 Note:- ansible-playbook name.yml --extra-vars "variable=value" (passing variable form command line)

Eg(6):- 
       ---  # multiple tasks in playbook 
       - hosts: all
         user: ani
         sudo: yes
         connection: ssh
         gather_facts: yes
         vars_prompt:
           - name: variable_name
             prompt: Pleae Enter The Package Name to Install. 
         tasks:
           - name: install "{{ variable_name }}" package
             action: yum name='{{ variable_name }}' state=present 
           - name: httpd update
             action: yum pkg=httpd state=update 
           - name: finger delete
             action: yum pkg=finger state=absent   
Eg(7):-	
	--- # handlers in playbook
	- hosts: all
          user: ani
          sudo: yes
          connection: ssh
          gather_facts: yes
          vars_prompt:
           - name: variable_name
           prompt: Pleae Enter The Package Name to Install. 
          tasks:
           - name: install "{{ variable_name }}" package
             action: yum name='{{ variable_name }}' state=present
             notify: restart vsftpd
          handlers:  
           - name: restart vsftpd
             action service name=vsftpd state=restarted
        
       Note:- having ability to call another task, only when the task run successfully(dependency)
               specifing when a task/tasks should be run.

Outline the playbook:
---------------------
--- # outlining to my playbook
- hosts: tek
  tasks:
   - name: Display Date&Time For Begining of Playbook
     raw: /usr/bin/date  > /home/redhat7/begin_playbook_timestamp.log
   - name: Install ftp
     yum: pkg=ftp state=present
     notify: restart the ftp
   - name: install telnet
     yum: pkg=telnet state=present 
   - name: moving logs
     raw: yum list installed > /home/redhat7/telnet_installed.log
   - name: Display Date&Time For Ending of Playbook
     raw: /usr/bin/date  > /home/redhat7/end_playbook_timestamp.log
  handlers:
   - name: restart the ftp
     action: service name=ftp state=started
        
   Note:- raw module is used to run the operating system commands   
   Note:- how to know the command path in linux
            * which <command_name>
            * which date
            * which useradd, cat, touch, ls, usermod, chmod ..etc 
            * echo $PATH
   Note:- yum list
           yum list installed
           yum list installed vsftpd (or) rpm -q vsftpd
           yum info ftp
           yum install/update/remove <package_name>         
     	
Dry Run:
---------
- without executing the steps, just checking what are the possibilities(format, syntax...etc) ansible will do
  eg:- ansible-playbook filename.yml --check
Note:- we will use this in production

Asynchronous Actions and polling:
---------------------------------
 - while using ansible against multiple machines, the operations may run longer then usual. so, we will not have a control/track on it.
 - to have control whetere the task is running are not and running the tasks parallel, we use async mode.
 - maximum runtime to timeout
 - how frequently to poll for status
            eg:-  task-1 (sequence task executions)                 
                  task-2
                  task-3 
                  task-1 | task-2 | task-3(parallel task executions)

- async: 300 (if it running beyond 300 sec then it will automatically get terminated) 
- poll: 6
- to get the status of a parallelly running tasks we use poll option.  
- it will check and get some data on specified time given. 

run once:
---------
- it will run the task only one time in every 1st machine of group, if you specify hosts: tutes also.
     eg:- run_once: true

Delegate_to:
------------
specifing a individual host to run the task
    eg:- delegate_to: localhost
    
loop:
----
if you want to run single task multiple times, we use loops
--- # loop 
- hosts: all
  tasks:
    - name: adding list of users
      user: name={{ item }} state=present
      with_items:
        - user1
        - user2
        - user3

(or)
	- vim
        - curl
        - unzip
        - wget

Conditional:
------------
--- # conditional playbook
- hosts: VmTutes
  tasks: 
    - name: install apache2 for ubuntu
      command: apt-get -y install apache2
      when: ansible_os_family == "ubuntu"
    - name: install apache for redhat
      command: yum -y install httpd
      when: ansible_os_family == "RedHat"

Vault:
-----
ansible allows keeping sensitive data such as passwords/usernames or keys in encrypted files, rather then as plain text in your playbooks.
      * ansible-vault create playbook.yml
      * ansible-vault edit playbook.yml
      * ansible-vault rekey playbook.yml
      * ansible-vault decrypt playbook.yml
      * ansible-vault encrypt playbook.yml
 note:- we can run the file, but we can't see what we written in the playbook.
  
include statements:
------------------     
if you have comman tasks, which is going to be used in many playbooks, we can use 'include statements' rather then re-writing everytime.
  eg:-  --- # include playbook
        - hosts: VmTutes
          tasks:
            - include: vinu.yml
Tags:
----
- if you want to run a specific task which ever you like, then use tags.
     ansible-playbook vinu.yml --tags tag_name
     ansible-playbook vinu.yml --skip-tags tag_name 

--- # Tags playbook
- hosts: tek
  tasks:
   - name: enter your name
     raw: echo "vinodh" > /home/VmTutes/vinodh.log
     tags:
      - firstname
   - name: designation
     raw: echo "devops_engineer" > /home/VmTutes/vinodh.log
     tags:
       - role


Roles:
------
- we can organize playbooks into a directory structure called roles.
- rather then putting all the content in the playbook, we can divide the content of the playbook into seperate files where we will have seperate directory structure.
- for running diff functionalitys on one machine we need to right multiple tasks, which is not recommanded and difficult to maintain also.
- adding more then one functionalitys to playbooks will make it difficult to maintain in single file.
- and roles concept is advanced one to include statement.
- we can create n-number of roles under roles directory
- Directory Structure
      superuser.yml(master playbook)
          roles/name-of-the-role
               tasks/main.yml
               vars/main.yml 
               handlers/main.yml 
               defaults/main.yml
               meta/main.yml
 Note: 
 	default path of roles:
        	/etc/asible/roles
    	we can alternately keep the master playbook in a diff location and specify the role path in ansible.cfg
 	in the /etc/ansible/ansible.cfg, uncomment roles_path and add the roles directory
       	       roles_path =/home/ansible/playbooks/roles
       
Condition in roles:
-------------------
---
- hosts: VmTutes
  roles:
    - role-1(role name)      
          (OR)
    - { role: role-1, when: ansible_os_family == "RedHat" }
    - { role: role-2, when: ansible_os_family == "Ubuntu" }
          
wait_for:
----------
- it waits for condition before continuning
---
- hosts: VmTutes
  tasks:
    - name: install httpd package
      yum: pkg=httpd state=latest
    - name: wait for service listening on port 80
      wait_for:
         port: 80
         state: started
              (OR)
         path: /home/redhat02/vinusahi.log 

Note:- systemctl start httpd (OR) service httpd start

Moving playbooks from one machine to another:
---------------------------------------------
- here we again we will use version control system (scm/vcs)
    1. git init (your playbooks)
    2. git push remote repository (github)
    3. git clone repo url.....


Task
----
update yum package and
install below packages
        - vsftpd    
        - sysstat
        - httpd
        - mariadb-server
Remove the existing installed folder
rm -rf /usr/localcw/opt/
Re-create the /usr/localcw/opt/sact directory.
mkdir -p /usr/localcw/opt/sact
Change to the newly created SACT directory. 
cd /usr/localcw/opt/sact
Download the current release tarball to the system.
wget†https://sact.it.att.com/dist/sact-client-20211102.tar.gz
Extract the downloaded tarball.
tar xzf sact-client-20211102.tar.gz
Remove the downloaded tarball which is no longer needed.
rm sact-client-20211102.tar.gz

 		            				=========THE END=======
			
			              +91-7204143230(WhatsApp/Call), Email:- [email protected]