Lab 6 - Infrastructure Automationπ
Lab 6.1 Configure the NAT Network
Lab 6.2 Set up GitHub Repository
Lab 6.3 Install the CSR1000v VM
Lab 6.4 Use Ansible to Back Up and Configure a Device
Lab 6.5 Use Ansible to Automate Installing a Web Server
6.1 Configure the NAT Networkπ
Objectivesπ
Part 1: Create the NAT Network
Part 2: Configure the DEVASC VM to use the NAT Network
Instructionsπ
Part 1: Create the NAT Networkπ
Important
If you properly completed Part 1, Step 2 of the first lab (Lab 1 - Dev Environment) then it's likely this NAT network is already configured. Simply verify the settings match the outputs below, but don't change anything if they are already set correctly from Lab 1.
-
Press Ctrl+H, or click the Network icon on the left (see the screenshot), or click File > Tools > Network
-
Click on the NAT Networks tab
-
If you already see a NAT Network called DEVASC with the IPv4 Prefix 10.0.2.0/24 then you already have the NAT Network and can skip to Part 2. Otherwise, click the Create button at the top of the window.
-
In the Name box at the bottom of the screen type DEVASC. In the IPv4 Prefix box type 10.0.2.0/24. Ensure that the Enable DHCP checkbox is checked. You do not need to check the Enable IPv6 checkbox. Click the Apply button to apply the settings.
Part 2: Configure the DEVASC VM to use the NAT Networkπ
-
Return to the list of virtual machines, click on the DEVASC-LABVM virtual machine, then click the Settings button
-
In the settings window, click on Network in the left navigation pane. On the Adapter 1 tab, change the Attached to: dropdown to NAT Network and ensure the Name field says DEVASC. Click OK to close the settings.
6.2 Set up GitHub Repositoryπ
Objectivesπ
Part 1: Join the GitHub Classroom
Part 2: Initialize the Local Repository
Part 3: Set up the Remote Repository
Instructionsπ
Part 1: Join the GitHub Classroomπ
-
Follow the GitHub assignment link posted in Canvas. If you did not complete the setup in Lab 2.2 you will need to authorize GitHub Classroom to link with your account and select your name from the list of students.
-
Accept the assignment and refresh the page until it says your repository has been created. Click the link to proceed to the repository.
Important
GitHub Classroom is currently experiencing a bug where you might receive a Repository Access Issue error after accepting the assignment. If this happens, check the e-mail connected to your GitHub account for an invitation e-mail from GitHub. Use the View Invitation link in the e-mail to see the link to accept the invitation and proceed to the repository.
-
Select the Code dropdown and copy the HTTPS URL. Store it somewhere for use in a later step.
Tip
If you've configured your VM to use SSH to connect to GitHub instead of HTTPS, click on the Code dropdown, select the SSH tab, and copy the URL from there instead.
Part 2: Initialize the Local Repositoryπ
You will be creating a local repository from a folder on the DEVASC VM. This folder already contains some files, so you will need to initialize a repository in the folder, pull down the files from the remote GitHub Classroom repository, then add the local files to the local repository to combine the remote and local files into a single repository.
-
Inside the DEVASC VM, open a terminal and change to the
~/labs/devnet-src/ansibledirectory.devasc@labvm:~$ cd labs/devnet-src/ansible/ devasc@labvm:~/labs/devnet-src/ansible$ -
View the listing of the files and folders currently in the
ansibledirectory.devasc@labvm:~/labs/devnet-src/ansible$ ls -la total 16 drwxr-xr-x 4 devasc devasc 4096 Jun 1 2020 . drwxr-xr-x 17 devasc devasc 4096 Mar 8 21:57 .. drwxr-xr-x 2 devasc devasc 4096 Jun 2 2020 ansible-apache drwxr-xr-x 2 devasc devasc 4096 Jun 2 2020 ansible-csr1000v devasc@labvm:~/labs/devnet-src/ansible$ -
Initialize this directory as a Git repository (donβt miss the
.at the end of the command).devasc@labvm:~/labs/devnet-src/ansible$ git init . Initialized empty Git repository in /home/devasc/labs/devnet-src/ansible/.git/ devasc@labvm:~/labs/devnet-src/ansible$
Part 3: Set up the Remote Repositoryπ
-
Since we initialized our own local repository, rather than cloning an existing remote repository, we need to tell Git the location of the remote repository to synchronize with. Configure the location of the remote repository using the
git remote addcommand. Use the URL to the GitHub Classroom repository you copied at the end of Part 1, not the one in the command below.Tip
If you've configured your VM to use SSH to connect to GitHub, use the SSH URL that you copied in step 1, rather than the HTTPS link.
devasc@labvm:~/labs/devnet-src/ansible$ git remote add origin https://github.com/Ontario-Tech-NITS/lab-6-infrastructure-automation-<username>.git devasc@labvm:~/labs/devnet-src/ansible$Important
Make sure you use your GitHub URL that you copied in Part 1, not the one in the command example! Also, if you're using SSH, your URL will start with
git@github.comrather thanhttps://. -
Verify that the remote is properly configured with the
git remote --verbosecommand.devasc@labvm:~/labs/devnet-src/ansible$ git remote --verbose origin https://github.com/Ontario-Tech-NITS/lab-6-infrastructure-automation-<username>.git (fetch) origin https://github.com/Ontario-Tech-NITS/lab-6-infrastructure-automation-<username>.git (push) devasc@labvm:~/labs/devnet-src/ansible$ -
Pull down the files from the remote repository into the local repository. Remember to use your Personal Access Token as the password.
Tip
If you've configured your VM to use SSH to connect to GitHub instead of HTTPS, you will not be asked for a username and password, although you may be asked for a passphrase for your SSH key, if you configured one.
devasc@labvm:~/labs/devnet-src/ansible$ git pull origin main Username for 'https://github.com': username Password for 'https://username@github.com': Personal Access Token remote: Enumerating objects: 16, done. remote: Counting objects: 100% (16/16), done. remote: Compressing objects: 100% (11/11), done. remote: Total 16 (delta 1), reused 6 (delta 0), pack-reused 0 (from 0) Unpacking objects: 100% (16/16), 5.73 KiB | 2.87 MiB/s, done. From github.com:Ontario-Tech-NITS/lab-6-infrastructure-automation-josh-test-student * branch main -> FETCH_HEAD * [new branch] main -> origin/main devasc@labvm: :~/labs/devnet-src/ansible$ -
Use
git statusto verify all the local files and folders are currently untracked.devasc@labvm:~/labs/devnet-src/ansible$ git status On branch main Untracked files: (use "git add <file>..." to include in what will be committed) ansible-apache/ ansible-csr1000v/ nothing added to commit but untracked files present (use "git add" to track) devasc@labvm:~/labs/devnet-src/ansible$ -
Add the files from the local working folder to the staging area (donβt miss the . at the end of the command).
devasc@labvm:~/labs/devnet-src/ansible$ git add . devasc@labvm:~/labs/devnet-src/ansible$ -
Commit these new files to the local repository. Use the commit message Initializing the repository.
devasc@labvm:~/labs/devnet-src/ansible$ git commit -m "Initializing the repository" [main d37a4d7] Initializing the repository 8 files changed, 4 insertions(+) create mode 100644 ansible-apache/ansible.cfg create mode 100644 ansible-apache/checklocalinfo.yml create mode 100644 ansible-apache/hosts create mode 100644 ansible-apache/servers create mode 100644 ansible-csr1000v/ansible.cfg create mode 100644 ansible-csr1000v/checklocalinfo.yml create mode 100644 ansible-csr1000v/hosts create mode 100644 ansible-csr1000v/servers devasc@labvm:~/labs/devnet-src/ansible$ -
Use
git statusagain to verify that all files have been committed to the local repository and that you are working on a clean tree.devasc@labvm:~/labs/devnet-src/ansible$ git status On branch main nothing to commit, working tree clean devasc@labvm:~/labs/devnet-src/ansible$ -
Push the local repository to the remote repository on GitHub, adding the files from the DEVASC VM to the existing repository. Remember to use your Personal Access Token when prompted for your password.
Tip
If you've configured your VM to use SSH to connect to GitHub instead of HTTPS, you will not be asked for a username and password, although you may be asked for a passphrase for your SSH key, if you configured one.
devasc@labvm:~/labs/devnet-src/ansible$ git push origin main Username for 'https://github.com': username Password for 'https://username@github.com': Personal Access Token Enumerating objects: 7, done. Counting objects: 100% (7/7), done. Delta compression using up to 2 threads Compressing objects: 100% (4/4), done. Writing objects: 100% (6/6), 617 bytes | 617.00 KiB/s, done. Total 6 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0) To github.com:Ontario-Tech-NITS/lab-6-infrastructure-automation-<username>.git 3d55449..d37a4d7 main -> main devasc@labvm:~/labs/devnet-src/ansible$ -
Using a web browser, open the remote repository on GitHub and verify that you see the newly tracked files and folders. Your local and remote repositories are now synchronized, and you are ready to complete the rest of the lab, committing your changes as you go (when instructed).
6.3 Install the CSR1000v VMπ
Objectivesπ
Part 1: Install the CSR1000v VM on VirtualBox
Part 2: Verify Communications to CSR1000v VM
Backgroundπ
In this lab, you will install the CSR1000v Cloud Services Router. This is a Cisco software virtual router deployed on a virtual machine (VM) instance on x86 server hardware. When the Cisco CSR 1000v is deployed on a VM, the Cisco IOS XE software functions exactly the same as if it were deployed on a traditional Cisco hardware platform. You can configure different features depending on the Cisco IOS XE software image.
Note
The CSR1000v name will be shortened to CSR1kv in future labs. However, for this lab we use CSR1000v.
Instructionsπ
Part 1: Install the CSR1000v VM on VirtualBoxπ
Install the CSR1000v VM directly on your x86 computer. It requires at least 4GB of RAM.
Step 1: Download the CSR1000v ISO fileπ
Important
Only the instructor is able to download ISO files from Cisco. The CSR1000v ISO has been downloaded and shared on Canvas for your use only in this class.
Cisco does not make this software publicly available for free, and you are only allowed to use the software as part of this course.
- Download the
CSR1kv ISOfile from the Labs module on Canvas. This will require you to use your @ontariotechu.net e-mail account. Note the location of the downloaded image on your computer.
Step 2: Download the CSR1000v VM OVA fileπ
-
Download the
CSV1kv VirtualBox OVAfile from the Labs module on Canvas. This will require you to use your @ontariotechu.net e-mail account. Note the location of the downloaded OVA file on your computer.Note
This file is different from the one you downloaded in step 1. The OVA file is a virtual machine template file that has some pre-configured settings youβll use for this lab. The ISO file is the actual Cisco IOS-XE CSR1000v virtual machine image, which you will install into the virtual machine template you downloaded as an OVA file, in the next step.
Step 3: Install the CSR1000v VMπ
-
Open Oracle VirtualBox Manager if itβs not already open.
-
Select File > Import Appliance or press Ctrl+I.
-
The source of the appliance is Local File System. Click in the File box and browse to the location of the downloaded
CSR1000v_for_VirtualBox.ovafile, and click Finish to start the import process. You will now see the CSR1000v VM added to VirtualBox. -
Once the import process is complete, click the Settings button on the CSR1000v VM.
-
Select Network from the menu on the left, then change the Attached to: dropdown from Host-only Adapter to NAT Network. Ensure the name field says DEVASC and click OK.
Note
NAT Network will allow the CSR1000v VM to communicate with the DEVASC VM thatβs already running.
Step 4: Update the installation ISO locationπ
-
Click the Settings button on the CSR1000v VM.
-
Click Storage from the menu on the left, then select the first CD device shown under Storage Devices. It should currently say
csr1000v-universalk9-install_for_VirtualBox_3.iso, and is likely the second item in the list, after theCSR1000v-disk.vdihard drive. -
With the CD drive selected, click the small blue disc icon next to IDE Primary Device 1 on the far right and select Choose a disk file⦠from the dropdown menu
-
Select the ISO file you downloaded in step 1, called
csr1000v-universalk9.16.09.05.iso, then click Open.Important
Do NOT change the Second CD Drive settings. That is used for the initial configuration of the router.
-
Click OK to save the Virtual Machine settings.
Step 5: Start CSR1000v VMπ
-
Select the CSR1000v VM and click Start.
-
During the loading process you will see several messages including a message to Press any key to continue. Press any key to continue the installation.
-
A selection screen will eventually appear where you can choose different configuration options. Do not choose any configuration options. Installation will continue on its own. If it does not start automatically after a few seconds, ensure the first option is selected and press Enter.
-
Wait for the initial installation process to be completed. This will take several minutes the first time you boot the CSR1000v and it will likely need to reboot at least once. Subsequent loads of the VM will be much faster once the image has been installed.
You will begin to see IOS messages from different processes including %SSH, %PKI and %CRYPTO_ENGINE. After a few minutes the messages will stop, and the router has finished loading. For example:
Tip
You can press Host+C or select View > Scaled Mode to make the CSR1000v window scalable and easier to read. The Host key defaults to the right-hand Ctrl key on your keyboard.
-
Within the VM window, press Enter. You should see a Cisco Networking Academy message and the router prompt: CSR1kv>.
-
Enter
enablefor the privileged EXEC prompt. There is no enable password.CSR1kv> enable CSR1kv#Note
By default, the Host key is set to the right-hand Ctrl key on your keyboard. This key is used for navigating the VirtualBox interface, such as entering/leaving full screen mode (Host+F). If you find your cursor is stuck inside of the CSR100v VM window, pressing the Right Ctrl key should let you escape.
Part 2: Verify Communications to CSR1000v VMπ
In this Part, you will verify communications between devices:
Step 1: Verify the CSR1000v IPv4 addressπ
-
From the CSR1000v VM, use the
show ip interface briefcommand to verify the IPv4 address of the GigabitEthernet1 interface. The CSR1000v should be using the IPv4 address from the10.0.2.0/24address space.CSR1kv# show ip interface brief Interface IP-Address OK? Method Status Protocol GigabitEthernet1 10.0.2.5 YES DHCP up up CSR1kv#Important
Make note of this address and use it in the rest of this lab in place of the default of
10.0.2.5.
Step 2: Ping the CSR1000v VM from the DEVASC VM VMπ
-
Switch to the DEVASC VM VM.
-
Open a Terminal window.
-
Ping the CSR1000v VM at its IPv4 address (press Ctrl+C to stop the pings). Make sure to replace
10.0.2.5with the IP address you noted at the end of Step 1.devasc@labvm:~/labs/devnet-src/ansible$ ping 10.0.2.5 PING 10.0.2.5 (10.0.2.5) 56(84) bytes of data. 64 bytes from 10.0.2.5: icmp_seq=1 ttl=255 time=7.62 ms 64 bytes from 10.0.2.5: icmp_seq=2 ttl=255 time=1.27 ms 64 bytes from 10.0.2.5: icmp_seq=3 ttl=255 time=1.39 ms 64 bytes from 10.0.2.5: icmp_seq=4 ttl=255 time=1.59 ms ^C --- 10.0.2.5 ping statistics --- 4 packets transmitted, 4 received, 0% packet loss, time 3011ms devasc@labvm:~/labs/devnet-src/ansible$Important
Ensure that these pings are successful, and not timing out or giving other errors, before moving on.
Step 3: Establish a secure shell (SSH) session with the CSR1000vπ
Some of the tasks you will complete in later labs will require an SSH session with the CSR1000v.
-
Connect to the CSR1000v with SSH from the DEVASC VM. If you are prompted to accept the RSA key, type
yes. Use the passwordcisco123!to authenticate. Notice that you are automatically in privileged EXEC mode. Typeexitto end the SSH session. Remember to use the IP address of your CSR1000v VM in place of the one used in the example.devasc@labvm:~/labs/devnet-src/ansible$ ssh cisco@10.0.2.5 Password: * * ** ** *** *** *** Cisco Networking Academy *** *** *** *** This software is provided for *** *** Educational Purposes *** *** Only in Networking Academies *** *** *** ** ** * * CSR1kv# exit Connection to 10.0.2.5 closed by remote host. Connection to 10.0.2.5 closed. devasc@labvm:~/labs/devnet-src/ansible$
Step 4: From the DEVASC VM, access the CSR1000v WebUI (Web User Interface)π
-
Open the Chromium Web Browser on the DEVASC VM.
-
For the URL enter:
https://10.0.2.5Note
Be sure to use
httpsand the IP address of your CSR1000v VM. -
If your browser displays a warning similar to, Your connection is not private:
-
Click Advanced.
-
Click Proceed to 10.0.2.5 (unsafe).
-
-
You will now see a LOGIN screen. Enter the following:
-
Username:
cisco -
Password:
cisco123! -
Click LOGIN NOW.
You will now see the Dashboard for the CSR1000v. You are now accessing the CSR1000v's WebUI from the DEVASC virtual machine.
Note
At any time when you are done with the CSR1000v VM, simply shut it down from VirtualBox Manager. If you are continuing immediately to the next part of the lab, leave the CSR1000v VM running.
-
6.4 Use Ansible to Back Up and Configure a Deviceπ
Objectivesπ
Part 1: Configure Ansible
Part 2: Use Ansible to Back up a Configuration
Part 3: Use Ansible to Configure a Device
Backgroundπ
In this lab, you will explore the fundamentals of how to use Ansible to automate some basic device management tasks. First, you will configure Ansible in your DEVASC VM. Next, you will use Ansible to connect to the CSR1000v and back up its configuration. Finally, you will configure the CSR1000v with IPv6 addressing using Ansible.
Instructionsπ
Part 1: Configure Ansibleπ
In this part, you will configure Ansible to run from a specific directory.
Important
Ensure that both the DEVASC VM and the CSR100v VM are running and completely loaded before starting this lab.
Step 1: Open the Ansible directory in VS Codeπ
-
Open VS Code .
-
Click File > Open Folder... and navigate to the
~/labs/devnet-src/ansiblefolder. -
Click Open.
-
The two subdirectories for the Ansible labs are now loaded in the VS Code EXPLORER pane for your convenience. In this part of the lab, you will work with the
ansible-csr1000vdirectory.Note
If prompted, check the Trust the authors of all files in the parent folder 'devnet-src' box, and click Yes, I trust the authors
Step 2: Edit the Ansible inventory fileπ
Ansible uses an inventory file called hosts that contains device information used by Ansible playbooks. The default location for the Ansible inventory file is /etc/ansible/hosts as specified in the default ansible.cfg in the same /etc/ansible directory.
These default files are used when Ansible is run globally. However, in this lab you will run Ansible from the ansible-csr1000v directory. Therefore, you need separate hosts and ansible.cfg files for each lab.
Note
The terms hosts file and inventory file are synonymous and will be used interchangeably throughout the Ansible labs.
The Ansible inventory file defines the devices and groups of devices that are used by the Ansible playbook. The file can be in one of many formats, including YAML and INI, depending on your Ansible environment. The inventory file can list devices by IP address or fully qualified domain name (FQDN) and may include host specific parameters as well.
-
In VS Code, open the
hostsfile in theansible-csr1000vdirectory (not theansible-apachedirectory!). -
Add the following lines to the
hostsfile and save (use the IP address of your CSR1kv VM from lab 6.2). Note that the line starting withCSR1kvis all one line, ending with theansible_network_os parameter.# Enter the hosts or devices for Ansible playbooks CSR1kv ansible_user=cisco ansible_password=cisco123! ansible_host=10.0.2.5 ansible_network_os=iosAfter the comment (
#), thehostsfile begins with an alias,CSR1kv. An alias is used from within the Ansible playbook to reference a device. After the alias, thehostsfile specifies three variables that will be used by the Ansible playbook to access the device. These are the SSH credentials Ansible needs to securely access the CSR1000v VM.-
ansible_useris a variable containing the username used to connect to the remote device. Without this, the user that is running the Ansible playbook would be used. -
ansible_passwordis a variable containing the corresponding password foransible_user. If not specified, the SSH key would be used. -
ansible_hostis a variable containing the IP address or FQDN of the device. -
ansible_network_osis a variable containing the operating system of the network device, in this case, Cisco IOS
-
-
Save the
hostsfile when you are done.
Step 3: Display the Ansible version and default ansible.cfg locationπ
-
To see where Ansible stores the default
ansible.cfgfile, first open a terminal window and navigate to~/labs/devnet-src/ansible.devasc@labvm:~/$ cd ~/labs/devnet-src/ansible devasc@labvm:~/labs/devnet-src/ansible$ -
Type
ansibleto get a list of the ansible commands. Notice the--versionoption.devasc@labvm:~/labs/devnet-src/ansible$ ansible usage: ansible [-h] [--version] [-v] [-b] [--become-method BECOME_METHOD] [--become-user BECOME_USER] [-K] [-i INVENTORY] [--list-hosts] [-l SUBSET] [-P POLL_INTERVAL] [-B SECONDS] [-o] [-t TREE] [-k] [--private-key PRIVATE_KEY_FILE] [-u REMOTE_USER] [-c CONNECTION] [-T TIMEOUT] [--ssh-common-args SSH_COMMON_ARGS] <output omitted> devasc@labvm:~/labs/devnet-src/ansible$ -
Use the
ansible --versioncommand to display version information. Notice that this lab is using version 2.9.9. Ansible also includes certain default files in the output, including a default configuration file,ansible.cfg.devasc@labvm:~/labs/devnet-src/ansible$ ansible --version ansible 2.9.9 config file = /etc/ansible/ansible.cfg configured module search path = ['/home/devasc/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules'] ansible python module location = /usr/lib/python3/dist-packages/ansible executable location = /usr/bin/ansible python version = 3.8.2 (default, Apr 27 2020, 15:53:34) [GCC 9.3.0] devasc@labvm:~/labs/devnet-src/ansible$
Step 4: Display the default ansible.cfg fileπ
The ansible.cfg file is used by Ansible to set certain default values. These values can be modified.
-
Using the default path displayed in the
ansible --versioncommand, display the default configuration file. Notice this is a very long file. You can pipe the output of thecatcommand tomoreso that it displays one page at a time. Highlighted are the entries that will be in youransible.cfgfile for this lab. Don't change any settings in this file!devasc@labvm:~/labs/devnet-src/ansible$ cat /etc/ansible/ansible.cfg | more # config file for ansible -- https://ansible.com/ # =============================================== # nearly all parameters can be overridden in ansible-playbook # or with command line flags. ansible will read ANSIBLE_CONFIG, # ansible.cfg in the current working directory, .ansible.cfg in # the home directory or /etc/ansible/ansible.cfg, whichever it # finds first [defaults] # some basic default values... #inventory = /etc/ansible/hosts <output omitted> # uncomment this to disable SSH key host checking #host_key_checking = False <output omitted> # retry files # When a playbook fails a .retry file can be created that will be placed in ~/ # You can enable this feature by setting retry_files_enabled to True # and you can change the location of the files by setting retry_files_save_path #retry_files_enabled = False <output omitted> devasc@labvm:~/labs/devnet-src/ansible$Notice that Ansible shows that the inventory
hostsfile it will use by default is/etc/ansible/hosts. In a previous step, you edited the inventoryhostsfile in theansible-csr1000vdirectory. In the next step you will edit a newansible.cfgfile to use thehostsinventory file that you created earlier instead of the default one.
Step 5: Change the location of the ansible.cfg fileπ
-
Ansible will use the config file located in
/etc/ansible/ansible.cfgunless there is an ansible.cfg file in the current directory. Change to theansible-csr1000vdirectory. There is already a placeholderansible.cfgfile in this directory. Display the current location ofansible.cfgwith theansible --versioncommand.devasc@labvm:~/labs/devnet-src/ansible$ cd ansible-csr1000v/ devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ ansible --version ansible 2.9.9 config file = /home/devasc/labs/devnet-src/ansible/ansible-csr1000v/ansible.cfg <output omitted> devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ -
Display the file to see that it is empty, except for a single comment. You will edit this file in the next step.
devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ cat ansible.cfg # Add to this file for the Ansible lab devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$
Step 6: Edit the ansible.cfg fileπ
Now, you need to edit your ~/labs/devnet-src/ansible/ansible-csr1000v/ansible.cfg file to include the location of your hosts inventory file. Remember, the default config file in /etc/ansible/ansible.cfg uses the inventory file in /etc/ansible/hosts.
- Open the
~/labs/devnet-src/ansible/ansible-csr1000v/ansible.cfgfile in VS Code . -
You can remove the comment. Add the following lines to the file and save it.
# config file for ansible-csr1000v [defaults] # Use local hosts file in this folder inventory=./hosts host_key_checking = False # Don't worry about RSA Fingerprints retry_files_enabled = False # Do not create "retry files" deprecation_warnings = False # Do not show warningsLike Python, the
#is used for comments within theansible.cfgfile. If the entry refers to a file name such asinventory=./hoststhe comment cannot come after the entry. Ansible treats the#and the comment that follows as part of the filename.Therefore, in these cases, the
#comment must be on a separate line. However, variables can have a comment on the same line as shown forhost_key_checkingandretry_files_enabled.The
ansible.cfgfile tells Ansible where to find the inventory file and sets certain default parameters. The information you entered in youransible.cfgfile is as follows:-
inventory=./hosts- Your inventory file is thehostsfile in the current directory. -
host_key_checking = False- The local development environment does not have SSH keys set up. You have set thehost_key_checkingto False, which is the default. In a production network,host_key_checkingwould be set to True. -
retry_files_enabled = False- When Ansible has problems running playbooks for a host, it will output the name of the host into a file in the current directory ending in.retry. To prevent clutter, it is common to disable this setting. -
deprecation_warnings=False- Deprecation warnings indicate usage of legacy features that are slated for removal in a future release of Ansible. You have disabled this warning.
-
Part 2: Use Ansible to Back up a Configurationπ
In this part, you will create an Ansible playbook that will automate the process of backing up the configuration of the CSR1000v. Playbooks are at the center of Ansible. When you want Ansible to get information or perform an action on a device or group of devices, you run a playbook to get the job done.
An Ansible playbook is a YAML file containing one or more plays. Each play is a collection of tasks.
-
A play is a matching set of tasks to a device or group of devices.
-
A task is a single action that references a module to run along with any input arguments and actions. These tasks can be simple or complex depending on the necessary permissions, the order to run the tasks, and so on.
A playbook may also contain roles. A role is a mechanism for breaking a playbook into multiple components or files, simplifying the playbook and making it easier to reuse. For example, the common role is used to store tasks that can be used across all of your playbooks. Roles are beyond the scope of this lab.
The Ansible YAML playbook includes objects, lists and modules.
-
A YAML object is one or more key/value pairs. Key/value pairs are separated by a colon without the use of quotation marks, for example
hosts: CSR1kv. -
An object can contain other objects such as a list. YAML uses lists or arrays. A hyphen
-is used for each element in the list. -
Ansible ships with a number of modules (called the module library) that can be executed directly on remote hosts or through playbooks. An example is the
ios_commandmodule used to send commands to a Cisco IOS device and return the results. Each task typically consists of one or more Ansible modules.
You run an Ansible playbook using the ansible-playbook command, for example:
ansible-playbook backup_cisco_router_playbook.yaml -i hosts
The ansible-playbook command uses parameters to specify:
-
The playbook you want to run (
backup_cisco_router_playbook.yaml) -
The inventory file and its location (
-i hosts).
Step 1: Create your Ansible playbookπ
The Ansible playbook is a YAML file. Make sure you use the proper YAML indentation. Every space and dash is significant. You may lose some formatting if you copy and paste the code in this lab, therefore, it's recommend you write this code out manually.
-
In VS Code , create a new file in the
ansible-csr1000vdirectory calledbackup_cisco_router_playbook.yaml.Important
Be careful to use this exact filename for the autograder to grade your work properly!
-
Add the following information to the file (indents are 2 spaces each). Save the file when you are done.
--- - name: AUTOMATIC BACKUP OF RUNNING-CONFIG hosts: CSR1kv gather_facts: false connection: network_cli tasks: - name: DISPLAYING THE RUNNING-CONFIG ios_command: commands: - show running-config register: config - name: SAVE OUTPUT TO ./backups/ copy: content: "{{ config.stdout[0] }}" dest: "backups/show_run_{{ inventory_hostname }}.txt"
Step 2: Examine your Ansible playbookπ
The playbook you have created contains one play with two tasks. The following is an explanation of your playbook:
-
---This is at the beginning of every YAML file, which indicates to YAML that this is a separate document. Each file may contain multiple documents separated by--- -
name: AUTOMATIC BACKUP OF RUNNING-CONFIG- This is the name of the play. -
hosts: CSR1kv- This is the alias of the device in the previously configuredhostsfile. By referring to this alias in your playbook, the playbook can use all the parameters associated with this inventory file entry which includes theusername,password, andIP addressof the device. -
gather_facts: false- At the start of a playbook, Ansible will gather facts about the remote device, such as the OS version, IP addresses, and hardware. This is not needed for our particular playbook, but is often very useful for automating many devices at once. -
connection: network_cli- Uses a plugin specifically for connecting to the CLI of network devices. -
tasks:- This keyword indicates one or more tasks to be performed.
The first task is to display the running-config.
-
name: DISPLAYING THE RUNNING-CONFIG- The name of this task. -
ios_command:- This is an Ansible module that is used to send commands to a Cisco IOS device and return the results read from the device. However, it does not support configuration commands. Theios_configmodule is used for this purpose, as you will see in the next Part of this lab.
Note
In the Linux terminal, you can use the ansible-doc <module_name> command to view the manual pages for any module and the parameters associated with that module. (e.g. ansible-doc ios_command)
-
commands:- This parameter is associated with theios_commandmodule. It is used to list the Cisco IOS commands in the playbook that are to be sent to the remote device. The resulting output from the command is returned. -
show running-config- This is the Cisco IOS command sent using theios_commandmodule. -
register: config- Ansible includes registers used to capture output of a task to a variable. This entry specifies that the output from the previousshow running-configcommand will be stored in the variableconfig.
The second task is to save the output:
-
name: SAVE OUTPUT TO ./backups/- The name of this task -
copy:- This is an Ansible module used to copy files to a remote location. There are two parameters associated with this module:-
content: "{{ config.stdout[0] }}"- The specified value for this parameter is the data stored in theconfigvariable, the Ansible register variable used in the previous task. Standard output (stdout) is the default file descriptor where a process can write output used in Unix-like operating systems, such as Linux and Mac OS X. -
dest: "backups/show_run_{{ inventory_hostname }}.txt"- This is the path and file name to where the file should be copied. Theinventory_hostnamevariable is an Ansible "magic variable" that automatically uses the hostname as configured in thehostsfile. In your case, recall that this isCSR1kv. This parameter results in a file namedshow_run_CSR1kv.txtstored in thebackupsdirectory. The file will contain the output of theshow running-configcommand. You will create thebackupsdirectory in the next step.
-
Step 3: Run the Ansible backup Playbookπ
-
In Part 1, you started the CSR1000v VM. Ping it to verify you can access it (use the address of your CSR1kv, which might not be the same as the example). Enter Ctrl+C to abort the ping.
devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ ping 10.0.2.5 PING 10.0.2.5 (10.0.2.5) 56(84) bytes of data. 64 bytes from 10.0.2.5: icmp_seq=1 ttl=63 time=0.913 ms 64 bytes from 10.0.2.5: icmp_seq=2 ttl=63 time=0.875 ms ^C --- 10.0.2.5 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1000ms rtt min/avg/max/mdev = 0.875/0.894/0.913/0.019 ms devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ -
Create the
backupsdirectory. As indicated in the last line of your playbook, this is the directory where the backup configuration file will be stored.devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ mkdir backupsImportant
Make sure you are still in the
~/labs/devnet-src/ansible/ansible-csr1000vwhen you run themkdircommand. -
Now you can run the Ansible playbook using the
ansible-playbookcommand:Ansible Shell Sessiondevasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ ansible-playbook backup_cisco_router_playbook.yaml PLAY [AUTOMATIC BACKUP OF RUNNING-CONFIG] ****************************************************************************** TASK [DISPLAYING THE RUNNING-CONFIG] *********************************************************************************** ok: [CSR1kv] TASK [SAVE OUTPUT TO ./backups/] *************************************************************************************** changed: [CSR1kv] PLAY RECAP ************************************************************************************************************* CSR1kv : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$Note
In many examples you will see the playbook run using the
-i <inventory-filename>option. For example:devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ ansible-playbook backup_cisco_router_playbook.yaml -i hostsThis option tells Ansible the location and name of the inventory file; the list of devices the playbook will use. This option is not necessary because you configured the inventory file name and location in your local
ansible.cfgfile:inventory=./hosts. You can use the-i <inventory-filename>option to override the information in theansible.cfgfile.The PLAY RECAP should display
ok=2 changed=1indicating a successful playbook execution.If your Ansible playbook fails, some of the things to check in your playbook are:
-
Make sure your
hostsandansible.cfgfiles are correct. -
Make sure the YAML indentation is correct.
-
Make sure your IOS command is correct.
-
Check all the Ansible playbook syntax.
-
Verify you can ping the CSR1000v.
If you continue to have problems, try typing one line at a time and running the playbook each time.
-
Step 4: Verify the backup file has been createdπ
-
In VS Code , open the
backupsfolder and open theshow_run_CSR1kv.txtfile. You can also use the terminal window to cat the file withcat backups/show_run_CSR1kv.txt. You now have a backup of the CSR1000v configuration.devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ cat backups/show_run_CSR1kv.txt Building configuration... Current configuration : 4004 bytes ! ! Last configuration change at 23:57:14 UTC Sun May 17 2020 ! version 16.9 service timestamps debug datetime msec service timestamps log datetime msec platform qfp utilization monitor load 80 no platform punt-keepalive disable-kernel-core platform console virtual ! hostname CSR1kv ! <output omitted>
Part 3: Use Ansible to Configure a Deviceπ
In this part, you will create another Ansible playbook to configure IPv6 addressing on the CSR1000v router.
Step 1: View your hosts inventory fileπ
-
Re-examine your
hostsinventory file. As a reminder, this file contains the aliasCSR1kvand three inventory variables for theusername,password, andhost IP address. The playbook for this part will also use this file and theansible.cfgfile you created early in the lab.devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ cat hosts # Enter the hosts or devices for Ansible playbooks CSR1kv ansible_user=cisco ansible_password=cisco123! ansible_host=10.0.2.5 ansible_network_os=ios devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$
Step 2: Create a new playbookπ
-
In VS Code , create a new file in the
ansible-csr1000vdirectory calledcisco_router_ipv6_config_playbook.yaml.Important
Be careful to use this exact filename for the autograder to grade your work properly!
-
Add the following information to the file. Make sure you use the proper YAML indentation. Every space and dash is significant. You may lose some formatting if you copy and paste the code in this lab, therefore, it's recommend you write this code out manually. Save the file when you are done.
--- - name: CONFIGURE IPv6 ADDRESSING hosts: CSR1kv gather_facts: false connection: network_cli tasks: - name: SET IPv6 ADDRESS ios_config: parents: "interface GigabitEthernet1" lines: - description IPv6 ADDRESS - ipv6 address 2001:DB8:ACAD:1::1/64 - ipv6 address FE80::1:1 link-local - name: SHOW IPv6 INTERFACE BRIEF ios_command: commands: - show ipv6 interface brief register: output - name: SAVE OUTPUT ./ios_configurations/ copy: content: "{{ output.stdout[0] }}" dest: "ios_configurations/IPv6_output_{{ inventory_hostname }}.txt"
Step 3: Examine your Ansible playbookπ
Much of this playbook is similar to the playbook you created in the previous part. The main difference is the first task SET IPv6 ADDRESS.
The following is a brief description of the items in the task:
-
ios_config:- This is an Ansible module used to configure an IOS device. You can use theansible-doc ios_configcommand to see the details for the parents and lines parameters used in this playbook. -
parents: "interface GigabitEthernet1"- This parameter indicates the interface to configure. -
lines:- An ordered set of IOS commands are configured in this section, specifying the IPv6 addressing information for the GigabitEthernet1 interface.
The rest of the playbook is similar to the tasks in the previous part. The second task uses the ios_command module and the command show ipv6 interface brief to display output and send it to the register output.
The last task saves the information in the register output to a file IPv6_output_CSR1kv.txt in the ios_configurations subdirectory.
Note
for Cisco IOS configuration playbooks to be considered idempotent, you must use the full commands as they would appear in the running configuration, not shortened versions (e.g., use no shutdown rather than no shut, or interface GigabitEthernet1 rather than int g1).
Step 4: Run the Ansible playbook to configure IPv6 addressing on the CSR1000v VMπ
-
In Part 1, you started the CSR1000v VM. Ping it to verify you can still access it. Enter Ctrl+C to abort the ping.
devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ ping 10.0.2.5 PING 10.0.2.5 (10.0.2.5) 56(84) bytes of data. 64 bytes from 10.0.2.5: icmp_seq=1 ttl=63 time=0.913 ms 64 bytes from 10.0.2.5: icmp_seq=2 ttl=63 time=0.875 ms ^C --- 10.0.2.5 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1000ms rtt min/avg/max/mdev = 0.875/0.894/0.913/0.019 ms devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ -
Create the directory
ios_configurations. As indicated in the last line of your playbook, this is the directory where the output for theshow ipv6 interface briefcommand will be stored.devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ mkdir ios_configurations devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ -
Now you can run the Ansible playbook using the
ansible-playbookcommand. The-vverbose option can be used to display the tasks being performed in the playbook.devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ ansible-playbook -v cisco_router_ipv6_config_playbook.yaml Using /home/devasc/labs/devnet-src/ansible/ansible-csr1000v/ansible.cfg as config file PLAY [CONFIGURE IPv6 ADDRESSING] *********************************************** TASK [SET IPv6 ADDRESS] ******************************************************** changed: [CSR1kv] => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"}, "banners": {}, "changed": true, "commands": ["interface GigabitEthernet1", "description IPv6 ADDRESS", "ipv6 address 2001:DB8:ACAD:1::1/64", "ipv6 address FE80::1:1 link-local"], "updates": ["interface GigabitEthernet1", "description IPv6 ADDRESS", "ipv6 address 2001:DB8:ACAD:1::1/64", "ipv6 address FE80::1:1 link-local"]} TASK [SHOW IPv6 INTERFACE BRIEF] *********************************************** ok: [CSR1kv] => {"changed": false, "stdout": ["GigabitEthernet1 [up/up]\n FE80::1:1\n 2001:DB8:ACAD:1::1"], "stdout_lines": [["GigabitEthernet1 [up/up]", " FE80::1:1", " 2001:DB8:ACAD:1::1"]]} TASK [SAVE OUTPUT ./ios_configurations/] *************************************** changed: [CSR1kv] => {"changed": true, "checksum": "60784fbaae4bd825b7d4f121c450effe529b553c", "dest": "ios_configurations/IPv6_output_CSR1kv.txt", "gid": 900, "group": "devasc", "md5sum": "56e879f15e6e776cf131cec5abfc1886", "mode": "0664", "owner": "devasc", "size": 67, "src": "/home/devasc/.ansible/tmp/ansible-local-3897abxawwgb/ansible-tmp-1710014758.4905267-3965-179789089872527/source", "state": "file", "uid": 900} PLAY RECAP ********************************************************************* CSR1kv : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$Note
The first time you run the playbook, the
PLAY RECAPshould displayok=3changed=2andfailed=0indicating a successful execution.
Step 5: Verify the file of the output has been createdπ
-
In VS Code , open the
ios_configurationsfolder and click theIPv6_output_CSR1kv.txtfile. You can also use the terminal window to view the file withcat ios_configurations/IPv6_output_CSR1kv.txt. This displays the IPv6 addresses of GigabitEthernet1.devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ cat ios_configurations/IPv6_output_CSR1kv.txt GigabitEthernet1 [up/up] FE80::1:1 2001:DB8:ACAD:1::1 devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$
Step 6: Verify the configuration has changed on the CSR1kv VMπ
-
Switch to the CSR1kv VM and enter the command
show ipv6 interface briefand confirm that you see the newly configured IPv6 address on GigabitEthernet1.CSR1kv# show ipv6 interface brief GigabitEthernet1 [up/up] FE80::1:1 2001:DB8:ACAD:1::1 CSR1kv#
Step 7: Test the idempotency of the Ansible playbookπ
Idempotency means that running the same procedure multiple times will always result in the same end state. In the case of this Ansible playbook, Ansible should not make any changes to the switch or saved output file if the IPv6 address is already configured on GigabitEthernet1.
-
Execute the playbook again and watch the output to see how it is different from the first time you ran it.
devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ ansible-playbook -v cisco_router_ipv6_config_playbook.yaml Using /home/devasc/labs/devnet-src/ansible/ansible-csr1000v/ansible.cfg as config file PLAY [CONFIGURE IPv6 ADDRESSING] *********************************************** TASK [SET IPv6 ADDRESS] ******************************************************** ok: [CSR1kv] => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"}, "changed": false} TASK [SHOW IPv6 INTERFACE BRIEF] *********************************************** ok: [CSR1kv] => {"changed": false, "stdout": ["GigabitEthernet1 [up/up]\n FE80::1:1\n 2001:DB8:ACAD:1::1"], "stdout_lines": [["GigabitEthernet1 [up/up]", " FE80::1:1", " 2001:DB8:ACAD:1::1"]]} TASK [SAVE OUTPUT ./ios_configurations/] *************************************** ok: [CSR1kv] => {"changed": false, "checksum": "60784fbaae4bd825b7d4f121c450effe529b553c", "dest": "ios_configurations/IPv6_output_CSR1kv.txt", "gid": 900, "group": "devasc", "mode": "0664", "owner": "devasc", "path": "ios_configurations/IPv6_output_CSR1kv.txt", "size": 67, "state": "file", "uid": 900} PLAY RECAP ********************************************************************* CSR1kv : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0Notice that the output now says
ok=3andchanged=0. Ansible has recognized that everything is already at the desired end state and made no changes (idempotency). If you watch the timestamp on theIPv6_output_CSR1kv.txtfile, youβll also notice that it does not change when you rerun the playbook.
Step 8: Commit the changes to the repositoryπ
-
Use
git statusto see which files have been added and modified since the last commit.devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ git status On branch main Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) modified: ansible.cfg modified: hosts Untracked files: (use "git add <file>..." to include in what will be committed) backup_cisco_router_playbook.yaml backups/ cisco_router_ipv6_config_playbook.yaml ios_configurations/ no changes added to commit (use "git add" and/or "git commit -a") devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ -
Add all the files and folders to the staging area with
git add .(donβt miss the "." at the end). Verify all files have now been staged withgit status.devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ git add . devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ git status On branch main Changes to be committed: (use "git restore --staged <file>..." to unstage) modified: ansible.cfg new file: backup_cisco_router_playbook.yaml new file: backups/show_run_CSR1kv.txt new file: cisco_router_ipv6_config_playbook.yaml modified: hosts new file: ios_configurations/IPv6_output_CSR1kv.txt devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ -
Commit the changes to the local repository using the message Completed Ansible router configuration playbooks.
devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ git commit -m "Completed Ansible router configuration playbooks" [main fa87e3c] Completed Ansible router configuration playbooks 6 files changed, 239 insertions(+), 1 deletion(-) create mode 100644 ansible-csr1000v/backup_cisco_router_playbook.yaml create mode 100644 ansible-csr1000v/backups/show_run_CSR1kv.txt create mode 100644 ansible-csr1000v/cisco_router_ipv6_config_playbook.yaml create mode 100644 ansible-csr1000v/ios_configurations/IPv6_output_CSR1kv.txt devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$Note
You can now shut down the CSR1kv virtual machine as it is no longer needed for the rest of the lab.
6.5 Use Ansible to Automate Installing a Web Serverπ
Objectivesπ
Part 1: Configure Ansible
Part 2: Verify Communications with the Local Webserver
Part 3: Create Ansible Playbooks to Automate Webserver Installation
Part 4: Add Options to Your Ansible Playbook for Apache Web Servers
Backgroundπ
In this lab, you will first configure Ansible so that it can communicate with a webserver application. You will then create a playbook that will automate the process of installing Apache on the webserver. You will also create a customized playbook that installs Apache with specific instructions.
Instructionsπ
Part 1: Configure Ansibleπ
The DEVASC VM comes preinstalled with a number of dummy IPv4 addresses you can use for various scenarios and simulations. In this Part, you will configure Ansible to use one of the dummy IPv4 addresses for a local webserver.
Step 1: Enable the SSH serverπ
-
Open a new Terminal window in the DEVASC VM
-
The SSH server is disabled in the DEVASC VM, along with other services that are typically not required. Start it with the following command.
devasc@labvm:~/labs/devnet-src/ansible$ sudo systemctl start ssh devasc@labvm:~/labs/devnet-src/ansible$Note
The SSH server and sshpass utility have already been installed in your VM. For your reference, these are installed using the following commands (you do not need to run these now!): Install SSH
devasc@labvm:~/labs/devnet-src/ansible$ sudo apt-get install openssh-serverInstall sshpass
devasc@labvm:~/labs/devnet-src/ansible$ sudo apt-get install sshpass
Step 2: Open the ansible directory in VS Codeπ
-
Open VS Code .
-
Click File > Open Folder... and navigate to the
/labs/devnet-src/ansiblefolder if itβs not already open. -
Click Open.
-
The two subdirectories for the Ansible labs are now loaded in the VS Code EXPLORER pane for your convenience. In this lab, you will work with the
ansible-apachedirectory.Note
If prompted, check the Trust the authors of all files in the parent folder βdevnet-srcβ box, and click Yes, I trust the authors
Step 3: Edit the Ansible inventory fileπ
-
Open the
hostsfile in theansible-apachedirectory (notansible-csr1000v). -
Add the following lines to the hosts file and save.
[webservers] 192.0.2.3 ansible_ssh_user=devasc ansible_ssh_pass=Cisco123! -
The credentials
devascandCisco123!are admin credentials for the DEVASC VM. The IPv4 address you will use for this lab is192.0.2.3. This is a static IPv4 address on the VM under thedummy0interface, as shown in the output for theip addrcommand.devasc@labvm:~/labs/devnet-src/ansible$ ip addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether 08:00:27:97:ae:11 brd ff:ff:ff:ff:ff:ff inet 10.0.2.15/24 brd 10.0.2.255 scope global dynamic enp0s3 valid_lft 45882sec preferred_lft 45882sec inet6 fe80::a00:27ff:fe97:ae11/64 scope link valid_lft forever preferred_lft forever 3: dummy0: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default qlen 1000 link/ether a6:44:a7:e8:6a:9e brd ff:ff:ff:ff:ff:ff inet 192.0.2.1/32 scope global dummy0 valid_lft forever preferred_lft forever inet 192.0.2.2/32 scope global dummy0 valid_lft forever preferred_lft forever inet 192.0.2.3/32 scope global dummy0 valid_lft forever preferred_lft forever inet 192.0.2.4/32 scope global dummy0 valid_lft forever preferred_lft forever inet 192.0.2.5/32 scope global dummy0 valid_lft forever preferred_lft forever inet6 fe80::a444:a7ff:fee8:6a9e/64 scope link valid_lft forever preferred_lft forever 4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default link/ether 02:42:9c:cb:fc:7c brd ff:ff:ff:ff:ff:ff inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0 valid_lft forever preferred_lft forever devasc@labvm:~/labs/devnet-src/ansible$
Step 5: Edit the ansible.cfg fileπ
-
In VS Code , open the
ansible.cfgin theansible-apachesubdirectory. -
You can remove the comment. Add the following lines to the file and save it. The
ansible.cfgfile tells Ansible where to find the inventory file and sets certain default parameters.[defaults] # Use local hosts file in this folder inventory=./hosts # Don't worry about RSA Fingerprints host_key_checking = False # Do not create retry files retry_files_enabled = False
Part 2: Verify Communications with the Local Webserverπ
In this Part, you will verify that Ansible can send commands to the local webserver.
Step 1: Use the ping module to verify that Ansible can ping the webserverπ
-
In the Terminal window, change to the
ansible-apachedirectory and use the Ansiblepingmodule to verify communications with the devices listed within thewebserversgroup of yourhostsinventory file.devasc@labvm:~/labs/devnet-src/ansible$ cd ansible-apache devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$ ansible webservers -m ping 192.0.2.3 | SUCCESS => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python3" }, "changed": false, "ping": "pong" } devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$Note
If multiple devices were listed under the
webserversgroup in yourhostsinventory file, the output would indicate similar information for each device.
Step 2: Use the command module to verify Ansible can communicate with the webserverπ
-
Use the Ansible
commandmodule to verify communications with the devices listed within thewebserversgroup of yourhostsinventory file. In this example you send the argument-a "/bin/echo hello world"to ask the local webserver to respond with "hello world".devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$ ansible webservers -m command -a "/bin/echo hello world" 192.0.2.3 | CHANGED | rc=0 >> hello world devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$
Part 3: Create Ansible Playbooks to Automate Webserver Installationπ
In this Part, you will create two Ansible playbooks. The first playbook will automate the echo test you did in the previous Part.
Imagine you are bringing a hundred webservers online. The [webserver] group in the hosts file would list all the necessary information for each webserver. You can then use a simple playbook to verify communications with all of them with one command.
In the second playbook, you will create and automate the installation of Apache webserver software.
Step 1: Create your Ansible playbook to test your webserver groupπ
In this step you will create an Ansible playbook to perform the same echo command.
-
In VS Code , create a new file in the
ansible-apachedirectory calledtest_apache_playbook.yaml.Important
Be careful to use this exact filename for the autograder to grade your work properly!
-
Add the following information to the file. Make sure you use the proper YAML indentation. Every space and dash is significant. You may lose some formatting if you copy and paste the code in this lab, therefore, it's recommend you write this code out manually. Save the file when you are done.
--- - hosts: webservers tasks: - name: run echo command command: /bin/echo hello world
Step 2: Run the Ansible playbook to test your webserver groupπ
-
Run the Ansible playbook using the
ansible-playbookcommand using the-vverbose option. You should see output similar to the following.devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$ ansible-playbook -v test_apache_playbook.yaml Using /home/devasc/labs/ansible/ansible-apache/ansible.cfg as config file PLAY [webservers] ************************************************************** TASK [Gathering Facts] ********************************************************* ok: [192.0.2.3] TASK [run echo command] ******************************************************** changed: [192.0.2.3] => {"changed": true, "cmd": ["/bin/echo", "hello", "world"], "delta": "0:00:00.002062", "end": "2020-05-20 21:35:32.346595", "rc": 0, "start": "2020-05-20 21:35:32.344533", "stderr": "", "stderr_lines": [], "stdout": "hello world", "stdout_lines": ["hello world"]czjqqkd:77} PLAY RECAP ********************************************************************* 192.0.2.3 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$
Step 3: Create your Ansible playbook to install Apacheπ
-
In VS Code , create a new file in the
ansible-apachedirectory calledinstall_apache_playbook.yaml.Important
Be careful to use this exact filename for the autograder to grade your work properly!
-
Add the following information to the file. Make sure you use the proper YAML indentation. Every space and dash is significant. You may lose some formatting if you copy and paste the code in this lab, therefore, it's recommend you write this code out manually. Save the file when you are done. The highlighted text is explained in the next step.
--- - hosts: webservers become: yes tasks: - name: INSTALL APACHE2 apt: name=apache2 update_cache=yes state=latest - name: ENABLE MOD_REWRITE apache2_module: name=rewrite state=present notify: - RESTART APACHE2 handlers: - name: RESTART APACHE2 service: name=apache2 state=restarted
Step 4: Examine your Ansible playbookπ
The following is an explanation of some of the significant lines in your playbook:
-
hosts: webservers- This references thewebserversgroup of devices in yourhostsinventory file. This playbook will be run for all the devices with this group. -
become: yes- Thebecomekeyword activatessudocommand execution, which will allow tasks such as installing applications. On a Cisco device, this would be equivalent to usingenableto get to Privileged EXEC. -
apt:- Theaptmodule is used to manage packages and application installations on Linux. In this case, you are telling Ansible to useaptto install the latest version ofapache2if its not already installed. -
handlers:- Handlers are similar to a task but are not run automatically. They are called by another task, similar to how a function in programming is called. Notice that the taskENABLE MOD_REWRITEcalls the handlerRESTART APACHE2.
Step 5: Run the Ansible backup to install Apacheπ
-
Run the Ansible playbook using the
ansible-playbookcommand using the-vverbose option. The first time Apache installed on your VM, the taskINSTALL APACHE2will take anywhere from 30 seconds to a few minutes depending on your internet speed.devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$ ansible-playbook install_apache_playbook.yaml Using /home/devasc/labs/ansible/ansible-apache/ansible.cfg as config file PLAY [webservers] ************************************************************** TASK [Gathering Facts] ********************************************************* ok: [192.0.2.3] TASK [INSTALL APACHE2] ********************************************************* changed: [192.0.2.3] TASK [ENABLE MOD_REWRITE] ****************************************************** changed: [192.0.2.3] RUNNING HANDLER [RESTART APACHE2] ********************************************** changed: [192.0.2.3] PLAY RECAP ********************************************************************* 192.0.2.3 : ok=4 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$Note
The PLAY RECAP should display
ok=4andfailed=0indicating a successful playbook execution. If you run the playbook again you should getchanged=0rather thanchanged=3, because the playbook is idempotent and will not make changes if the server is already in the desired state.
Step 6: Verify Apache has been installedπ
-
Use the following command to verify that Apache is now installed. Press Q to quit.
devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$ sudo systemctl status apache2 β apache2.service - The Apache HTTP Server Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor preset: enabled) Active: active (running) since Thu 2026-03-12 22:30:26 UTC; 1min 41s ago Docs: https://httpd.apache.org/docs/2.4/ Process: 17777 ExecStart=/usr/sbin/apachectl start (code=exited, status=0/SUCCESS) Main PID: 17801 (apache2) Tasks: 55 (limit: 4628) Memory: 5.3M CGroup: /system.slice/apache2.service ββ17801 /usr/sbin/apache2 -k start ββ17803 /usr/sbin/apache2 -k start ββ17804 /usr/sbin/apache2 -k start Mar 12 22:30:26 labvm systemd[1]: Starting The Apache HTTP Server... Mar 12 22:30:26 labvm systemd[1]: Started The Apache HTTP Server. devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$ -
Open the Chromium Web Browser and enter the IPv4 address for your new server,
192.0.2.3, to see the default Apache2 web page.
Part 4: Add Options to Your Ansible Playbook for Apache Web Serversπ
In a production environment, the Apache2 default installation is typically customized for the specific features needed by the organization. An Ansible playbook can help automate these configuration tasks, as well. In this part, you will customize your playbook by specifying that the Apache server use a different port number.
Step 1: Create your Ansible playbook for installing Apacheπ
-
In VS Code , create a new file in the
ansible-apachedirectory calledinstall_apache_options_playbook.yamlImportant
Be careful to use this exact filename for the autograder to grade your work properly!
-
Add the following information to the file. Make sure you use the proper YAML indentation. Every space and dash is significant. You may lose some formatting if you copy and paste the code in this lab, therefore, it's recommend you write this code out manually. Save the file when you are done.
--- - hosts: webservers become: yes tasks: - name: INSTALL APACHE2 apt: name=apache2 update_cache=yes state=latest - name: ENABLE MOD_REWRITE apache2_module: name=rewrite state=present notify: - RESTART APACHE2 - name: APACHE2 LISTEN ON PORT 8081 lineinfile: dest=/etc/apache2/ports.conf regexp="^Listen 80" line="Listen 8081" state=present notify: - RESTART APACHE2 - name: APACHE2 VIRTUALHOST ON PORT 8081 lineinfile: dest=/etc/apache2/sites-available/000-default.conf regexp="^<VirtualHost \*:80>" line="<VirtualHost *:8081>" state=present notify: - RESTART APACHE2 handlers: - name: RESTART APACHE2 service: name=apache2 state=restartedImportant
The lines that include
lineinfileshould each be on one line in your file, including theregexp=,line=, andstate=parameters. They may appear on multiple lines on this page due to word wrapping.This playlist is very similar to the previous one with the addition of two tasks that have the webservers listen on port 8081 instead of port 80.
The
lineinfilemodule is used to replace existing lines in the/etc/apache2/ports.confand/etc/apache2/sites-available/000-default.conffiles using Regular Expressions (regexp). You can search the Ansible documentation for more information on thelineinfilemodule.
Step 2: Examine the two files that will be modified by the playbookπ
-
Display the files
/etc/apache2/ports.confand/etc/apache2/sites-available/000-default.conf. Notice the webserver is currently listening on port 80.devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$ cat /etc/apache2/ports.conf # If you just change the port or add more ports here, you will likely also # have to change the VirtualHost statement in # /etc/apache2/sites-enabled/000-default.conf Listen 80 <IfModule ssl_module> Listen 443 <output omitted> devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$ cat /etc/apache2/sites-available/000-default.conf <VirtualHost *:80> # The ServerName directive sets the request scheme, hostname and port that # the server uses to identify itself. This is used when creating # redirection URLs. In the context of virtual hosts, the ServerName <output omitted> devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$
Step 3: Run the Ansible Playbookπ
-
Run the Ansible playbook using the
ansible-playbookcommand.devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$ ansible-playbook install_apache_options_playbook.yaml PLAY [webservers] ************************************************************** TASK [Gathering Facts] ********************************************************* ok: [192.0.2.3] TASK [INSTALL APACHE2] ********************************************************* ok: [192.0.2.3] TASK [ENABLE MOD_REWRITE] ****************************************************** ok: [192.0.2.3] TASK [APACHE2 LISTEN ON PORT 8081] ********************************************* changed: [192.0.2.3] TASK [APACHE2 VIRTUALHOST ON PORT 8081] **************************************** changed: [192.0.2.3] RUNNING HANDLER [RESTART APACHE2] ********************************************** changed: [192.0.2.3] PLAY RECAP ********************************************************************* 192.0.2.3 : ok=6 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$Note
The PLAY RECAP should display
ok=6andfailed=0indicating a successful playbook execution. You also will see the two PORT tasks are marked aschanged. Note if you run the playbook again you should getchanged=0rather thanchanged=3, because the playbook is idempotent and will not make changes if the server is already in the desired state.
Step 4: Verify that Apache has been installedπ
-
View the files
/etc/apache2/ports.confand/etc/apache2/sites-available/000-default.confagain. Notice that the playbook modified these files to listen on port 8081.devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$ cat /etc/apache2/ports.conf # If you just change the port or add more ports here, you will likely also # have to change the VirtualHost statement in # /etc/apache2/sites-enabled/000-default.conf Listen 8081 <IfModule ssl_module> Listen 443 </IfModule> <IfModule mod_gnutls.c> Listen 443 </IfModule> <output omitted> devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$ cat /etc/apache2/sites-available/000-default.conf <VirtualHost *:8081> # The ServerName directive sets the request scheme, hostname and port that # the server uses to identify itself. This is used when creating # redirection URLs. In the context of virtual hosts, the ServerName <output omitted> devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$ -
Open the Chromium web browser and enter the IPv4 address for your new server. But this time specify 8081 as the port number,
192.0.2.3:8081, to see the default Apache2 web page.Note
Although you can see in the
ports.conffile that Apache2 is also listening on port 443, this is for secure HTTP (HTTPS). You have not yet configured Apache2 for secure access. This, of course, would be added to your Ansible playbook, but is beyond the scope of this lab.
Step 5: Push your changes to GitHubπ
-
Use
git statusto see which files have been added and modified since the last commit.devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$ git status On branch main Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) modified: ansible.cfg modified: hosts Untracked files: (use "git add <file>..." to include in what will be committed) install_apache_options_playbook.yaml install_apache_playbook.yaml test_apache_playbook.yaml no changes added to commit (use "git add" and/or "git commit -a") devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$ -
Add all the files and folders to the staging area with
git add .(donβt miss the "." at the end). Verify all files have now been staged withgit status.devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$ git add . devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$ git status On branch main Changes to be committed: (use "git restore --staged <file>..." to unstage) modified: ansible.cfg modified: hosts new file: install_apache_options_playbook.yaml new file: install_apache_playbook.yaml new file: test_apache_playbook.yaml devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$ -
Commit the changes to the local repository using the message Lab Complete!.
devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$ git commit -m "Lab Complete!" [main 3e465ca] Lab Complete! 5 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 ansible-apache/install_apache_options_playbook.yaml create mode 100644 ansible-apache/install_apache_playbook.yaml create mode 100644 ansible-apache/test_apache_playbook.yaml devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$ -
Push all the changes you made in the local repository back to the GitHub repository to complete the lab. Remember to use your Personal Access Token when asked for your GitHub password.
Tip
If youβve configured your VM to use SSH to connect to GitHub instead of HTTPS, you will not be asked for a username and password, although you may be asked for a passphrase for your SSH key, if you configured one.
devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$ git push origin main Username for 'https://github.com': username Password for 'https://username@github.com': Personal Access Token Enumerating objects: 26, done. Counting objects: 100% (23/23), done. Delta compression using up to 2 threads Compressing objects: 100% (18/18), done. Writing objects: 100% (19/19), 4.91 KiB | 4.92 MiB/s, done. Total 19 (delta 3), reused 0 (delta 0), pack-reused 0 (from 0) remote: Resolving deltas: 100% (3/3), completed with 1 local object. To github.com:Ontario-Tech-NITS/lab-6-infrastructure-automation-josh-test-student.git aa2d83e..3e465ca main -> main devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$ -
In your browser, return to the repository on github.com and verify all your changes are present, along with the corresponding commit messages. Wait a minute or so for the autograder tests to complete and ensure that it says passing in green.













