²©ñRŠÊ˜·³Ç

Network Automation

Date: Dec 20, 2020 By . Sample Chapter is provided courtesy of .

In this sample chapter from 31 Days Before Your CCNP and CCIE Enterprise Core Exam, you will review network configuration management tools such as Puppet, Chef, Ansible, and SaltStack.

ENCOR 350-401 Exam Topics

Key Topics

Today we review network configuration management tools such as Puppet, Chef, Ansible, and SaltStack. As you saw yesterday, scripting can help you gather data or modify configurations. In addition, while you can use a language such as Python to perform manual programming, there are also tools you can use specifically for configuration automation and network management.

Today we also look at the Cisco IOS Embedded Event Manager (EEM), which is a unique subsystem in Cisco IOS Software. EEM is a powerful and flexible tool for automating tasks and customizing the behavior of Cisco IOS Software and the operation of a device.

Configuration Management Tools

A configuration management tool may require an agent, which is a piece of software that must be installed on the system or device you want to manage. In a network automation use case, this requirement could be problematic because some network devices cannot support running agents and loading general software. In a situation where the network devices do not support an agent, you can use a tool that supports proxy agents or a tool that does not require agents at all.

There are two core types of configuration management tools, and there is also a third type that is usually a derivation of an agent-based tool:

  • Agent-based configuration: With agent-based tools, an agent must be installed on every device that the configuration management tool will manage.

  • Agentless configuration: Agentless tools do not require that an agent be installed on every device; instead, they communicate via SSH or another API that a device supports.

  • Proxy-agent configuration: This type of configuration does not require an agent on every device, but it does require some type of “process” or “worker” to communicate with the master server and the remote device.

Configuration management tools define target end states and allow maximum flexibility to automate 1 device or 10,000 devices. For example, you might want to ensure that your networking devices have the latest version of their software. When you describe what you want to automate in a configuration management tool, you often use a domain-specific language (DSL) or a structure markup language such as YAML. A DSL is a language that is designed specifically to express solutions to problems in a particular domain; in other words, DSLs are special-purpose computer languages and limited compared to a language such as Python or Ruby, which are general-purpose languages.

Some of the benefits of using configuration management tools are fast implementation, lower failure rates, shortened times between fixes, and, importantly, faster user adoption for nonprogrammers. Using these tools also brings the networking environment close to the concept of continuous delivery. It enables infrastructure as code (IaC), which is the idea of writing software for the infrastructure so you can deploy the entire environment by leveraging code rather than manually defining all parameters, which makes it a programmable infrastructure.

From a networking perspective, it is common to deploy changes manually. As an example of changes, you might add a VLAN across a data center or campus, or you might make daily changes to firewall policies for new applications that are deployed. When there is a defined manual workflow to perform a set of tasks, proper tools should be used to automate it. It does not make sense to spend an hour performing a change when it could take just a few minutes to make the change by using a properly engineered tool. Tools such as Puppet, Chef, Ansible, and SaltStack can dramatically reduce the number of manual interactions in a network.

Configuration management tools are often referred to as DevOps tools. Organizations that have implemented some form of DevOps practices use these configuration management and automation tools to automate application, infrastructure, and network deployments to a high degree without the need to do manual programming using a language such as Python. These tools reduce the time it takes to perform certain tasks and offer greater predictability.

Configuration Management for Networking

Puppet, which was created in 2005, has been in use longer than Chef and Ansible. Puppet manages systems in a declarative manner, which means you define an ideal state of the target system without worrying about how it happens. (In reality, this is the approach that all these tools take.) Puppet is written in Ruby and refers to its automation instruction set as Puppet manifests. The major point to realize is that Puppet is agent based.

As mentioned earlier, agent based means that a software agent must be installed on all devices that you want to manage with Puppet, including servers, routers, switches, and firewalls. It is often impossible to load an agent on every network device, so the number of devices that can be used with a new Puppet package is limited. This can be remedied thanks to the use of Puppet proxy devices. Regardless, this means that Puppet has a greater barrier to entry when getting started.

Chef, another popular configuration management tool, follows much the same model as Puppet. Chef is based in Ruby, uses a declarative model, is agent based, and refers to the Chef automation instruction as recipes (groups of which are called cookbooks).

It is often difficult to load agents onto all machines to automate them. However, even when it is technically possible to do so, deploying the solution or tool can be time-consuming. Ansible was created as an agentless alternative to Puppet and Chef. Red Hat acquired Ansible in 2015, and IBM more recently acquired Red Hat. Being natively agentless significantly lowers the barrier to entry from an automation perspective. Because Ansible is agentless, it can integrate and automate a device by using an API. For example, integrations can use REST APIs, Network Configuration Protocol (NETCONF), SSH, or even Simple Network Management Protocol (SNMP), if desired. A playbook is a set of Ansible tasks (instructions) that is used to automate devices. Each playbook consists of one or more plays, each of which consists of individual tasks. Ansible is written in Python.

It is worth noting that each of these tools had its start in automation for applications and cloud infrastructure. It was not until each of them had a significant amount of traction in the market that they started to include network automation in their portfolios.

Salt, by SaltStack, is an agent-based configuration management and orchestration tool that is similar to Puppet and Chef. Each Salt-managed node must have a Salt minion service installed. Usually, this approach is not an issue on a server, but in the networking world, it is not always possible to install custom software on the network equipment that you want to manage. To solve this problem with Salt, you can use a proxy minion, which is basically a minion that does not need to be installed on the targeted device and can run ubiquitously. In other words, proxy minions run intermediate software that mediates between the Salt master and the Salt minion. The Salt master is a master daemon that is used for sending configurations and commands to the Salt minions. The Salt master is basically a machine that manages the infrastructure and dictates policies. Salt minions receive the configuration and commands from the master daemon. It is the responsibility of Salt minions to execute the instructions sent by the Salt master, report job success, and provide data related to the underlying host.

Salt is written in Python, and it uses a message queue–based system called ZeroMQ to push commands and configuration to minions. It also allows for publish and subscribe messaging.

Figure 3-1 compares these three configuration management tools. Notice the relationships of the different deployment models: agent based, agentless, and hybrid.

Next we look at each of these tools in more detail.

System Management with Ansible

Ansible is open-source provisioning software that allows for centralized configuration management. Ansible was originally written by Michael DeHann of AnsibleWorks, which was acquired by Red Hat in 2015. Red Hat in turn was acquired by IBM in 2019. Ansible is free and open source and is included as part of Fedora. It is also available for RHEL, CentOS, Scientific Linux, and other operating systems through their respective package management systems or the Python package management tool pip.

Unlike other management platforms and services, Ansible does not require an agent to be installed on the system that it manages, nor does Ansible need or use a centralized controller for configuration management. It is possible to perform automation from any management system by referencing inventories, modules, or playbooks.

Its declarative approach means that you only tell Ansible what you want to achieve as a final goal instead of encoding all instructions to reach it. For example, you do not have to tell Ansible where a specific service resides, how to start it, and what to do after it starts. You simply say, “I want this service to be started, and then I want another service to be restarted.”

System Management with Ansible: Components

The components of Ansible come together to make a very powerful management system. Understanding each component and the relationships between the components is essential to realizing their power:

  • Ansible control station is the management station and launching point for all Ansible activities. Unlike many other management platforms, Ansible does not require a dedicated server or elaborate hardware to manage an environment. You could literally manage an enterprise from your personal laptop.

  • ▪ An Ansible module is a standalone collection of commands that is written in a standard scripting language (for example, Python) and used to execute a state change. An administrator can write an Ansible module using any language that supports the JavaScript Object Notation (JSON) data format.

  • Playbooks are files that are used to define the desired or final state and also used to orchestrate operation across multiple nodes.

  • Inventory files contain systems managed by Ansible. An administrator uses an inventory file to group managed systems. Inventory files can be dynamically built by contacting a remote API that responds with a valid JSON response.

  • YAML files are commonly referred to as configuration files and destinations for data being stored. Ultimately, YAML is a data format that is transported over Secure Shell (SSH) by default and with PowerShell support for Windows nodes over the WS-Management protocol.

  • Ansible Tower is a web service console (GUI) that follows the REST standard for programmability. It is a licensed product from Red Hat, based on the open-source AWX Project.

System Management with Ansible: Tools

Managing Ansible is a simple process that basically involves selecting a terminal program to connect to your management server running Ansible. You can select your preferred text editor for creating and editing inventory files, playbooks, and modules, and you can use your preferred version control service to manage access to code and control collaboration and editing. Examples of these tools include PuTTY for SSH access, Visual Studio Code for configuration file management, and GitLab for storage, collaboration, and version control. All this can be done from any Linux-based machine that has Python and Ansible installed.

How Ansible Works

Working with Ansible requires only a few quick installation and update steps. Once the installation and update are complete, you can configure Ansible operations and defaults. The inventory file and modules work together to help you execute your changes to the specified target systems.

You can install Ansible in multiple ways, the easiest of which is to use Python pip. With a Python virtual environment active, execute pip install ansible, and you are done. You can then execute ansible -version to verify that the installation was successful. Many operating systems offer Ansible prepackaged in their repositories (for example, yum install ansible, apt-get install ansible). Ansible configuration files are used to configure Ansible operations. The base configuration file is located at /etc/ansible/ansible.cfg.

Inventory files enable an administrator to define an inventory of systems against which Ansible modules will be executed. The basic contents of an inventory file are hosts and groups. Host entries point to the Domain Name System (DNS) name or IP address of a managed end system, and a group is a collection of hosts under a collective label.

How Ansible Works: Push Model

With Ansible installed and upgraded and a list of devices in your network defined in an inventory file, you can manage configuration modules and execute them to make changes to your managed devices.

An Ansible module can be thought of as a small program pushed to and run on a managed device to achieve the desired configuration state for that device. Most modules are standalone. Ansible also gives an administrator the ability to write modules by using standard scripting languages such as Python. With more than 750 built-in modules, organized by vendor and technology, Ansible enables administrators to ramp up and manage their environments quickly and easily.

You can use the ansible-doc modulename command to quickly view information about how to use an installed module. For more information, see .

When you have modules installed, you can execute them from the Ansible host against the systems defined with your inventory file by using the ansible-playbook example-playbook.yml command. Ansible connects to all systems defined in the inventory simultaneously, makes the prescribed changes, and displays the status PLAY RECAP on the terminal screen.

Ansible also supports ad hoc execution of modules. To use this feature, run the command ansible host1,group2 -m modulename -a moduleargs, where host1 and group2 are entries defined in your inventory file, modulename is the name of the Ansible module you want to execute, and moduleargs are the required arguments for the specific module.

Some modules don’t require arguments and can be called only with modulename; for example, ansible host1,host2,host3 -m ping returns success if all hosts are reachable. In this example, ping is the name of the module being called.

Ansible Playbooks: Terms

Ansible uses some specific terminology for orchestration through playbooks, as shown in Table 3-1.

Table 3-1 Ansible Terms

Term

Description

Module

Code, written using any of a number of scripting languages (for example, Python), to perform an action on a managed device.

Task

An action referencing a module to run together with input argument and actions.

Play

A set of tasks for a host or group of hosts.

Playbook

A file, written in YAML, that includes one or more plays.

Role

A set of playbooks, often prebuilt, used to execute a standard configuration in a repeatable manner. You can assign multiple roles to a single host.

For example, an inventory file might contain server1, server2, and server3 host entries that are part of the internet_servers group, which should have ssh_server, http_server, and php_server roles applied.

Ansible Playbooks: Components

An Ansible playbook is a simple human-readable text file in YAML format, with keywords that Ansible recognizes as instructions. Because YAML is a plaintext file, it is ideal for collaboration and makes troubleshooting much easier because line numbering and version control provide insight into what was changed and when and who made the changes.

A playbook can be named and consists of hosts and tasks that should be performed. A lot of optional keywords can be used to change the way Ansible interacts with hosts defined in an inventory file. For example, gather_facts is an instruction to Ansible that enables or disables runtime variables available to tasks. Setting it to no makes execution faster, but the tasks lose access to variables that Ansible collects before execution; for example, ansible_distribution would be empty instead of containing the value Ubuntu or RedHat.

Figure 3-2 shows an example of an Ansible playbook.

A pound sign (#) indicates a comment; Ansible ignores everything from the # to the end of the line.

The vars section contains user-defined variables that are later referenced in the tasks section. Variable expansion is done by enclosing a variable name inside double curly brackets—for example, {{ variable }}.

The tasks section contains tasks that are executed in the order in which they are listed, and they are executed in linear fashion on each host; that is, when one task finishes on all hosts, execution of the next task starts. This behavior can be changed by setting strategy to free in the top-level section of the playbook.

Ansible can run in parallel on a maximum of five hosts. If you add more hosts, you must wait longer for each task to complete. You can change this behavior by setting forks to 20 in the top-level section of the playbook.

Each section under tasks starts with an optional name, followed by a module name that you want to use (apt and service in Figure 3-2). Module parameters belong under the module name and must be indented to indicate that they belong to the module and not the task. Some module parameters are required; others are optional. You can find out which parameters are required by using an equals (=) sign in the output of ansible-doc apt.

The playbook in the example in Figure 3-2 declares the variable packages and connects to server1 and server2. The first task updates the apt cache with the latest package information from remote repositories and installs the tcpdump and apache2 packages. The second task starts the apache2 web server and enables the apache2 web server to start on boot.

Ansible Playbooks: Inventory File

An inventory file is a collection of all the hosts that are managed by Ansible. It is a simple plaintext file in which you specify hosts, logical groupings, and special variables for Ansible.

Figure 3-3 shows an example of an inventory file that contains the following information:

  • ▪ A group named servers with two hosts, each with a special variable ansible_port to indicate that sshd is running on a nonstandard port

  • ▪ A group named switches with two hosts

  • ▪ A group named routers with two hosts

  • ▪ A group named datacenter with groups servers, switches, and routers as members

03fig03.jpg

Figure 3-3 Ansible Inventory Example

You can target any of the hosts or groups in your inventory by changing the hosts keyword in your playbook. The group datacenter is convenient when you want to execute something on all the desired groups or set a variable for all groups in one place. There is also a predefined default group named all, which you can use to target all hosts in your inventory.

Ansible: Executing the Playbooks

You can execute a playbook by using the ansible-playbook -u username root example.yml command, where -u username is your username for administrative login and example.yml is the name of your playbook. Ansible uses the root username by default, so you can omit -u in this command if you want to use root.

Figure 3-4 shows an example of an Ansible Playbook running.

In the example shown in Figure 3-4, Gathering Facts runs before any tasks to collect system information and populate variables that the tasks might need. You can disable this behavior by setting gather_facts to false. The Install packages task runs first, Start and enable web server runs second, and PLAY RECAP tells you how many tasks made changes on each host (two in this case).

System Management with Puppet

Puppet is a configuration management tool that you can use to automate configuration deployment in your infrastructure. The Puppet configuration management tool has the following features:

  • ▪ Puppet is an open-source project managed by a company called Puppet.

  • ▪ It is written in C++, Clojure, and Ruby.

  • ▪ It uses Puppet’s declarative language to describe a desired configuration.

  • ▪ It can be used on many different systems, including various Linus distributions (such as Red Hat and Ubuntu), various UNIX systems, and Windows.

Puppet Architecture

Puppet has a client/server architecture. The client in Puppet is called the agent, and the server is called the master. The master controls the complete configuration, and the agent periodically pulls the configuration from master. The following workflow is used to update the agent’s configuration:

  1. An agent node requests a catalog from the master.

  2. The master compiles the Puppet code and returns the catalog with the required configuration.

  3. The agent applies the configuration by checking the state of the resources and applying the required changes.

  4. The agent responds with the report.

This procedure is repeated periodically. By default, an agent requests the configuration every 30 minutes. Typically, you would want to manage the complete infrastructure with one tool. Puppet requires that an agent be installed on each managed node. However, you cannot install an agent on some devices, such as switches, routers, and firewalls. For those devices, you need to configure a node as a proxy for devices. The proxy performs all communication with the master, connects to the device, and applies the configuration.

Basic Puppet Concepts

When you use Puppet, it is important to be familiar with its basic concepts:

  • Resource: This is the portion of Puppet code that describes a particular aspect of a system.

  • Class: This is a collection of resources that can be reused multiple times.

  • Manifest: This configuration file describes how to configure your resources.

  • Catalog: This is a compiled configuration for each individual node.

  • Module: This is a collection of manifests, templates, and other files that is used to configure multiple options of a specific feature and can be reused.

The most elementary Puppet entity is called a resource. It is a unit of configuration that you use in configuration files. You need to define a resource type, a title, and one or more attributes with specific values. A resource is defined with the following syntax:

<TYPE> { '<TITLE>': <ATTRIBUTE> => <VALUE>, }

You can list multiple attributes, separated with commas. You can also write attributes on multiple lines. Resources must be unique to avoid having conflicting values for the same resource. The uniqueness is achieved with the resource title and the name attribute. If resources are not unique, you get an error when compiling the configuration.

You can group resources into classes. Classes are similar to classes in regular programming languages, as you can use them to better organize the code. Before you can use a class, you need to define a class. Defining a class means specifying the class’s configuration and making it available for later use. The class definition does not specify any actual configuration for nodes.

The main configuration of the infrastructure is specified in a manifest. The manifest stores the Puppet code that describes how resources should be configured. The manifest is a text file with the .pp extension. It uses UTF-8 encoding. The manifest can be a single file, or you can specify configuration in a directory that contains multiple manifests. Puppet treats multiple files as one. The main manifest is usually called site.pp.

The configuration in manifests is compiled into a catalog for each individual node. The catalog describes the desired state of a specific node and is generated from the logic that is defined in the manifest. The master node sends the catalog to the agent. The agent applies the required configuration to the resource to bring the node to the desired state.

When you start writing complex manifests, you probably want to store your code in modules. Modules allow reusability. They are used to configure a specific part of the infrastructure. Modules contain all previously described elements, including resources, classes, and manifests. You can write your own modules, but you must follow a defined structure and place the module in the correct location on the system. There are also a lot of modules available from Puppet Forge, written by Puppet developers and members of the open-source community. When you develop or install a module, the module gives you classes and resources that you can use in your configuration code. You can use these classes in the same way you would define classes inline in the main manifest.

Puppet Example

Example 3-1 shows a Puppet configuration with the following objectives applied to two Linux servers called puppeta01 and puppeta02:

  • ▪ Configure the IP address on the network interface.

  • ▪ Configure the default gateway.

  • ▪ Configure the DNS server.

  • ▪ Configure the NTP address.

This code would be added to a file called site.pp.

Example 3-1 Puppet Configuration Script

The first class in Example 3-1, conf_if, accepts the ip_address variable. The first action is to create a file in the correct location, which is specified with the path attribute. The content attribute specifies the content of the file. The content is created with the template function, which evaluates the specified template with the defined variables. In this case, you need to pass the ip_address variable. The content attribute uses the $settings::manifest variable to point to the correct location on the file system. Next, you need to disable and enable the interface to apply the new configuration. The exec resource uses the require attribute, which adds a dependency. The code first creates a file, then executes the ifdown command, and finally executes the ifup command.

The second class in the example, conf_dns, creates a template that will be used in the /etc/resolv.conf file and applies the 192.168.1.253 and 192.168.1.254 IP addresses to the DNS configuration of the device.

The final two sections define the nodes that will receive the required configuration. Both nodes call the conf_if class for IP address assignment, call the conf_dns class, and call an external NTP module called ntp that was previously installed.

Now that the configuration is ready, the last step is to execute the puppet agent -t command on the node to run the pull request and update the configuration; alternatively, you can just wait until the next pull period.

System Management with Chef

Chef is a powerful automation platform that transforms complex infrastructure into code, enabling data center infrastructure automation with a declarative, intent-based model. Whether you’re operating in the cloud, on premises, or in a hybrid environment, Chef automates how applications are configured, deployed, and managed across your network, no matter its size.

Chef is built around simple concepts: achieving desired state, using centralized modeling of IT infrastructure, and using resource primitives as building blocks. These concepts enable you to quickly manage any infrastructure with Chef. These very same concepts allow Chef to handle the most difficult infrastructure challenges and customer use cases; anything that can run the Chef client can be managed by Chef.

Chef, like Ansible and Puppet, exists as software packages that you install and run. Chef (the company) offers several products; Chef Automate is the product that most people refer to simply as Chef. As with Puppet, in production, you are likely to run Chef as a server (in what is called server-client mode), and engineering staff use multiple Chef workstations to build Chef files that are stored on the Chef server. However, you can also run Chef in standalone mode (called Chef Zero), which is helpful when you’re just getting started and learning in the lab.

Chef uses an architecture similar to that of Puppet. For network devices, each managed device (called a Chef node or Chef client) runs an agent. The agent performs configuration monitoring in that the client pulls recipes and resources from the Chef server and then adjusts its configuration to stay in sync with the details in those recipes and run lists. Note, however, that Chef requires on-device Chef client code, and many Cisco devices do not support a Chef client, so you are likely to see more use of Ansible and Puppet for Cisco device configuration management.

Chef Concepts

When you use Chef, it is important to be familiar with its basic concepts:

  • Chef server: The Chef server acts as a hub for configuration data. It stores the following:

    • ▪ Cookbooks

    • ▪ Recipes (the policies that are applied to nodes)

    • ▪ Metadata that describes each registered node that is being managed by the Chef client

  • Node: A node is any physical, virtual, or cloud machine or switch configured to be maintained by a Chef client.

  • Chef client: The Chef client runs locally on every node that is registered with the Chef server. It performs all configuration tasks specified by the run list and brings the client into the desired state.

  • Chef resources: This is a grouping of managed objects/attributes and one or more corresponding implementations. It describes the desired state for a configuration item and declares the steps needed to bring that item to the desired state. It specifies a resource type, such as a package, template, or service, and lists additional details (also known as attributes) as necessary. Resources are grouped into recipes, which describe working configurations.

  • Cookbook: A cookbook defines a scenario and contains everything that is required to support that scenario. A cookbook is used for device configuration and policy distribution and includes the following elements:

    • ▪ Recipes that specify the resources to use and the order in which they are to be applied

    • ▪ Attribute values

    • ▪ File distributions

    • ▪ Templates

    • ▪ Extensions to Chef, such as libraries, definitions, and custom resources

  • Recipe: A recipe is a collection of resources, defined using patterns (resource names, attribute/value pairs, and actions). Helper code is added to a recipe by using Ruby. Recipes must follow the following guidelines:

    • ▪ A recipe must be stored in a cookbook.

    • ▪ A recipe may use the results of a search query and read the contents of a data bag.

    • ▪ A recipe may have a dependency on one (or more) recipes.

    • ▪ A recipe must be added to a run list before it can be used by the Chef client.

    • ▪ A recipe is always executed in the same order as listed in a run list.

    • ▪ The Chef client runs a recipe only when asked to do so.

Chef Example

Example 3-2 shows a sample cookbook configuration of a switch’s Layer 3 and Layer 2 interfaces. The Ethernet 1/1 interface is configured as a Layer 3 interface with an IP address and a subnet mask. Notice that Layer 3 functionality is enabled thanks to the switchport_mode 'disabled' command. Interface Ethernet 1/2 is assigned to VLAN 100 and is configured as an access port.

Example 3-2 Chef Configuration Script

System Management with SaltStack

Created by Thomas Hatch in 2011, Salt, now known as SaltStack, is a modular, Python-based configuration management tool that is designed for high-speed data collection/execution. The tool has gained considerable traction in the enterprise because of its performance benefits over competing solutions, including Ansible.

SaltStack’s speed and performance benefits are made possible by its lightweight ZeroMQ messaging library, which is a framework for establishing concurrent, persistent TCP connections between the server and agents (that is, the Salt master and minions). The platform is available as an open-source project or as an enterprise commercial offering known as SaltStack Enterprise.

Salt Architecture

At the core of the Salt ecosystem are two critical components: the master and the minion. The other components play supporting roles to make the ecosystem work. Figure 3-5 provides a high-level view of a Salt architecture example, which includes the following components:

  • Master: The master is the server that runs the core services to communicate with the minions. It also contains the key store for encryption between the minions.

  • Minion: A minion is a Python-based endpoint that can be deployed on all major Linux and Windows operating systems. The minions are connected to the master, and you can have the master ask them to do a variety of tasks by adding an easy-to-understand YAML file or by directly running commands from the master.

  • SSH (agentless): Salt supports an agentless mode over SSH for assets that don’t have minions installed. Salt SSH supports the same system normalization functions that are supported by the minions.

  • Proxy minion: On assets where agents cannot be deployed or where it is not possible to use SSH for remote access, a Salt proxy minion can be used. The proxy minion is designed to connect to network devices and IoT devices.

  • Monitor (beacons): Minions can be configured to monitor files, processes, services, and a host of other things. They can also generate events when certain criteria are met, such as failed logins, unauthorized changes to critical files or processes, or even unexpected changes in CPU load or disk usage.

  • Respond (reactor): Another feature of Salt is its ability to react to events and take actions. The reactor can be configured to take predefined actions based on certain event criteria (such as restarting the MySQL service if it stops). This helps organizations achieve a state of event-driven SecOps IT automation.

  • States or formulas: These are files that contain YAML and templated data to configure minions.

  • Grains: Salt comes with an interface to derive information about the underlying system. This is called the grains interface because it presents Salt with grains of information. Grains are collected for the operating system, domain name, IP address, kernel, OS type, memory, and many other system properties. The grains interface is made available to Salt modules and components so that the right Salt minion commands are automatically available on the right systems.

  • Pillars: A pillar is an interface for Salt that is designed to offer global values that can be distributed to minions. A pillar is a free-form resource of data (that can be JSON, YAML, or whatever you need), and it can either be stored in a file or externally. A pillar allows integration with other systems where a shared data store would be of value (for example, an ITSM or asset register).

  • Mine: This is used for data fetching so that you can also return data from minions and store it to be used in other tasks, such as for template-based state configuration.

SaltStack Example

Example 3-3 shows a sample configuration that sets the NTP server IP addresses on specific devices. The example creates the necessary pillar files, ntp_server.sls and top.sls. ntp_server.sls contains a list of IP addresses that the devices should use to synchronize their clocks. The top.sls file lists the devices that need to be configured with the NTP addresses. The * tells Salt to provide the content from ntp_servers.sls to all minions.

Example 3-3 SaltStack Configuration Script

The first salt command in this example refreshes the local information on the minions, and the second salt command checks to make sure the data has been loaded correctly on the devices. The output confirms that the three devices are now configured to contact the two NTP servers at 172.17.17.1 and 172.17.17.2.

Embedded Events Manager

Cisco IOS Embedded Event Manager (EEM) supports more than 20 event detectors that are highly integrated with different Cisco IOS Software components to trigger actions in response to network events. These scripts are programmed using either a simple command-line interface (CLI) or a scripting language called Tool Command Language (Tcl). In this section, we first review EEM and then look more closely at Tcl scripting.

EEM Architecture

EEM consists of three components:

  • Policies: Policies, or scripts, are either applets or Tcl scripts configured by the administrator.

  • EEM server: The EEM server is the director of EEM. When a configured event occurs, the associated action is implemented.

  • Event detectors: An event detector is used as a trigger, based on certain conditions. Some of these conditions include monitoring for syslog events, online insertion and removal (IOR), CLI input, and timers.

Figure 3-6 illustrates the relationship between these three components.

Policies

Policies, or scripts, are either applets or Tcl scripts configured by the administrator:

  • Applets: With applets, users do not need to know how to write Tcl scripts. The body of an applet appears in the configuration of a Cisco IOS device. Applets were designed to provide a simpler interface for EEM.

  • Tcl scripts: Policies can be defined through the IOS CLI. Scripts provide more control than do applets.

EEM Server

The EEM server is a bridge between the policies and internal Cisco IOS subsystems used in the event detectors. Some of the functions of the EEM server are to register events seen in the IOS subsystems, store information about an events, publish events, request additional information about events, register internal script directories, register Tcl scripts and applets, and process actions taken by user-defined scripts.

Event Detectors

Event detectors monitor the operational state of processes on an IOS device. These processes run at medium priority and are always operational. On detecting an event, an event detector sends an alert that provides information about the specific event. The list that follows describes a few of the event detectors in Cisco IOS:

  • Syslog event detector: This event detector is triggered when a syslog message match is seen in the output of the console. Additional granularity can be achieved depending on the number of occurrences for any given message. Console logging does not have to be active for the syslog event detector to generate events; this is completely independent of which logging targets are configured.

  • SNMP event detector: A specific SNMP variable can be polled, and if the SNMP variable reaches a threshold, a trigger can be generated.

  • IP SLA event detector: This detector publishes an event when an IP service-level agreement (SLA) reaction is triggered.

  • Interface event detector: This detector monitors interface counters based on a defined threshold value. The threshold can be specified as an absolute value or as an incremental value.

  • CLI event detector: This event detector triggers when a specified command is entered via a console or Telnet/SSH session. This detector screens CLI commands that match a regular expression. When a match is found, an event is published, and the CLI event detector can perform a logical match before the command is parsed and executed.

  • NetFlow event detector: When a NetFlow event is triggered, the NetFlow event detector publishes an event.

  • Enhanced object tracking event detector: This event detector is triggered when the status of the tracked object changes. A unique number identifies each tracked object. This number is specified on the tracking CLI, and the detector process uses this number to track a specific object. The tracking process periodically polls the tracked objects and notes any change in value. The changes in the tracked object are communicated to the event detector process either immediately or after a specified delay. The object values are reported as either up or down. Enhanced object tracking is now integrated with EEM to allow EEM to report on the status change of a tracked object. For example, the Hot Standby Router Protocol (HSRP) active router may change because of the loss of a neighbor router or due to an interface state change.

  • Routing event detector: This event detector is invoked when information in the Routing Information Base (RIB) has been changed.

The EEM event detectors have evolved based on IOS releases. The functionality of event detection and action depends on the specific release. Use the Cisco Feature Navigator () or the show event manager version command to discover which version of EEM is supported on your device. The current latest version of EEM is 4.0.

Writing EEM Policies

As mentioned earlier, EEM offers the ability to monitor events and take informational or corrective action when monitored events occur or a threshold is reached. An EEM policy is an entity that defines an event and the actions to be taken when that event occurs. There are two types of EEM policies: an applet or a script. An applet is a simple form of policy that is defined in the CLI configuration. A script is a form of policy that is written in Tcl.

The version of EEM is based on the IOS release cycle. It is important to understand the functionality of EEM based on the IOS image so that you fully understand the features and functionality of the event detectors and what is supported.

EEM Applet

Using an EEM applet is a concise method for defining event screening criteria and the actions to be taken when a particular event occurs. In applet configuration mode, three types of configuration statements are supported. The event commands are used to specify the event criteria that trigger the applet to run, the action commands are used to specify an action to perform when the EEM applet is triggered, and the set command is used to set the value of an EEM applet variable.

Only one event configuration command is allowed in an applet configuration. When applet configuration mode is exited and the no event command is present, a warning is displayed, stating that no event is associated with the applet. If no event is specified, the applet is not considered registered. When no action is associated with the applet, events are still triggered, but no actions are performed. Multiple action configuration commands are allowed in an applet configuration. Use the show event manager policy registered command to display a list of registered applets.

Before modifying an EEM applet, you need to be aware that the existing applet is not replaced until you exit applet configuration mode. While you are in applet configuration mode modifying the applet, the existing applet may be executing. It is safe to modify the applet without unregistering it. When you exit applet configuration mode, the old applet is unregistered, and the new version is registered.

The action configuration commands are uniquely identified using the label argument, which can be any string value. Actions are sorted in ascending alphanumeric key sequence, using the label argument as the sort key, and they are run using this sequence.

The EEM schedules and runs policies on the basis of an event specification that is contained within a policy. When applet configuration mode is exited, EEM examines the event and action commands that are entered and registers the applet to be run when a specified event occurs.

EEM Script

You define scripts by using an ASCII editor and then copying the script to the networking devices to register them with EEM. EEM supports Tcl scripts.

EEM allows you to write and implement your own policies using Tcl. Writing an EEM policy involves several actions:

  • ▪ Selecting the event for which the policy is run.

  • ▪ Defining the event detector options associated with logging and responding to the event.

  • ▪ Choosing the actions to be followed when the event occurs.

Cisco provides enhancements to Tcl in the form of keyword extensions that facilitate the development of EEM policies. The main categories of keywords identify the detected event, the subsequent action, utility information, counter values, and system information.

Writing an EEM Policy Using the Cisco IOS CLI

To register an applet with EEM, you can first define environment variables that the applet will use. EEM environment variables for EEM policies are defined using the EEM event manager environment configuration command. By convention, every Cisco EEM environment variable begins with an underscore (_). You can display the EEM environment variables set on a system by using the show event manager environment privileged EXEC command. For example, you can create EEM policies that can send emails when an event occurs. The variables could include _email_server, _email_to, _email_from, and _email_cc. These variables could then be used in the applet to generate email notifications when specific events occur.

Once the (optional) variables are defined, you use the event manager applet applet-name global configuration command to enter EEM configuration mode. You then use the event and action commands to build the applet. Only one event command is allowed in an EEM applet, but multiple action commands are permitted.

Some of the EEM events that are available are CLI events, config events, interface events, routing events, syslog events, SNMP events, and track events. EEM actions can be numerous, and it can be helpful to add labels so you can sort them.

Example 3-4 shows the creation of an applet that matches a syslog pattern using a regular expression. When the interface GigabitEthernet2/0 changes state to down, an event trigger is generated. The event in this case is to generate a syslog message and email the network administrator that there is an issue with the interface. Notice that environment variables are defined for use in the applet.

Example 3-4 EEM Applet Example

Using EEM and Tcl Scripts

Tool Command Language (Tcl), invented in the late 1980s, is a dynamic programming or scripting language, an interpreter, and a C library. Tcl helps users control other applications or utilities by using basic flow control.

Tcl is built into Cisco routers and switches to allow engineers to interact directly with a device by using various Tcl scripts. Tcl is a very useful scripting language that provides many ways to streamline different tasks that can help with day-to-day operations and monitoring of a network. The following are some of the tasks that can be automated by using these scripts:

  • ▪ Verifying IP and IPv6 reachability by using ping

  • ▪ Verifying IP and IPv6 reachability by using traceroute

  • ▪ Checking interface statistics

  • ▪ Retrieving SNMP information by accessing MIBs

  • ▪ Sending email messages containing CLI output from Tcl scripts

Most often, basic Tcl scripts are entered line by line in the Tcl shell. However, for more advanced scripting methods, you can load a script into the flash memory of the device you are working on and execute the script from there.

You can also verify that an image you are using has the Tcl interpreter by just entering the command tclsh at the router prompt in privileged mode:

Router# tclsh
Router(tcl)#

As you can see here, the command prompt changes to show that you are in Tcl mode. Commands entered at the (tcl) prompt will be handled by the Tcl interpreter if it understands them. If a command is not understood, it is passed along to the standard IOS command process.

Example 3-5 shows a simple Tcl script that pings three devices. That script is saved with the name ping_script.tcl and is copied to the router’s flash memory by using TFTP. An EEM applet called myping is then defined that calls the Tcl script. Notice that when the applet is executed, the router pings the three addresses defined in the Tcl script.

Example 3-5 Tcl and EEM Example

Study Resources

For today’s exam topics, refer to the following resources for more study.

Resource

Module, Chapter, or Links

CCNP and CCIE Enterprise Core ENCOR 350-401 Official Cert Guide

29

CCNP and CCIE Enterprise Core & CCNP Advanced Routing Portable Command Guide

11

Embedded Event Manager Configuration Guide, Cisco IOS Release 15M&T