Files
kodekloud-engineer/100 - days of devops/devops-89.md

162 lines
6.2 KiB
Markdown

# Assignment
Developers are looking for dependencies to be installed and run on Nautilus app servers in Stratos DC. They have shared some requirements with the DevOps team. Because we are now managing packages installation and services management using Ansible, some playbooks need to be created and tested. As per details mentioned below please complete the task:
a. On jump host create an Ansible playbook /home/thor/ansible/playbook.yml and configure it to install httpd on all app servers.
b. After installation make sure to start and enable httpd service on all app servers.
c. The inventory /home/thor/ansible/inventory is already there on jump host.
d. Make sure user thor should be able to run the playbook on jump host.
Note: Validation will try to run playbook using command ansible-playbook -i inventory playbook.yml so please make sure playbook works this way, without passing any extra arguments.
# Solution
# Ansible Playbook — install and enable httpd on all App Servers
Create `/home/thor/ansible/playbook.yml` so `ansible-playbook -i inventory playbook.yml` installs
httpd and brings the service up on all app servers — with **no extra arguments**.
> Note: this is an Ansible task, not Kubernetes — no manifests to pipe into `kubectl`. The heredoc
> below writes the playbook.
## Step 0 — The inventory already exists; leave it alone
Requirement (c) confirms the inventory is already in place. **Don't recreate or overwrite it**
just verify its contents:
```bash
cat /home/thor/ansible/inventory
```
Confirm it lists the app servers with their connection variables. If it lacks
`ansible_become_pass` and the app-server users need a sudo password, add that per host — the
playbook requires privilege escalation and you can't pass `-K` at runtime.
## Step 1 — Playbook
```bash
cat > /home/thor/ansible/playbook.yml <<'EOF'
---
- name: Install and enable httpd on all app servers
hosts: all
become: yes
tasks:
- name: Install httpd package
ansible.builtin.yum:
name: httpd
state: present
- name: Start and enable httpd service
ansible.builtin.service:
name: httpd
state: started
enabled: yes
EOF
```
## Step 2 — Ensure `thor` can run it (requirement d)
```bash
ls -l /home/thor/ansible/
```
Creating the playbook with the heredoc above (as `thor`) already gives correct ownership. If the
directory was pre-created by another user and `thor` can't read the files, fix it:
```bash
sudo chown -R thor:thor /home/thor/ansible
chmod 644 /home/thor/ansible/playbook.yml
```
## How it works
### Why `become: yes`
Both tasks are privileged: installing a package writes to system directories and the RPM database,
and managing a systemd service requires root. The SSH users on the app servers are unprivileged, so
the play escalates once at the **play level** rather than repeating `become` on each task.
Because validation runs the bare command with no `-K`, the sudo password must come from
`ansible_become_pass` in the existing inventory. "Missing sudo password" at runtime means that
variable is absent or wrong — and it's the most common failure on this task, since there's no way to
supply it on the command line.
### Task 1 — install httpd
`ansible.builtin.yum` with **`state: present`** installs the package if it's missing and does nothing
if it's already there. That makes the task **idempotent**: the first run reports `changed`,
subsequent runs report `ok`. `state: latest` would instead upgrade on every run, which isn't what
"install" asks for.
These app servers are RHEL/CentOS-family, so `yum` is the correct package module. (On modern
RHEL 8+ the `dnf` module is its successor, and Ansible's `yum` module delegates to dnf where
appropriate — so `yum` works regardless.)
### Task 2 — start *and* enable
Requirement (b) has two distinct halves, and `ansible.builtin.service` covers both:
| Option | Effect |
|--------|--------|
| `state: started` | httpd is running **right now**. |
| `enabled: yes` | httpd starts automatically **on boot**. |
These are independent — a service can be running but not enabled (dies on reboot), or enabled but
not currently started. "Start and enable" requires both, so both are set.
### Ordering matters
The install task must precede the service task: you can't start a service whose unit file doesn't
exist yet. Ansible executes tasks top to bottom, so this ordering is a correctness requirement, not
just style. Reversing them would fail with "Could not find the requested service httpd."
### `hosts: all`
The inventory contains the app servers, so `all` targets exactly them — and it can't break if the
inventory's group name and the playbook's `hosts:` value ever drift apart.
### Requirement (d) — "thor should be able to run the playbook"
Validation runs as `thor`, so `thor` must be able to **read** the playbook and inventory. Writing the
file via heredoc as `thor` satisfies this automatically; Step 2 is a safety check for the case where
the directory was pre-created with root ownership, which would fail validation before Ansible even
starts.
### Host key checking
If a first-time SSH connection trips on host-key verification, add an `ansible.cfg` beside the
playbook — safest because it needs no extra command-line arguments:
```bash
cat > /home/thor/ansible/ansible.cfg <<'EOF'
[defaults]
host_key_checking = False
EOF
```
## Verify
```bash
cd /home/thor/ansible
# Connectivity first
ansible -i inventory all -m ping
# The actual validation command
ansible-playbook -i inventory playbook.yml
# httpd installed
ansible -i inventory all -b -m command -a "rpm -q httpd"
# Running AND enabled
ansible -i inventory all -b -m command -a "systemctl is-active httpd"
ansible -i inventory all -b -m command -a "systemctl is-enabled httpd"
```
Expected — `ping` returning `SUCCESS` on every server; the playbook finishing with `failed=0`;
`rpm -q httpd` printing an installed version; `is-active` returning `active`; and `is-enabled`
returning `enabled`.
> Check **both** `is-active` and `is-enabled` — passing only one means half the requirement was met.
> "Could not find the requested service httpd" ⇒ task order is wrong. "Missing sudo password" ⇒ the
> inventory needs `ansible_become_pass`.