Ansible

1) Introduction to Ansible

 -Provisioning
-Configuration
-Continuous Delivery
-Application Deployment
-Security Compliance

-simple
-agentless
-one basic dependency - python
-config in YAML and jinja2

https://docs.ansible.com/
https://docs.ansible.com/ansible/2.6/user_guide/intro_getting_started.html

-agentless

2) Setting up Ansible

Lab enviornment

Template
-Ansible Control Machine (ansible-controller
-Ansible Target Machine (target01)
-Ansible Target Machine (target02)


https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html#latest-release-via-dnf-or-yum

Ansible Troubleshooting Tips

Issues installing Ansible and its dependencies

Once the Debian VM is up and running make the following changes to the /etc/apt/sources.list file to get the Ansible installation working right.
  1. Comment the line starting deb cdrom
  2. Uncomment bottom two lines starting deb and deb-src
  3. Add the below two lines:
Final file:



Assumtions about control machine - requierments

- Python 6 or 7
- windows cannot be control machine ( ansible supports Windows as a target machine - you can use Aspel)
- control machine has to have ssh connection to target machines
-x ansible run as wiil have super user access on your posts. (this is not a strict requierment to actually run ansible and still can run without super user access, but since we are doing configuration managment systems configuration it is almost given that at some point  you are going to need do something that requiers sudo or root or super user access)

3) Introduction to YAML

a) Key Value Pair

Fruit: Apple
Vegetable: Carrot
Liquid: Water
Meat: Chicken

b) Array/List

Fruits:
-    Orange
-    Apple
-    Banana

Vegetables:
-    Carrot
-    Cauliflower
-    Tomato

c) Dictionary/Map

Banana:
     Calories: 105
     Fat: 0.4 g
     Carbs: 27 g

Grapes:
     Calories: 62
     Fat: 0.3 g
     Carbs: 16 g



d) Dictionary vs List vs list of Directionary


Dictionary - unordered
List Ordered

# - comment


4) Ansible Inventory Files

-stores information about target machine
-default inventory /etc/ansible/hosts


#Sample Inventory File

server1.company.com
server2.company.com

[mail]
server3.company.com
server4.company.com

[db]
server5.company.com
server6.company.com

[web]
server7.company.com
server8.company.com

[all_servers:children]
mail
db
web


#Sample Inventory File

web  ansible_host=server1.company.com
db     ansible_host=server2.company.com ansible_connection=winrm

localhost ansible_connection=localhost



Inventory Parameters:
-ansible_connection - ssh/winrm/localhost
-ansible_port - 22/5986
-ansible_user - root/administrator
-ansible_ssh_pass - password Linux
-ansible_password - password Windows


Ansible Vault - Security

cat inventory.txt
ansibletarget1 ansible_host=192.168.7.109 ansible_ssh_pass=osboxes.org
ansibletarget2 ansible_host=192.168.7.108 ansible_ssh_pass=osboxes.org

ansible ansibletarget2 -m ping -i inventory.txt
ansibletarget2 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

 ansible ansibletarget1 -m ping -i inventory.txt
ansibletarget1 | FAILED! => {
    "msg": "Using a SSH password instead of a key is not possible because Host Key checking is enabled and sshpass does not support this.  Please add this host's fingerprint to your known_hosts file to manage this host."
}

ERROR

Solution 1: ssh to target machine
Solution 2: change config vi /etc/ansible/ansible.cfg  un comment host_key_checking = false
-> nie rekomentowane na produkcji




5) Ansible Playbooks

Playbook - A single YAML file

Play - Defines a set of activites (tasks) to be run on hosts

Tasks - an action to be performed on the host
-execute a command
-run a script
-install a package
-shutdown/restart

#Simple Ansible Playbook1.yml
-
 name: Play 1
 hosts: localhost
 tasks:
  - name: Execute command 'date'
    command: date

  - name: Execute script on server
    script: test_script.sh

-
 name: Play 2
 hosts: localhost
 tasks:
  - name: Install httpd service
    yum:
          name: httpd
          state: present

  - name: Start web server
    service:
          name: httpd
          state: started

ansible-doc -l #list commands avaible


Execute Ansible Playbook
Syntax: ansible-playbook <playbook file name>

ansible-playbook playbook.yml
ansible-playbook --help

Running ansible

a) ansible

ansible <hosts> -a <command>
ansible all -a "/sbin/reboot"

ansible <hosts> -m <module>
ansible database -i inventory - m apt -a "name=mysql-server state=present"
ansible target1 -m ping

ansible all -m ping -i inventory.txt

b) ansible-playbook
ansible-playbook <playbook name>

cat playbook-pingtest.yml
-
 name: Test connectivity to target servers
 hosts: all
 tasks:
   - name: Ping test
     ping:


ansible-playbook playbook-pingtest.yml -i inventory.txt


6) Modules

a)System

service
-manage services - Start, Stop, Restart

#Sample Ansible Playbook1.yml
-
 name: Start Services in order
 hosts: localhost
 tasks:
  - name: Start the database service
    service: name=postgresql state=started

  - name: Start the httpd service
    service: name=httpd state=started

  - name: Start the nginx service
    service: name=nginx state=started


#Sample Ansible Playbook1.yml
-
 name: Start Services in order
 hosts: localhost
 tasks:
  - name: Start the database service
    service: 
      name: postgresql 
      state: started


-Why "started" and not "start"
Ensure service httpd is started 
if httpd is not already started -> start it
if httpd is already started -> do nothing


b)Commands

command
-executes a command on a remote node
  • The command module takes the command name followed by a list of space-delimited arguments.
  • The given command will be executed on all selected nodes. It will not be processed through the shell, so variables like $HOME and operations like "<"">""|"";" and "&" will not work (use the shell module if you need these features).
  • For Windows targets, use the win_command module instead.
https://docs.ansible.com/ansible/2.6/modules/command_module.html

ParameterChoices/DefaultsComments
argv
(added in 2.6)
Allows the user to provide the command as a list vs. a string. Only the string or the list form can be provided, not both. One or the other must be provided.
chdir
Change into this directory before running the command.
creates
A filename or (since 2.0) glob pattern, when it already exists, this step will not be run.
free_form
required
The command module takes a free form command to run. There is no parameter actually named 'free form'. See the examples!
removes
A filename or (since 2.0) glob pattern, when it does not exist, this step will not be run.
stdin
(added in 2.4)
Set the stdin of the command directly to the specified value.
warn
bool

(added in 1.8)
    Choices:
  • no
  • yes ←
If command_warnings are on in ansible.cfg, do not warn about this particular line if set to no.


#Sample Ansible Playbook1.yml
-
 name: Play 1
 hosts: localhost
 tasks:
  - name: Execute command 'date'
     command: date

  - name: Display resolv.conf contents
    command: cat /etc/resolv.conf

  - name: Display resolv.conf contents
    command: cat /etc/resolv.con chdir=/etc
#change into /etc directoy before running

  - name: Display resolv.conf contents
    command: mkdir /folder creates=/folder
#run only if folder does not exist





c)Files

script 
-runs a loclal script on a remote node after transfering it

1. copy script to remote systems
2. Execute script on remote systems


#Sample Ansible Playbook1.yml
-
 name: Play 1
 hosts: localhost
 tasks:
  - name: run a script on remots server
     script: /some/local/script.sh -arg1 -arg2


lineinfile
-search for a line in a file and replace it or add it if it doesn't exist

#Sample /etc/resolv.conf

nameserver 10.1.250.1
nameserver 10.1.250.2

nameserver 10.1.250.10

#Sample Ansible Playbook1.yml
-
 name: Add DNS server to resolv.conf
 hosts: localhost
 tasks:
  - lineinfile:
      path: /etc/resolv.conf
      line: 'nameserver 10.1.250.10'


#Sample script

echo "nameserver 10.1.250.10" >> /etc/resolv.conf

-ansible insure that is only ojne entry in file , script will keep adding them with every run



d)Database


e)Cloud

Amazon


Azure


Cloudstack


Google


Openstack


Ovirt


Rackspace


Vmware


f)Windows


g) more..

7) Variables

-store information that varies with each host

a) in inventory

#Sample Inventory File

web  ansible_host=server1.company.com
db     ansible_host=server2.company.com ansible_connection=winrm


b) in playbook

#Sample Ansible Playbook1.yml
-
 name: Add DNS server to resolv.conf
 hosts: localhost
 vars:
     dns_server: 10.1.250.10
 tasks:
   
      - lineinfile:
           path: /etc/resolv.conf
           line: 'nameserver {{ dns_server }}'

c) in variable files

#Sample Variable_file.yml
variable1: value1
variable2: value2


Jinja2 templating
source: '{{ inter_ip_range }}'


8) Conditionals

#Sample Inventory File

web1  ansible_host=server1.company.com
db     ansible_host=db.company.com ansible_connection=winrm
web2  ansible_host=server2.company.com

[all_servers]
web1
db
web2

#Sample Ansible Playbook1.yml
-
 name: Start services hosts: localhost
hosts: all_servers
 tasks: 
      -
           service: name=mysql state=started
           when: ansible_host  == db.company.com
      -
           service: name=httpd state=started
           when: ansible_host =='server1.company.com' or ansible_host =='server2.company.com'


#Sample Ansible Playbook1.yml
-
 name: Check status of service and email if its down
 hosts: localhost
 tasks: 
      -
           command: service httpd status
           register: command_output
      -
           mail:
               to: Admins <system.admins@company.com>
               subject: Service Alert
               body: 'Service {{ ansible_hostname }} is down.'
           when: command_output.stdout.find('down') != -1

https://docs.ansible.com/ansible/latest/user_guide/playbooks_conditionals.html


9) Loops

a) with_items

#Sample Ansible Playbook1.yml
-
 name: Install Packages
 hosts: localhost
 tasks:
      -
           yum: name='{{ item }}' state=present
          with_items:
                -       httpd
                -       binutils
                -       glibc






10) Roles

a) include
-include <playbook name>

b) include tasks and vars
 tasks:
  - include: tasks.yml
 vars_files:
  - variables.yml

roles:
   -webservers


Ansible Project
 inventory.txt.
 setup_application.yml
 roles
   webservers
      files
      templates
      tasks
      handlers
      vars
      defaults
      meta


11) Preparing Windows Server

-Ansible Control Machine can only be Linux and not Windows
-Windows machines can be targets of Ansible and thus be part of automation
-Ansible connects to a windows machine using winrm
-Requirement:
  *pywinrm module installed on the Ansible Control Machine - pip install "pywinrm>=0.2.2"
  *Setup WinRM - examples/scripts/ConfigureRemotingForAnsible.ps1
  *Different modes of authentication:
       ** Basic/Certificatwe/Kerberos/NTLM/CredSSP


12) Ansible-Galaxy

https://galaxy.ansible.com/

13) Patterns

 hosts : localhost

-host1, host2, host3
-group1, host1
-host*
-*.company.com

https://docs.ansible.com/ansible/2.6/user_guide/intro_patterns.html


14) Dynamic Inventory

ansible-playbook -i inventory.txt playbook.yml
ansible-playbook -i inventory.py playbook.yml


15) Developing Custom Modules

https://docs.ansible.com/ansible/2.5/dev_guide/developing_modules.html


16)Web Application

1. Identify Server
2. Python
3. Install Configure Start
4. Install Flask
5. source Code
6. Run

https://github.com/mmumshad/simple-webapp


Simple Web Application

This is a simple web application using Python Flask and MySQL database. This is used in the demonstration of development of Ansible Playbooks.
Below are the steps required to get this working on a base linux system.
  • Install all required dependencies
  • Install and Configure Database
  • Start Database Service
  • Install and Configure Web Server
  • Start Web Server

1. Install all required dependencies

Python and its dependencies
apt-get install -y python python-setuptools python-dev build-essential python-pip python-mysqldb

2. Install and Configure Database

Install MySQL database
apt-get install -y mysql-server mysql-client

3. Start Database Service

  • Start the database service
    service mysql start
    
  • Create database and database users
    # mysql -u <username> -p
    
    mysql> CREATE DATABASE employee_db;
    mysql> GRANT ALL ON *.* to db_user@'%' IDENTIFIED BY 'Passw0rd';
    mysql> USE employee_db;
    mysql> CREATE TABLE employees (name VARCHAR(20));
    
  • Insert some test data
    mysql> INSERT INTO employees VALUES ('JOHN');
    

4. Install and Configure Web Server

Install Python Flask dependency
pip install flask
pip install flask-mysql
  • Copy app.py or download it from source repository
  • Configure database credentials and parameters

5. Start Web Server

Start web server
FLASK_APP=app.py flask run --host=0.0.0.0

6. Test

Open a browser and go to URL
http://<IP>:5000                            => Welcome
http://<IP>:5000/how%20are%20you            => I am good, how about you?
http://<IP>:5000/read%20from%20database     => JOHN


WebApp  Installation Instructions for Centos 7


The installation procedure is a bit different on Centos 7. So those of you following this course from the first course, please follow the below instructions:
# Install Python Pip and dependencies on Centos 7
-------------------------------------------------
sudo yum install -y epel-release python python-pip
sudo pip install flask flask-mysql
# If you come across a certification validation error while running the above command, please use the below command.
# sudo pip install --trusted-host files.pythonhosted.org --trusted-host pypi.org --trusted-host pypi.python.org flask flask-mysql

# Install MySQL Server on Centos 7
---------------------------------------------
wget http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm
sudo rpm -ivh mysql-community-release-el7-5.noarch.rpm
sudo yum update
sudo yum -y install mysql-server
sudo service mysql start

# Inventory file

db_and_web_server1 ansible_ssh_pass=Passw0rd ansible_host=192.168.1.6
db_and_web_server2 ansible_ssh_pass=Passw0rd ansible_host=192.168.1.15

#Ansible Playbook
-
 name: Deploy Web Application
 hosts: db_and_web_server*
 tasks:
  - name: Install dependecies
    apt: name={{ item }} state=installed
    with_items: 
     - python-setuptools 
     - python-dev 
     - build-essential 
     - python-pip 
     - python-mysqldb

  - name: Install MySQL database
    apt: name={{ item }} state=installed
    with_items: 
     - mysql-server 
     - mysql-client


  - name: Start Mysql Service
    service:
     name: mysql
     state: started
     enabled: yes

  - name: Create Application Database
    mysql_db: name=employee_db state=present

  - name: Create Application DB User
    mysql_user:
     name: db_user
     password: Passw0rd
     priv: '*.*:ALL'
     state: present
     host: '%'


  - name: Install Python Flask dependencies
   pip:
     name: {{ item }}
     state: present
   with_items:
     - flask
     - flask-mysql



  - name: Copy web-server code
    copy: src=app.py dest=/opt/app.py


  - name: Run web-server
    shell FLASK_APP=/opt/app.py nohup flask run --host=0.0.0.0


  #app.py
import os
from flask import Flask
from flaskext.mysql import MySQL # For newer versions of flask-mysql
# from flask.ext.mysql import MySQL # For older versions of flask-mysql
app = Flask(__name__)
mysql = MySQL()
mysql_database_host = 'MYSQL_DATABASE_HOST' in os.environ and os.environ['MYSQL_DATABASE_HOST'] or 'localhost'
# MySQL configurations
app.config['MYSQL_DATABASE_USER'] = 'db_user'
app.config['MYSQL_DATABASE_PASSWORD'] = 'Passw0rd'
app.config['MYSQL_DATABASE_DB'] = 'employee_db'
app.config['MYSQL_DATABASE_HOST'] = mysql_database_host
mysql.init_app(app)
conn = mysql.connect()
cursor = conn.cursor()
@app.route("/")
def main():
return "Welcome!"
@app.route('/how are you')
def hello():
return 'I am good, how about you?'
@app.route('/read from database')
def read():
cursor.execute("SELECT * FROM employees")
row = cursor.fetchone()
result = []
while row is not None:
result.append(row[0])
row = cursor.fetchone()
return ",".join(result)
if __name__ == "__main__":
app.run()




17) Asynchronous Actions
18) Error Handling
19) Jinja 2 Templating
20) Lookups
21) Vault
22) Dynamic Inventory
23) Custom Modules
24) Plugins
25) Practice

26) playable
sudo docker run -p 80:8080 mmumshad/ansible-playable

Komentarze

Popularne posty z tego bloga

Kubernetes

Helm

Ansible Tower / AWX