Task 4. Create an ansible role¶
1. Create the Role Structure¶
Use the init command to initialize the base structure of a new role, saving time on creating the various directories and main.yml files a role requires
$ ansible-galaxy init username.lbsvc --offline - username.lbsvc was created successfully
You should then have the framework for your role:
$ ls -R username.lbsvc/ username.lbsvc/: README.md defaults files handlers meta tasks templates tests vars username.lbsvc/defaults: main.yml username.lbsvc/files: username.lbsvc/handlers: main.yml username.lbsvc/meta: main.yml username.lbsvc/tasks: main.yml username.lbsvc/templates: username.lbsvc/tests: inventory test.yml username.lbsvc/vars: main.yml
2. Create the Role Variables¶
In the defaults/main.yml file, copy the following content:
---
username: "admin"
password: "supernetops"
app_name: "myAppTask4"
pool_name: "{{ app_name }}_pool"
redirect_port: "80"
vip_ip: "10.1.20.101"
vip_port: "443"
pool_members:
- port: "9081"
host: "10.1.10.20"
- port: "9082"
host: "10.1.10.20"
- port: "9083"
host: "10.1.10.20"
This is the key/value pairs variables to use in your role. here, variables are passed to the defaults folder. In the existing fch.run_docker role, variables are passed to the vars folder. Both solutions are valid depending on what you want to achieve and the precedence
Note:¶
- If multiple variables of the same name are defined in different places, they win in a certain order, which is:
- extra vars (-e in the command line) always win
- then comes connection variables defined in inventory (ansible_ssh_user, etc)
- then comes “most everything else” (command line switches, vars in play, included vars, role vars, etc)
- then comes the rest of the variables defined in inventory
- then comes facts discovered about a system
- then “role defaults”, which are the most “defaulty” and lose in priority to everything.
https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html#variable-precedence-where-should-i-put-a-variable
3. Create the Role Tasks¶
Copy/paste the following tasks in your tasks/main.yml file:
---
- name: Create nodes
bigip_node:
server: "{{ inventory_hostname }}"
user: "{{ username }}"
password: "{{ password }}"
host: "{{item.host}}"
name: "{{item.host}}"
validate_certs: False
with_items: "{{pool_members}}"
delegate_to: localhost
- name: Create pool
bigip_pool:
server: "{{ inventory_hostname }}"
user: "{{ username }}"
password: "{{ password }}"
name: "{{pool_name}}"
lb_method: "round-robin"
monitors: "/Common/http"
validate_certs: False
delegate_to: localhost
- name: Add Pool members
bigip_pool_member:
server: "{{ inventory_hostname }}"
user: "{{ username }}"
password: "{{ password }}"
name: "{{item.host}}"
host: "{{item.host}}"
port: "{{item.port}}"
pool: "{{pool_name}}"
validate_certs: False
with_items: "{{pool_members}}"
delegate_to: localhost
- name: Add Virtual Server
bigip_virtual_server:
server: "{{ inventory_hostname }}"
user: "{{ username }}"
password: "{{ password }}"
name: "{{ app_name }}_vs_https"
destination: "{{ vip_ip }}"
port: "{{ vip_port }}"
all_profiles:
- http
- name: clientssl
context: client-side
pool: "{{pool_name}}"
snat: "automap"
validate_certs: False
delegate_to: localhost
- name: Add Redirect Virtual Server
bigip_virtual_server:
server: "{{ inventory_hostname }}"
user: "{{ username }}"
password: "{{ password }}"
name: "{{ app_name }}_vs_http_redirect"
destination: "{{ vip_ip }}"
port: "80"
all_profiles:
- http
irules:
- "_sys_https_redirect"
validate_certs: False
delegate_to: localhost
4. (Optional)Create your role meta file¶
This is mainly for documentation, and to help you find the best role for reuse. The file to edit is ./meta/main.yml :
galaxy_info:
author: <Your name>
company: <Your Company
license: license (GPLv2, CC-BY, etc)
min_ansible_version: 2.5
platforms:
- name: Ubuntu
versions:
- all
categories:
- ….
galaxy_tags:
- bigip
- networking
- selfip
- bigip
- F5
5. Securing sensitive information¶
Keeping passwords in clear text in probably the worst thing we have done yet :( Let’s secure it using ansible vault (https://docs.ansible.com/ansible/2.4/vault.html). “Vault” is a feature of ansible that allows keeping sensitive data such as passwords or keys in encrypted files, rather than as plaintext in your playbooks or roles. These vault files can then be distributed or placed in source control.
The default and easiest way is to encrypt the whole variable file and ask for the vault password when running the playbook. As of version 2.3, Ansible also supports encrypting single values inside a YAML file, using the !vault tag to let YAML and Ansible know it uses special processing. This feature is covered in more details below.
The ansible-vault encrypt_string command will encrypt and format a provided string into a format that can be included in ansible-playbook YAML files.
To encrypt your admin password as a cli arg, you need to provide a Vault password (you can put anything as soon as you remember it as You will need to unlock your vault several times in the upcoming tasks):
$ ansible-vault encrypt_string 'supernetops' --name 'password'
New Vault password:
Confirm New Vault password:
password: !vault |
$ANSIBLE_VAULT;1.1;AES256
38623963623565303065613262316437313830643032336364663938383238343864623661633264
3730396430336332623563303861616632633630376139300a326664356235373565363138323533
61626537336361633464636135393864616332376231363137643732666563303739323438633266
3864663163643433390a333132643562663034393862383861616635666335313032663638663937
6665
Encryption successful
Then replace the password line in your defaults/main.yml file
username: "admin"
password: "supernetops"
…
by the encrypted string previously generated:
username: "admin"
password: !vault |
$ANSIBLE_VAULT;1.1;AES256
38623963623565303065613262316437313830643032336364663938383238343864623661633264
3730396430336332623563303861616632633630376139300a326664356235373565363138323533
61626537336361633464636135393864616332376231363137643732666563303739323438633266
3864663163643433390a333132643562663034393862383861616635666335313032663638663937
6665
Finally copy your role to /etc/ansible/roles:
$ sudo cp -R **username**.lbsvc /etc/ansible/roles/
Running your playbook:¶
create a playbook called /tmp/task4.yml and paste the following content (be sure your rename username.lbsvc with your username):
---
- name: Configure http service
hosts: production:&bigip
gather_facts: false
roles:
- { role: username.lbsvc }
then run your playbook:
$ ansible-playbook /tmp/task4.yml --ask-vault-pass -vvv
you can check on your BigIP the service have been created.
You can easily run the same role to add pool members to the configuration (remember: F5 ansible playbooks are idempotent):
$ ansible-playbook /tmp/task4.yml --ask-vault-pass --extra-vars 'pool_members=[{"port":"9084","host":"10.1.10.20"},{"port":"9085","host":"10.1.10.20"}]'
or run the same playbook for a new service without touching the playbook YAML file:
$ ansible-playbook /tmp/task4.yml --ask-vault-pass --extra-vars 'pool_members=[{"port":"9082","host":"10.1.10.20"},{"port":"9081","host":"10.1.10.20"}] app_name="my2ndApp_task4" vip_ip="10.1.20.102"'
You can run it as many time as you want as it is… did I already told you about idempotency?