Goal: I'm trying to copy /home/foo/certificates/*/{fullchain.cer,*.key}
from one server (tower.example.com) to other nodes.
When trying the task with verbose options, it's stuck. Output logs can be found there (Ansible 2.5): https://gist.github.com/tristanbes/1be96509d4853d647a49d30259672779
- hosts: staging:web:tower:!tower.example.com
gather_facts: yes
become: yes
become_user: foo
tasks:
- name: synchronize the certificates folder
synchronize:
src: "/home/foo/certificates/"
dest: "{{ certificates_path }}/"
rsync_opts:
- "--include=fullchain.cer"
- "--include=*.key"
delegate_to: tower.example.com
I'm running this playbook on localhost.
What I except of this is to connect as foo on tower.example.com then, to ssh as foo to servers of groups web and staging to rsync push the content of the folder matching the filters.
I can run other playbooks on tower.example.com
I can connect on tower.example.com with my user and then sudo -i && su foo to foo.
As foo, I can connect to other hosts as foo for servers under group web and staging.
What am I missing?
It looks like tower.example.com may not have ssh access to the other hosts. This would cause Ansible to get stuck as ssh is waiting for a password. You can fix this by
generating a new ssh key on tower.example.com and authorizing it on the other hosts, and/or
setting up ssh-agent forwarding.
Alternatively, you could fetch the certificates to a temp folder on localhost and copy them to the other hosts. This avoids the use of delegate_to, but is not as efficient as syncing the files directly between the remote hosts.
Related
In my job there is a playbook developed in the following way that is executed by ansible tower.
This is the file that ansible tower executes and calls a playbook
report.yaml:
- hosts: localhost
gather_facts: false
connection: local
tasks:
- name: "Execute"
include_role:
name: 'fusion'
main.yaml from fusion role:
- name: "hc fusion"
include_tasks: "hc_fusion.yaml"
hc_fusion.yaml from fusion role:
- name: "FUSION"
shell: ansible-playbook roles/fusion/tasks/fusion.yaml --extra-vars 'fusion_ip_ha={{item.ip}} fusion_user={{item.username}} fusion_pass={{item.password}} fecha="{{fecha.stdout}}" fusion_ansible_become_user={{item.ansible_become_user}} fusion_ansible_become_pass={{item.ansible_become_pass}}'
fusion.yaml from fusion role:
- hosts: localhost
vars:
ansible_become_user: "{{fusion_ansible_become_user}}"
ansible_become_pass: "{{fusion_ansible_become_pass}}"
tasks:
- name: Validate
ignore_unreachable: yes
shell: service had status
delegate_to: "{{fusion_user}}#{{fusion_ip_ha}}"
become: True
become_method: su
This is a summary of the entire run.
Previously it worked but throws the following error.
stdout: PLAY [localhost] \nTASK [Validate] [1;31mfatal: [localhost -> gandalf#10.66.173.14]: UNREACHABLE! => {\"changed\": false, \"msg\": \"Failed to connect to the host via ssh: Warning: Permanently added '10.66.173.14' (RSA) to the list of known hosts.\ngandalf#10.66.173.14: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password), \"skip_reason\": \"Host localhost is unreachable\"
When I execute ansible-playbook roles/fusion/tasks/fusion.yaml --extra-vars XXXXXXXX from the command line with user awx it works.
Also I validated the connection from the server where ansible tower is running to where you want to connect with the ssh command and if it allows me to connect without requesting a password with the user awx
fusion.yaml does not explicitly specify connection plugin, thus default ssh type is being used. For localhost this approach usually brings a number of related problems (ssh keys, known_hosts, loopback interfaces etc.). If you need to run tasks on localhost you should define connection plugin local just like in your report.yaml playbook.
Additionally, as Zeitounator mentioned, running one ansible playbook from another with shell model is a really bad practice. Please, avoid this. Ansible has a number of mechanism for code re-use (includes, imports, roles etc.).
I have a requirement to setup an application and for that I need to install Nginx as root and then run another Java application as a different application user.
The condition for this is, I have a privileged user "priv_suer" which has sudo and I'm running the playbook as this user as I need to install and configure Nginx. But my application user is different from this user "app_user" which is unprivileged application only user.
The issue I'm facing is, this app_user needs password to become app_user. So in my case I need two passwords one is to become root and another one to become app_user.
I referred Understanding privilege escalation: become and only option I could find was "ansible_become_password".
Can anyone help me with this?
I think that privilege escalation can help. My solution is:
Declare different groups for servers running your Java applications and servers you want to install Nginx. In your case, the two groups can share the same servers.
Here below I give an example of inventory.yml file:
all:
children:
app:
hosts:
127.0.0.1:
vars:
ansible_become_pass: app_user#123
ansible_python_interpreter: /usr/bin/python3
ansible_user: app_user
nginx:
hosts:
127.0.0.1:
vars:
ansible_become_pass: root#123
ansible_python_interpreter: /usr/bin/python3
ansible_user: root
An example of playbook is as follow:
- hosts: app
tasks:
- name: Install Java app
become: yes
- hosts: nginx
tasks:
- name: Install NGINX
become: yes
Finally, run your ansible playbook with an inventory provided using -i option:
ansible-playbook -i etc/ansible/inventory.yml etc/ansible/playbook.yml
I'm looking to create a playbook on ansible to gather info of more than 300 hosts and save the info to a file. I get 2 diffente issues, one not being able to save the info to a file and the second issue comes because of telnet connection of some hosts, only working for ssh hosts.
ansible 2.9.3
under vm CentOS7
Already tried:
- name: "[SCAN][IOS] IOS play for scanning facts"
hosts: CISCO
connection: network_cli
ignore_errors: true
ignore_unreachable: true
vars:
ansible_network_os: ios
gather_facts: False
tasks:
- name: run show logging host ip on remote devices
ios_command:
commands: show run | i logging host
register: output
- debug:
var: output["stdout_lines"]
This playbook shows the ssh hosts results according to the configuration required, but I'm not able to save this info to a file.
On the other hand I would like to run this commands on telnet hosts, is it possible to run this in both connection types together and save to file?
I'm starting out with ansible and I'm looking for a way to create a boilerplate project on the server and on the local environment with ansible playbooks.
I want to use ansible templates locally to create some generic files.
But how would i take ansible to execute something locally?
I read something with local_action but i guess i did not get this right.
This is for the webbserver...but how do i take this and create some files locally?
- hosts: webservers
remote_user: someuser
- name: create some file
template: src=~/workspace/ansible_templates/somefile_template.j2 dest=/etc/somefile/apps-available/someproject.ini
You can delegate tasks with the param delegate_to to any host you like, for example:
- name: create some file
template: src=~/workspace/ansible_templates/somefile_template.j2 dest=/etc/somefile/apps-available/someproject.ini
delegate_to: localhost
See Playbook Delegation in the docs.
If your playbook should in general run locally and no external hosts are involved though, you can simply create a group which contains localhost and then run the playbook against this group. In your inventory:
[local]
localhost ansible_connection=local
and then in your playbook:
hosts: local
Ansible has a local_action directive to support these scenarios which avoids the localhost and/or ansible_connection workarounds and is covered in the Delegation docs.
To modify your original example to use local_action:
- name: create some file
local_action: template src=~/workspace/ansible_templates/somefile_template.j2 dest=/etc/somefile/apps-available/someproject.ini
which looks cleaner.
If you cannot do/allow localhost SSH, you can split the playbook on local actions and remote actions.
The connection: local says to not use SSH for a playbook, as shown here: https://docs.ansible.com/ansible/latest/user_guide/playbooks_delegation.html#local-playbooks
Example:
# myplaybook.yml
- hosts: remote_machines
tasks:
- debug: msg="do stuff in the remote machines"
- hosts: 127.0.0.1
connection: local
tasks:
- debug: msg="ran in local ansible machine"
- hosts: remote_machines
tasks:
- debug: msg="do more stuff in remote machines"
I've got a basic Ansible playbook like so:
---
- name: Provision ec2 servers
hosts: 127.0.0.1
connection: local
roles:
- aws
- name: Configure {{ application_name }} servers
hosts: webservers
sudo: yes
sudo_user: root
remote_user: ubuntu
vars:
- setup_git_repo: no
- update_apt_cache: yes
vars_files:
- env_vars/common.yml
- env_vars/remote.yml
roles:
- common
- db
- memcached
- web
with the following inventory:
[localhost]
127.0.0.1 ansible_python_interpreter=/usr/local/bin/python
The Provision ec2 servers task does what you'd expect. It creates an ec2 instance; it also creates a host group [webservers] and adds the created instance IP to it.
The Configure {{ application_name }} servers step then configures that server, installing everything I need.
So far so good, this all does exactly what I want and everything seems to work.
Here's where I'm stuck. I want to be able to fire up an ec2 instance for different roles. Ideally I'd create a dbserver, a webserver and maybe a memcached server. I'd like to be able to deploy any part(s) of this infrastructure in isolation, e.g. create and provision just the db servers
The only ways I can think of to make this work... well, they don't work.
I tried simply declaring the host groups without hosts in the inventory:
[webservers]
[dbservers]
[memcachedservers]
but that's a syntax error.
I would be okay with explicitly provisioning each server and declaring the host group it is for, like so:
- name: Provision webservers
hosts: webservers
connection: local
roles:
- aws
- name: Provision dbservers
hosts: dbservers
connection: local
roles:
- aws
- name: Provision memcachedservers
hosts: memcachedservers
connection: local
roles:
- aws
but those groups don't exist until after the respective step is complete, so I don't think that will work either.
I've seen lots about dynamic inventories, but I haven't been able to understand how that would help me. I've also looked through countless examples of ansible ec2 provisioning projects, they are all invariably either provisioning pre-existing ec2 instances, or just create a single instance and install everything on it.
In the end I realised it made much more sense to just separate the different parts of the stack into separate playbooks, with a full-stack playbook that called each of them.
My remote hosts file stayed largely the same as above. An example of one of the playbooks for a specific part of the stack is:
---
- name: Provision ec2 apiservers
hosts: apiservers #important bit
connection: local #important bit
vars:
- host_group: apiservers
- security_group: blah
roles:
- aws
- name: Configure {{ application_name }} apiservers
hosts: apiservers:!127.0.0.1 #important bit
sudo: yes
sudo_user: root
remote_user: ubuntu
vars_files:
- env_vars/common.yml
- env_vars/remote.yml
vars:
- setup_git_repo: no
- update_apt_cache: yes
roles:
- common
- db
- memcached
- web
This means that the first step of each layer's play adds a new host to the apiservers group, with the second step (Configure ... apiservers) then being able to exclude the localhost without getting a no hosts matching error.
The wrapping playbook is dead simple, just:
---
- name: Deploy all the {{ application_name }} things!
hosts: all
- include: webservers.yml
- include: apiservers.yml
I'm very much a beginner w/regards to ansible, so please do take this for what it is, some guy's attempt to find something that works. There may be better options and this could violate best practice all over the place.
ec2_module supports an "exact_count" property, not just a "count" property.
It will create (or terminate!) instances that match specified tags ("instance_tags")