Managing remote machines direcly using ansible commands
<yambe:breadcrumb>Ansible|Ansible</yambe:breadcrumb>
Managing remote machines directly using ansible commands
Running simple shell command on all remote machines
Steps for managing remote machine are:
- Add all remote node FQDN or IPs in a text file (one on each line).
- echo <machine IP or FQDN> >> ansible_hosts
- Then setup trust based ssh to all hosts mentioned in ansible_hosts file using:
- ssh-copy-id root@<machine IP or FQDN>
- Finally to "/bin/echo hello" command on all remote machines use:
- ansible all -i ansible_hosts -a "/bin/echo hello"
Note that without no_log option the commands are recorded in remote systems syslog and can be seen at /var/log/messages. A better way to run commands is to use shell module as follows:
ansible all -i ansible_hosts -m shell -a "echo hello"
with a very big advantage of not having to type full absolute path for the executable.
When running any command with the Ansible ad-hoc CLI, pay particular attention to shell quoting rules, so the local shell doesn’t eat a variable before it gets passed to Ansible. For example, using double vs single quotes as shown below:
ansible all -i ansible_hosts -m shell -a "echo $HOSTNAME"
or
ansible all -i ansible_hosts -m shell -a 'echo $HOSTNAME'
would evaluate the variable on the box where command is run vs evaluation of varilables on remote machine.
Disabling remote ssh host key checking
Running ansible to manage remote hosts when their public keys are not present in '~/.ssh/known_hosts' does not works. To solve this either manually those keys can be added by doing ssh to every node being managed. Or checking of remote host public ssh keys can be disabled by editing ansible configuration. System wide ansible configuration goes in '/etc/ansible/ansible.cfg'. A local user specific override can be done in '~/.ansible.cfg'. To disable ssh key checks use:
[defaults] host_key_checking = False
in one of these two configuration file locations.
The same can also be done for current shell temporarily using:
export ANSIBLE_HOST_KEY_CHECKING=False
Warning: Please note that disabling checks for remote ssh keys will make system vulnerable to Man-In-The-Middle (MITM) attacks.
Ansible command options
Various ansible command options are:
- Host name
First a required argument is host where the ansible command should operate. We can use keyword 'all' or '*' to run the ansible command on all hosts. We can specify group name, where group is properly defined in hosts file to run command on all hosts in the group. Finally we can specify pattern or individual host name to run command only on hosts which satisfy the pattern (192.168.122.*). More than one host or pattern can be specified separated by colon(:).
It is also possible to specify a pattern or a group and then exclude specific hosts or other groups from overall selection using ! operator. Example
192.168*:!192.168.122.101
On shell remember to escape ! by using \ Further if no hosts match then ansible shows "No hosts match" message.
It is also possible to get intersection of two groups using & operator as follows:
webservers:&staging
Please note that even when we use pattern only hosts which are present in hosts file can be contacted or managed.- Hosts file
- We can specicy custom hosts file using '-i'. Default is '/etc/ansible/hosts'. All hosts specified at top of file are treated as uncategorized hosts. After such hosts we can specify a group name such as '[dns]', '[test_dns]' etc and set of hosts under given group. These group names can be used to specify hosts to operate on in ansible command or playbook.
- Module
- We can specify which module to invoke using '-m'. Default is command
- Arguments
- Arguments to the module being invoked can be passed using -a
- Fork
- To configure multiple machines in parallel we can use '-f' option with an integer argument.
- Ask-pass
- To configure ansible to ask ssh root password for remote machine we can use --ask-pass or -l
Ansible modules basics
To learn any ansible module first read its syntax and purpose from ansible docs at http://docs.ansible.com/list_of_all_modules.html For example read information on copy module and try commands mentioned in this article to understand its purpose.
Copy module
To copy a file from ansible server to specified remote hosts use:
ansible dns_hosts -i dns_hosts -m copy -a "src=/etc/hosts dest=/etc/hosts"
Note that output would look similar to:
192.168.122.103 | success >> { "changed": true, "checksum": "ab27c9b77077dd2a9f15246324ca0f8d31436b2f", "dest": "/etc/hosts", "gid": 0, "group": "root", "md5sum": "8cff70896b6b562833d9b14bd8d7bbb9", "mode": "0644", "owner": "root", "size": 308, "src": "/root/.ansible/tmp/ansible-tmp-1423134324.77-50906221386053/source", "state": "file", "uid": 0 } 192.168.122.102 | success >> { "changed": true, "checksum": "ab27c9b77077dd2a9f15246324ca0f8d31436b2f", "dest": "/etc/hosts", "gid": 0, "group": "root", "md5sum": "8cff70896b6b562833d9b14bd8d7bbb9", "mode": "0644", "owner": "root", "size": 308, "src": "/root/.ansible/tmp/ansible-tmp-1423134324.76-153401053249562/source", "state": "file", "uid": 0 }
On running the same copy command again, value of changed in output would change from true to false. Example output on running same copy command is:
192.168.122.103 | success >> { "changed": false, "checksum": "ab27c9b77077dd2a9f15246324ca0f8d31436b2f", "dest": "/etc/hosts", "gid": 0, "group": "root", "mode": "0644", "owner": "root", "path": "/etc/hosts", "size": 308, "state": "file", "uid": 0 } 192.168.122.102 | success >> { "changed": false, "checksum": "ab27c9b77077dd2a9f15246324ca0f8d31436b2f", "dest": "/etc/hosts", "gid": 0, "group": "root", "mode": "0644", "owner": "root", "path": "/etc/hosts", "size": 308, "state": "file", "uid": 0 }
For further information on copy module visit http://docs.ansible.com/copy_module.html
yum module
Use
ansible dns_hosts -i dns_hosts -m yum -a "name=bind-utils" -f 10
to install bind-utils on all dns_hosts or
ansible dns_hosts -i dns_hosts -m yum -a "name=bind-chroot state=absent" -f 10
to remove bind-chroot from all dns_hosts
In yum module state option can be specified to be absent, present or latest depending upon whether given package should be removed (if present), should be present (even if current version is older than latest available via yum), or should be latest possible package available via yum. Other options can be learned from http://docs.ansible.com/yum_module.html
file module
To ensure file has specific permission and owernhip
ansible webservers -m file -a "dest=/home/saurabh/.ssh/authorized_keys mode=400 owner=saurabh group=saurabh"
For creating directories with given permission and ownership:
ansible webservers -m file -a "dest=/home/saurabh/.ssh/ mode=700 owner=saurabh group=saurabh state=directory"
For deleting files or directories (recursively, if needed):
ansible webservers -m file -a "dest=/tmp/delete_me state=absent"
user module
To create or ensure user exists use:
ansible all -m user -a "name=foo password=<crypted password here>"
For example
ansible servers -m user -i hosts_file -a 'name=saurabh password=$6$sN4rhde4Wv$F7cH7b4ZG.lmEYy.U334LQvZ0d7EIntlrOxahoh70w/nBKgspJ9AWrlA9RFnZ1Tv0Gi.7TH.bmw4k71A3ct79/'
Here crypted password can be generated using following method:
[root@barjatiyarklp ~]# mkpasswd -l 10 -s 0 mv0iSwy8zC [root@barjatiyarklp ~]# python Python 2.6.6 (r266:84292, Jan 22 2014, 09:42:36) [GCC 4.4.7 20120313 (Red Hat 4.4.7-4)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import crypt >>> crypt.crypt("<password>", "$6$<salt>") '$6$<salt>$SrPXyEZ1bOhORDPvsFH.5Z5W9VHWYBXUE3rnYhfdboAc.BBhQT7Nwe3BgTSShA4ykP.keRw8.AmbC2uN/QnvN0' >>> crypt.crypt("rekall123", "$6$mv0iSwy8zC") '$6$mv0iSwy8zC$Jrg0uunksVqAtHRhE0ik6LRJNTEIzTNMiCzNMkkmvTdMYLdr.3Wau/5DBV9RYp2bzL9M53bxF/u7d432CN8rj0' >>> [root@barjatiyarklp ~]#
This can also be done using one single command as:
python -c "import crypt; print crypt.crypt('iiit123','\$6\$$(mkpasswd -l 10 -s 0)')"
Similarly users can be deleted or it can be ensured that given user does not exists using:
ansible all -m user -a "name=foo state=absent"
service module
To ensure that a given service is running and also enabled on startup use:
ansible webservers -m service -a "name=httpd state=started enabled=yes"
Time limited background operations
To run a command in background use:
ansible all -B 3600 -P 0 -a "/usr/bin/long_running_operation --do-stuff"
To check on the job status later, use async_status module by passing it the job id that is returned when original job is run in the background, as follows:
ansible web1.example.com -m async_status -a "jid=488359678239.2844"
Gathering facts or setup module
To simply get facts for specific machines use:
ansible all -m setup
<yambe:breadcrumb>Ansible|Ansible</yambe:breadcrumb>