====== Ansible ======
=== Experimenting environment ===
Here is an environment for experimenting:
https://github.com/skipidar/ExperimentsProject-4Ansible-usingVagrant/wiki
=== Configuration of ansible ===
Add hosts here: **/etc/ansible/hosts**
local ansible_host=127.0.0.1 ansible_connection=local
slave ansible_host=10.0.0.11 ansible_user=vagrant ansible_ssh_private_key_file=/home/vagrant/.ssh/key.myexperimental.openssh.ppk
Add the ssh **private-key** in openSSH form here, which will be used by ansible
/home/vagrant/.ssh/id_rsa
Example:
-----BEGIN RSA PRIVATE KEY-----
MIIEoQIBAAKCAQEAxQRyoCBSijfLHpuQKR+0/nsO4p66r4xDre0nJZ8FgHwW+ATd
zRr/Mu6C5DgS1ENY9No8yOH56zqnqlhoQpTY5d+wypbkkF3AG3N0D0DrHK4CHjjP
NylHAm4+ATuU68agYOVTPycY19DXaAgQBqtJlRVHhMB9ZJ+ugAdKINjpW//8uwvP
HisH6GYbA5zWugNHmyfNLdYdJcdozTUprHFkRz6E2HyCxEuhurbcHtsEEfgCd93f
bHn2utRg24VIRFNZF24C6N/OSrsmdKbYsQV/VygHEo6VYM4DUOcz1nzU5f3f5k1p
itgBbyVqIID++XwxNCl8wAjUWFEHvA+xyf4ZywIBJQKCAQB/y4ifN498P92y/R89
RP/HqcR3UjPnfZOvFl6U8YcHO7vfJcBNsKWI0g+2oOmecN/Bavb+18S0QbjdMm0k
RN+3s7DyHK/u8LP2IWAJ5OuIOYTVVUgjx79bhcdavt0jUGgHf/6lgSTfBAFYPJTG
Dj2RIo9BWkN/iiwABLp2K9WjdHiYwMm2bQqZx2lB4oNPyfhdEUAmd2cdVCfH60mq
315KRjO9TgH3ORz43I62rFwSiEaP2VDWhG8nOiMp8wONhaES41uZ05pGA6F9cAdO
DvPpK4QcwZ8KZdkJQJBhXu3UvfIS1C6AZ7b08lf+ifU5shqZMerVPxY6RC6FzSRV
rs7tAoGBAPSrlQjDhHcCLFd/FyCuTaYQQhokbYRdeZ1bRj5Sv62XB6K8u6NeuKIB
4v3W24dnZb51xhk4SOFOXC2lxR0q56MxVsZwl+5vRJEt7wlVYy4yK8JH4r1shDZG
/FxQzIfkjxIxMoVhqKL2tdhlE+p0ZPZFRiTCvougXDCaMAfdlGrfAoGBAM4j+DoM
E8s5JlaUSIDws5f7axrOGy8lwWNzDtnHmVqoX/0Ck0cIcEhj1SzuYG64qtc5qL7p
ej9lU+eqaYWfPbLo+LnrIadaMPxQAG7DS0PILoPJAVgZl3PGUfjvk0kEH03YE8cj
OiRpefS9rbp2z1HtYQ30iQZzdmS+Q2c9ptqVAoGALkn5md/M8+unhizNBi7Qa4aJ
C91g09pVR0ielitUsiN9/DGLSGvdvckBbks+Sgyki9EXo+gNycK3fkH03AEyvgJq
XOTeeTelMDkfYqFzoPS8K6y8May/ETAGOvqHj1TBHx4QehllF+l8WV87HoS5J6w9
s+19/r15OaChTZifidcCgYEAgCQyhPLAMjhIQ6hIvtrQgRHoofW93wmhulxHgHUn
+hWjc8NUocb5sHVo1r2xkO9VcQgqoDBFEqbFdFUs1oWVDll4BN5FWjElXpKYfDQ1
tINbL1Nvicq4F4keMvXKQiUoN073iaBGvLBE5D6OloE0xDmdMjA5gIz2kaa0Rxh8
egkCgYB7QihLpX+8sDAyENjs5ylJgsOV8N6e2Twhqjy1B0j0SZoXToOB/Grohk5m
BZOsSCeSn4Qb+N8aX0EFXuUHCZVXsYnv8fpiZEYReXNij0mi5MbYby8eY24V9iuO
Xixof23aO5mPprsvg/s+GHfbXtZmApDi+wVoN9YNMN43ovxB+w==
-----END RSA PRIVATE KEY-----
Add the ssh **public-key** in openSSH form here, which will be used by ansible
/home/vagrant/.ssh/authorized_keys
Example:
ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEAxQRyoCBSijfLHpuQKR+0/nsO4p66r4xDre0nJZ8FgHwW+ATdzRr/Mu6C5DgS1ENY9No8yOH56zqnqlhoQpTY5d+wypbkkF3AG3N0D0DrHK4CHjjPNylHAm4+ATuU68agYOVTPycY19DXaAgQBqtJlRVHhMB9ZJ+ugAdKINjpW//8uwvPHisH6GYbA5zWugNHmyfNLdYdJcdozTUprHFkRz6E2HyCxEuhurbcHtsEEfgCd93fbHn2utRg24VIRFNZF24C6N/OSrsmdKbYsQV/VygHEo6VYM4DUOcz1nzU5f3f5k1pitgBbyVqIID++XwxNCl8wAjUWFEHvA+xyf4Zyw== rsa-key-20170928vagrant@master:~$
Configure the ssh-key permissions. Ansible will check them and if someone else can access the keys decine the usage of the key.
chmod -R 700 /home/vagrant/.ssh
==== Debugging the connection ====
Try connecting to the server using ssh
ssh ec2-user@48.114.120.127 -p 22 -i /root/vagrant-home/ssh/demokey.pem
Try using the **-vvvv** parameter.
ansible slave -vvvv -m ping
==== Introduction ====
Here is a good introduction:
https://serversforhackers.com/c/an-ansible-tutorial
==== Commands ====
Send a command to all ansible hosts
ansible all -m ping -u "ec2-user"
Send a command to slave only
ansible slave -m ping -u "ec2-user"
Execute a shell command remotely. \\
The module used here is shell - it is not that the shell is executed remotely, but using the argument **-m** an ansible **module** is used.
The **-a** flag is used to pass any **arguments** to the module
ansible all -s -m shell -a 'apt-get install nginx'
==== Playbook ====
Hierarchy:
* Playbook
* Tasks - declarative describtion of as to be state
* Handlers - secondary, after tasks
=== Tasks ===
Create the following playbook in a file addmycowsay.yaml
---
- hosts: local
tasks:
- name: install cowsay
apt: pkg=cowsay state=installed update_cache=true
And execute the playbook
ansible-playbook addmycowsay.yaml
So the syntax is the following:
---
- hosts:
tasks:
- name:
: pkg= state=installed update_cache=true
=== Handlers ===
---
- hosts: local
tasks:
- name: Install Nginx
apt: pkg=nginx state=installed update_cache=true
notify:
- Start Nginx
handlers:
- name: Start Nginx
service: name=nginx state=started
==== Become non root ====
To allow becoming non priviledged user to things must be set to True in **/etc/ansible/ansible.cfg**
**Important**: The given settings must be uncommented at the right locations in ansible.cfg. It is insufficient to append those settings to ansible.cfg.
allow_world_readable_tmpfiles = True
pipelining = True
To uncomment them programmatically do
sed -i 's/.*pipelining.*/pipelining = True/' /etc/ansible/ansible.cfg
sed -i 's/.*allow_world_readable_tmpfiles .*/allow_world_readable_tmpfiles = True/' /etc/ansible/ansible.cfg
Here is an example playbook, which shows how to become the user "oracle"
# Setup the infrastructure for Faktura
- hosts: "myhost"
become: yes
become_method: sudo
become_user: oracle
vars:
allow_world_readable_tmpfiles: true
tasks:
# an error is thorwn when becoming unpriviledged user. Hence use sudo
- name: install oracle client
shell: |
whoami
args:
chdir: /tmp/client
environment:
DISTRIB: /tmp/client
==== Remove Old SSH Key Fingerprint ====
When connecting to an unknown host - your are asked whether to trust it.
Linux then stores a fingerprint of the key associated with the host.
If the host then changes, e.g. because of the replacement of the EC2 machine behind the host - connection will fail.
To remove the fingerprint do:
ssh-keygen -R '45.157.214.126'
==== Extra vars alias arguments ====
Pass external variables as arguments to the playbook, to e.g. define hosts outside of the playbook.
ansible-playbook myplaybook.yaml --extra-vars "host=yourhost"
And here is myplaybook:
- hosts: "{{ host }}"
become: true
become_method: sudo
become_user: root
...
==== Ansible behind proxy ====
If you configure the Hosts to use corkscrew, then ansible will be able to reach the machines:
Open /home/vagrant/.ssh/config, add
Host *
ProxyCommand corkscrew 194.138.0.33 9400 %h %p
==== Galaxy ====
You can use the galaxy (https://galaxy.ansible.com/intro) to share roles or download them.
A role "cmacrae.sensu" might be downloaded using
ansible-galaxy install cmacrae.sensu
After that you can embed the role into your playbooks:
---
- name: Install sensu
hosts: slave
become: true
roles:
- { role: cmacrae.sensu, sensu_master: true, sensu_include_dashboard: true }
==== MODULE FAILURE - rc 127 ====
When ssh works, but the ping fails with
$ ansible slaves -m ping -vvvv
ansible 2.5.0
config file = /etc/ansible/ansible.cfg
configured module search path = [u'/home/vagrant/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python2.7/dist-packages/ansible
executable location = /usr/bin/ansible
python version = 2.7.12 (default, Nov 19 2016, 06:48:10) [GCC 5.4.0 20160609]
"module_stdout": "",
"msg": "MODULE FAILURE",
"rc": 127
}
Then it will help to ssh to the remote host and install python
ssh 34.242.178.166 -l ubuntu -i /home/vagrant/.ssh/DevOpsBootCamp.openssh.ppk
ubuntu@34.242.178.166: sudo apt install python
Check https://github.com/ansible/ansible/issues/25941
==== AWX installation ====
The UI, which enables team management and delegation is available as the AWX project
https://github.com/ansible/awx
==== Importing and Including ====
|include*|Is done evaluated at runtime|
|Import*|Is done at compile time. PREFER THAT.|
=== import_tasks ===
Can be used, to extract equal steps you want to reuse in a separate file.
|import_tasks*| Allows passing variables. Requires the imported file to have only tasks, no "hosts" etc.|
Usecase: requirements for a Renderer/Viewer which needs the same preparations.
common_requirements.yaml
It is important, that you dont have the header here. Only tasks
- name: Creates product configuration file
file:
path: /etc/apt/apt.conf.d/product
state: touch
owner: ubuntu
group: ubuntu
mode: 0700
- name: product config content
copy:
dest: "/etc/apt/apt.conf.d/product"
content: |
Acquire::https::repo.product.com {
Verify-Peer "true";
Verify-Host "true";
SslCert "/etc/ssl/product/MYCERT.crt";
SslKey "/etc/ssl/product/MYKEY.key";
};
Renderer:
---
- hosts: "{{ host }}"
become: true
become_method: sudo
become_user: root
tasks:
- name: Install product requirements
import_tasks: common_requirements.yml
vars:
host: aws
- name: Install renderer
become: true
apt: product_renderer
Viewer:
---
- hosts: "{{ host }}"
become: true
become_method: sudo
become_user: root
tasks:
- name: Install product requirements
import_tasks: common_requirements.yml
vars:
host: aws
- name: Install VIEWER, reusing the tasks
become: true
apt: product_viewer
=== import_playbook ===
Unfortunately lacks the possibility to pass in variables.
Which makes it unusable
==== Read remote files ====
To read remote file do use slurp
- name: set facts
set_fact:
dest_timestamp: /tmp/progress/timestamp
- name: Slurp timestamp file
slurp:
src: "{{ dest_timestamp }}"
register: slurpfile
- name: set the timestamp fact
set_fact:
timestamp: "{{ slurpfile['content'] | b64decode }}"
- name: timestamp variable
debug: msg="{{ timestamp }}"
==== Execute a shell script, as a user with a valid environment ====
Sometimes you face the issues, that the environment variables defined by some tool, installed for a special user - are not defined, when you execute the tool.
To execute some installed software in a valid environment, \\
with /home/bashrc \\
with /etc/profile.d \\
etc
use the following approach.
# unfortunately the environment defined by tool in /etc/profile.d - is not taken up by ansible. Explicitely requesting the interactive shell is necessary here
- name: processing step
shell:
sudo -iu ubuntu yourtool.sh > /tmp/logs/yourtool.log 2>&1
args:
executable: /bin/bash
-i [command]
The -i (simulate initial login) option runs the shell specified in the passwd(5) entry of the target user as a login shell. This means that login-specific
resource files such as .profile or .login will be read by the shell. If a command is specified, it is passed to the shell for execution. Otherwise, an
interactive shell is executed. sudo attempts to change to that user's home directory before running the shell. It also initializes the environment, leaving
DISPLAY and TERM unchanged, setting HOME, MAIL, SHELL, USER, LOGNAME, and PATH, as well as the contents of /etc/environment on Linux and AIX systems. All other
environment variables are removed.
See https://github.com/ansible/ansible/issues/4854
UNfortunately the aproach with become_user - does not have the same result