Which Red Hat CoE are the easiest or hardest

Maybe you have decided you want to go move on from your RHCSA/RHCE and want to take some ‘Certificate of Expertise’ level exams. Red Hat offer a range of exams, and from this range you can select 5 exams and become a Red Hat Certified Architect. A title that only lasts 3 years (from the date of your first CoE exam). Take a 6th exam and you are RHCA Level 2, take a 7th and you are RHCA Level 3 and so on.

but first some housekeeping …

Hit like if you like this post and would like to see more like it, or follow to be kept informed of any new posts

 

You can find a list of RHCA exams here: https://www.redhat.com/en/services/certification/rhca

rhca-coe-hardest0

Once upon a time, How hard Red Hat Exams are were loosely based on their numbering system:
– A 200-level exam would be at a System Administrator Level
– A 300-level exam would be at a RHCE Level
– A 400-level exam would be at a Advanced Level (RHCE+)

This has changed in recent years but can sometimes still provide a rough guide. I have tried to search a few different sites trying to gather other people’s opinions on how hard they found exams and try and collate them into a list. Obviously how hard someone finds an exam is very subjective but if 10 people say an exam is hard; then the exam is probably going to be hard.

Please note that blog post is based on other people’s comments rather than my own experiences.

hardest-banner

 

Based on what I have found, people fall into 3 main camps:

1. Path of Least Resistance i.e. Easiest exams

These are people that will cherry pick the easiest exams to obtain the RHCA

2. Linux Guru – Toughest Exams

These are people that will cherry pick the hardest exams to try and prove their worth

3. Interest/Work-focused

These are people who mix and match between easy and hard exams, and often link them to ones they do at work or are already familiar with.
I would urge you to consider which of the above you are – are you trying to obtain a title OR are you trying to obtaining skills? I wasn’t able to find out about every exam – but below are the trends I found:

Exams consistently rated as easy:

These are the exams that are almost universally considered Easy, I either found no one (or very few) people claiming they were hard and lots that consider them easy.

– EX318 Virtualization
– EX210 OpenStack
– EX436 Clustering

Exams consistently rated as hard:

These are the exams that are almost universally considered Hard, I either found no one (or very few) people claiming they were easy and lots that consider them hard.
– EX333 Network Services – No Longer available
– EX442 Performance Tuning – Considered the hardest exam still available
– EX342 Troubleshooting

Exams inconsistently rated:

And finally, these are the exams that I found some people claiming were really easy and others claiming them as really hard. However I will mention that more people considered them hard than easy.

– EX280 OpenShift
– EX405 Puppet
– EX407 Ansible

Word of warning:

What I would say in conclusion, is that none of these exams are “gimme’s” that is to say if you do not prepare and walk into an exam based on you being “The main man(or woman) at work” or “I am so good and experienced that I don’t need to study” – you are almost certainly going to fail.

EX407 Requirement 9: Download roles from an Ansible Galaxy and use them

Disclaimer:

These are my notes following my self-study on Ansible. No material comes from either Red Hat course or the Red Hat exam. You will not find any NDA information here. All contents are my own thoughts/understanding on the subject matter.

Requirement:

The following is taken from official Red Hat Exam requirements.

Download roles from an Ansible Galaxy and use them

My notes:

Firstly please familiarise yourself with my post introducing roles

 

Ansible Galaxy is the community website for Ansible Roles. Here you will find many good (and many more not-so-good) roles. You are normally able to download and install them – but please be sensible.

 

Searching for a role

You can either use a browser and go to https://galaxy.ansible.com/ or use the command line

$ ansible-galaxy search httpd

Found 161 roles matching your search:

Name Description
—- ———–
2kloc.trellis-monit Install and configure Monit service in Trellis.
acropia.httpd IT Professional

 

Installing a role

# download into default location
sudo ansible-galaxy install geerlingguy.apache
# download into specified folder (called roles)
ansible-galaxy install geerlingguy.apache -p role

Note: you can use –offline for non-internet connected machines

Once downloaded, you can reference them like my example here

EX407 Requirement 8: Create and work with roles

Disclaimer:

These are my notes following my self-study on Ansible. No material comes from either Red Hat course or the Red Hat exam. You will not find any NDA information here. All contents are my own thoughts/understanding on the subject matter.

Requirement:

The following is taken from official Red Hat Exam requirements.

Create and work with roles

My notes:

This is one of the more simpler tasks, and couples well with Objective #9. I consider it simpler because it’s one of those things that I wouldn’t consider “core”. If you think about the smallest unit of measurement in terms of Ansible – you are looking at a single playbook, what roles are – is a collection of playbooks along with any required files. Essentially a Role is Ansible’s package management system.

 

Role structure

  1. defaults – default values are expected to be overwritten
  2. files – static files referenced by tasks
  3. handlers – main.yml contains handler definitions
  4. meta – main.yml contains meta information about the role (author version etc)
  5. tasks – main.yml contains list of main tasks
  6. templates – contains jinja2 template files
  7. tests – can contain a test.yml to test the role
  8. vars – main.yml has roles variables

 

Where do roles live:

They can exist:

  • Globally
  • Locally (any path)

You can view the global path by issuing command

$ grep roles_path /etc/ansible/ansible.cfg
#roles_path = /etc/ansible/roles

ls /etc/ansible/roles/
ansible-hardening-master  geerlingguy.java jpnewman.apache

As you can see above, I have downloaded 3 items into my default role location

 

Walkthrough demo of role:

 

1. Let’s create a role:

Note: it’s called Ansible-Galaxy because you can download roles from https://galaxy.ansible.com/

$ ansible-galaxy init –offline linuxbuff.testrole
– linuxbuff.testrole was created successfully

2. Let’s look at the structure of a role

These are the files that the above command has created

./README.md
./defaults
./defaults/main.yml
./files
./handlers
./handlers/main.yml
./meta
./meta/main.yml
./tasks
./tasks/main.yml
./templates
./tests
./tests/inventory
./tests/test.yml
./vars
./vars/main.yml

If you look at the main.yml (ansible version of index.html)  – you see that they are all just placeholder yml files.

You can edit as many or as few files as you wish.

3. Let’s have a play – our role will do the following

Deliver a file called /etc/mach_info

This file will contain the line (where x.x.x.x is the real IP address)

“This machine’s IP address is: x.x.x.x”

 

4. Create role steps

# Create template file (note templates are normally postfixed with .j2)

echo “This machine’s IP address is: {{ ansible_default_ipv4.address }}” > templates/mach_info.j2

# Update tasks/main.yml with

– name: deliver file
template: src=mach_info.j2 dest=/etc/mach_info

 

5. Create Playbook

One of my issues with roles is that information is held outside the role. E.g. the playbook to actually call the role isn’t part of the role. So we have to create it by hand


– hosts: all
become: yes
roles:
– linuxbuff.testrole

 

6. Let’s run the playbook (which runs the role)

[ansible@ansible1 ~]$ ansible-playbook linuxbuff.testrole.yml

PLAY [ansible1] **********************************************************************************************************************

TASK [Gathering Facts] ***************************************************************************************************************
ok: [ansible1]

TASK [linuxbuff.testrole : deliver file] *********************************************************************************************
changed: [ansible1]

PLAY RECAP ***************************************************************************************************************************
ansible1 : ok=2 changed=1 unreachable=0 failed=0

 

7. Test

[ansible@ansible1 ~]$ cat /etc/mach_info
This machine’s IP address is: 192.168.1.51

 

Variations:

There are a couple of ways of calling the roles – one example might be by passing a variable to it e.g.

--- 
- hosts: webservers
  roles:
   - role: role1
   - role: role2
     var1: val1
     var2: val2

 

 

EX407 Requirement 6: Create and use templates to create customized configuration files

Disclaimer:

These are my notes following my self-study on Ansible. No material comes from either Red Hat course or the Red Hat exam. You will not find any NDA information here. All contents are my own thoughts/understanding on the subject matter.

Requirement:

The following is taken from official Red Hat Exam requirements.

Create and use templates to create customized configuration files 

My notes:

Templates remind me of the old-school ‘mail-merge’ utilities where you take a standard file and substitute one or two elements to customise it.

The common use-case in today’s world is a response file or a configuration file. Where 95% of the file remains the same but you may with to substitute one or two lines with custom info e.g. hostname

Think of the template module as the “copy+” module. Files to be templated are typically postfixed with the .j2 extension e.g. index.html.j2

The template module will copy a file AND will run the Jinja2 parser to substitute  values enclosed in double curly braces with variables/facts e.g:

Template configuration file example:

If I had a file I wanted to delivery called app.config and it looked like the below

local_hostname = {{ ansible_hostname }}

listen_port = 809

It would will substitute to (if hostname of server is saturn1):

local_hostname = saturn1

listen_port = 809

 

Step by step guide:

1. You need a file you want to deliver which contains the tags mentioned above (as a note, if it doesn’t contain any tags it won’t error, the template will turn into a dumb copy module). We will create a basic file as below

$ cat mytemplates/foo.j2
local_hostname = {{ ansible_hostname }}
listen_port = 809

 

2. Then you call the template module with one of two syntax examples below:

# use within a role

– name: write file
template:
src: template.j2
dest: /var/www/html/index.htm

 

# use outside a role

– template:
src: ./mytemplates/foo.j2
dest: /etc/file.conf
owner: bin
group: wheel
mode: 0644

 

3. Let’s run the playbook

ansible-playbook temp.yml

PLAY [Deploy response file] ***********************************************************************************

TASK [Gathering Facts] ****************************************************************************************
ok: [ansible1]

TASK [deliver response file] **********************************************************************************
changed: [ansible1]

PLAY RECAP ****************************************************************************************************
ansible1 : ok=2 changed=1 unreachable=0 failed=0

 

4. And finally, check the output

$ ansible ansible1 -a “cat /etc/file.conf”
ansible1 | CHANGED | rc=0 >>
local_hostname = ansible1
listen_port = 809

 

I am a big fan of this module, it’s quick and powerful.

 

EX407 Requirement 4: Utilize an existing dynamic inventory script

Disclaimer:

These are my notes following my self-study on Ansible. No material comes from either Red Hat course or the Red Hat exam. You will not find any NDA information here. All contents are my own thoughts/understanding on the subject matter.

Requirement:

The following is taken from official Red Hat Exam requirements.

Utilize an existing dynamic inventory script

My notes:

An inventory is effectively one or more files that contain host information. They are typically used to group servers together, for example, you can group all your webservers together and then refer to them collectively as ‘webservers’.

It is mandatory to have an inventory file (unless running against localhost) and the default (static) inventory file is:

/etc/ansible/hosts

The inventory file is specified within the ansible configuration file:

/etc/ansible/ansible.cfg

However it is possible to update this to use an alternate (and dynamic) inventory.

 

Purpose of an (Dynamic) Inventory:

The purpose of an dynamic inventory is to be used to that the inventory details are logically separated from the Ansible configuration – this is especially relevant if your machines are cloud based or if your inventory information is volatile.

 

 

Dynamic Inventory Example Script:

A dynamic inventory is any file that is executable and outputs JSON formatted text.

Below is an example of a dynamic inventory script – note that the task specifies using an existing script rather than writing one from scratch but belt and braces and all that.

#!/bin/bash
echo “{”
echo ‘”double” : [ “node6”, “node7″ ],’
echo ‘”single” : [ “node5” ]’
echo “}”

The script respond to –list and –host <hostname> options

The above isn’t a great example but it works – your final one should support both –list and –host

 

Sample Dynamic Inventory Output:

As with any inventory file you can call it using the -i <inventorypath> option. In the below example I have called my dynamic inventory script d1.sh and given it 755 permissions.

$ ansible -i ./d1.sh all -m ping -o
node4 | SUCCESS => {“changed”: false, “ping”: “pong”}
node1 | SUCCESS => {“changed”: false, “ping”: “pong”}
node2 | SUCCESS => {“changed”: false, “ping”: “pong”}

 

It also has a default host-level variable set – this variable serves no function yet but is useful in later sections. For now, it’s only relevant to know it is possible to define a variable against a host.

 

There really isn’t too much more to it than that.

 

EX407 Requirement 3: Use both static and dynamic inventories to define groups of hosts

Disclaimer:

These are my notes following my self-study on Ansible. No material comes from either Red Hat course or the Red Hat exam. You will not find any NDA information here. All contents are my own thoughts/understanding on the subject matter.

Requirement:

The following is taken from official Red Hat Exam requirements.

Use both static and dynamic inventories to define groups of hosts

My notes:

An inventory is effectively one or more files that contain host information. They are typically used to group servers together, for example, you can group all your webservers together and then refer to them collectively as ‘webservers’.

It is mandatory to have an inventory file (unless running against localhost) and the default inventory file is:

/etc/ansible/hosts

The inventory file is specified within the ansible configuration file:

/etc/ansible/ansible.cfg

 

Purpose of an Inventory:

The purpose of an inventory is to be used alongside a playbook to target servers accordingly, this way server information is abstracted away from the code. This can be very useful where you have multiple environments where the hostnames may differ but their function is the same e.g.

DEV:

webservers: devws1, devws2

appservers: devas1, devas2

 

TEST:

webservers: testws1, testws2

appservers: testas1, testas2

 

Using the above example your playbooks would always target either webservers or appservers and wouldn’t worry about what their actual hostname was. Think of an inventory is a mapping file.

 

Inventory Types:

There are two types of Inventory: static and dynamic.

A static inventory is a plain text file which doesn’t change, it is possible to have a dynamic inventory (referenced in the same way) which is a shell script which can generate the information in the correct format. This is covered in Objective 4.

 

Sample Static Inventory:

[single]
node6 role=webserver
[double]
node7
node8
[allthree:children]
single
double
[double:vars]
role=dbserver

 

So let’s break down the above and talk through the components:

[single]
node6 role=webserver

This is a group of 1 server, the servers hostname is ‘node6’. If I wanted to run a playbook on this server I could either use the target group name of ‘single’ or use the hostname of ‘node6’

It also has a default host-level variable set – this variable serves no function yet but is useful in later sections. For now, it’s only relevant to know it is possible to define a variable against a host.

 

[double]
node7
node8

There is a group called ‘double’ which is comprised of two hosts, node7 and node8. Using the target name of ‘double’ in a playbook will apply to both hosts. It is also possible to target just a single host by using the hostname of node7 or node8

 

[allthree:children]
single
double

This is where things get a little more interesting as I have a group of groups. A group called ‘allthree’ has the 2 sub-groups called ‘single’ and ‘double’

 

[double:vars]
role=dbserver

This is another example of setting a variable, but this time it is on the group level. All group members of the group called ‘double’ will inherit the variable role of dbserver unless they have a host level variable set (which neither node7 or node8 do).

EX407 Requirement 2: Run ad-hoc Ansible commands

Disclaimer:

These are my notes following my self-study on Ansible. No material comes from either Red Hat course or the Red Hat exam. You will not find any NDA information here. All contents are my own thoughts/understanding on the subject matter.

Requirement:

The following is taken from official Red Hat Exam requirements.

Run ad-hoc Ansible commands

My notes:

Running ad-hoc commands is one of the most powerful and useful features of a tool like Ansible. It allows Ansible to go out to the target server – run the command and then produce the output.

In my example – I have two nodes – my Ansible master and my target groups, one containing a single host and one containing two hosts. Snippet below:

#/etc/ansible/hosts

[single]
node6

[double]
node6
node7

My earlier posts show how to set up Ansible.

Ad-hoc commands should be used in place of a playbook when the command is a ‘throw-away’ or a one-off. You should not use it to make changes that should be repeatable – use a playbook for that.

The general syntax is as follows:

ansible <host|group> -m <module> -a “arguments for module” [-b]

 

Example 1: Run against the double group a command to list the contents of /tmp

[ansible@node8 ~]$ ansible double -m shell -a “ls /tmp”
node6 | SUCCESS | rc=0 >>
ansible_K9ZnXc
file1

node7 | SUCCESS | rc=0 >>
ansible_5GrUB8
systemd-private-3fc12661ca9e4ebf9b763e9c2cadc46e-httpd.service-cloqmu

 

Example 2: Run against a single node a command to list the contents of /tmp

[ansible@node8 ~]$ ansible node6 -m shell -a “ls /tmp”
node6 | SUCCESS | rc=0 >>
ansible_Lnj8KU
file1

 

As you can see in the above example – it is possible to run an ad-hoc command agaisnt a single node OR against a group of servers.

Now lets try something different – my user as you can see is ‘ansible’ – this user has sudo priveleges to run root-level commands but this needs a special flag to be added to the command. Example below

 

Example 3: Root level operations

[ansible@node8 ~]$ ansible node6 -m shell -a “ls /root”
node6 | FAILED | rc=2 >>
ls: cannot open directory /root: Permission deniednon-zero return code

[ansible@node8 ~]$ ansible node6 -m shell -a “ls /root” -b
node6 | SUCCESS | rc=0 >>
anaconda-ks.cfg
conditional.pp
original-ks.cfg

 

In the first instance the command failed, the second instance used the ‘-b’ flag which allowed it to become-root.

You will need root privileges for operations such as user addition, checking secure log files etc.

 

Example 4: Add software

The earlier examples all used the shell module – this example uses the yum module

[ansible@node8 ~]$ ansible node6 -m yum -a “name=dos2unix state=present” -b
node6 | SUCCESS => {
“changed”: true,
“failed”: false,
“msg”: “Warning: RPMDB altered outside of yum.\n”,
“rc”: 0,
“results”: [
“Loaded plugins: fastestmirror, langpacks\nLoading mirror speeds from cached hostfile\n * base: centos.mirroring.pulsant.co.uk\n * extras: mozart.ee.ic.ac.uk\n * updates: mozart.ee.ic.ac.uk\nResolving Dependencies\n–> Running transaction check\n—> Package dos2unix.x86_64 0:6.0.3-7.el7 will be installed\n–> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package Arch Version Repository Size\n================================================================================\nInstalling:\n dos2unix x86_64 6.0.3-7.el7 base 74 k\n\nTransaction Summary\n================================================================================\nInstall 1 Package\n\nTotal download size: 74 k\nInstalled size: 190 k\nDownloading packages:\nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n Installing : dos2unix-6.0.3-7.el7.x86_64 1/1 \n Verifying : dos2unix-6.0.3-7.el7.x86_64 1/1 \n\nInstalled:\n dos2unix.x86_64 0:6.0.3-7.el7 \n\nComplete!\n”
]
}

 

Example 5 – Use the setup module

Ad-hoc commands are often used with the setup module to find out information about the host

[ansible@node8 ~]$ ansible single -m setup -a “filter=ansible_hostname”
node6 | SUCCESS => {
“ansible_facts”: {
“ansible_hostname”: “node6”
},
“changed”: false,
“failed”: false
}

 

Ad hoc commands really are as simple as that.

 

 

 

EX407 Requirement 1: Understand core components of Ansible

Disclaimer:

These are my notes following my self-study on Ansible. I have neither taken the Red Hat course or the Red Hat exam. All contents are my own thoughts/understanding on the subject matter.

 

Requirement:

The following is taken from official Red Hat Exam requirements.

Understand core components of Ansible

  • Inventories
  • Modules
  • Variables
  • Facts
  • Plays
  • Playbooks
  • Configuration files

 

My notes:

Ansible is an agent-less Configuration Management Tool. It uses software that is pre-installed on most Linux servers (namely openssh and sudo) to connect from a ‘master’ to a ‘client’ and then runs a series of commands based on an list of desired states. An example is ‘ensure user joe exists’. Ansible will run and ensure joe exists. It doesn’t matter whether joe existed before or not, Ansible will take care of that logic and ensure at the end it exists.

This ‘task’ isn’t a task per-se. It’s merely to understand the components of Ansible so you can use them later.

 

Inventories:

Either a dynamic or static file (default) that lists hostnames in INI format. The default inventory is /etc/ansible/hosts and has a format similar to the below

[planets]
saturn.example.com

venus.example.com

 

[oceans]

pacific.example.com

In the above inventory, there are 3 hosts. The host group planets has the hosts saturn and venus and oceans hotgroup has a single host of pacific

 

Modules:

Not to be confused with Puppet modules. In Ansible speak a module is a bit of code that does a task. There are lots of modules pre-bundled with Ansible. An example is the yum module which handles yum based package management. Another example is the file module which handles file creation.

 

Variables:

Variables can be used (just like all other programming languages) to control behaviour. It allows you to move changeable items out of playbooks. An example would be a hostname variable. This is something that doesn’t need to be hardcoded into a playbook but can be fed in to customise the flow. Variables are typically held on the master server and not the client.

 

Facts:

Very similar to variables in the way they can be used to alter behavior.  However, these are held/compiled on the client server. Each client provides hundreds of facts about itself to Ansible. An example would be the Operating System version. If the CentOS version is 7 then the Time Server package should be chrony and if it’s 6 then it should be ntp.

 

Plays:

Put simply a play is merely a list of tasks that need to be carried out. A logical Play would be to create a web server you would a.) install httpd, b.) customise the html pages and c.) start the service

 

Playbooks:

A playbook is a collection of one or more plays.

 

Configuration Files:

The main ansible configuration file is /etc/ansible/ansible.cfg – which is very nicely commented. Almost all the options are present even if they are not actively set.

 

 

Ansible Tips Series – Ansible ‘man’ Pages

Ansible comes with comprehensive documentation. With examples and is a great source of information.

In the exam, there will (presumably) be no internet connectivity. So it’s always useful to give yourself somewhere to ‘go’ for help. This should provide some information as to how this can be achieved.

List all modules

ansible-doc -l

Example of output

aos_template Manage AOS Template
apache2_mod_proxy Set and/or get members’ attributes of an Apache httpd 2.4 mod_proxy balancer pool
apache2_module enables/disables a module of the Apache2 webserver
apk Manages apk packages
apt Manages apt-packages
apt_key Add or remove an apt key
apt_repository Add and remove APT repositories

This command will list all modules and a headline of what it does.  This is useful precursor to finding the module you need but does have one issue. Unless you can identify the correct module for the required task from the title or headline then you are out of luck.

This may sound silly but there are some modules where the name isn’t explicit e.g. the get_url module can be used to download files from web servers – it could also be called web_download_file module and still be valid.

In puppet you can use puppet-doc | less to get a full listing for every ‘module’. This makes finding what you need easier. Also you can not search for Ansible documentation using the man command nor does it appear in the /usr/share/doc structure.

The following can be used to create a directory and pre-load it with all the ‘man’ pages for Ansible Modules and this can then be searched using conventional means (grep etc)

mkdir ansible-man ; cd ansible-man

ansible-doc -l | awk ‘{print $1}’ | while read CMD
do
ansible-doc $CMD > $CMD
done

The above command takes 8 minutes to run on my machine.

 

 

EX407 Self Study Analysis – Areas for focus

Disclaimer:

Please note that everything in this post is my opinion. I have not been on the course or the exam. I am not using any resources that are not freely available. I am not suggesting this is how YOU should do it – this is how I am doing it.

 

That aside, let’s jump right in.

In my previous post, I made a number of suggestions on how to handle Self-Study topics. Here I go through that process with EX407

 

Task 0:

Exam Objectives

Course Outline

 

Task 1:

Ultimately this is going to be a tightly focused exam. Nothing suggests knowing anything other than Ansible is required. So really it’s one large area for learning which is Ansible itself.

 

Task 2 and 3:

 

Following my suggestion of drawing lines between the course and the exam – leads to the following (rather messy) picture below.

ex407 comparison

  1. The items in blue map one-to-many.
  2. The items in red generally map one-to-one
  3. There do not appear to be any orphans (bar use documentation which is a given)

The Orange Box in my mind would be the high-value areas. If I was designing the exam I would do something as follows:

 

– Create multiple inventory/host files
– Create a play that uses variables to decide whether to deliver it’s payload. Ensure it performs error checking and handles a particular type of failure
– Playbooks that use different variables (including precedence)
– Do something with Ansible Vault
– Do something with Tower
– Do something basic with roles
– Run a adhoc commands to do something

 

Task 4:

If it was me creating the exam, I wouldn’t test parallelism … what’s the point? nothing. Also, it would normally mean you would need tens of servers which creates overhead. I am therefore assigning this a low priority

Roles looks like a big area, so I think exam will only ask to do a simple task.