Perform rolling configuration changes to ACLs on managed nodes, and automatically recover from any errors.
Outcomes
Control the process that updates the Access Control Lists (ACLs) on configured network devices by processing the update in multiple batches, rather than updating all devices at once.
As the student user on the workstation machine, use the lab command to prepare your system for this exercise, and to ensure that all required resources are available.
This command also creates a project directory with the files needed for the exercise.
[student@workstation ~]$ lab start network-rolling
Instructions
Open the /home/student/network-rolling directory in VS Code and review the junos_config_update.yml playbook.
Open VS Code and navigate to → .
Navigate to → and click .
If prompted, select , and then click .
Select the junos_config_update.yml playbook.
The playbook aims to perform an update of the Access Control Lists (ACLs) on the Juniper Junos managed nodes.
---
- name: Update Juniper Junos managed nodes to use new ACLs
hosts: junos
gather_facts: false
tasks:
- name: Juniper NETCONF configuration
ansible.builtin.import_tasks: tasks/junos_netconf_enable.yml
- name: Juniper Junos ACL configuration
ansible.builtin.import_tasks: tasks/junos_acl_config.ymlThe task in the tasks/junos_acl_config.yml file updates the ACLs, but that file does not exist yet.
Use VS Code to create the tasks/junos_acl_config.yml file and then use the junipernetworks.junos.junos_acls module to configure ACLs with the following characteristics:
The Juniper Junos managed nodes must have a single Access Control List (ACL) named junos_acl.
The ACL must use the ipv4 protocol family.
The ACL must have the following list of Access Control Entries (ACEs):
Table 7.1. First ACE
| Description | Value |
|---|---|
| Filter term name |
permit_igmp
|
| Action to take |
permit
|
| Protocol |
igmp
|
| Source address |
172.25.250.100/32
|
Table 7.2. Second ACE
| Description | Value |
|---|---|
| Filter term name |
bgp_12
|
| Source addresses |
|
| Source port protocol |
bgp
|
| Protocol |
tcp
|
Table 7.3. Third ACE
| Description | Value |
|---|---|
| Filter term name |
allow_ssh
|
| Source port protocol |
ssh
|
| Protocol |
tcp
|
To review the documentation for the junipernetworks.junos.junos_acls resource module, run the ansible-navigator doc junipernetworks.junos.junos_acls -m stdout command.
In VS Code, right-click the tasks folder and select .
Enter junos_acl_config.yml as the file name.
Edit the tasks/junos_acl_config.yml file so that it contains a task named Juniper Junos ACL configuration that uses the junipernetworks.junos.junos_acls module.
Start the dictionary of ACLs with one ACL named junos_acl, and use the ace parameter to start listing the ACEs:
---
- name: Juniper Junos ACL configuration
junipernetworks.junos.junos_acls:
state: merged
config:
- acls:
- name: junos_acl
aces:Add the first Access Control Entry (ACE) using the details in the "First ACE" table. Pay attention to the indentation for each level:
The name, grant, protocol, and source parameters have the same level of indentation.
The address of the source given by the address parameter must be indented two spaces more than the source parameter.
---
- name: Juniper Junos ACL configuration
junipernetworks.junos.junos_acls:
state: merged
config:
- acls:
- name: junos_acl
aces:
- name: permit_igmp
grant: permit
protocol: igmp
source:
address: 172.25.250.100/32Add the second ACE using the details in the "Second ACE" table. Pay attention to the indentation for each level:
The name, source, and protocol parameters have the same level of indentation.
The list of addresses of the source given by the address parameter must be indented at least as much as the address parameter.
This file indents the list by an extra two spaces.
The address parameter must be indented two spaces more than the source parameter.
The source port protocol given by the eq parameter must be indented two spaces more than the port_protocol parameter.
The port_protocol parameter must be indented two spaces more than the source parameter.
---
- name: Juniper Junos ACL configuration
junipernetworks.junos.junos_acls:
state: merged
config:
- acls:
- name: junos_acl
aces:
- name: permit_igmp
grant: permit
protocol: igmp
source:
address: 172.25.250.100/32
- name: bgp_12
source:
address:
- 12.0.0.0/16
- 12.1.0.0/16
port_protocol:
eq: bgp
protocol: tcpAdd the third ACE using the details in the "Third ACE" table. Pay attention to the indentation for each level:
The name, source, and protocol parameters have the same level of indentation.
The source port protocol given by the eq parameter must be indented two spaces more than the port_protocol parameter.
The port_protocol parameter must be indented two spaces more than the source parameter.
---
- name: Juniper Junos ACL configuration
junipernetworks.junos.junos_acls:
state: merged
config:
- acls:
- name: junos_acl
aces:
- name: permit_igmp
grant: permit
protocol: igmp
source:
address: 172.25.250.100/32
- name: bgp_12
source:
address:
- 12.0.0.0/16
- 12.1.0.0/16
port_protocol:
eq: bgp
protocol: tcp
- name: allow_ssh
source:
port_protocol:
eq: ssh
protocol: tcpAdd the afi parameter to the junos_acl ACL with a value of ipv4.
The indentation is the same as the acls parameter.
---
- name: Juniper Junos ACL configuration
junipernetworks.junos.junos_acls:
state: merged
config:
- acls:
- name: junos_acl
aces:
- name: permit_igmp
grant: permit
protocol: igmp
source:
address: 172.25.250.100/32
- name: bgp_12
source:
address:
- 12.0.0.0/16
- 12.1.0.0/16
port_protocol:
eq: bgp
protocol: tcp
- name: allow_ssh
source:
port_protocol:
eq: ssh
protocol: tcp
afi: ipv4The junos_config_update.yml playbook is ready to configure the ACLs on the managed nodes.
Add a task to the playbook to verify that the managed nodes have the expected ACL configuration.
Take the value of the acl_config variable, which you can find in the acls.yml variables file, as the ACL's configuration that is expected on the managed nodes.
Edit the junos_config_update.yml playbook in VS Code.
Add the acls.yml variables file to the play, and then add a third task named Assert that ACLs were correctly configured that imports the tasks/junos_acl_verify.yml tasks file:
--- - name: Update Juniper Junos managed nodes to use new ACLs hosts: junos gather_facts: falsevars_files:- acls.ymltasks: - name: Juniper NETCONF configuration ansible.builtin.import_tasks: tasks/junos_netconf_enable.yml - name: Juniper Junos ACL configuration ansible.builtin.import_tasks: tasks/junos_acl_config.yml- name: Assert that ACLs were correctly configuredansible.builtin.import_tasks: tasks/junos_acl_verify.yml
Create the tasks/junos_acl_verify.yml file with two tasks:
The first task uses the junipernetworks.junos.junos_acls module to gather the ACL configuration from the managed nodes.
This collected configuration is the one the managed nodes have after the ACL configuration task finishes.
The second task uses the ansible.builtin.assert module to verify that the collected configuration is as expected.
If the collected configuration differs from the expected configuration, then the task fails.
---
- name: Gather Junos ACL configuration
junipernetworks.junos.junos_acls:
state: gathered
register: result
- name: Assert that ACLs were correctly configured
ansible.builtin.assert:
that: acl_config == result['gathered']The junos_config_update.yml playbook runs against all the managed nodes in the junos inventory group.
You want to be sure that the change is the expected configuration before applying the change to all the managed nodes.
To mitigate the effects of unforeseen deployment errors, configure the play to run in batches.
The first batch must contain one managed node. If a task in the play fails, Ansible must stop the play for the remaining managed nodes.
The second batch must contain 25% of the managed nodes.
The third batch must contain the remaining managed nodes.
Also implement a "fail fast" strategy to ensure that the playbook execution stops if any managed node fails a task.
Edit the junos_config_update.yml playbook in VS Code.
Use the serial directive to process the managed nodes in three batches:
---
- name: Update Juniper Junos managed nodes to use new ACLs
hosts: junos
gather_facts: false
vars_files:
- acls.yml
serial:
- 1
- 25%
- 100%
tasks:
...output omitted...The lab environment in this course only has two Juniper Junos managed nodes in the junos inventory group, so this strategy is hypothetical, something that you could implement in your real environment.
With this strategy in the course lab environment, the play runs against one of the managed nodes, and if successful, then it runs against the other.
Add the max_fail_percentage directive to the play with a value of 0 to implement a "fail fast" strategy that stops the execution of the play at any failure:
---
- name: Update Juniper Junos managed nodes to use new ACLs
hosts: junos
gather_facts: false
vars_files:
- acls.yml
max_fail_percentage: 0
serial:
- 1
- 25%
- 100%
tasks:
...output omitted...The complete junos_config_update.yml playbook must consist of the following content:
---
- name: Update Juniper Junos managed nodes to use new ACLs
hosts: junos
gather_facts: false
vars_files:
- acls.yml
max_fail_percentage: 0
serial:
- 1
- 25%
- 100%
tasks:
- name: Juniper NETCONF configuration
ansible.builtin.import_tasks: tasks/junos_netconf_enable.yml
- name: Juniper Junos ACL configuration
ansible.builtin.import_tasks: tasks/junos_acl_config.yml
- name: Assert that ACLs were correctly configured
ansible.builtin.import_tasks: tasks/junos_acl_verify.ymlRun the junos_config_update.yml playbook to update the ACLs.
The playbook fails.
Increase the output verbosity of the ansible-navigator command to provide detailed task execution information of the failure.
Switch to the tab in VS Code, or change to the /home/student/network-rolling directory in a GNOME terminal:
[student@workstation ~]$ cd ~/network-rolling [student@workstation network-rolling]$
Use the ansible-navigator command to run the playbook:
[student@workstation network-rolling]$ansible-navigator run \junos_config_update.ymlPLAY [Update Juniper Junos managed nodes to use new ACLs] ************************ TASK [Enable the NETCONF service] ************************************************ changed: [junos1.lab.example.com]TASK [Juniper Junos ACL configuration] ******************************************* ...output omitted... TASK [Assert that ACLs were correctly configured] ******************************** fatal: [junos1.lab.example.com]: FAILED! => {
"assertion": "acl_config == result['gathered']" "changed": false, "evaluated_to": false, "msg": "Assertion failed" } NO MORE HOSTS LEFT *************************************************************** ...output omitted... PLAY RECAP *********************************************************************** junos1.lab.example.com : ok=3 changed=2 unreachable=0 failed=1 ...
Use the ansible-navigator command to run the playbook again.
This time increase the output verbosity by using the -vvv option.
Notice that the gathered ACL configuration on the managed node contains an ACL called bgp_13_acl in addition to the new junos_acl ACL.
The Assert that ACLs were correctly configured task in the tasks/junos_acl_verify.yml file fails because the acl_config variable does not contain the additional ACL.
[student@workstation network-rolling]$ansible-navigator run \junos_config_update.yml -vvv...output omitted... "gathered": [ { "acls": [ { "aces": [ { "name": "bgp_13", "protocol": "tcp", "source": { "address": "13.0.0.0/16", "port_protocol": { "eq": "bgp" } } } ],"name": "bgp_13_acl"}, { "aces": [ { "grant": "permit", "name": "permit_igmp", "protocol": "igmp", "source": { "address": "172.25.250.100/32" } }, { "name": "bgp_12", "protocol": "tcp", "source": { "address": [ "12.0.0.0/16", "12.1.0.0/16" ], "port_protocol": { "eq": "bgp" } } }, { "name": "allow_ssh", "protocol": "tcp", "source": { "port_protocol": { "eq": "ssh" } } } ],"name": "junos_acl"} ], "afi": "ipv4" } ], ...output omitted...
At this point you can restore any backup that you have made of the managed node before running the junos_config_update.yml playbook, send a notification about the failed deployment, and so on.
Because you want the expected ACL updated configuration in the complete junos group of managed nodes, modify your playbook to fix the issue.
You can fix the issue in more than one way. For example, you can back up the existing configuration on the managed node, delete the configuration, and then generate a new configuration.
For this guided exercise, you modify the playbook to override the managed node configuration with the configuration provided in the task.
Modify the Juniper Junos ACL configuration task in the tasks/junos_acl_config.yml file so that the task overrides the current ACL configuration instead of merging it:
---
- name: Juniper Junos ACL configuration
junipernetworks.junos.junos_acls:
state: overridden
config:
- acls:
- name: junos_acl
aces:
...output omitted...Use the ansible-navigator command to run the playbook:
[student@workstation network-rolling]$ansible-navigator run \junos_config_update.ymlPLAY [Update Juniper Junos managed nodes to use new ACLs] ************************ TASK [Enable the NETCONF service] ************************************************ ok: [junos1.lab.example.com]...output omitted... TASK [Assert that ACLs were correctly configured] ******************************** ok: [junos1.lab.example.com] => {
"changed": false, "msg": "All assertions passed" } PLAY [Update Juniper Junos managed nodes to use new ACLs] ********************
...output omitted... TASK [Assert that ACLs were correctly configured] ******************************** ok: [junos2.lab.example.com] => {
"changed": false, "msg": "All assertions passed" } PLAY RECAP *********************************************************************** junos1.lab.example.com : ok=4 changed=1 unreachable=0 failed=0 ... junos2.lab.example.com : ok=4 changed=2 unreachable=0 failed=0 ...
They playbook runs against one managed node. | |
This time the configuration on the managed node is as expected. | |
The | |
The classroom environment only has two managed nodes in the |
Close the /home/student/network-rolling directory in VS Code.
If you are using the GNOME terminal, return to the /home/student directory.
Click → in VS Code to close the /home/student/network-rolling directory.
If you are using the GNOME terminal, run the cd command to return to the student home directory:
[student@workstation network-rolling]$ cd