Difference between revisions of "Ansible"
Plittlefield (talk | contribs) |
Plittlefield (talk | contribs) |
||
Line 252: | Line 252: | ||
state: touch | state: touch | ||
modification_time: '<nowiki>{{ "%Y%m%d%H%M.%S" | strftime(usr.stat.ctime) }}</nowiki>' | modification_time: '<nowiki>{{ "%Y%m%d%H%M.%S" | strftime(usr.stat.ctime) }}</nowiki>' | ||
+ | |||
+ | === Copying SSH Keys === | ||
+ | |||
+ | https://medium.com/@visualskyrim/ansible-playbook-deploy-the-public-key-to-remote-hosts-da3f3b4b5481 | ||
=== Advanced Usage === | === Advanced Usage === |
Revision as of 14:43, 25 March 2022
Introduction
Ansible is an open-source software provisioning, configuration management, and application-deployment tool enabling infrastructure as code.
It is used to deploy and maintain many servers at once, from the command line.
- Control Node = Admin Computer
- Host Node = Remote Server
How To Install and Configure Ansible on Ubuntu 20.04
Requirements
Python 2.6+ or Python 3.5+
Installation
sudo apt remove ansible python3 -m pip install ansible echo "export PATH=$PATH:$HOME/.local/bin" >> ~/.bashrc source ~/.bashrc ansible-galaxy collection install community.docker
Configuration
Add your hosts...
sudo nano /etc/ansible/hosts
[servers] myserver ansible_host=123.456.789.0 [all:vars] ansible_python_interpreter=/usr/bin/python3
Check the config...
ansible-inventory --list -y
all: children: servers: hosts: myserver: ansible_host: 123.456.789.0 ansible_python_interpreter: /usr/bin/python3 ungrouped: {}
Check the config with hosts file specified...
ansible-inventory --list -y -i ./inventory/hosts
Testing
List Hosts
./inventory/hosts
[servers] server1 ansible_connection=ssh ansible_user=username1 domain.uk ansible_connection=ssh ansible_user=username2 nas ansible_connection=ssh ansible_user=username3
ansible -i ./inventory/hosts servers --list-hosts hosts (3): server1 domain.uk nas
Ping
ansible -i ./inventory/hosts servers -m ping ansible -i ./inventory/hosts server1.mydomain.com -m ping
Echo
Get all hosts to output a word on the command line...
ansible all -a "/bin/echo hello" -i ./inventory/hosts
Uptime
Uptime for a single host...
ansible hostname -m command -a "uptime" -i ./inventory/hosts
Uptime for all hosts in a group...
ansible groupname -m command -a "uptime" -i ./inventory/hosts
Uptime for all hosts...
ansible all -m command -a "uptime" -i ./inventory/hosts
AWS SSH Key
ansible all -m ping -u ubuntu --private-key=~/.ssh/myserver.pem
myserver | SUCCESS => { "changed": false, "ping": "pong" }
Commands
You can perform one off commands on a single host or multiple hosts.
Hostname
ansible all -u ubuntu --private-key=~/.ssh/myserver.pem -a "hostname -f"
Update Package Cache
ansible all -u ubuntu --private-key=~/.ssh/myserver.pem -a "sudo apt-get update"
Playbooks
Playbooks are YAML text files which contain commands and options in a text file, just like a docker compose file.
The file contains 'modules' which perform different tasks.
Examples
See if hosts are alive by using only Gather Facts
99_gather.yml
- name: gather facts become: true hosts: all
... and run it on all but 1 host (by using the limit option with an exclamation mark (!host) (!host1:!host2)...
ansible-playbook -i ~/Bin/ansible-homelab/inventory/hosts ~/Bin/ansible-homelab/playbooks/ubuntu/99_gather.yml --limit '!server1'
Update Package List and Upgrade System
Create hosts file...
./inventory/hosts
[servers] server1 ansible_connection=ssh ansible_user=user1 server2 ansible_connection=ssh ansible_user=user2 server3 ansible_connection=ssh ansible_user=user3
Check the list of hosts is readable..
ansible -i ./inventory/hosts all --list-hosts
Create the playbook file...
./playbooks/apt.yml
- hosts: "*" become: yes tasks: - name: apt apt: update_cache: yes upgrade: 'yes'
Run the playbook command...
ansible-playbook ./playbooks/apt.yml -i ./inventory/hosts
To run this playbook on a single host or multiple hosts, you would use the -l (limit) option at the end of the command line...
ansible-playbook ./playbooks/apt.yml -i ./inventory/hosts -l server1 ansible-playbook ./playbooks/apt.yml -i ./inventory/hosts -l server1,server2
Create single directory using the 'file' module
Create the playbook...
nano mkdir.yml
- hosts: all tasks: - name: Ansible file module create directory file: path: ~/backups state: directory
Run the playbook (dry run)...
ansible-playbook -C mkdir.yml
Run the playbook...
ansible-playbook mkdir.yml
Create multiple directories using the 'file' module
Create the playbook...
nano mkdirs.yml
- hosts: all tasks: - name: Ansible create multiple directories with_items file: path: ~/backups/{{item}} state: directory with_items: - 'mysql' - 'repository' - 'config'
Run the playbook...
ansible-playbook mkdirs.yml
https://linuxhint.com/create-directory-ansible/
Install Apache web server software and start it on a Red Hat based system
- name: Playbook hosts: webservers become: yes become_user: root tasks: - name: ensure apache is at the latest version yum: name: httpd state: latest - name: ensure apache is running service: name: httpd state: started
Touch a file based on the date of another file
- hosts: alpine become: yes tasks: - name: Get stats of a file ansible.builtin.stat: path: /usr register: usr - name: Print a debug message ansible.builtin.debug: msg: "Path exists and is a directory" when: usr.stat.isdir is defined and usr.stat.isdir - name: Print a debug message ansible.builtin.debug: msg: "ctime is {{ usr.stat.ctime }}" - name: touch file /root/misc/system_installed file: path: /root/misc/system_installed state: touch modification_time: '{{ "%Y%m%d%H%M.%S" | strftime(usr.stat.ctime) }}'
Copying SSH Keys
https://medium.com/@visualskyrim/ansible-playbook-deploy-the-public-key-to-remote-hosts-da3f3b4b5481
Advanced Usage
Blocks, Rescue and Always
The tasks in the block
execute normally. If any tasks in the block return failed, the rescue
section executes tasks to recover from the error. The always
section runs regardless of the results of the block and rescue sections.
- name: Attempt and graceful roll back demo
block: - name: Print a message ansible.builtin.debug: msg: 'I execute normally' - name: Force a failure ansible.builtin.command: /bin/false - name: Never print this ansible.builtin.debug: msg: 'I never execute, due to the above task failing, :-(' rescue: - name: Print when errors ansible.builtin.debug: msg: 'I caught an error' - name: Force a failure in middle of recovery! >:-) ansible.builtin.command: /bin/false - name: Never print this ansible.builtin.debug: msg: 'I also never execute :-(' always: - name: Always do this ansible.builtin.debug: msg: "This always executes"
https://docs.ansible.com/ansible/latest/user_guide/playbooks_blocks.html
Example - Set up a server Firewall
This is good when you want to set up a server's firewall using the UFW module. It prevents you from accidentally blocking yourself out of a server :-)
- name: Setup admin production UFW hosts: my_hosts gather_facts: no tasks: - block: - name: Reset UFW ufw: state: reset - name: Allow outgoing ufw: default: allow direction: outgoing - name: Disallow ingoing ufw: default: deny direction: incoming - name: Establish regular admin rules ufw: rule: allow direction: in port: '5432' proto: tcp from_ip: '{{ item }}' loop: - 123.456.789/32 - 987.654.321/32 always: - name: Grant ssh access ufw: rule: allow direction: in port: '22' proto: tcp from_ip: 321.456.987/32 - name: Enable Firewall ufw: state: enabled
Variables
Standard variables
{{ ansible_facts["eth0"]["ipv4"]["address"] }}
https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html
Custom variables
Example 1 - run the WordPress command line tool to install or update the software...
ansible-playbook wp.yml --extra-vars "major=true installcli=true"
wp.yml
- name: Install WordPress Cli register: wpclidonwloaded become: yes when: installcli is defined get_url: url: https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar dest: "{{ wpclipath }}" mode: '0755' owner: "{{ wpcliuser }}" group: "{{ wpcligroup }}" - name: Update WordPress Core (Major version) command: "{{ wpclipath }} core update" when: major is defined args: chdir: '{{ projects[inventory_hostname].blog_folder }}'
Example 2 - create a folder from a one-off command line custom variable...
ansible-playbook website.yml --extra-vars "domain=mybusiness.com"
website.yml
- name: create directory for web site file: path: "/var/www/{{ domain }}" state: directory