Bookmark this page

Guided Exercise: Performing Rolling Configuration Updates

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

  1. Open the /home/student/network-rolling directory in VS Code and review the junos_config_update.yml playbook.

    1. Open VS Code and navigate to FileOpen Folder.

    2. Navigate to Homenetwork-rolling and click Open.

      Note

      If prompted, select Trust the authors of all files in the parent folder 'student', and then click Yes, I trust the authors.

    3. 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.yml
  2. The 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

    DescriptionValue
    Filter term name permit_igmp
    Action to take permit
    Protocol igmp
    Source address 172.25.250.100/32

    Table 7.2. Second ACE

    DescriptionValue
    Filter term name bgp_12
    Source addresses

    12.0.0.0/16

    12.1.0.0/16

    Source port protocol bgp
    Protocol tcp

    Table 7.3. Third ACE

    DescriptionValue
    Filter term name allow_ssh
    Source port protocol ssh
    Protocol tcp

    Note

    To review the documentation for the junipernetworks.junos.junos_acls resource module, run the ansible-navigator doc junipernetworks.junos.junos_acls -m stdout command.

    1. In VS Code, right-click the tasks folder and select New File. Enter junos_acl_config.yml as the file name.

    2. 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:
    3. 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/32
    4. Add 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: tcp
    5. Add 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: tcp
    6. Add 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: ipv4
  3. The 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.

    1. 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: false
        vars_files:
          - acls.yml
        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.yml
    2. 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']
  4. 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.

    1. 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...

      Important

      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.

    2. 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...
    3. 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.yml
  5. Run 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.

    1. Switch to the Terminal 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]$
    2. Use the ansible-navigator command to run the playbook:

      [student@workstation network-rolling]$ ansible-navigator run \
      junos_config_update.yml
      
      PLAY [Update Juniper Junos managed nodes to use new ACLs] ************************
      
      TASK [Enable the NETCONF service] ************************************************
      changed: [junos1.lab.example.com] 1
      
      TASK [Juniper Junos ACL configuration] *******************************************
      
      ...output omitted...
      
      TASK [Assert that ACLs were correctly configured] ********************************
      fatal: [junos1.lab.example.com]: FAILED! => { 2
          "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 ...

      1

      The playbook starts running only against one managed node in the junos inventory group.

      2

      The Assert that ACLs were correctly configured task failed to run against the junos1.lab.example.com managed node. This failure is enough to abort the play.

    3. 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...
  6. 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.

    Note

    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.

    1. 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...
    2. Use the ansible-navigator command to run the playbook:

      [student@workstation network-rolling]$ ansible-navigator run \
      junos_config_update.yml
      
      PLAY [Update Juniper Junos managed nodes to use new ACLs] ************************
      
      TASK [Enable the NETCONF service] ************************************************
      ok: [junos1.lab.example.com] 1
      
      ...output omitted...
      
      TASK [Assert that ACLs were correctly configured] ********************************
      ok: [junos1.lab.example.com] => { 2
          "changed": false,
          "msg": "All assertions passed"
      }
      
      PLAY [Update Juniper Junos managed nodes to use new ACLs] ******************** 3
      
      ...output omitted...
      
      TASK [Assert that ACLs were correctly configured] ********************************
      ok: [junos2.lab.example.com] => { 4
          "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 ...

      1

      They playbook runs against one managed node.

      2

      This time the configuration on the managed node is as expected.

      3

      The Update Juniper Junos managed nodes to use new ACLs play starts running on the next batch of managed nodes.

      4

      The classroom environment only has two managed nodes in the junos inventory group, so the play now runs against the junos2.lab.example.com managed node.

  7. Close the /home/student/network-rolling directory in VS Code. If you are using the GNOME terminal, return to the /home/student directory.

    1. Click FileClose Folder in VS Code to close the /home/student/network-rolling directory.

    2. If you are using the GNOME terminal, run the cd command to return to the student home directory:

      [student@workstation network-rolling]$ cd

Finish

On the workstation machine, use the lab command to complete this exercise. This step is important to ensure that resources from previous exercises do not impact upcoming exercises.

[student@workstation ~]$ lab finish network-rolling

Revision: do457-2.3-7cfa22a