A Bit of Everything 1 Flashcards
Install Python on managed nodes
ansible -u root -i inventory ansible3 –ask-pass -m raw -a ‘yum install python3’
{Look up ansible modules for ping
what is the url for module info?
show documentation for ping
locate the file for the ping module and view it
show how to use parameters in a playbook - basically just use a command that just shows how to do things with the module.
ansible-doc -l | grep ping
docs.ansible.com
ansible-doc ping
grab the file location and go there
ansible-doc -s ping
FOR URL
quick links (On Right)
Ansible Package Docs Home or choose modules and plugins index}
install a list of items
httpd
vsftpd
nmap
- name: using lists
hosts: all
tasks:- name: Install Packages
yum:
name:- httpd
- vsftpd
- nmap
state: lateset
- name: Install Packages
What are the two ways you can use to create a multiline screen
”| >”
>
Setup httpd and then test if it’s working
- name: Install and Start HTTPD
hosts: ansible2
tasks:- name: Install HTTPD
yum:
name: httpd
state: latest - name: Start HTTPD
service:
name: httpd
state: started
enabled: yes - name: Open port 80
firewalld:
service: http
state: enabled
permanent: True - name: Restart Firewalld
service:
name: firewalld
state: restarted
- name: Install HTTPD
- name: Test HTTPD accessability
hosts: localhost
tasks:- name:
uri:
url: http://ansible2
- name:
…
How would you print your ansible configuration?
How would you show only the configuration parts that are being implemented? If there is something that doesn’t show up here there might be a typo.
How do you show all the collections you currently have?
How do you install a collection
ansible-config view
ansible-config dump –only-changed
ansible-galaxy collection list
ansible-galaxy collection install this.collection
Show facts for ansible2
Show facts
ansible ansible2 -m setup
Via Ansible facts show
hostname
distribution
ipv4
network interfaces
storage devices
size of /dev/sda1
version distribution
ansible_facts[‘hostname’]
ansible_facts[‘distribution’]
ansible_facts[‘default_ipv4’][‘address’]
ansible_facts[‘intefaces’]
ansible_facts[‘devices’]
ansible_facts[‘devices’][‘sda][‘partitions’][‘sda1’]
ansible_facts[‘distribution_version’]
Create a playbook that checks if the memory of the managed node is about 50 megs
What form of measurement is disk space measured in?
debug:
msg: ‘test’
when: ansible_facts[‘memory_mb’][‘real’][‘free’] > 50
disks are measured in bytes
Create a playbook that says ‘using CentOS 8.1’ if the distribution is 8.1 and the distribution is centos
debug:
msg: ‘using CentOS 8.8’
when: ansible_facts[‘distribution_version’] == ‘8.1’ and ansible_facts[‘distribution’] == ‘CentOS’
Create Custom Facts and store them on the managed hosts
This should give variables for web packages, ftp packages and then their services
Show how you would call that information in a playbook
Show Custom Facts
/etc/ansible/facts.d
[packages]
web_package = httpd
ftp_package = vsftpd
[services]
web_service = httpd
ftp_service = vsftpd
create a playbook to store them, file should end with .fact
The file should be called listing68.fact and stored in /etc/ansible/facts.d
{{ ansible_facts[‘ansible_local’][‘listing68’][‘packages’][‘web_package’] }}
ansible all -m setup -a ‘filter=ansible_local’
Create Custom Facts in under a group called software.
The facts should be for a package, service, state, and enabled = True.
Check if you can see the facts
Install a package Using all these custom facts
Use a playbook to copy the file over
vi custom.facts
[packages]
package = httpd
service = httpd
state = started
enabled = true
ansible all -m setup -a ‘filter=ansible_local’
vi install.yml
- name: install
hosts: all
tasks:
- name install
dnf:
name: “{{ ansible_facts[‘ansible_local’][‘custom’][‘software’][‘package’] }}”
state: “{{ ansible_facts[‘ansible_local’][‘custom’][‘software’][‘state’] }}”
- name: Start Service
service:
name: “{{ ansible_facts[‘ansible_local’][‘custom’][‘software’][‘service’] }}”
state: {{ ansible_facts[‘ansible_local’][‘custom’][‘software’][‘state’] }}
enabled: {{ ansible_facts[‘ansible_local’][‘custom’][‘software’][‘enabled’] }}
Create a variable file, it should be in it’s own directory.
Use that variable file to install a package
mkdir /vars/
vi /vars/common
my_package: nmap
my_ftp_service: vsftpd
my_file_service: smb
- name: Install
hosts: ansible2
vars_files: vars/common
tasks:- name: Install
dnf:
name: “{{ my_package }}”
state: latest
- name: Install
create variables for ansible2
create variables for nodes
In project folder:
mkdir host_vars
vim host_vars/ansible2
package: httpd
mkdir group_vars
vim group_vars/nodes
package: vsftpd
What do you call lists and dictionaries in Ansible
array - list
dictionary - hash
Create a variable file called users-dictionary
One dictionary should be named linda and should contain a username, shell, and home directory..
Call these all in a playbook and print it to stdout
mkdir /vars
cd /vars
vi users-dictionary
users:
linda:
username: linda
homedir: /home/linda
shell: /bin/bash
lisa:
username: lisa
homedir: /home/linda
shell: /bin/bash
Name 5 important Magic Variables
hostvars - all hosts in inventory and their assigned variables
groups - All groups in inventory
group_names - List groups this host is currently a member of
inventory_hostname - Specifies inventory hostname of current host
inventory_file - Name of current inventory file that is used.
ansible localhost -m debug -a “var=hostvars[‘ansible1’]”
Create a password file
use the password in it to create a playbook name secret.yml
run the playbook
run the playbook with you manually typing in the password
touch /root/.passfile
chmod 600 /root/passfile
ansible-vault –vault-password-file=/root/.passfile secret.yml
ansible-playbook –vault-password-file=/root/.passfile secret.yml
ansible-playbook –ask-vault-pass secret.yml
ansible-playbook –vault-id @prompt
Via Ansible Vault, encrypt, decrypt, change password and edit a file
ansible-vault encrypt this.yml
ansible-vault decrypt this.yml
ansible-vault rekey this.yml
ansible-vault edit this.yml
What are vault-ids?
use them in a playbook by creating two variable files with vault-ids, give them two separate password files and run the playbook
How do you manually enter passwords for all the encrypted files that have vault-ids?
cd vars/
ansible-vault create common_one –vault-id sercret1@/path/to/passfile
package: httpd (contents of common_one)
ansible-vault create common_two –vault-id sercret2@/path/to/passfile
cd ../
vi test.yml
- name: test
hosts: all
var_files:- vars/common_one
- vars/common_two
ansible-playbook test.yml \
– vault-id sercret1@/path/to/passfile
– vault-id sercret2@/path/to/passfile
TO MANUALLY ENTER PASSWORDS AS THEY COME IN
ansible-playbook test.yml –vault-id @prompt
What are the 6 register keys?
cmd - the command that was used
rc - return code
stderr - error message generated by the command
stderr_lines - error messages shown by line
stdout - command output
stdout_lines
When would you use loops vs a list?
list - you can use this for a module like yum because it will go through the list:
yum:
name:
- this
- that
You would use a loop with service: since it can’t iterate through your list
Loop through a list to start services for httpd and nmap
- name: Service
hosts: ansible2
tasks:- name: Service
service:
name: “{{ item }}”
state: started
loop:- httpd
- firewalld
- name: Service
Create a variable called ‘services’ and start the services listed in it via a loop
- name: Service
hosts: ansible2
vars:
services:
- httpd
- firewalld
tasks:- name: Service
service:
name: “{{ item }}”
state: started
loop: “{{ services }}”
- name: Service
Create a file with multivalued variables. You should have a variable named ‘users’ and the should contain three items of linda lisa and anna. These will have usernames, homedirectories and shells for the users. Import the variable file and loop through user creation for the users.
users:
- username: linda
homedir: /home/linda
shell: /bin/bash
- username: lisa
homedir: /home/lisa
shell: /bin/bash - username: anna
homedir: /home/linda
shell: /bin/bash
- name: Create Users
hosts: ansible2
vars_files:- vars/user-dictionary.yml
tasks: - name: Create Users
user:
name: “{{ item[‘username’] }}”
home: “{{ item[‘homedir’] }}”
shell: “{{ item[‘shell’] }}”
loop: “{{ users }}”
Here we can see that users is what it’s looping through, so it’s looping through the list of dictionaries. First it goes to the first list item and grabs the username, homedir, and shell, next it goes back to the top and goes through the second item in the list, etc
- vars/user-dictionary.yml
What are the conditional statements
variable is defined - if the var exists
variable is not defined - if the variable doesn’t exist
ansible_distribution in distributions - first variable is present in list mentioned as second
EXAMPLE:
when: ansible_os_family in [‘Debian’, ‘RedHat’, ‘Suse’]
variable - variabe is true, 1, or yes
not variable - variable is false, 0, or no
key == ‘value’
key > ‘value’
key <= ‘value’
key > ‘value’
key >= ‘value’
key != value
Create a playbook that check if sda, sdb exists, the last should check that sdc DOESN’T exist
- name: Does SDA exist
debug:
msg: ‘SDA does exist’
when: ansible_facts[‘devices’][‘sda’] is defined- name: Does SDB exist
debug:
msg: ‘SDB does exist’
when: ansible_facts[‘devices’][‘sdb’] is defined - name: Does SDC exist
debug:
msg: ‘SDB does not exist’
when: ansible_facts[‘devices’][‘sdc’] is not defined
- name: Does SDB exist
…
Create a variable with a boolean value. Check if it’s true
- name: test
hosts: all
vars:
aged: True
tasks:- name: Check if aged is True
debug:
msg: ‘aged is True’
when: aged
- name: Check if aged is True
How would you do the following in a playbook
disregard errors
stop facts from being gathered
make the handlers notified prior to an error run
stop the playbook from proceeding if you get a failed task
make a task never give the changed output
ignore_errors: yes
gather_facts: false
force_handlers: true <- all handlers notified prior to error will run. They still need to notify the handlers by being changed.
When a failing task is encountered, how do you stop the playbook from proceeding on all servers
any_errors_fatal: true <- normally a task would run on the rest of the servers even if something failed. This fails right away if one server fails so others won’t as well.
changed_when: false
Create a playbook with two plays in it.
the only task in the first play is for the localhost and it should create a file named index.html in its tmp directory.
The next play should have the below tasks:
install httpd
copy the index file to var/www/html/index.html - if this is successful then you should run a handler that restarts httpd
- name: Create file on localhost
hosts: localhost
tasks:- name: Create index.html on localhost
copy:
content: ‘welcome to the webserver’
dest: /tmp/index.html
- name: Create index.html on localhost
- name: Set up Web Server
hosts: all
tasks:- name: Install httpd
dnf:
name: httpd
state: latest - name: copy over index.html
copy:
src: /tmp/index.html
dest: /var/www/html/
notify: restart_web
- name: restart_web
service:
name: httpd
state: restarted
… - name: Install httpd
Create a playbook that forces the handlers to run, updates the kernel, and then reboots the server if the kernel update results in a change
- name: Update the kernel
hosts: all
force_handlers: true
tasks:- name: Update kernel
yum:
name: kernel
state: latest
notify: reboot_server
handlers: - name: reboot_server
command: rebootforce_handlers just means that handlers will be ran even if nothing changes. It does NOT mean that they will run if there is an error prior to them.
- name: Update kernel
Create a playbook with two tasks:
print hello world
if world exists in the output make the task fail
don’t let the failure prevent the next task from running
- name: Update the kernel
hosts: all
tasks:- name: Print
command: echo hello world
ignore_errors: true
register: command_result
failed_when: “‘world’ in command_result.stdout” - name: See if we get here
debug:
msg: second task executed
- name: Print
Create a playbook that prints a fail message when the word ‘word’ is found in an echo command but continues going
Use a separate module to do this, not a when conditional statement.
- name: Update the kernel
hosts: all
register_errors: yes
tasks:- name: Print
command: echo hello world
ignore_errors: true
register: command_result - name: Error
fail:
msg: Command has failed
when: “‘world’ in command_result.stdout” - name: See if we get here
debug:
msg: second task executed
- name: Print
Create a block of tasks
First it will remove a file
If there are any issues with this task failing, create a file in /tmp called ‘rescuefile’ and allow the playbook to complete.
Next, regardless of success or failure of the first task, have a task run make a log message.
There should be a message noting everything that’s happening in the playbook.
- name: using blocks
hosts: all
tasks:- name: Intended to be successful block
block:- name: remove file
shell:
cmd: rm /var/www/html/index.html - name: print status
debug:
msg: ‘block was operated’ - name: create a file
rescue:- name: create a file
shell:
cmd: touch /tmp/rescuefile - name: print rescue status
debug:
msg: ‘Rescue complete’
always:- name: log message
shell:
cmd: logger hello
- name: log message
- name: always print this message
debug:
msg: logger update
- name: create a file
- name: remove file
- name: Intended to be successful block
Register a files stats and make a condition based on one of the pieces of info. If it is not met, force the playbook to fail
- command: touch /tmp/statfile
- name stat file
stat:
path: /tmp/statfile
register: fs - fail:
msg: ‘unexpected file mode’
when: fs.stat.mode != ‘0640’
Check SSHD for the permitrootlogin line and change it to no
If this causes a change, restart sshd
- name: SSH config hosts: all tasks: - name: Disable Root Login lineinfile: dest: /etc/ssh/sshd_config regexp: '^PermitRootLogin' line: 'PermitRootLogin no' notify: restart sshd handlers: - name: Restart SSHD service: name: sshd state: restarted
Create a file named /tmp/hosts and add the below lines to it:
192.168.4.110 host1.example.com
192.168.4.110 host1.example.com
- name: Add Hosts hosts: all tasks: - name: Create file file: path: /tmp/hosts state: touch - name: Add junk blockinfile: path: /tmp/hosts block: | 192.168.4.110 host1.example.com 192.168.4.110 host1.example.com state: present
Create a file on ansible1
register it’s status in a variable and print it
Change the user to ‘ansible’ if that isn’t the owner
Add another play that:
gets the motd from ansible1, put it in your temp directory
Add a play that adds text the motd
copy the motd to ansible2
- name: Testing file manipulation
hosts: ansible1
tasks:- name: Create a new file
file:
path: /tmp/newfile
state: touch - name: Check file status
stat:
path: /tmp/newfile
register: newfile - name: debugging
debug:
msg: “{{ newfile }}” - name: Change file owner if needed
file:
path: /tmp/newfile
owner: ansible
when: newfile.stat.pw_name != ‘ansible’
- name: Create a new file
- name: Fetching remote file
hosts: ansible1
tasks:- name: Fetch file from a remote machine
fetch:
src: /etc/motd
dest: /tmp
- name: Fetch file from a remote machine
- name: Add text to the file that is now on localhost
hosts: localhost
tasks:- name: Add a message
blockinfile:
path: /tmp/ansible1/etc/motd
block: |
Welcome to this server
for authorized users only
state: present - name: Copy file to ansible2
hosts: ansible2
tasks:- name: copy motd file
copy:
src: /tmp/ansible/etc/motd
dest: /tmp
- name: copy motd file
- name: Add a message
What is the semanage file you need to download?
policycoreutils-python-utils
Install Selinux commands
Create a file
Give it the contenxt type httpd_sys_content_type
Run restorecon
- name: show selinux
hosts: all
tasks:- name: Install required packages
dnf:
name: policycoreutils-python-utils
state: latest - name: Create test file
file:
name: /tmp/testfile
state: touch - name: Set Selinux Context
sefcontext:
target: /tmp/selinux
setype: httpd_sys_content_t
state: present
notify:- run restorecon
- name: run restorecon
command: restorecon -v /tmp/selinux - name: Install required packages
Create a playbook variable of httpd_read_user_content
Enable SElinux in targeted mode
Check the boolean’s status/info and register it
Show the boolean’s status
Enabled the boolean
- name: enable selinux and boolean
hosts: ansible1
vars:- my_boolean: httpd_read_user_content
tasks: - name: Enable SELinux
selinux:
policy: targeted
state: enforcing - name: Check current {{ my_boolean }} boolean status
shell: getsebool -a | grep {{ my_boolean }}
register: bool_stat - name: Show boolean status
debug:
msg: the current {{ my_boolean }} status is {{ bool_stat.stdout }} - name: enable boolean
seboolean:
name: “{{ my_boolean }}”
state: yes
persistent: yes
- my_boolean: httpd_read_user_content
Grab a file from another server
fetch
Install , start and configure a webserver that has the DocumentRoot set to the /web directory. The file should be called index.html and it should say something welcoming the user to the server.
Ensure that SElinux is enabled and allows acces to the web server document root.
SElinux should allow user to publish web pages from their home directory.
This will reveal something is wrong when you try to curl the page, figure out why.
Best practice for a long playbook like this it to create the file header and add the task names prior.
- name: Managing web server SELinux properties
hosts: ansible1
tasks:- name: Ensure SELinux is enabled and enforcing
selinux:
policy: targeted
state: enforcing - name: install webserver
dnf:
name: httpd
state: latest - name: start and enable webserver
service:
name: httpd
state: started
enabled: true - name: open firewall service
block:- firewalld:
service: http
state: enabled
immediate: yes
- firewalld:
- name: create /web directory
file:
path: /web
state: directory - name: create index.html file in /web
copy:
content: |
welcome to the web server
dest: /web/index.html - name: use lineinfile to change webserver config
lineinfile:
path: /etc/httpd/conf/httpd.conf
regexp: ‘^<Directory “/var/www”>
line: ‘<Directory “/web”>’ - name: use sefcontext to set context on new documentroot
sefcontext:
target: /web(/.*)?
setype: httpd_sys_content_t
state: present - name: run resorecon
shell: restorecon -Rv /web - name: allow web server to run user content
seboolean:
name: httpd_read_user_content
state: yes
persistent: yes
- name: Ensure SELinux is enabled and enforcing
What are the four jinja 2 Template elements?
data = sample text
comment = {# comment #}
vairable = {{ ansible_facts[‘this’][‘that’] }
expression = {% for myhost in groups[‘web’]%}
{{ myhost }}
{% endfor % }
The above is a for loop
This file is managed by Ansible
Create a jinja2 file that says the below and then send it to the server you want with permissions you assign to it
You are part of a group with the following members:
member=ansible1:8080
member=ansible2:8080
member=ansible3:8080
Add the ansible_managed variable to you ansible.cfg
{{ ansible_managed }}
{% for host in groups[‘all’] %}
member={{ host }}:8080
{% endfor %}
vi test.yml
template:
src: jinja.j2
dest: /tmp/jinja
owner: root
group: root
mode: 0777
Create a jinja2 template that prints either one of two things on a web server:
if it’s apache2:
Welcome to Apache2
if its anything else
Welcome to httpd
Use a vairable in your playbook called apache_package that specifies where or not it is ap
vars:
- apache_package: httpd
tasks:
- template
src: jinja.j2
dest: /tmp/httpd.conf
jinja file
{% if kapache_package == ‘apache2’ %}
welcome to apache2
{% else %}
welcome to httpd
{% endif %}
In terms of Jinja2, how do you convert your variable to json, yaml, or check if it contains an ip address
{{ myvar | to_json }}
{{ myvar | to_yaml }}
{{ myvar | ipaddr }}
What are the different role directories and what do they do?
defaults - default variables that ma y be overwritten by other variables
files - static files that are needed by role tasks
handlers - handlers for use in this role
meta - metadata, like dependencies, plus license and maintainer info
tasks - Role task definitions
templates
tests - optional inventory and test.yml file to test role
vars - variables that are not meant to be overwritten
Where can you store roles?
./roles - store roles in current project directory. This location has the highest precedence
/.ansible/roles - exists in the current user home dir and makes the role available to the current user only. Second highest precedence
/etc/ansible/roles - location where roles stored to make them accessible to any user.
/usr/share/ansible/roles - Location where roles are stored after they are installed from rpm files. Lowest precedence
Create custom role directory structure
ansible-galaxy init rolename
How do you add roles to a playbook
roles:
- role1
- role2
What goes first, roles or tasks?
Roles, unless otherwise specified
pre_tasks:
post_tasks: - run tasks after roles but also after tasks specified in the playbook as well as the handlers they call.
Create a role directory
Create a jinja file with a motd That says
Welcome to (your server)
This file was created on (creation time)
Contact (admin’s e-mail) if anything is wrong
copy that file to a server
create variables for your role: system_manager to use in you jinja file: anna@example.com
In meta, give the author name, description, company liscence, and min_ansible_version: 2.5
Take example from pg 212
How do you add role dependencies?
Create one dependency that changes one of the default variables and another dependency that only runs when the server is in production
vi httin the meta/main.yml
dependencies:
- role: apache
vars:
apache_port: 80
- role: mariadb
when: environment == ‘production’
(This will look for the environment variable in the playbook vars, roles, etc. Basically anywhere that has anything to do with the play)
What should you call the main playbook for your project directory?
site.yml
How do you get to the ansible galaxy site?
galaxy.ansible.com
Perform a command line ansible-galaxy search
os should be redhat
author
tags
get more info about the role
ansible-galaxy search –platforms redhat
–author me
–galaxy-tags httpd
ansible-galaxy info this.role
Where do ansible-galaxy roles usually install?
How do you change this to /home/ansible/roles?
~/.ansible/roles
ansible-galaxy install this.role -p /home/ansible/roles
Create a requirements file and install it
vi roles/requirements.yml
- name: geerlingguy.apache
src: https://github.com/geerlingguy/ansible-role-apache
scm: git
version: v2.0.0 - name: geerlingguy.nginx
version: “2.7.0”
ansible-galaxy install -r requirements.yml
Show how you would run two different inventories for a playbook.
Can you put a directory as the argument to this parameter?
ansible-playbook -i /etc/hosts -i /tmp/hosts
ansible-playbook -i /path/to/directory
What is the difference between serial and parallel tasks?
Serial tasks makes all tasks executed on a host or group of hosts before proceeding to the next. This will run the whole playbook for a group of tasks and the move to the next.
Parallel manages the number of hosts on which tasks are executed simultaneously.
What is the default max number of simultaneous connections ansible can have at once?
How do you change this in the config file?
How do you change this while running a playbook?
5
forks = 6
This will run each task 6 servers at a time in parallel
ansible-playbook -f 6
How would you run all tasks in serial for sets of three servers at a time? What would be a good situation to use this?
serial: 3
If you have a 1000 servers and you have to update and then start the new version.
If you just did this normally, it would slowly update each one until finished and then restart after.
Doing this 3 at a time prevents servers from being down. Only 3 will be updated quickly and then started, then it will move on to 3 more servers.
SERIAL - 3 servers run the WHOLE playbook at a time.
PARALLEL - 3 servers will run a TASK at a time.
How do you print the time it takes to run a playbook
time ansible-playbook test.yml
Create a playbook that does something simple like printing a message.
Create another playbook that prints a message that says it’s importing a play, and then import your other playbook
What should the main playbook be called?
vi site.yml
- name: Run a task
hosts: all
tasks:- debug:
msg; Importing Playbook
- debug:
- name: Importing a playbook
import_playbook: test.yml
Another example:
- import_playbook: webserver.yml
- name: Configure Load Balancer
hosts: lb
tasks:- name: Install HAProxy
yum:
name: haproxy
state: present
- name: Install HAProxy
- import_playbook: database.yml
How do you statically import tasks?
How do you dynamically import them?
When should you use one or the other
import_tasks = static, read prior to playbook so they can’t be modified to do anything else, they are what they are.
include_tasks = dynamic. They’re use the moment you need them
dynamic when task is used in conditional, can assign variables, generally what you’d want to use.
Name a mix of three pros and cons of dynamic and static tasks
Static (import_tasks)
- Loops can’t be used with them
- if Variable is used to specify the name of the file to import, this cannot be a host or group inventory variable
- Using a conditional on the entire import_tasks file the conditional is applied to each task that is involved
Dynamic (include_tasks)
- tasks aren’t displayed in ansible-playbook –list-tasks
- You can’t –start -at-task
- You can’t use notify statement in main playbook to trigger a handler that is in the included tasks file.
What is best practice when importing/including files in terms of packages, users, services, etc
Make them a variable. So The variable {{ user1 }} can be set in the imported task and you can rename it in your play.
Create an included task file to install software and keep it as generic as possible and then use it in a playbook.
Also, assign variables so they are part of just that imported task.
Also, for your included file, give it something to do in terms of a list of options.
LOTS OF PRACTICE WITH THIS SINCE IT WILL ERASE SOME TIME IN THE RHCE FOR MORE COMPLICATED WORK!
The task file should install a variable name, like {{ package }}, don’t set this variable.
In you main playbook, import/include it and set the name to whatever you want.
PG. 244
Included tasks must be in TASKS or you will get an error.
What option should be set if you want your playbook to always check itself
check_mode: true
Show differences in files after you run a playbook
ansible-playbook –check –diff
What is the proper way to log ansible-playbooks
export ANSIBLE_LOG_PATH=”/var/log/ansible.log”
OR
in the ansible.cfg
log_path = /var/log/ansible.log
THESE FILES WILL GET BIG
Run playbooks task by task and have it ask you to continue or not
ansible-playbook –step
List all tasks in a playbook and then start at one
ansible-playbook –list-tasks test.yml
ansible-playbook –start-at-task=”task name”
Create a playbook that tests if your web server contains “Welcome”. If it doesn’t cause it fail via conditional.
You should have the server’s message in a variable to do this, print that content
hosts: localhost
tasks:
- name: connect to webserver
uri:
url: url here
retrun_content: yes
register: this
failed_when: “‘welcome’ not in this.content”
- debug:
var: this.content
Let’s say we have a managed node with multiple ips, but we only want to connect via 192.168.4.55.
how can we set this up in the ansible.cfg
ansible3.example.com ansible_host=192.168.4.55
What does assert do?
Performs conditional action
Works with ‘that’ which defines a list of conditionals
If any conditional is false the task fails
Uses ‘success_msg’ and ‘fail_msg’
Have the playbook request the user to create a variable named filesize. You should specify the user types in a file size in megabytes
Use assert to check if the filesize is less than or equal to 100 or greater than or equal to 1
use an escape character in one of your messages
Next create a zeroed out file of that size
Assert fails a task, which means it will actually still try the task on all servers even if one fails
vars_prompt:
- name: filesize
prompt: “your message here”
tasks
assert:
that:
- “( filesize | int ) <= 100 }}”
- “( filesize | int ) >= 1 }}”
fail_msg: “fail's escape character”
success_msg: “”
- name: create a file
command: dd if=/dev/zero of=/bigfile bs=1 count={{ filesize }}
Create a file that checks if vgdata exists
use assert to print a fail and success message depending on that conditional
Example at 271
Create a playbook that uses tags
Next only run one of the tagged tasks
debug:
msg: One
tags:
- debug
dnf:
name: httpd
state: latest
tags:
- install
ansible-playbook –tags “install”
Can tags be used for included or imported tasks?
only static not dynamic
so this would work for import_tasks but not include_tasks
same with include_roles
List all tasks in a playbook. Show all their tags as well
ansible-playbook –list-tags –list-tasks test.yml
Which tasks won’t be displayed via –list-tasks?
tasks inside block/rescue/always sections and dynamically and statically included tasks
import_tasks (static) will normally show up unless it’s in the block, rescue, or always section. Similarly, include_tasks (dynamic) won’t appear at all because it’s loaded at runtime.
What are special tags?
List them
They modify how the tag works.
These are premade tags. normally we wouldn’t use tagged and untagged because if a task has no tag ansible denotes that already with untagged, the opposite is true for tagged.
always - task always runs unless specified with –skip-tags always
never - Never runs a task unless otherwise specified
tagged - runs all tagged tasks
untagged - runs all untagged tasks
all - runs all tasks
How would you run two specific tagged tasks that contain either the tags ‘one’ or ‘two’?
ansible-playbook playbook.yml –tags one,two,three,
You have a task with the tags never and debug.
how would you run tasks with these tags
ansible-playbook –tags all,debug
This runs everything but only executes tasks with the debug tag. The book says this will run debug and the rest of the tasks as well, so test these out.
–tags never,debug actively skips never tasks.
Create a playbook that removes ansible from the wheel group
reboot the node
Try to ping it to diagnose issues
make the user part of wheel again
ping the managed node once more
test.yml
user:
name: ansible
groups: ‘ ‘
ansible ansible3 -m reboot
ansible ansible3 -m raw -a “usermod -aG wheel ansible” -u root -k
What is the module and arguments you will need to Setup a yum repo?
yum_repository:
name - name of repo
description - description of repo
file - the .repo file created in /etc/yum.repos.d on the managed machine to store the rpo info
baseurl - url that identifies how to access the repo
gpgcheck
Update all packages on a node
yum:
name: ‘*’
state: latest
What is a package group and how do you install one?
Group of related packages which makes installation easier
yum:
name: ‘@virtualization host’
state: latest
What module do you use to store installed packages in facts?
Perform a playbook that installs software, updates package information in facts.
Next show package information
- package_facts:
manager: auto - debug:
var: ansible_facts.packages[‘nmap’]
manage: This tells which package manager to communicate with. Auto auto detects appropriate package manager
apparently what we’re doing above is gathering facts on installed packages
What is a repository
Directory that contains rpm files as well as repo metadta which is an index that allows the repo client to figure out which packages are available in it.
Install FTP
Start and Enable FTP
Open firewall for FTP traffic
Make sure FTP shared repo directory is available
Download packages to the repo
Use createrepo to generate metadata/index
Page 290
Register your RHEL credentials for the subscription manager
Find out what pools are available in your account
Connect to a pool
Find out what additional repos are available to your account
Register to use additional repos
subscription-manager register –username=my_username –password=my_password
subscription-manager –available
subscription-manager attach –pool=poolID
subscription-manager repos –list
subscription-manager repos –enable “repos nameol;./”
pool - collection of software channels available to your account.
What are two modules for subscriptions you can use?
redhat_subscription - enables you to perform subscription and registration in one task
rhsm_reposistory - Enables you to add subscription manager repos
purge: true <- disable repos it requires name: though
or just
name: “*”
state: disabled
state can be enabled or disabled
name is always mandatory
name can be comma separated for multiple entries or you can use a yaml list
Fetch a gpg key and setup a repo client
What command do you use when you have gpg key errors?
- name: Get GPG pub key
rpm_key:
key: ftp://control.example.com/repo/RPM-GPG-KEY
state: present - name: Set up the repo client
yum_repository:
file: myrepo
name: myrepo
description: example repo
baseurl: ftp://control.example.com/repo
enabled: yes
gpgcheck: yes
state: present
I believe the below was a troubleshooting thing for the gpg keys from last time:
rpm –import /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release
Via playbook fully register a new machine and add a new repo to the managed machine.
This play won’t be runnable as such because important additional info needs to be provided.
- name: register and subscribe ansible5
redhat_subscription:
username: bob@example.com
password: verysecretpassword
state: present - name: Configure additional repo access
rhsm_repository:
name: - rh-gluster-3-client-for-rhel-8-x86_64-rpms
- rhel-8-for-x86_64-appstream-debug-rpms
state: present
Set up a repo server that is based on ftp
Create a second play that configures the clients with appropriate repo access
Next install a package
pg 294
Create either an http repo or an ftp repo
install createrepo/createrepo_c
subscription-manager repos –list-enabled
subcription-manager repos –disable * - or just repo names
mkdir /localrepo
dnf install –downloadonly –downloaddir /localrepo
vi /etc/yum.repos.d/local.repo
[centos7]
name=centos7
baseurl=file:///localrepo/ (this is the direcat ctory we created)
enabled=1
gpgcheck=0
createrepo /localrepo
dnf clean all (clear repo cache)
dnf install nmap
if you setup http your base will be
baseurl=http://ansible3/repo
baseurl=ftp://ansible3/repo
localrepo should either be on /var/www/html/repo
or
var/ftp/repo/
or
var/vsftpd/repo/
You will need to configure selinux appropriately here
for ftp with user and pass
baseurl=http://user:pass@example.com/myrepo/Dev-Repo
troubleshooting
dnf clean all
vi /etc/httpd/conf/httpd.conf
Directory
Require all granted < add this line, this let’s everyone use it
or you can add
require ip 192.168.1.0/24 < allow a range of ips
If you want to specify just the repo directory just configure that path similarly
What does a gpg key do vs a repomd.xml file?
GPG - enables verification
repomd.xml - creates a detached signature that crypotgraphically proves the metadata hasn’t been altered. This is signed with your private key.
Without signing and verifying a gpg key is just a pair of numbers.
On all nodes create a directory for ansible’s sudo configuration. Allow it to not have to use a password
How is ansible tower different here?
vi /etc/sudoers.d/ansible
ansible ALL=(ALL) NOPASSWD:ALL
Ansible Tower allows you to store ansible’s password securely so it can use sudo
What is a project directory?
A directory for a project that includes everything that project needs to run.
Playbooks
Inventory
Variable Files
Additional files used to include tasks
ansible.cfg configuration files
In terms of an inventory file, how would you format:
server(1-16)@example.com
server[1:16]@example.com
Let’s say you have created two groups (web, db) and want those to be subgroups to a parent group called servers. How would you format this?
[servers:children]
web
db
Show hosts in an inventory called inventory
Show all hosts in the inventory file
ansible-inventory -i /inventory –list-hosts
–list will do so in JSON format
ansible -i inventory all –list
Your inventory file used to be used to assign variables, but this is deprecated. What is used in it’s place?
Show an example of variables in the inventory file
[web:vars]
ansibile_user=ansible
ansible:password=123
These should now go int host_vars and group_vars directories
Configure the Ansible Configuration file and explain it
All of this can be used per playbook
[defaults]
remote_user = ansible
host_key_checking = false
inventory = inventory
[privilege_escalation]
become = True
become_method = sudo
become_user = root
become_ask_pass = False
[defaults] - generic info
[privilege_escalation] - How ansible user should require admin privileges to connect to managed hosts
remote_user - user used to connect to managed device
host_key_checking - Should ssh host keys be checked
Create an inventory file in your ansible user’s home. It should have the ansible servers ungrouped, two devices in the web and db groups
a servers group with db and web as a part of that group
Show all hosts in this inventory
Show all hosts that aren’t a part of a group
Show a hierarchical overview of the inventory
Show the contents in json format
cd /home/ansible
ansible1
ansible2
[web]
web1
web2
[db]
db[1:2]
[servers:children]
web
db
ansible -i inventory all –list-hosts
ansible -i inventory ungrouped –list-hosts
ansible-inventory -i inventory –graph
ansible-inventory -i inventory –list
Create an ansible configuration file in the ansible home directory
show your inventory without using the -i option now
cd /home/ansible
vi ansible.cfg
[defaults]
remote_user = ansible
host_key_checking = false
inventory = inventory
[privilege_escalation]
become = True
become_method = sudo
become_user = root
become_ask_pass = False
copy the inventory file to the main home directory (remember they have to be in the same directory here)
ansible-inventory –list
Say you don’t have python installed on a managed node. How would you install python?
ansible -u root -i inventory ansible3 –ask-pass -m raw -a ‘yum install python3’