Introduction
This article has practice questions for ansible, which can be very useful to prepare for your Red Hat Certified Engineer exam.
LAB
Your Lab should consist of one controller node and four managed nodes. If you think your laptop does not have enough MEMORY or storage to run 6 VMs, you can order VPS from SeiMaxim. At least one node should have a separate disk attached to the nodes so you can practice partitions, LVMs, etc.
This article is not designed as a sample exam. I‘ve tried to create the sample questions in blocks of similar topics. Before attempting, you need to configure your systems to create an environment for your question. So please utilize snapshots to revert to your original state in a short period.
Questions about Ansible Installation and configuration
Question:1
Creating inventory files is the most critical aspect of an ansible environment, and this exam question is imminent.
- Install ansible in controller node.
- Group creation for your inventory file should be as shown below:
node1 should be the member of proxy group node2 and node3 should be the member of webservers group. node4 should be the member of database group. Create a new group called “prod” and put your webservers group in that new group.
Answer:1
To install Ansible, you can follow this link seimaxim.
You can create an inventory file like shown below:
[proxy] node1 [webservers] node2 node3 [database] node4 [prod:children] webservers
Questions about ad-hoc commands
Question:1
-
- Create repository file for MariaDB server using the ad-hoc command with the following commands:
- name: MariaDB
- description: Repository MariaDB-Server
- base URL: http://yum.mariadb.org/10.5/centos8-amd64
- GPGKEY: https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
- GPGCHECK: yes
- enabled: active
*You can even create a playbook instead of a shell script.
Question:2
This question prepares your environment so your ansible user can perform the tasks.
- Generate the script which creates the user named “ali” and copies the SSH public key of user “ansible”.
- User ali, which you have created, should be able to be a SUDO.
Question:3
-
- Set Red Hat Enterprise Linux ISO as a disk to the node:
- whatever hypervisor you are using, attach the ISO image with the repo server, so mount /dev/sr0 to /mnt and have all the files from the ISO into the /mnt.
- make a directory named /repo and copy everything to /mnt/repo.
- In the last part, you can generate repo files with the following information:
- The first repo file should contain the BaseOS, and the second repo file should contain the AppStream.
- baseuls of both files are file:///repo/BaseOS & file:///repo/AppStream, respectively.
- gpgcheck must of 0.
Answers: Questions about ad-hoc commands
Answer: 1
ansible database -m yum_repository -a "name=mariadb description='Repository MariaDB-Server' baseurl='http://yum.mariadb.org/10.5/centos8-amd64' gpgkey='https://yum.mariadb.org/RPM-GPG-KEY-MariaDB' gpgcheck=yes enabled=yes" -b
You can create a file repo.sh and put the above-mentioned query into that file, make it executable, and run it.
Answer2: Create a file “vim adhoc.sh”.
#!/bin/bash /usr/local/bin/ansible all -b -m user -a "name=ali state=present" /usr/local/bin/ansible all -b -m file -a "path=/home/ali/.ssh state=directory owner=ali" /usr/local/bin/ansible all -b -m copy -a "src=/home/ali/.ssh/id_rsa.pub dest=/home/ali/.ssh/authorized_keys directory_mode=yes" /usr/local/bin/ansible all -b -m lineinfile -a "path=/etc/sudoers state=present line='ali ALL=(ALL) NOPASSWD: ALL'"
once you exit from adhoc.sh file, make it executable with ” chmod +x adhoc.sh”.
Answer3: You can try it by yourself.
Questions about file content – variables & facts
Question: 1
-
- Create a playbook, which can do as shown below:
- Create a file on all the servers at this path /etc/motd.
- The file contains “MY SERVER”.
Question: 2
-
- Create a playbook, which can do as shown below:
- Create a file on all the servers at this path /etc/motd.
- The file contains “MY SERVER: <Server Name> “.
you replace the server Name with the actual HOSTNAME of the server.
Question: 3
-
- Create a playbook, which can do as shown below:
- The existing file (/etc/motd) should be removed ( if any).
- host group proxy should have the line “This Is PROXY Server”.
- Host group webservers should have the line “These Are The WEBSERVERS”.
- Host group database should have the line “This is “DATABASE server
Question: 4
-
- In this question, you are going to practice the configuration of the SSH Server.
- Create a playbook, which can do the following tasks:
Set banner to /etc/motd X11Forwarding is disabled MaxAuthTries is set to 3
Question: 5
- Create a playbook such as servers.yml, which should generate the network file as shown below:
- Servers.yml must use a jinja2 file called servers.j2, and when servers.yml is executed, it creates the file servers.txt on the servers group of webservers and database servers.
for example, your file should contain information as shown below:
<FQDN> <HOSTNAME> <IPADDRESS> node1.seimaxim.com node1 192.168.1.12
Question: 6
- Create a playbook, which generates a file named “details.txt” file on each server with the following information:
The file should be placed in the root directory: /root
HOSTNAME: <hostname> MEMORY_TOTAL: <Total actual memory should be presented here> MEMORY_FREE: <Free Memory available on the system> IPV4: <IP address of the system> FQDN: <fqdn> SDA_DISK_SIZE: </dev/sda1 disk size> SDC_DISK_SIZE: </dev/sdc> #if disk is not attach,it should put NONE
Question: 7
- Create a playbook that checks the file’s existence.
print the message “File Exists” if the file exists and print the message “File does not exist”if the file does not exist.
Question: 8
- Create a playbook that performs the shown below actions:
- Change the line “Listen 80” in the /etc/httpd/conf/httpd.conf to “Listen 8080”.
- Allow the port 8080 in firewall and restart the httpd services
Question: 9
- Create a playbook that performs the shown below actions:
- Change the default target to the multi-user.target with the file module by using links. don’t use shell command to set-default target.
Question: 10
- Create a playbook that performs the shown below actions:
- Run this playbook against the webservers group.
- A custom Ansible fact server_role=webservers is created that can be retrieved from ansible_local.custom.sample_exam when using Ansible setup module.
Answers : Questions about file content – variables & facts
Answer: 1
[ali@control ansible]$ vi motd.yml --- - hosts: all become: yes tasks: - name: Write content in the file copy: dest: /etc/motd content: "MY SERVER"
Answer: 2
[ali@control ansible]$ vi motd.q2.yml --- - hosts: webservers become: yes tasks: - name: Write content in the file copy: dest: /etc/motd content: "MY SERVER: {{ ansible_facts['hostname']}}"
Answer: 3
[ali@control ansible]$ cat motd.q3.yml --- - hosts: all become: yes tasks: - name: Generate the file motd content file: path: /etc/mtd state: absent - name: Proxy Server file content copy: dest: /etc/motd content: "This Is PROXY Server" when: "'proxy' in group_names" - name: WEBSERVERS file content copy: dest: /etc/motd content: "These Are The WEBSERVERS" when: "'webservers' in group_names" - name: Database Server file content copy: dest: /etc/motd content: "This is DATABASE Server&amp;amp;amp;amp;amp;amp;quot" when: "'database' in group_names"
Answer: 4
--- - hosts: all become: yes tasks: - name: Set Banner to /etc/motd lineinfile: path: /etc/ssh/sshd_config regex: "^Banner" line: "Banner /etc/motd" - name: Disable X11Forwarding lineinfile: path: /etc/ssh/sshd_config regex: "^X11Forwarding" line: "X11Forwarding no" - name: Set MaxAuthTries to 3 lineinfile: path: /etc/ssh/sshd_config regex: "^MaxAuthTries" line: "MaxAuthTries 3"
Answer: 5
cat servers.yml --- - hosts: all become: yes tasks: - name: Generating a file by the jinja2 file template: src: servers.j2 dest: /root/servers.txt
[ali@control ansible]$ vi servers.j2 {% for host in groups['webservers']%} {{ hostvars[host]['ansible_facts']['fqdn']}} {{ hostvars[host]['ansible_facts']['hostname']}} {{ hostvars[host]['ansible_facts']['default_ipv4']['address']}} {% endfor %}
To check if the files has been generated. [ali@control ansible]$ ansible all -m shell -a "cat /root/servers*" -b node3 | CHANGED | node2.seimaxim.com node2 10.0.2.15 node3.seimaxim.com node3 10.0.2.15 node4 | CHANGED | node2.seimaxim.com node2 10.0.2.15 node3.seimaxim.com node3 10.0.2.15 node1 | CHANGED | node2.seimaxim.com node2 10.0.2.15 node3.seimaxim.com node3 10.0.2.15 node2 | CHANGED | node2.seimaxim.com node2 10.0.2.15 node3.seimaxim.com node3 10.0.2.15
Answer: 6
--- - hosts: all become: yes tasks: - name: generate a report blockinfile: path: /root/report.txt create: yes block: | MEMORY_TOTAL: {{ ansible_facts['memtotal_mb' ]}} MEMORY_FREE: {{ ansible_facts['memfree_mb' ]}} HOSTNAME: {{ ansible_facts['hostname']}} IPV4: {{ ansible_facts['default_ipv4']['address']}} FQDN: {{ ansible_facts['fqdn'] }} SDA_DISK_SIZE: {{ ansible_facts['devices']['sda']['partitions']['sda1']['size'] }} SDB_DISK_SIZE: {{ ansible_devices.sdc.size | default('NONE') }}
You can check it by this command
#To check the report's content run shown below command [ali@control ansible]$ ansible all -m shell -a "cat /root/report.txt" -b
Answer: 7
--- - hosts: all become: yes tasks: - name: Check if the file exists stat: path: /var/www/html/index.html # or you can put the path of your desired file register: result - debug: msg: "THE FILE EXISTS" when: result.stat.exists == true - debug: msg: "THE FILE DOES'T EXIST" when: result.stat.exists == false
Answer: 8
# you must have installed httpd or you can put any other file to practice this senario --- - hosts: webservers become: yes tasks: - name: Modify the content of httpd.conf replace: path: /etc/httpd/conf/httpd.conf regexp: 'Listen 80' replace: 'Listen 8080' notify: restart_httpd handlers: - name: restart_httpd # must be same as notify service: name: httpd state: restarted
Answer: 9
--- - hosts: database become: yes tasks: - name: Change the default target file: src: /usr/lib/systemd/system/multi-user.target dest: /etc/systemd/system/default.target state: link
Answer: 10
--- - hosts: webservers become: yes tasks: - name: Ensure the directory exists file: path: "/etc/ansible/facts.d/" state: directory recurse: yes - name: Copy content to file in new directory copy: content: "[sample_exam]nserver_role=webserversn" dest: "/etc/ansible/facts.d/custom.fact"
Questions about packages installation
Question: 1
- Create a yml file, which performs the below tasks on webservers(httpd).
- Install the latest firewall and httpd.
- Make sure that your httpd service is allowed through firewalls.
- Create a file /var/www/html/index.html and put the entry “Server name is: hostname” so the hostname in the index.html should be replaced with the actual hostname from the system.
For example, when we do curl http://node2 it should give me “Server name is: node2”.
Question: 2
-
- Create a playbook that performs the shown below activities:
- The playbook will create a directory /webdir with the permission of 2755, and the owner is also webdir user.
- You should have already configured apache to run your page from /var/www/html/index.html.
- Create a link of your index.html in the /webdir, which should be accessible with the http://node1/webdir/index.html.
- Your /var/www/webdir/index.hml should contain “I AM FROM WEBDIR”.
- Answers: Questions about packages installation
Answer: 1
--- - hosts: webservers become: yes tasks: - name: Install packages on webservers yum: name: - httpd - firewalld state: latest - name: Start firewalld and httpd on webservers service: name: "{{ item }}" state: started enabled: yes loop: - httpd - firewalld - name: Opening Port through FW firewalld: service: http permanent: yes immediate: yes state: enabled - name: Creation of index.html copy: dest: /var/www/html/index.html content: "Server name is: {{ ansible_facts['hostname'] }}"
Answer: 2
--- - hosts: node2 become: yes tasks: - name: Create the webdir user user: name: webdir state: present - name: Create a directory file: mode: '2755' path: /webdir state: directory - name: Create Symbolic Link file: src: /webdir dest: /var/www/html/webdir state: link - name: Create index.html copy: dest: /var/www/html/webdir/index.html content: " I AM FROM WEBDIR"
Questions about users & groups
Question: 1
- Create a playbook that performs the shown below tasks:
- Create a group on all the servers named “admin”.
- Create a group on all the servers named “members”.
Here is the file user_list.yml, In the exam, it will be provided.
--- users: - username: eli uid: 1201 password: abcdeXYZ group: admin - username: vincent uid: 1202 password: cdefgXYZ group: admin - username: sandy uid: 2201 password: edfegZBC group: members - username: patrick uid: 2202 password: gjfezBCG group: members
- Users whose user ID starts with 1 should be created on servers in the webservers host group. The user password, shell, and UID should be used from the user_list.yml variable file.
- Users whose user ID starts with 2 should be created on servers in the database host group. The user password, shell, and UID should be used from the user_list.yml variable.
- Users uid starting from 1* should be the member of supplementary group admin.
- Users uid starting from 2* should be the member of supplementary group members.
- The shell should be set to
/bin/bash
for all users. - Account passwords should use the SHA512 hash format.
- The SSH Key of your main ansible user should be uploaded. Dont generate the new SSH key just use your primary ansible user key, which you are using to connect from the controller node.
Answers: Questions about users & groups
Answer:1
--- - hosts: all become: yes vars_files: - user_list.yml tasks: - name: Create the group named admin group: name: admin state: present - name: Create the group named admin group: name: members state: present - name: Create users on webservers whose user ID starts with 1 user: name: "{{ item.username }}" shell: /bin/bash groups: "{{ item.group }}" append: yes uid: "{{ item.uid }}" password: "{{ item.password | password_hash('sha512') }}" with_items: "{{ users }}" when: - "'webservers' in group_names" - "item.uid|string|first == '1'" - name: Create users on database whose user ID starts with 2 user: name: "{{ item.username }}" shell: /bin/bash groups: "{{ item.group }}" append: yes uid: "{{ item.uid }}" password: "{{ item.password | password_hash('sha512') }}" with_items: "{{ users }}" when: - "'database' in group_names" - "item.uid|string|first == '2'" - name: Create SSH directory for users on webservers hosts file: path: "/home/{{ item.username }}/.ssh/" state: directory owner: "{{ item.username }}" group: "{{ item.group}}" mode: "0700" with_items: "{{ users }}" when: - "'webservers' in group_names" - "item.uid|string|first == '1'" - name: Create SSH directory for users on database hosts file: path: "/home/{{ item.username }}/.ssh/" state: directory owner: "{{ item.username }}" group: "{{ item.group }}" mode: "0700" with_items: "{{ users }}" when: - "'database' in group_names" - "item.uid|string|first == '2'" - name: Copy private SSH-key to users on the webserver hosts copy: src: /home/ali/.ssh/id_rsa.pub dest: "/home/{{ item.username }}/.ssh/authorized_keys" owner: "{{ item.username }}" group: "{{ item.group }}" mode: "0600" with_items: "{{ users }}" when: - "'webservers' in group_names" - "item.uid|string|first == '1'" - name: Copy private SSH-key to users on the database hosts copy: src: /home/ali/.ssh/id_rsa.pub dest: "/home/{{ item.username }}/.ssh/authorized_keys" owner: "{{ item.username }}" group: "{{ item.username }}" mode: "0600" with_items: "{{ users }}" when: - "'database' in group_names" - "item.uid|string|first == '2'"
Questions about roles
Question: 1
- Use ansible Galaxy to download and Install the ansible-galaxy role named geerlingguy.nginx
- The requirement file should install this role.
- change the name to Nginx
Question: 2
Create a role called apache and store it in your ansible directory “roles”. This role should satisfy the requirements below:
- The httpd, mod_ssl and php packages are installed. Apache service is running and enabled on boot.
- The firewall is configured to allow all incoming traffic on HTTP port TCP 80 and HTTPS port TCP 443.
- Apache service should be restarted every time the file
/var/www/html/index.html
is modified. - A Jinja2 template file
index.html.j2
is used to create the file/var/www/html/index.html
with the following content:
The address of the server is: IPV4ADDRESS
IPV4ADDRESS is the IP address of the managed node.
Create a playbook /home/automation/plays/apache.yml
that uses the role and runs on hosts in the webservers host group.
Question: 3
- Create a playbook of any name, and that playbook should do as shown below:
- The playbook runs over all the managed hosts and uses the time sync role ( Red Hat system role)
- This role should be able to change the time server to nl.pool.ntp.org .
Answers: Questions about roles
Answer:1
Step 1: Type "ansible-galaxy search nginx --author geerlingguy --platforms EL" to find the geeglinguy.nginx role Step 2: "ansible-galaxy info geerlingguy.nginx" to check more information about this role. Step 3: Create requirement.yml file as show below:
- src: geerlingguy.nginx version: "2.7.0" name: Nginx
Step 4: Run this commad "ansible-galaxy install -r requirement.yml" Step 5: Run "ansible-galaxy list" to make sure that new role has been installed sucessfully. [Note] Prior to this task you need to have ansible-galaxy in your system. Make sure you have added the correct path of roles directory in your ansible.cfg file with roles_path =< Path of your ansible directory to have the roles >
Answer: 2
Step 1: Create the empty role by "ansible-galaxy init apache" run this command in your roles directory, for it is /home/ali/ansible/roles Step 2: Create the handler file roles/apache/handlers/main.yml.
--- - name: restart_apache service: name: httpd state: restarted enabled: yes
Step 3: Create the main task file roles/apache/tasks/main.yml
--- - name: Ensure the packages httpd, mod_ssl and php are installed yum: name: "{{ item }}" state: latest loop: - httpd - mod_ssl - php - name: Ensure that the service httpd is enabled service: name: httpd state: started enabled: yes - name: Ensure the firewall ports 80 and 443 are open firewalld: service: "{{ item }}" permanent: yes immediate: yes state: enabled loop: - http - https - name: Create index.html from template template: src: index.html.j2 dest: /var/www/html/index.html notify: restart_apache ...
Step 4: Create a template file index.html.j2.
The address of the server is: {{ ansible_facts['default_ipv4']['address']}}
Step 5: Create a general apache file to run the role.
--- - hosts: webservers become: yes roles: - apache
Answer: 3
Step 1: you must have RHEL system roles installed and settled all the paths. Step 2: Copy the roles into your ansible directory or change the path of roles_path in ansible.cfg file. Step 3: Copy /usr/share/doc/rhel-sytem-roles/timesync/example-timesync-playbook.yml to home directory. Step 4: Edit the file has shome below: --- - hosts: all vars: timesync_ntp_servers: - hostname: nl.pool.ntp.org ibrust: yes roles: - rhel-system-roles.timesync Step 5: Run shown above yaml file to settle the ntp server.
Questions about disk partitions and LVM
Question: 1-A
- Create a playbook that should perform the following tasks:
- Create a primary partition on /dev/sdb disk with the size of 2GB ( or anything according to your availability: just keep a couple of GBs for the next question).
- Create a volume group named “RedHat”.
- Create an lv named “exam”.
- Formate the new lv as xfs.
- Create a new directory named /mydir on it.
- Mount /mydir so it can sustain the reboot.
Question: 2-B
- Create a playbook that performs the following tasks:
- Use the remaining VG “RedHat” space and create a new LV named “ex294”.
- Formate the new lv with ext4.
- Create a folder named “/exam” and mount it so it can sustain the reboot.
Answers: Questions about disk partitions and LVM
Answer: Q1A
--- - hosts: database become: yes tasks: - name: Create The Partition parted: device: "/dev/sdb" number: 1 state: present part_end: 1GiB - name: Create VG lvg: vg: "RedHat" pvs: "/dev/sdb1" - name: Create LV lvol: lv: "exam" vg: "RedHat" size: 500m - name: Formate filesystem: fstype: "xfs" dev: "/dev/mapper/RedHat-exam" - name: Mount the FS mount: path: "/mydir" src: "/dev/mapper/RedHat-exam" fstype: "xfs" state: mounted
Answer: Q1B
--- - hosts: database become: yes tasks: - name: Create New LV On existing VG lvol: lv: "ex294" vg: "RedHat" size: 100%FREE - name: Format new LV filesystem: fstype: "ext4" dev: "/dev/mapper/RedHat-ex294" - name: Mount new volume mount: path: "/exam" src: "/dev/mapper/RedHat-ex294" fstype: "ext4" state: mounted
Questions about cron
Question: 1
- Create a playbook that performs the following tasks:
- Should create a crontab file /etc/cron.d/uptime.
- The task must run by the user ( any user you wish in your server).
- Every 5th minute from 9 to 5 on weekdays.
- The task should run uptime and put an entry here: /home/ali/ansible/my_uptime_cron.txt.
Question: 2
- Create a playbook that performs the following tasks:
- Create a root crontab record that runs every hour.
- The cron job appends the file
/var/log/time.log
with the output from the date command.
Question: 3
- Create a playbook, which should perform shown below tasks:
- Runs a fstrim command every day at 8:30 AM and 4:30 PM.
Question: 4
- Create a playbook, which should perform shown below tasks:
- Remove the corn job which you created in Q3.
Question: 5
- Create a yaml file, which should perform shown below tasks:
- Run a backup of /etc/passwd, /etc/group & /etc/shadow
Answers: Questions about cron
Answer:1
--- - hosts: all become: yes tasks: - name: Crontab file cron: name: uptime command user: ali minute: "*/5" hour: 9-5 days: 1-5 job: "uptime &amp;amp;amp;amp;amp;amp;gt;&amp;amp;amp;amp;amp;amp;gt; /home/ali/ansible/my_uptime_cron.txt" cron_file: my_uptime_cron.txt state: present
Answer: 2
--- - hosts: all become: yes tasks: - name: Create crontab-record on proxy hosts cron: name: "Append the output of 'date' to /var/log/time.log" minute: "0" job: "date &amp;amp;amp;amp;amp;amp;gt;&amp;amp;amp;amp;amp;amp;gt; /var/log/time.log"
Answer: 3
--- - hosts: all become: tasks: - name: Run Fstrim cron: name: "Run FSTRIM" minute: "30" hour: "8,4" job: "fstrim -a"
Answer: 4
--- - hosts: all become: tasks: - name: Run Fstrim cron: name: "Run FSTRIM" state: absent
Answer: 5
--- - hosts: all become: yes tasks: - name: Backup user data cron: name: Backup Users hour: 5 minute: 30 weekday: 1-5 user: root job: 'tar -czf /root/user.tgz /etc/passwd /etc/shadow' cron_file: user_backup