DevOps Fundamentals
DevOps Fundamentals: Linux, Jenkins, Docker, Kubernetes, Ansible and Terraform
This guide is written for beginners, but the examples and practices are suitable for real development, test, and production environments.
Commands that use sudo, rm -r, package removal, network changes, Kubernetes deletion, Docker pruning, or terraform destroy can cause data loss or downtime. Test them in a lab before using them on production systems.
How to use this guide
- Practise Linux commands in a disposable virtual machine or container.
- Type each command yourself instead of only reading it.
- Keep application code, infrastructure code, and configuration in Git.
- Use the interview questions to test your understanding.
- Use each chapter's cheat sheet for revision.
Table of contents
- #1. Linux basics
- #2. VI and Vim editors
- #3. Linux user management
- #4. Downloading files with curl and wget
- #5. Operating-system and package management
- #6. Linux services and systemd
- #7. Linux networking
- #8. DNS and name resolution
- #9. Java and Java build tools
- #10. Jenkins
- #11. Docker
- #12. Kubernetes
- #13. Ansible
- #14. Terraform
- #15. Suggested hands-on learning path
1. Linux basics
What is Linux?
Linux is an operating-system kernel used by distributions such as Ubuntu, Debian, Rocky Linux, AlmaLinux, Red Hat Enterprise Linux, Amazon Linux, and Fedora. Most cloud servers, containers, Kubernetes nodes, and DevOps tools run on Linux.
Why do DevOps engineers use Linux?
Linux is stable, automatable, secure when configured correctly, and widely supported by cloud and infrastructure tools. A DevOps engineer commonly uses Linux to manage files, users, services, processes, networking, deployments, logs, and automation.
Use man <command> or <command> --help before using an unfamiliar option.
echo
What is it?
Prints text or variable values to standard output.
Why do we use it?
Use it in shell scripts, debugging, pipelines, and to create short text files.
Syntax
echo [OPTION] [TEXT]
Command breakdown
echo is the command. -n avoids the ending newline. -e enables supported escape sequences in many shells. $NAME expands a variable.
Example
echo "Hello Linux"
name="Madhan"
echo "User: $name"
echo -n "No newline"
Expected output
The supplied text or expanded variable appears in the terminal.
Common use cases
Printing status messages, checking variables, generating simple configuration lines.
Interview question
What is the difference between echo "$var" and echo $var? Quoting preserves spaces and prevents unwanted word splitting.
Common mistakes
Using echo for complex or untrusted data; shell implementations can differ.
Best practices
Quote variables and prefer printf when exact formatting is important.
Summary
echo quickly prints text and variable values.
pwd
What is it?
Prints the absolute path of the current working directory.
Why do we use it?
It confirms where you are before creating, editing, or deleting files.
Syntax
pwd [OPTION]
Command breakdown
-P resolves symbolic links to the physical path; -L keeps the logical path.
Example
pwd
pwd -P
Expected output
Example: /home/madhan/projects.
Common use cases
Navigation checks and safety checks before destructive commands.
Interview question
What does pwd stand for? Print working directory.
Common mistakes
Running rm or deployment commands without checking the current directory.
Best practices
Run pwd before bulk file operations.
Summary
pwd shows your current location.
ls
What is it?
Lists files and directories.
Why do we use it?
It helps inspect directory contents, permissions, owners, sizes, and timestamps.
Syntax
ls [OPTIONS] [PATH]
Command breakdown
-l long format, -a hidden files, -h human-readable sizes, -t sort by time, -R recursive.
Example
ls
ls -la
ls -lh /var/log
ls -lat
Expected output
A table or list of directory entries.
Common use cases
Finding files, checking permissions, reviewing recent log files.
Interview question
Why does ls not show .env by default? Names beginning with . are hidden.
Common mistakes
Assuming ls output is safe to parse in scripts.
Best practices
Use find, shell globs, or structured tools for scripts; use ls -lah interactively.
Summary
ls displays directory contents.
cd
What is it?
Changes the shell working directory.
Why do we use it?
It lets you navigate the filesystem.
Syntax
cd [DIRECTORY]
Command breakdown
cd .. moves to the parent, cd - returns to the previous directory, cd or cd ~ goes home.
Example
cd /var/log
cd ..
cd -
cd ~
Expected output
Usually no output; the shell location changes.
Common use cases
Moving between projects, configuration directories, and logs.
Interview question
What is the difference between an absolute and relative path? Absolute starts from /; relative starts from the current directory.
Common mistakes
Using paths containing spaces without quoting.
Best practices
Use tab completion and quote paths such as cd "My Project".
Summary
cd changes the current directory.
mkdir
What is it?
Creates a directory.
Why do we use it?
Applications need directories for source code, logs, uploads, configuration, and backups.
Syntax
mkdir [OPTIONS] DIRECTORY...
Command breakdown
-p creates missing parent directories and does not fail if directories already exist. -m sets permissions.
Example
mkdir reports
mkdir -p projects/api/config
mkdir -m 750 private-data
Expected output
Normally no output when successful.
Common use cases
Creating project structures and deployment directories.
Interview question
What does mkdir -p do? It creates the complete parent path safely.
Common mistakes
Creating nested paths without -p, or using insecure permissions.
Best practices
Use meaningful names and deliberate permissions.
Summary
mkdir creates one or more directories.
mkdir -p
What is it?
Creates a directory tree, including any missing parents.
Why do we use it?
It makes setup scripts repeatable and prevents “No such file or directory” errors.
Syntax
mkdir -p PATH...
Command breakdown
-p means parents. Existing directories are accepted without an error.
Example
mkdir -p /srv/myapp/{config,data,logs}
Expected output
Creates /srv/myapp and the three child directories.
Common use cases
Bootstrap scripts, CI/CD workspaces, container bind-mount directories.
Interview question
Why is mkdir -p useful in automation? It is idempotent for existing directory paths.
Common mistakes
Assuming it sets secure permissions automatically.
Best practices
Set ownership and permissions separately after creation.
Summary
mkdir -p creates nested directory paths safely.
rm
What is it?
Removes files; with options it can remove directories.
Why do we use it?
It cleans temporary files, obsolete artifacts, and incorrect files.
Syntax
rm [OPTIONS] FILE...
Command breakdown
-i asks before removal, -f forces, -v shows removed files, -r recursively removes directories.
Example
rm old.txt
rm -i important.txt
rm -v *.tmp
Expected output
Normally no output unless verbose or an error occurs.
Common use cases
Cleanup scripts and removal of old build outputs.
Interview question
Can a normal rm be undone? Not reliably; it normally bypasses the desktop recycle bin.
Common mistakes
Using broad wildcards, running as root, or typing an incorrect absolute path.
Best practices
Preview with ls, use -i when learning, and keep backups.
Summary
rm permanently removes filesystem entries.
rm -r
What is it?
Recursively removes a directory and everything inside it.
Why do we use it?
It is used to delete directory trees such as generated build folders.
Syntax
rm -r DIRECTORY
Command breakdown
-r traverses child directories. -f suppresses prompts and many errors, making rm -rf especially dangerous.
Example
rm -r build/
rm -ri old-project/
Expected output
The directory tree is removed.
Common use cases
Removing generated dependencies, cache folders, or temporary environments.
Interview question
Why is rm -rf / dangerous? It attempts recursive forced deletion from the filesystem root.
Common mistakes
Copying destructive commands without checking variables or the current path.
Best practices
Use safeguards such as set -u, parameter validation, backups, and least privilege.
Summary
rm -r recursively deletes directories.
cp
What is it?
Copies files.
Why do we use it?
It creates backups, stages configuration, and duplicates templates.
Syntax
cp [OPTIONS] SOURCE DESTINATION
Command breakdown
-i prompts before overwrite, -v is verbose, -p preserves metadata, -a archives recursively and preserves attributes.
Example
cp app.conf app.conf.bak
cp -iv source.txt /tmp/
cp -p script.sh backup/
Expected output
The destination file is created or replaced.
Common use cases
Backups, deployment staging, copying configuration templates.
Interview question
What is the difference between cp -r and cp -a? -a preserves more metadata and links.
Common mistakes
Overwriting a destination unintentionally.
Best practices
Use -i interactively and version configuration in Git.
Summary
cp copies files.
cp -r
What is it?
Recursively copies directories.
Why do we use it?
It duplicates a complete project or directory tree.
Syntax
cp -r SOURCE_DIRECTORY DESTINATION
Command breakdown
-r copies each child recursively.
Example
cp -r website/ website-backup/
Expected output
A new directory tree is created at the destination.
Common use cases
Local backups and copying static assets.
Interview question
What happens if the destination directory exists? The source may be copied inside it depending on paths.
Common mistakes
Unexpected nested directories and missing metadata preservation.
Best practices
Use trailing paths carefully; prefer cp -a for backups.
Summary
cp -r copies directory trees.
mv
What is it?
Moves or renames files and directories.
Why do we use it?
It reorganizes files and performs atomic renames on the same filesystem.
Syntax
mv [OPTIONS] SOURCE DESTINATION
Command breakdown
-i prompts before overwrite, -n never overwrites, -v shows actions.
Example
mv draft.txt final.txt
mv -i app.conf /etc/myapp/
mv logs/ archive/
Expected output
The source path disappears and the destination path exists.
Common use cases
Renaming releases, organizing files, deploying with directory swaps.
Interview question
Is mv always atomic? Renames on the same filesystem commonly are; cross-filesystem moves require copy and delete.
Common mistakes
Overwriting existing files or moving into the wrong directory.
Best practices
Use -i or -n, and verify destination ownership.
Summary
mv moves or renames files and directories.
touch
What is it?
Creates an empty file if absent or updates timestamps if present.
Why do we use it?
It quickly creates placeholders and can trigger timestamp-based workflows.
Syntax
touch [OPTIONS] FILE...
Command breakdown
-c does not create missing files; -t supplies a timestamp.
Example
touch new.txt
touch .env.example
touch -c existing.txt
Expected output
A zero-byte file may be created; otherwise timestamps change.
Common use cases
Creating files before editing and updating modification times.
Interview question
Does touch clear an existing file? No.
Common mistakes
Expecting it to write content.
Best practices
Use meaningful extensions and correct ownership.
Summary
touch creates empty files or updates timestamps.
cat
What is it?
Reads and concatenates files to standard output.
Why do we use it?
It is useful for short files, pipelines, and joining content.
Syntax
cat [OPTIONS] [FILE...]
Command breakdown
-n numbers lines; multiple files are printed in order.
Example
cat /etc/os-release
cat -n app.conf
cat part1 part2 > combined.txt
Expected output
File contents appear in the terminal or are redirected.
Common use cases
Viewing short configuration files and combining files.
Interview question
Why is cat not ideal for huge logs? It prints everything at once.
Common mistakes
Using it on binary or very large files.
Best practices
Use less for long files and tail for live logs.
Summary
cat prints or combines file contents.
cat > file
What is it?
Redirects standard input into a file and overwrites it.
Why do we use it?
It quickly creates a small file from terminal input or command output.
Syntax
cat > FILE
# type content
# press Ctrl+D to finish
Command breakdown
> redirects and truncates the destination before writing. Ctrl+D sends end-of-file from an interactive terminal.
Example
cat > new.txt
Hello Linux
This file is new.
# Press Ctrl+D
Expected output
new.txt contains the typed lines; old contents are lost.
Common use cases
Creating short lab files and test configuration.
Interview question
What is the difference between > and >>? > overwrites; >> appends.
Common mistakes
Accidentally truncating a valuable file.
Best practices
Use an editor or a here-document for important multi-line configuration.
Summary
cat > creates or replaces a file with input.
cat >> file
What is it?
Appends standard input to the end of a file.
Why do we use it?
It adds lines without deleting existing content.
Syntax
cat >> FILE
# type content
# press Ctrl+D
Command breakdown
>> opens the destination in append mode.
Example
cat >> notes.txt
Additional note
# Press Ctrl+D
Expected output
The new lines appear after the old content.
Common use cases
Appending host entries or notes in controlled scripts.
Interview question
Can repeated automation create duplicates with >>? Yes.
Common mistakes
Appending duplicate or malformed configuration repeatedly.
Best practices
Check before appending; use configuration-management tools for production.
Summary
cat >> appends input to a file.
less
What is it?
Views text one screen at a time without loading everything into the terminal.
Why do we use it?
It is ideal for logs, manuals, and long configuration files.
Syntax
less [OPTIONS] FILE
Command breakdown
Use /text to search, n next result, N previous, g top, G bottom, q quit, -S prevents line wrapping.
Example
less /var/log/syslog
less -S access.log
Expected output
An interactive pager opens.
Common use cases
Reading long logs and command output.
Interview question
How do you follow a growing file in less? Press F; use Ctrl+C to stop following.
Common mistakes
Using cat where interactive navigation is needed.
Best practices
Pipe output to less, for example systemctl status app | less.
Summary
less is an interactive file viewer.
head
What is it?
Prints the beginning of a file.
Why do we use it?
It quickly checks headers, sample rows, and initial log lines.
Syntax
head [OPTIONS] FILE
Command breakdown
-n N prints N lines; -c N prints N bytes.
Example
head app.log
head -n 20 data.csv
Expected output
By default, the first 10 lines.
Common use cases
Inspecting CSV headers and initial configuration.
Interview question
How do you show the first five lines? head -n 5 file.
Common mistakes
Assuming it validates the entire file.
Best practices
Use it for inspection, not completeness checks.
Summary
head prints the start of a file.
tail
What is it?
Prints the end of a file and can follow changes.
Why do we use it?
It is one of the main tools for monitoring application logs.
Syntax
tail [OPTIONS] FILE
Command breakdown
-n N prints N lines; -f follows; -F follows by name and handles rotation better.
Example
tail -n 50 app.log
tail -F /var/log/nginx/access.log
Expected output
The last lines appear; follow mode continues printing new lines.
Common use cases
Live troubleshooting and watching deployment logs.
Interview question
Difference between -f and -F? -F retries and follows a filename across rotation.
Common mistakes
Leaving follow sessions running or watching the wrong environment.
Best practices
Use timestamps and structured logging; stop with Ctrl+C.
Summary
tail reads the end of files and follows logs.
grep
What is it?
Searches text for lines matching a pattern.
Why do we use it?
It filters logs, configuration, process output, and command results.
Syntax
grep [OPTIONS] PATTERN [FILE...]
Command breakdown
-i ignore case, -n line number, -r recursive, -v invert, -E extended regex, -w whole word.
Example
grep -n "ERROR" app.log
grep -ri "database" config/
ps aux | grep nginx
Expected output
Matching lines are printed.
Common use cases
Log analysis, configuration searches, and pipeline filtering.
Interview question
What does exit status 1 mean? No matching line; it is not necessarily a command failure.
Common mistakes
Forgetting to quote regex patterns or matching the grep process itself.
Best practices
Use grep -F for literal text and grep -R carefully on large trees.
Summary
grep finds matching text.
find
What is it?
Searches the filesystem using names, types, sizes, ownership, times, and other conditions.
Why do we use it?
It finds files reliably and can execute actions on matches.
Syntax
find PATH [TESTS] [ACTIONS]
Command breakdown
-name, -iname, -type f|d, -size, -mtime, -user, -exec ... {} \;.
Example
find . -type f -name "*.log"
find /var/log -type f -mtime +30
find . -type f -name "*.tmp" -delete
Expected output
Matching paths are printed unless another action is used.
Common use cases
Cleanup, locating configuration, and audit checks.
Interview question
Why quote "*.log"? It prevents the shell from expanding it before find runs.
Common mistakes
Using -delete or -exec rm before reviewing matches.
Best practices
Run the same find without deletion first.
Summary
find locates files using detailed conditions.
chmod
What is it?
Changes file permission bits.
Why do we use it?
It controls who can read, write, or execute files.
Syntax
chmod [OPTIONS] MODE FILE...
Command breakdown
Symbolic: u/g/o/a plus +/-/= and r/w/x. Numeric: read=4, write=2, execute=1; e.g. 750.
Example
chmod +x deploy.sh
chmod 640 app.conf
chmod -R u=rwX,g=rX,o= webroot/
Expected output
Permissions change; normally no output.
Common use cases
Making scripts executable and protecting secrets.
Interview question
What does 755 mean? Owner rwx, group r-x, others r-x.
Common mistakes
Using chmod 777 as a quick fix or adding execute permission to data files.
Best practices
Apply least privilege and understand directory execute permission.
Summary
chmod changes file and directory permissions.
chown
What is it?
Changes file owner and optionally group.
Why do we use it?
Services need correct ownership to read configuration and write data safely.
Syntax
chown [OPTIONS] OWNER[:GROUP] FILE...
Command breakdown
-R recursive; user:group changes both owner and group.
Example
sudo chown appuser:appgroup app.conf
sudo chown -R appuser:appgroup /srv/myapp/data
Expected output
Ownership changes.
Common use cases
Fixing deployment ownership and service data directories.
Interview question
Why can normal users not give files to arbitrary users? It would bypass quotas and security controls.
Common mistakes
Recursively changing ownership on system paths or mounted data without review.
Best practices
Limit the target path and verify with ls -l.
Summary
chown changes ownership.
ln
What is it?
Creates hard links or symbolic links.
Why do we use it?
Links provide aliases, versioned release pointers, and shared file references.
Syntax
ln [OPTIONS] TARGET LINK_NAME
Command breakdown
Without -s, creates a hard link. -s creates a symbolic link. -f replaces destination; -n affects symlink handling.
Example
ln -s /srv/releases/2026-07-24 /srv/current
ln original.txt second-name.txt
Expected output
A new link path is created.
Common use cases
Pointing current to a release and managing shared configuration.
Interview question
Difference between hard and symbolic links? Hard links reference the same inode; symbolic links store a path.
Common mistakes
Creating relative symlinks from the wrong directory or deleting a target and leaving a broken link.
Best practices
Use absolute targets for operational links unless portability requires relative links.
Summary
ln creates hard or symbolic links.
history
What is it?
Displays shell command history.
Why do we use it?
It helps repeat commands and review recent work.
Syntax
history [N]
Command breakdown
history 20 shows the latest 20 entries. !! repeats the last command; !123 repeats entry 123, but verify before use.
Example
history 20
history | grep kubectl
Expected output
Numbered previous commands appear.
Common use cases
Troubleshooting and recalling long commands.
Interview question
Where is Bash history usually stored? ~/.bash_history, with session behavior controlled by shell settings.
Common mistakes
Leaving passwords or tokens in command-line history.
Best practices
Use secret managers, environment injection, and history-safe methods.
Summary
history shows prior shell commands.
clear
What is it?
Clears the visible terminal screen.
Why do we use it?
It reduces visual clutter while keeping the shell session active.
Syntax
clear
Command breakdown
No important arguments for normal use; Ctrl+L often provides similar behavior.
Example
clear
Expected output
The terminal viewport is cleared.
Common use cases
Improving readability during demonstrations.
Interview question
Does clear delete command history? No.
Common mistakes
Assuming it removes sensitive data from scrollback or logs.
Best practices
Close or reset the terminal when sensitive scrollback must be removed.
Summary
clear cleans the terminal display, not history.
Linux basics: interview questions
- What is the difference between an absolute path and a relative path?
- What is the difference between
>and>>? - Explain Linux permissions such as
640,750, and755. - What is the difference between a hard link and a symbolic link?
- How would you locate files older than 30 days?
- Why is
rm -rfdangerous in automation? - How do you follow a log file across log rotation?
Linux basics cheat sheet
| Goal | Command |
|---|---|
| Show location | pwd |
| List all files | ls -lah |
| Create nested folders | mkdir -p a/b/c |
| Copy a directory safely | cp -a source/ backup/ |
| Rename a file | mv old new |
| View a long file | less file |
| Follow a log | tail -F app.log |
| Search text | grep -Rni "text" path/ |
| Find log files | find . -type f -name "*.log" |
| Make script executable | chmod +x script.sh |
| Change ownership | sudo chown user:group file |
2. VI and Vim editors
What are VI and Vim?
vi is a modal terminal text editor available on many Unix-like systems. Vim means Vi Improved and provides more features, syntax highlighting, plugins, and improved editing behavior.
Why do we use them?
Servers may not have a graphical editor. VI or Vim lets an administrator edit configuration, scripts, Kubernetes YAML, service files, and emergency fixes through an SSH terminal.
Editor modes
| Mode | Enter mode | Purpose |
|---|---|---|
| Normal/command | Press Esc |
Navigate and run editing commands |
| Insert | Press i, a, o, etc. |
Type text |
| Visual | Press v, V, or Ctrl+V |
Select characters, lines, or blocks |
| Command-line | Press : in normal mode |
Save, quit, replace, configure |
vim app.conf
Essential commands
| Action | Command | Explanation |
|---|---|---|
| Insert before cursor | i |
Enters insert mode |
| Append after cursor | a |
Enters insert mode after cursor |
| New line below | o |
Opens a line below |
| Return to normal mode | Esc |
Stops inserting/selecting |
| Delete character | x |
Deletes character under cursor |
| Delete line | dd |
Deletes/cuts the current line |
| Delete 5 lines | 5dd |
Repeats dd five times |
| Copy line | yy |
Yanks the current line |
| Copy 5 lines | 5yy |
Yanks five lines |
| Paste after | p |
Pastes after cursor/current line |
| Paste before | P |
Pastes before cursor/current line |
| Undo | u |
Undoes last change |
| Redo | Ctrl+r |
Redoes an undone change |
| Search forward | /word |
Searches for word |
| Next occurrence | n |
Repeats search in same direction |
| Previous occurrence | N |
Repeats search in reverse |
| Replace current line | :s/old/new/g |
Replaces every match in current line |
| Replace whole file | :%s/old/new/g |
Replaces every match in the file |
| Confirm each replacement | :%s/old/new/gc |
Prompts before each change |
| Save | :w |
Writes the file |
| Quit | :q |
Quits if no unsaved change |
| Save and quit | :wq or ZZ |
Saves and closes |
| Quit without saving | :q! |
Discards unsaved changes |
| Go to first line | gg |
Moves to top |
| Go to last line | G |
Moves to bottom |
| Page down | Ctrl+f |
Scrolls one page forward |
| Page up | Ctrl+b |
Scrolls one page backward |
| Half-page down | Ctrl+d |
Scrolls half a page down |
| Half-page up | Ctrl+u |
Scrolls half a page up |
Ctrl+p is commonly completion or movement to the previous line depending on mode; it is not the normal page-up command. Use Ctrl+b for page up and Ctrl+f for page down.
Practical example
sudo vim /etc/hosts
- Press
i. - Add the required entry.
- Press
Esc. - Type
:wqand press Enter.
Common mistakes
- Typing while still in normal mode.
- Forgetting
sudofor protected files. - Using
:q!and losing changes. - Running a global replacement without
cconfirmation. - Editing generated configuration rather than its source template.
Best practices
- Back up critical configuration before editing.
- Validate configuration after changes.
- Use syntax highlighting and line numbers:
:syntax onand:set number. - Store long-lived configuration in Git and deploy it through automation.
Interview questions
- Explain Vim's normal, insert, visual, and command-line modes.
- How do you copy five lines and paste them?
- How do you replace a word throughout a file with confirmation?
- What is the difference between
:q,:q!, and:wq?
VI/Vim cheat sheet
Open: vim file
Insert: i
Normal mode: Esc
Delete line: dd
Copy line: yy
Paste: p
Undo: u
Redo: Ctrl+r
Search: /word
Next: n
Save: :w
Save and exit: :wq
Discard and exit: :q!
3. Linux user management
whoami
What is it?
Prints the effective username of the current process.
Why do we use it?
It confirms which account is executing commands.
Syntax
whoami
Command breakdown
There are no commonly required options.
Example
whoami
Expected output
Example: madhan or root.
Common use cases
Checking privilege context before administration.
Interview question
Difference between login user and effective user? sudo can change the effective identity for a command.
Common mistakes
Assuming the shell is running as the expected user.
Best practices
Check identity before destructive actions.
Summary
whoami prints the effective username.
id
What is it?
Displays user ID, group ID, and group memberships.
Why do we use it?
Permissions are evaluated using numeric IDs and groups.
Syntax
id [USER]
Command breakdown
Without a user, shows current identity. -u, -g, and -G show IDs.
Example
id
id appuser
id -u
Expected output
Example: uid=1000(madhan) gid=1000(madhan) groups=....
Common use cases
Debugging file access and service accounts.
Interview question
Why can a user gain access after joining a group only after a new login? Group membership is loaded into the session.
Common mistakes
Looking only at usernames and ignoring numeric IDs on mounted storage.
Best practices
Use dedicated service accounts and least-privilege groups.
Summary
id shows numeric and named identity information.
su
What is it?
Starts a shell as another user.
Why do we use it?
It is used for testing a service account or switching administrative context.
Syntax
su [OPTIONS] [USER]
Command breakdown
su - user starts a login shell with the target user environment. Without a username, it normally targets root.
Example
su - appuser
su -
Expected output
A new shell starts after authentication.
Common use cases
Testing permissions and running commands as a service user.
Interview question
Difference between su user and su - user? The hyphen loads the target login environment.
Common mistakes
Using a mixed environment without - or sharing root passwords.
Best practices
Prefer sudo with audited, limited permissions.
Summary
su switches user shells.
sudo
What is it?
Runs an allowed command with another identity, usually root.
Why do we use it?
It grants controlled administrative access and creates audit records.
Syntax
sudo [OPTIONS] COMMAND
Command breakdown
-u user chooses an account, -i starts a login shell, -l lists allowed commands.
Example
sudo systemctl restart nginx
sudo -u www-data id
sudo -l
Expected output
The command runs with elevated or alternate privileges.
Common use cases
Package installation, service control, and protected file changes.
Interview question
Where is sudo policy configured? Commonly /etc/sudoers and /etc/sudoers.d/, edited with visudo.
Common mistakes
Granting unrestricted NOPASSWD: ALL or running entire scripts as root unnecessarily.
Best practices
Grant the minimum command set and use visudo.
Summary
sudo provides controlled privilege escalation.
passwd
What is it?
Changes a user password and manages password status.
Why do we use it?
It secures interactive accounts and can lock or expire passwords.
Syntax
passwd [OPTIONS] [USER]
Command breakdown
Normal users change their own password; root can target another user. Common administrative options include -l lock and -u unlock, subject to distribution behavior.
Example
passwd
sudo passwd appuser
sudo passwd -l olduser
Expected output
Interactive password prompts or a status message.
Common use cases
Account onboarding, credential rotation, and disabling login.
Interview question
Does locking a password always disable every login method? No; SSH keys or other methods may still work.
Common mistakes
Using weak passwords or assuming a locked password disables all access.
Best practices
Prefer SSH keys, MFA where available, and remove unused accounts.
Summary
passwd manages account passwords.
groups
What is it?
Lists group memberships for a user.
Why do we use it?
Groups provide shared access without giving broad permissions.
Syntax
groups [USER]
Command breakdown
Without a user, displays groups for the current identity.
Example
groups
groups appuser
Expected output
A space-separated group list.
Common use cases
Debugging permissions and validating onboarding.
Interview question
How do supplementary groups affect permissions? Any matching group permission may grant access.
Common mistakes
Expecting a current shell to see newly added groups immediately.
Best practices
Start a new login session after group changes.
Summary
groups shows group membership.
User-management production example
sudo useradd --create-home --shell /bin/bash deploy
sudo passwd deploy
sudo usermod -aG docker deploy
id deploy
Membership in the docker group commonly provides root-equivalent control over the Docker host. Grant it only to trusted administrators.
Interview questions
- What is the difference between a UID and a GID?
- Why is
sudogenerally preferred to sharing the root password? - What is the difference between
su userandsu - user? - How do supplementary groups affect file permissions?
User-management cheat sheet
| Goal | Command |
|---|---|
| Current username | whoami |
| Identity and groups | id |
| Switch with login environment | su - user |
| Run one privileged command | sudo command |
| View sudo rights | sudo -l |
| Change password | passwd |
| Show groups | groups user |
4. Downloading files with curl and wget
curl
What is it?
Transfers data using URLs and supports HTTP, HTTPS, APIs, authentication, headers, uploads, and many other protocols.
Why do we use it?
DevOps engineers use it to test APIs, check health endpoints, download artifacts, and automate web requests.
Syntax
curl [OPTIONS] URL
Command breakdown
-o FILE saves to a chosen filename; -O uses the remote filename; -L follows redirects; -I fetches headers; -f fails on HTTP errors; -sS is quiet but still shows errors; -H adds a header; -X sets a method; -d sends data; --connect-timeout and --max-time limit waiting.
Example
curl https://example.com
curl -fL https://example.com/app.tar.gz -o app.tar.gz
curl -I https://example.com
curl -sS -H "Authorization: Bearer $TOKEN" https://api.example.com/health
curl -X POST -H "Content-Type: application/json" -d '{"name":"demo"}' https://api.example.com/items
Expected output
Response content is printed unless redirected; with -o, the file is saved. Exit status is non-zero for many failures, especially when -f is used.
Common use cases
API testing, health checks, artifact download, webhook testing.
Interview question
Why combine -f, -L, -s, and -S in scripts? Follow redirects, fail on HTTP errors, hide progress, and still show errors.
Common mistakes
Not following redirects, printing secrets, ignoring status codes, or downloading unverified files.
Best practices
Use TLS, checksums/signatures, timeouts, --retry, and secret-safe headers.
Summary
curl is a general-purpose URL and API client.
wget
What is it?
Downloads files non-interactively and supports recursive retrieval, resuming, and mirroring.
Why do we use it?
It is convenient for downloading packages or larger files from scripts and terminals.
Syntax
wget [OPTIONS] URL
Command breakdown
-O FILE chooses output filename; -c continues a partial download; -q is quiet; --show-progress displays progress; --timeout; --tries; --content-disposition respects server filenames.
Example
wget https://example.com/app.tar.gz
wget -O some-file.txt https://example.com/data
wget -c https://example.com/large.iso
Expected output
The file is written to the current directory or selected path, with progress information.
Common use cases
Downloading release artifacts and resuming large downloads.
Interview question
Difference between wget -O and curl -o? Both choose a local name; the option letters use different cases.
Common mistakes
Using -O with multiple URLs, disabling certificate checks, or trusting unverified downloads.
Best practices
Verify checksums and avoid --no-check-certificate in production.
Summary
wget is focused on reliable non-interactive downloads.
Download verification example
curl -fL https://example.com/app.tar.gz -o app.tar.gz
sha256sum app.tar.gz
# Compare the hash with a trusted value supplied by the publisher.
Interview questions
- How do you make
curlfail when a server returns HTTP 404 or 500? - How do you follow HTTP redirects?
- How do you resume a partial
wgetdownload? - Why should downloaded binaries be verified?
Download cheat sheet
| Goal | curl | wget |
|---|---|---|
| Save as filename | curl -o file URL |
wget -O file URL |
| Keep remote name | curl -O URL |
wget URL |
| Follow redirect | curl -L URL |
Usually handled automatically |
| Fail on HTTP errors | curl -f URL |
Non-zero status for server errors |
| Resume | curl -C - -O URL |
wget -c URL |
5. Operating-system and package management
Detecting the operating system
/etc/os-release
What is it?
A standard text file containing distribution identification such as name, version, and ID.
Why do we use it?
Automation needs to know whether it is running on Ubuntu, Debian, Rocky Linux, RHEL, or another distribution before choosing a package manager or service name.
Syntax and example
cat /etc/os-release
ls /etc/*release*
cat /etc/*release*
Expected output
NAME="Ubuntu"
VERSION="24.04 LTS ..."
ID=ubuntu
VERSION_ID="24.04"
Best practice
Prefer /etc/os-release in scripts. Globbing every release file is useful for manual investigation but produces distribution-specific content.
Package-management overview
| Distribution family | Low-level tool | High-level tool |
|---|---|---|
| RHEL, Rocky, AlmaLinux, Fedora | rpm |
dnf (yum may be a compatibility command) |
| Debian, Ubuntu | dpkg |
apt / apt-get |
rpm
What is it?
The low-level RPM Package Manager for installing, querying, verifying, and removing .rpm packages.
Syntax and examples
sudo rpm -i package.rpm
sudo rpm -Uvh package.rpm
sudo rpm -e package-name
rpm -q package-name
rpm -qa
rpm -ql package-name
rpm -qf /usr/bin/curl
rpm -V package-name
Command breakdown
-i: install a package file.-U: upgrade or install.-v: verbose.-h: progress hash marks.-e: erase by installed package name.-q: query.-a: all installed packages.-l: list files from a package.-f: identify the package owning a file.-V: verify installed files against package metadata.
Prefer dnf install ./package.rpm when possible because it resolves dependencies. Direct rpm -i does not automatically resolve all dependencies.
yum and dnf
What are they?
High-level package managers for RPM-based systems. Modern Fedora and current RHEL-family systems generally use DNF; yum may map to DNF for compatibility.
Examples
sudo dnf install ansible-core
sudo dnf remove ansible-core
dnf list installed ansible-core
dnf search nginx
sudo dnf update
sudo dnf clean all
sudo yum install httpd
Common options
-y: automatically answer yes. Use carefully in automation.--assumeno: preview without accepting.install,remove,upgrade,search,info,list.
apt
What is it?
A high-level package command used on Debian and Ubuntu systems.
Examples
sudo apt update
sudo apt install nginx
sudo apt remove nginx
sudo apt purge nginx
apt search ansible
apt show ansible
sudo apt upgrade
sudo apt autoremove
Important distinction
apt update refreshes repository metadata. It does not upgrade installed packages. apt upgrade installs available upgrades based on the refreshed metadata.
Common mistakes
- Installing packages without refreshing metadata.
- Mixing repositories from incompatible releases.
- Running unattended major upgrades without testing.
- Using
rpm -iand then manually fighting dependencies. - Removing packages without reviewing dependent packages.
Best practices
- Pin or deliberately control important package versions.
- Use trusted, signed repositories.
- Test upgrades in lower environments.
- Automate package state with Ansible rather than undocumented manual changes.
- Capture the base image and package version used by production.
Interview questions
- What is the difference between RPM and DNF/YUM?
- What is the difference between
apt updateandapt upgrade? - How do you find which RPM package owns a file?
- Why should repositories and packages be signature-verified?
Package-management cheat sheet
| Goal | RHEL family | Debian/Ubuntu |
|---|---|---|
| Refresh metadata | dnf makecache |
apt update |
| Install | dnf install pkg |
apt install pkg |
| Remove | dnf remove pkg |
apt remove pkg |
| Search | dnf search text |
apt search text |
| Package info | dnf info pkg |
apt show pkg |
| Upgrade | dnf upgrade |
apt upgrade |
6. Linux services and systemd
What is a service?
A service is a long-running background process such as Nginx, PostgreSQL, Docker, Jenkins, or SSH. Modern Linux distributions commonly manage services with systemd and the systemctl command.
service vs systemctl
| Command | Meaning |
|---|---|
service nginx start |
Compatibility interface, often translated to the system's service manager |
systemctl start nginx |
Native systemd service control |
Use systemctl on systemd-based distributions.
Core service commands
sudo systemctl start httpd
sudo systemctl stop httpd
sudo systemctl restart httpd
sudo systemctl reload httpd
sudo systemctl enable httpd
sudo systemctl disable httpd
systemctl status httpd
systemctl is-active httpd
systemctl is-enabled httpd
journalctl -u httpd
journalctl -u httpd -f
Command meanings
| Action | What it does | Downtime risk |
|---|---|---|
start |
Starts a stopped service | Low, assuming healthy configuration |
stop |
Stops a running service | High for dependent applications |
restart |
Stops and starts again | Usually causes a brief interruption |
reload |
Asks service to reload configuration without full restart | Lower, but service must support it |
enable |
Configures startup during boot | Does not necessarily start now |
disable |
Removes automatic boot startup | Does not necessarily stop now |
status |
Shows state and recent logs | Safe read-only operation |
systemctl enable --now nginx both enables the unit for boot and starts it immediately.
Unit file example
# /etc/systemd/system/myapp.service
[Unit]
Description=My Application
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=myapp
Group=myapp
WorkingDirectory=/srv/myapp
ExecStart=/usr/bin/java -jar /srv/myapp/app.jar
Restart=on-failure
RestartSec=5
EnvironmentFile=-/etc/myapp/myapp.env
NoNewPrivileges=true
PrivateTmp=true
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now myapp
systemctl status myapp
journalctl -u myapp -f
Common mistakes
- Editing a unit file without running
systemctl daemon-reload. - Assuming
enablestarts a service immediately. - Restarting before validating configuration, for example forgetting
nginx -t. - Running services as root unnecessarily.
- Storing secrets directly inside world-readable unit files.
Best practices
- Run each service as a dedicated non-root account.
- Configure restart policy and health monitoring.
- Validate configuration before reload/restart.
- Use
journalctland centralized logs. - Add systemd hardening options where compatible.
Interview questions
- What is the difference between
start,restart, andreload? - What is the difference between
enableandstart? - Why is
daemon-reloadrequired? - How do you view logs for a systemd service?
Services cheat sheet
systemctl status nginx
sudo systemctl start nginx
sudo systemctl reload nginx
sudo systemctl restart nginx
sudo systemctl enable --now nginx
sudo systemctl disable --now nginx
journalctl -u nginx -f
7. Linux networking
Networking concepts
IP address
An IP address identifies a network interface at the Internet Protocol layer. IPv4 example: 192.168.1.10. IPv6 example: 2001:db8::10.
Subnet and prefix
A subnet groups addresses that can communicate directly at Layer 3 without using a router. In 192.168.1.10/24, /24 means the first 24 bits identify the network. The typical address range is 192.168.1.0 through 192.168.1.255, though the first and last addresses have special roles in a traditional IPv4 subnet.
Default gateway
A default gateway is the router used when no more specific route matches the destination.
Router
A router forwards packets between networks. A Linux host can act as a router when forwarding is enabled and routing/firewall rules are configured.
DNS
DNS converts names such as db.internal.example into IP addresses and can store other records.
MAC address
A MAC address identifies a network interface at the local data-link layer, for example 52:54:00:12:34:56.
Interface
An interface is a network connection such as eth0, ens3, enp1s0, wlan0, or lo.
Static IP
A static address is configured to remain stable. Production servers often need predictable addresses, although clouds may attach stable private IP resources through their own control plane.
DHCP
Dynamic Host Configuration Protocol supplies network settings such as IP address, prefix, gateway, and DNS servers automatically.
Network diagram
Internet / Other Networks
|
[ ISP / Router ]
|
Default gateway: 192.168.1.1
|
----------------------------------------------------
| 192.168.1.0/24 |
| |
[App Server] [DB Server] [DNS Server]
192.168.1.10 192.168.1.11 192.168.1.100
MAC: aa:... MAC: bb:... MAC: cc:...
| |
-------------------- Local switch -------------------
ip link
What is it?
Shows and changes link-layer interface state.
Commands
ip link
ip -br link
sudo ip link set dev eth0 up
sudo ip link set dev eth0 down
Output
Shows interface name, flags, MTU, state, and MAC address.
ip addr
What is it?
Shows and changes IP addresses assigned to interfaces.
Commands
ip addr
ip -br addr
sudo ip addr add 192.168.1.10/24 dev eth0
sudo ip addr del 192.168.1.10/24 dev eth0
Command breakdown
addr add: add an address.192.168.1.10/24: host address and prefix.dev eth0: target interface.
Commands entered with ip addr add are generally runtime changes and may disappear after reboot. Use the distribution's persistent network configuration, NetworkManager, Netplan, systemd-networkd, or the cloud network configuration for permanent settings.
ip route
What is it?
Displays and manages the kernel routing table.
Commands
ip route
ip route get 8.8.8.8
sudo ip route add 10.20.0.0/16 via 192.168.1.1 dev eth0
sudo ip route add default via 192.168.1.1 dev eth0
sudo ip route del 10.20.0.0/16 via 192.168.1.1
Correct gateway syntax
sudo ip route add default via 192.168.1.1 dev eth0
The following is not an address command and is incorrect:
# Incorrect
ip addr add default via 192.168.1.1
What is IP forwarding?
IP forwarding allows a Linux host to forward packets received on one interface toward another destination, acting as a router.
sysctl net.ipv4.ip_forward
sudo sysctl -w net.ipv4.ip_forward=1
Persistent example:
# /etc/sysctl.d/99-router.conf
net.ipv4.ip_forward = 1
sudo sysctl --system
Forwarding alone is not a complete router setup. You may also need firewall forwarding policies, NAT, routes, and security controls.
Troubleshooting workflow
ip -br link
ip -br addr
ip route
ip route get 1.1.1.1
ping -c 4 192.168.1.1
ping -c 4 1.1.1.1
getent hosts example.com
ss -lntup
Interpretation:
- If the interface is down, fix the link.
- If there is no IP, check DHCP/static configuration.
- If there is no route, check the gateway.
- If IP connectivity works but names fail, check DNS.
- If the host is reachable but the application is not, check listening ports, firewall, and service health.
Common mistakes
- Confusing
ip addrwithip route. - Adding an address to the wrong interface.
- Creating duplicate default routes unintentionally.
- Changing a remote server network and losing SSH access.
- Enabling forwarding without firewall controls.
- Treating temporary
ipcommands as persistent configuration.
Best practices
- Use an out-of-band console before changing remote networking.
- Record current state before changes.
- Configure persistent networking with the platform-supported tool.
- Restrict routing and forwarding using firewall policy.
- Monitor packet loss, latency, interface errors, and route changes.
Interview questions
- What is the difference between an IP address, subnet, and gateway?
- What does
/24mean? - How do you add a default route?
- What is IP forwarding?
- How do you separate a DNS problem from a routing problem?
- What is the difference between a MAC address and an IP address?
Networking cheat sheet
| Goal | Command |
|---|---|
| Show links | ip -br link |
| Show addresses | ip -br addr |
| Show routes | ip route |
| Route decision | ip route get 8.8.8.8 |
| Add address | sudo ip addr add IP/PREFIX dev IFACE |
| Add default route | sudo ip route add default via GATEWAY dev IFACE |
| Show listening ports | ss -lntup |
| Test name resolution | getent hosts name |
8. DNS and name resolution
What is DNS?
The Domain Name System maps names to data such as IPv4 addresses (A), IPv6 addresses (AAAA), mail servers (MX), aliases (CNAME), and service records.
/etc/hosts
What is it?
A local static hostname mapping file.
Example
127.0.0.1 localhost
192.168.1.11 db db.internal.example
192.168.1.10 app app.internal.example
Safe ways to add an entry
sudo sh -c 'printf "%s\n" "192.168.1.11 db" >> /etc/hosts'
sudo echo "..." >> /etc/hosts usually does not elevate the shell redirection. Use sudo tee -a or sudo sh -c.
printf '%s
' '192.168.1.11 db' | sudo tee -a /etc/hosts
/etc/resolv.conf
What is it?
It describes resolver settings such as DNS name servers and search domains.
search internal.example
nameserver 192.168.1.100
nameserver 1.1.1.1
options timeout:2 attempts:3
On many systems /etc/resolv.conf is generated by NetworkManager, systemd-resolved, DHCP, or a cloud agent. Direct edits may be overwritten.
DNS resolution order
Linux name resolution is controlled by the Name Service Switch configuration, usually /etc/nsswitch.conf.
grep '^hosts:' /etc/nsswitch.conf
Example:
hosts: files dns
This commonly means:
- Check local files such as
/etc/hosts. - If no match is found, query configured DNS resolution services.
The actual order can contain additional mechanisms such as resolve, myhostname, mdns, or others.
Application asks for db.internal.example
|
v
Name Service Switch rules
|
+--------+---------+
| |
/etc/hosts DNS resolver
| |
+--------+---------+
|
IP address
nslookup
What is it?
A DNS query and troubleshooting tool.
nslookup example.com
nslookup example.com 192.168.1.100
nslookup -type=MX example.com
dig
What is it?
A detailed DNS query tool preferred for many DNS investigations.
dig example.com
dig A example.com
dig AAAA example.com
dig MX example.com
dig @192.168.1.100 db.internal.example
dig +short example.com
dig +trace example.com
getent hosts
dig and nslookup query DNS, but applications may follow the system's complete NSS resolution order. Use getent to test closer to normal application resolution:
getent hosts db
getent ahosts example.com
What if two DNS records use the same name?
- If
/etc/hostscontains a matching name andfilesappears beforednsinnsswitch.conf, the local entry is normally returned first. - If multiple DNS
AorAAAArecords exist for the same name, the DNS server can return multiple addresses. Clients may choose or rotate among them. - If different DNS servers contain conflicting data, the result depends on which resolver is queried, caching, search domains, and resolver policy.
Common mistakes
- Editing generated
/etc/resolv.confdirectly. - Forgetting the NSS order.
- Testing only with
ping; ICMP may be blocked even when DNS works. - Confusing authoritative DNS data with cached resolver results.
- Adding production host mappings manually to every server.
Best practices
- Manage shared records centrally in DNS.
- Use
/etc/hostsonly for local overrides, bootstrap, or controlled emergencies. - Set appropriate TTL values.
- Use redundant resolvers.
- Monitor query latency and failure rates.
- Avoid exposing internal DNS information publicly.
Interview questions
- What is the role of
/etc/nsswitch.confin name resolution? - What is the difference between
/etc/hostsand DNS? - Why might
/etc/resolv.confchanges disappear? - What is the difference between
dig,nslookup, andgetent hosts? - Explain
A,AAAA,CNAME, andMXrecords.
DNS cheat sheet
cat /etc/resolv.conf
grep '^hosts:' /etc/nsswitch.conf
getent hosts example.com
nslookup example.com
dig example.com
dig +short example.com
dig @DNS_SERVER name
dig +trace example.com
9. Java and Java build tools
Java execution model
MyClass.java --javac--> MyClass.class bytecode --JVM--> machine execution
packaged into JAR/WAR/EAR when required
JDK, JRE, and JVM
| Component | Meaning | Contains/does |
|---|---|---|
| JVM | Java Virtual Machine | Executes Java bytecode and manages runtime services such as memory |
| JRE | Java Runtime Environment | JVM plus runtime libraries required to run Java applications |
| JDK | Java Development Kit | Runtime plus development tools such as javac, jar, and javadoc |
Modern Java distributions may package runtime components differently, but the conceptual distinction remains useful: developers need compilation tools; a runtime executes bytecode.
javac
What is it?
The Java compiler. It compiles .java source files into .class bytecode.
javac MyClass.java
javac -d out src/com/example/MyClass.java
The source extension is .java, not .javac.
Expected result: MyClass.class or the package directory structure under out/.
java
Runs a compiled class or executable JAR.
java MyClass
java -cp out com.example.MyClass
java -jar myapp.jar
java -Xms256m -Xmx1g -jar myapp.jar
-cpor--class-path: locations containing classes and libraries.-jar: runs the JAR's configured main class.-Xms: initial heap size.-Xmx: maximum heap size.
jar
Creates, lists, extracts, and updates Java archives.
jar --create --file myapp.jar -C out .
jar --list --file myapp.jar
jar --extract --file myapp.jar
jar --create --file myapp.jar --main-class com.example.Main -C out .
Traditional short form:
jar cf myapp.jar -C out .
jar tf myapp.jar
jar xf myapp.jar
javadoc
Generates HTML API documentation from Java source documentation comments.
javadoc -d docs src/com/example/*.java
Expected result: HTML files under docs/, including an index page.
JAR vs WAR vs EAR
| Package | Full name | Typical content | Typical use |
|---|---|---|---|
| JAR | Java Archive | Classes, resources, metadata, sometimes dependencies | Libraries and standalone applications |
| WAR | Web Application Archive | Web application classes, libraries, web resources, deployment metadata | Servlet containers/application servers |
| EAR | Enterprise Application Archive | Multiple enterprise modules such as WARs and EJB JARs | Larger Jakarta EE deployments |
Build tools
Maven
Maven uses a project model, conventions, dependency coordinates, lifecycle phases, and commonly a pom.xml file.
mvn clean
mvn test
mvn package
mvn verify
mvn install
mvn dependency:tree
Minimal pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>1.0.0</version>
</project>
Gradle
Gradle uses a programmable build model, commonly Groovy or Kotlin DSL.
./gradlew clean
./gradlew test
./gradlew build
./gradlew dependencies
Simple Groovy build.gradle:
plugins {
id 'java'
}
group = 'com.example'
version = '1.0.0'
repositories {
mavenCentral()
}
test {
useJUnitPlatform()
}
Ant
Ant is task-oriented and usually configured through build.xml. It gives detailed control but has fewer conventions and does not provide dependency management by itself in the same way as Maven or Gradle.
ant
ant clean
ant compile
ant jar
Build-tool comparison
| Tool | Style | Main file | Strength |
|---|---|---|---|
| Maven | Convention and lifecycle | pom.xml |
Predictable structure and dependency ecosystem |
| Gradle | Programmable and incremental | build.gradle / .kts |
Flexibility and performance features |
| Ant | Explicit tasks | build.xml |
Fine-grained legacy/custom build control |
Common mistakes
- Compiling
MyClass.javacinstead ofMyClass.java. - Running a packaged class without the correct classpath.
- Committing build output such as
target/orbuild/. - Using unpinned or untrusted dependencies.
- Building with a different JDK version than production without compatibility checks.
Best practices
- Use Maven Wrapper (
mvnw) or Gradle Wrapper (gradlew) to standardize versions. - Run tests and dependency/security checks in CI.
- Publish immutable versioned artifacts to an artifact repository.
- Do not build production artifacts manually on servers.
- Configure JVM memory based on container/host limits and workload evidence.
Interview questions
- Explain the difference between JDK, JRE, and JVM.
- What does
javacproduce? - Compare JAR, WAR, and EAR.
- Explain Maven's
clean,test,package,verify, andinstallphases. - Why use Maven or Gradle wrappers?
Java cheat sheet
javac MyClass.java
java MyClass
jar --create --file app.jar -C out .
jar --list --file app.jar
javadoc -d docs src/*.java
mvn clean verify
./gradlew clean build
10. Jenkins
What is Jenkins?
Jenkins is an open-source automation server used to implement continuous integration and continuous delivery workflows. It can fetch code, build it, test it, scan it, package it, publish artifacts, and deploy it.
Why do we use it?
A repeatable pipeline reduces manual errors and gives every change the same build and validation process.
Developer -> Git push -> Jenkins Pipeline
| Checkout
| Build
| Test
| Scan
| Package
| Publish
| Deploy
v
Environment
Architecture
Controller
The Jenkins controller stores configuration, schedules jobs, provides the UI/API, and coordinates work.
Agent
An agent provides executors and a workspace where build steps run. Agents may be VMs, physical hosts, Docker containers, or ephemeral Kubernetes Pods.
Older material often says “master/slave.” Current Jenkins terminology is controller/agent.
+----------------------+
Git/Webhook ------>| Jenkins Controller |
| Queue, UI, Scheduling|
+----------+-----------+
|
+------------+-------------+
| |
+--------v---------+ +--------v---------+
| Linux Agent | | Kubernetes Agent |
| Maven, Docker | | Ephemeral Pod |
+------------------+ +------------------+
Jobs, builds, pipelines, and plugins
| Term | Meaning |
|---|---|
| Job | Saved automation configuration |
| Build | One execution of a job |
| Pipeline | Stages and steps describing delivery workflow as code |
| Plugin | Extension adding SCM, credentials, UI, integrations, steps, and other features |
| Artifact | Immutable file produced by a build, such as JAR, ZIP, image metadata, or report |
Declarative Pipeline example
pipeline {
agent any
options {
timestamps()
disableConcurrentBuilds()
}
environment {
APP_NAME = 'java-maven-app'
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Build and Test') {
steps {
sh './mvnw clean verify'
}
post {
always {
junit 'target/surefire-reports/*.xml'
}
}
}
stage('Package') {
steps {
archiveArtifacts artifacts: 'target/*.jar', fingerprint: true
}
}
stage('Build Image') {
steps {
sh 'docker build -t registry.example.com/myapp:${BUILD_NUMBER} .'
}
}
stage('Push Image') {
steps {
withCredentials([usernamePassword(
credentialsId: 'registry-credentials',
usernameVariable: 'REGISTRY_USER',
passwordVariable: 'REGISTRY_PASSWORD'
)]) {
sh '''
set +x
printf '%s' "$REGISTRY_PASSWORD" | \
docker login registry.example.com \
--username "$REGISTRY_USER" --password-stdin
docker push registry.example.com/myapp:${BUILD_NUMBER}
'''
}
}
}
stage('Deploy') {
when {
branch 'main'
}
steps {
sh 'kubectl set image deployment/myapp myapp=registry.example.com/myapp:${BUILD_NUMBER}'
sh 'kubectl rollout status deployment/myapp --timeout=5m'
}
}
}
post {
always {
cleanWs()
}
failure {
echo 'Pipeline failed. Review the failing stage and logs.'
}
}
}
Pipeline flow
- Webhook triggers Jenkins after a Git push.
- Jenkins queues the build.
- An agent receives an executor and workspace.
- Code is checked out.
- Build and tests run.
- Artifact or image is produced and versioned.
- Credentials are injected only around the step that needs them.
- Deployment runs for approved branches/environments.
- Rollout status and tests confirm success.
Common mistakes
- Building on the controller instead of agents.
- Storing secrets inside the Jenkinsfile.
- Installing too many unmaintained plugins.
- Using
latestas the only image tag. - Deploying even when tests or scans fail.
- Allowing every job unrestricted Docker socket or production credentials.
- Making mutable changes directly on servers outside the pipeline.
Best practices
- Keep
Jenkinsfilein the application repository. - Use ephemeral, isolated agents where practical.
- Back up Jenkins home and test restoration.
- Apply least privilege to credentials and agents.
- Pin tools and use immutable artifact versions.
- Add timeouts, retries only for transient failures, and concurrency controls.
- Protect production with approvals and environment-specific credentials.
- Keep plugins updated after testing and remove unused plugins.
Interview questions
- Explain Jenkins controller and agent responsibilities.
- What is the difference between a job and a build?
- Why use Pipeline as Code?
- How do you protect secrets in a Jenkins pipeline?
- How would you design zero-downtime deployment and rollback?
- Why should builds not normally run on the controller?
Jenkins cheat sheet
Jenkinsfile -> pipeline definition
agent -> where stages run
stage -> logical phase
steps -> commands/actions
post -> actions after stage/pipeline result
credentials-> inject securely for limited scope
artifact -> immutable build output
11. Docker
What is Docker?
Docker is a container platform. A container packages an application process with its userspace files and dependencies while sharing the host kernel.
Why do we use it?
Containers make development, CI, and deployment environments more consistent and reproducible.
Dockerfile --docker build--> Image --docker run--> Container
|
+--> Volume for persistent data
+--> Network for communication
Core concepts
Image
A read-only, layered application package used to create containers.
Container
A running or stopped instance created from an image. Writable container layers are normally ephemeral.
Volume
Docker-managed persistent storage independent of one container's lifecycle.
Network
A communication boundary that lets containers reach each other and external systems. On a user-defined network, containers can commonly resolve each other by name.
Dockerfile
A file containing instructions used to build an image.
Docker Compose
A YAML-based model for running a multi-container application with services, networks, volumes, configuration, and dependencies. Modern command syntax is docker compose.
Common Docker commands
Information
docker version
docker info
docker system df
Images
docker image ls
docker pull nginx:alpine
docker build -t myapp:1.0.0 .
docker tag myapp:1.0.0 registry.example.com/myapp:1.0.0
docker push registry.example.com/myapp:1.0.0
docker image inspect myapp:1.0.0
docker image rm myapp:1.0.0
Containers
docker run --name web -d -p 8080:80 nginx:alpine
docker container ls
docker container ls -a
docker logs web
docker logs -f --tail 100 web
docker exec -it web sh
docker inspect web
docker stop web
docker start web
docker restart web
docker rm web
Command breakdown:
docker run --name web -d -p 8080:80 nginx:alpine
run: create and start a container.--name web: assign a stable name.-d: detached mode.-p 8080:80: host port 8080 maps to container port 80.nginx:alpine: image and tag.
Volumes
docker volume create app-data
docker volume ls
docker volume inspect app-data
docker run -d --name db -v app-data:/var/lib/postgresql/data postgres:17
docker volume rm app-data
Networks
docker network create app-network
docker network ls
docker network inspect app-network
docker run -d --name web --network app-network nginx:alpine
docker network connect app-network another-container
docker network disconnect app-network another-container
docker network rm app-network
Cleanup
docker container prune
docker image prune
docker volume prune
docker network prune
docker system prune
Prune commands delete unused objects. Review what is considered unused before running them, especially volumes.
Production Dockerfile example
# syntax=docker/dockerfile:1
FROM eclipse-temurin:21-jdk AS build
WORKDIR /workspace
COPY .mvn/ .mvn/
COPY mvnw pom.xml ./
RUN ./mvnw -q -DskipTests dependency:go-offline
COPY src/ src/
RUN ./mvnw -q clean package -DskipTests
FROM eclipse-temurin:21-jre
RUN useradd --system --uid 10001 --create-home appuser
WORKDIR /app
COPY --from=build /workspace/target/*.jar /app/app.jar
USER 10001
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/app/app.jar"]
Docker Compose example
services:
app:
build:
context: .
image: example/myapp:1.0.0
restart: unless-stopped
environment:
DATABASE_HOST: db
DATABASE_PORT: "5432"
DATABASE_NAME: app
DATABASE_USER: app
DATABASE_PASSWORD_FILE: /run/secrets/db_password
secrets:
- db_password
ports:
- "8080:8080"
depends_on:
db:
condition: service_healthy
networks:
- backend
db:
image: postgres:17
restart: unless-stopped
environment:
POSTGRES_DB: app
POSTGRES_USER: app
POSTGRES_PASSWORD_FILE: /run/secrets/db_password
volumes:
- db_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app -d app"]
interval: 10s
timeout: 5s
retries: 5
networks:
- backend
volumes:
db_data:
networks:
backend:
driver: bridge
secrets:
db_password:
file: ./secrets/db_password.txt
docker compose config
docker compose build
docker compose up -d
docker compose ps
docker compose logs -f app
docker compose exec app sh
docker compose pull
docker compose up -d --remove-orphans
docker compose down
Bind mount vs volume
| Storage | Example | Best suited for |
|---|---|---|
| Bind mount | ./config:/app/config:ro |
Development source or explicit host-managed paths |
| Named volume | db_data:/var/lib/postgresql/data |
Persistent application data managed by Docker |
| tmpfs | memory-backed mount | Temporary sensitive or high-speed ephemeral data |
Common mistakes
- Running as root inside the image without need.
- Copying secrets into image layers.
- Using only
latesttags. - Writing database data only to the container layer.
- Publishing database ports publicly without need.
- Building huge images with build tools in the runtime layer.
- Ignoring
.dockerignore. - Using
docker execwith an image name instead of a container name/ID.
Best practices
- Use small trusted base images and multi-stage builds.
- Run as a non-root user.
- Pin versions or digests according to your update policy.
- Scan images and dependencies.
- Use read-only mounts and drop capabilities when possible.
- Add health checks where useful.
- Keep one main responsibility per container.
- Store persistent data in managed volumes or external services.
- Use secret management rather than environment files committed to Git.
Interview questions
- What is the difference between an image and a container?
- What is the difference between a bind mount and a named volume?
- Explain
EXPOSEversus publishing with-p. - Why use a multi-stage build?
- How do containers communicate by name in Compose?
- What happens to a container's writable layer when it is deleted?
Docker cheat sheet
docker build -t app:1.0.0 .
docker run --name app -d -p 8080:8080 app:1.0.0
docker ps -a
docker logs -f app
docker exec -it app sh
docker inspect app
docker stop app && docker rm app
docker compose config
docker compose up -d
docker compose logs -f
docker compose down
12. Kubernetes
What is Kubernetes?
Kubernetes is a platform for deploying and operating containerized applications across a cluster. It schedules workloads, maintains desired state, provides service discovery, performs controlled rollouts, and replaces failed workload instances through controllers.
Why do we use it?
A production application may need multiple replicas, rolling updates, service discovery, configuration injection, autoscaling, self-healing, and scheduling across many machines. Kubernetes provides APIs and controllers for these concerns.
Cluster architecture
Control Plane
+------------------------------------------------+
| API Server | Scheduler | Controller Manager |
| | etcd (cluster state) |
+----------------------+-------------------------+
|
Kubernetes API
|
+-------------------+-------------------+
| |
+--------v---------+ +--------v---------+
| Worker Node 1 | | Worker Node 2 |
| kubelet | | kubelet |
| container runtime| | container runtime|
| kube-proxy/CNI | | kube-proxy/CNI |
| Pods | | Pods |
+------------------+ +------------------+
Cluster
A set of control-plane and worker components managed as one Kubernetes environment.
Control plane
Coordinates the cluster. Older notes may call this the “master,” but control plane is the current term.
Worker node
A machine that runs application Pods and node components.
Node
A registered machine in the cluster. Control-plane machines can also be nodes, but production workloads are commonly placed on workers.
Basic kubectl commands
kubectl cluster-info
kubectl get nodes
kubectl get namespaces
kubectl get all -n default
kubectl api-resources
kubectl explain deployment.spec
Kubernetes YAML syntax
YAML uses indentation to represent structure. Use spaces, not tabs.
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.27-alpine
ports:
- name: http
containerPort: 80
Required object fields usually include:
apiVersion: API group and version.kind: resource type.metadata: name, namespace, labels, and annotations.spec: desired state.status: current observed state, normally maintained by Kubernetes.
The field is matchLabels, not matchLables. Labels in a controller selector must match labels in the Pod template.
Pod
Definition
The smallest deployable Kubernetes unit. A Pod contains one or more tightly coupled containers sharing network and specified storage.
Why use it?
Kubernetes schedules containers as Pods. A sidecar can share the same Pod when it must share lifecycle and localhost networking with the main container.
YAML
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
app: nginx
tier: frontend
spec:
containers:
- name: nginx
image: nginx:1.27-alpine
ports:
- name: http
containerPort: 80
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
memory: 128Mi
readinessProbe:
httpGet:
path: /
port: http
initialDelaySeconds: 2
periodSeconds: 5
Commands
kubectl apply -f pod.yaml
kubectl get pods -o wide
kubectl describe pod nginx
kubectl logs nginx
kubectl exec -it nginx -- sh
kubectl delete pod nginx --wait=true
Diagram
Pod: nginx
+----------------------------------+
| Shared network namespace |
| IP: 10.x.x.x |
| |
| +------------------------------+ |
| | nginx container :80 | |
| +------------------------------+ |
+----------------------------------+
Common mistakes
- Managing long-lived Pods directly instead of using a controller.
- Omitting resource requests and readiness checks.
- Storing persistent data only inside the container filesystem.
Best practices
Use Deployments, StatefulSets, Jobs, or other controllers for production workloads. Keep containers in one Pod only when they need tight lifecycle or data sharing.
ReplicationController
Definition
A legacy controller that maintains a specified number of Pod replicas.
YAML
apiVersion: v1
kind: ReplicationController
metadata:
name: myapp-rc
spec:
replicas: 3
selector:
app: myapp
tier: frontend
template:
metadata:
labels:
app: myapp
tier: frontend
spec:
containers:
- name: nginx
image: nginx:1.27-alpine
Commands
kubectl apply -f rc-definition.yml
kubectl get replicationcontrollers
kubectl describe replicationcontroller myapp-rc
kubectl scale replicationcontroller myapp-rc --replicas=5
kubectl delete replicationcontroller myapp-rc
Best practice
Learn it for legacy environments and interviews, but use Deployments/ReplicaSets for new stateless applications.
ReplicaSet
Definition
A controller that maintains a desired number of matching Pod replicas. It supports set-based label selectors.
YAML
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: myapp-replicaset
spec:
replicas: 3
selector:
matchLabels:
app: myapp
tier: frontend
template:
metadata:
labels:
app: myapp
tier: frontend
spec:
containers:
- name: nginx
image: nginx:1.27-alpine
Commands
kubectl apply -f replicaset-definition.yml
kubectl get replicasets
kubectl describe replicaset myapp-replicaset
kubectl scale replicaset myapp-replicaset --replicas=6
kubectl edit replicaset myapp-replicaset
kubectl delete replicaset myapp-replicaset
Diagram
ReplicaSet desired replicas: 3
|
+------+------+
| | |
Pod 1 Pod 2 Pod 3
Common mistake
Editing a ReplicaSet owned by a Deployment. The Deployment controller may overwrite or replace it.
Best practice
Use a Deployment to manage ReplicaSets for stateless applications.
Deployment
Definition
A controller that manages ReplicaSets and declarative updates for stateless Pods.
YAML
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deployment
labels:
app: myapp
spec:
replicas: 3
revisionHistoryLimit: 5
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
maxSurge: 1
selector:
matchLabels:
app: myapp
tier: frontend
template:
metadata:
labels:
app: myapp
tier: frontend
spec:
containers:
- name: nginx
image: nginx:1.27-alpine
ports:
- name: http
containerPort: 80
readinessProbe:
httpGet:
path: /
port: http
initialDelaySeconds: 2
periodSeconds: 5
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
memory: 128Mi
Commands
kubectl apply -f deployment.yml
kubectl get deployments
kubectl describe deployment myapp-deployment
kubectl get replicasets
kubectl get pods -l app=myapp
kubectl scale deployment myapp-deployment --replicas=6
kubectl set image deployment/myapp-deployment nginx=nginx:1.28-alpine
kubectl rollout status deployment/myapp-deployment
kubectl rollout history deployment/myapp-deployment
kubectl rollout undo deployment/myapp-deployment
kubectl delete deployment myapp-deployment
Diagram
Deployment
|
+--> ReplicaSet revision 2 (desired: 3)
| +--> Pod A
| +--> Pod B
| +--> Pod C
|
+--> ReplicaSet revision 1 (scaled down, retained for rollback)
Best practices
- Use immutable image tags or digests.
- Define readiness probes before claiming zero downtime.
- Set resource requests and appropriate limits.
- Set Pod security context and run as non-root when supported.
- Configure disruption budgets and topology spread for highly available workloads.
- Record deployment changes through GitOps or a controlled pipeline.
Namespace
Definition
A logical scope for names and many policies. Namespaces help separate teams, environments, or applications, but are not automatically a complete security boundary.
YAML
apiVersion: v1
kind: Namespace
metadata:
name: production
Commands
kubectl apply -f namespace.yaml
kubectl get namespaces
kubectl get pods -n production
kubectl config set-context --current --namespace=production
Best practices
Apply RBAC, NetworkPolicies, ResourceQuotas, LimitRanges, and naming standards per namespace.
ConfigMap
Definition
Stores non-secret configuration as key-value data or files.
YAML
apiVersion: v1
kind: ConfigMap
metadata:
name: myapp-config
data:
APP_ENV: production
LOG_LEVEL: info
application.properties: |
server.port=8080
feature.enabled=true
Commands
kubectl apply -f configmap.yaml
kubectl get configmap myapp-config -o yaml
kubectl create configmap example --from-literal=LOG_LEVEL=info --dry-run=client -o yaml
Pod usage
envFrom:
- configMapRef:
name: myapp-config
Best practice
Do not store passwords, tokens, or private keys in ConfigMaps.
Secret
Definition
Stores sensitive values for use by workloads. Kubernetes Secrets are base64-encoded in manifests and require encryption, RBAC, and external secret controls for strong protection.
YAML
apiVersion: v1
kind: Secret
metadata:
name: myapp-secret
type: Opaque
stringData:
DATABASE_USERNAME: app
DATABASE_PASSWORD: replace-through-secret-management
Commands
kubectl apply -f secret.yaml
kubectl create secret generic myapp-secret \
--from-literal=DATABASE_USERNAME=app \
--from-literal=DATABASE_PASSWORD='strong-value' \
--dry-run=client -o yaml
kubectl get secret myapp-secret
Best practices
- Never commit real Secret values to Git.
- Enable encryption at rest for cluster secrets.
- Use least-privilege RBAC.
- Prefer a managed secret store plus a supported integration.
- Rotate credentials and audit access.
Service
Definition
A Service provides a stable virtual address and DNS name for a changing set of selected Pods.
Client -> Service virtual IP/name -> Endpoint Pods
+-> Pod A
+-> Pod B
+-> Pod C
ClusterIP
Default service type. Exposes the service inside the cluster.
apiVersion: v1
kind: Service
metadata:
name: myapp
spec:
type: ClusterIP
selector:
app: myapp
tier: frontend
ports:
- name: http
port: 80
targetPort: http
NodePort
Exposes a port on each node in addition to the ClusterIP behavior. The default allocated range is commonly 30000-32767, subject to cluster configuration.
apiVersion: v1
kind: Service
metadata:
name: myapp-nodeport
spec:
type: NodePort
selector:
app: myapp
tier: frontend
ports:
- name: http
port: 80
targetPort: http
nodePort: 30008
Client -> NodeIP:30008 -> Service:80 -> Pod:80
LoadBalancer
Requests an external load balancer from a supported cloud provider or load-balancer implementation.
apiVersion: v1
kind: Service
metadata:
name: myapp-loadbalancer
spec:
type: LoadBalancer
selector:
app: myapp
tier: frontend
ports:
- name: http
port: 80
targetPort: http
Service commands
kubectl apply -f service-definition.yml
kubectl get services
kubectl describe service myapp
kubectl get endpointslices -l kubernetes.io/service-name=myapp
kubectl delete service myapp
Service mistakes
- Service selector does not match Pod labels.
targetPortdoes not match the container's listening port or named port.- Assuming a
LoadBalancerwill work without a cloud or load-balancer controller. - Using NodePort as the final Internet architecture without firewall and traffic design.
kubectl command reference
kubectl apply
Creates or updates resources declaratively from files.
kubectl apply -f deployment.yml
kubectl apply -f k8s/
kubectl diff -f k8s/
kubectl create
Creates a resource. Useful for imperative commands and generating YAML.
kubectl create namespace demo
kubectl run hello-minikube --image=nginx:1.27-alpine
kubectl create deployment web --image=nginx:1.27-alpine
kubectl create deployment web --image=nginx:1.27-alpine --dry-run=client -o yaml
kubectl run creates a Pod by default in modern Kubernetes. For a managed application, create a Deployment instead of relying on a bare Pod.
kubectl delete
Deletes resources.
kubectl delete -f deployment.yml
kubectl delete pod webapp --wait=true
kubectl delete deployment web
kubectl edit
Opens the live object in an editor.
kubectl edit deployment myapp
kubectl edit rs new-replica-set
Use for emergency changes; update the source manifest afterward to prevent configuration drift.
kubectl replace
Replaces an existing object from a complete manifest.
kubectl replace -f replicaset-definition.yml
It is less forgiving than apply because the supplied file is treated as the replacement representation. Declarative Git workflows normally prefer apply or server-side apply.
kubectl scale
Changes replica count.
kubectl scale deployment myapp --replicas=6
kubectl scale --replicas=6 -f deployment.yml
kubectl describe
Shows detailed resource state and events.
kubectl describe pod myapp-abc123
kubectl describe deployment myapp
kubectl logs
Reads container logs.
kubectl logs pod-name
kubectl logs -f pod-name
kubectl logs pod-name -c sidecar
kubectl logs pod-name --previous
kubectl logs -l app=myapp --tail=100 --prefix
kubectl exec
Runs a command in an existing container.
kubectl exec pod-name -- env
kubectl exec -it pod-name -- sh
kubectl exec -it pod-name -c app -- sh
-- separates kubectl options from the command executed inside the container.
Rollout and versioning
Recreate strategy
Old Pods are terminated before new Pods are created.
strategy:
type: Recreate
Use when old and new versions cannot run together, but plan for downtime.
RollingUpdate strategy
Kubernetes gradually adds new Pods and removes old Pods.
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
maxSurge: 1
Old: v1 v1 v1
Step: v1 v1 v1 v2
Step: v1 v1 v2 v2
New: v2 v2 v2
A rolling update is not automatically zero-downtime. The application also needs readiness checks, enough capacity, compatible dependencies, graceful shutdown, and suitable traffic handling.
Rollout commands
kubectl rollout status deployment/myapp
kubectl rollout history deployment/myapp
kubectl rollout history deployment/myapp --revision=2
kubectl rollout undo deployment/myapp
kubectl rollout undo deployment/myapp --to-revision=2
kubectl rollout pause deployment/myapp
kubectl rollout resume deployment/myapp
kubectl rollout restart deployment/myapp
Older examples use kubectl create -f deployment.yml --record. The --record flag is deprecated/removed in modern workflows. Use version control, annotations, CI/CD metadata, and immutable image references for change history.
Microservices architecture on Kubernetes
Internet
|
Ingress / Gateway
|
+----------------+----------------+
| |
frontend Service api Service
| |
frontend Pods +-------------+-------------+
| |
orders Service users Service
| |
orders Pods users Pods
| |
Database/Queue Database/Cache
Typical supporting resources:
- Deployment for stateless services.
- Service for stable discovery.
- ConfigMap for non-secret settings.
- Secret integration for credentials.
- Ingress or Gateway API for HTTP entry.
- StatefulSet/operator or managed service for stateful systems.
- NetworkPolicy for service-to-service restrictions.
- HorizontalPodAutoscaler for measured scaling.
- PodDisruptionBudget and topology spread for availability.
- Observability for logs, metrics, traces, and alerts.
Kubernetes production checklist
Kubernetes common mistakes
- Using tabs in YAML.
- Misspelling
matchLabels. - Selector and Pod label mismatch.
- Creating bare Pods for production services.
- Using
latestimage tags. - No readiness probe during rolling updates.
- No CPU/memory requests.
- Committing plaintext secrets.
- Editing live objects without updating Git.
- Assuming Kubernetes replaces database backups or application-level resilience.
Kubernetes interview questions
- Explain control plane, worker node, Pod, ReplicaSet, and Deployment.
- Why use a Deployment instead of a bare Pod?
- What happens if a Pod managed by a ReplicaSet is deleted?
- Explain
port,targetPort, andnodePort. - Compare ClusterIP, NodePort, and LoadBalancer.
- How does a Deployment perform a rolling update?
- What is required for a truly low-downtime rollout?
- What is the difference between ConfigMap and Secret?
- What happens when a Service selector matches no Pods?
- How do readiness and liveness probes differ?
- Why are resource requests important to the scheduler?
- What is configuration drift in Kubernetes?
Kubernetes cheat sheet
kubectl cluster-info
kubectl get nodes
kubectl get all -A
kubectl apply -f k8s/
kubectl get pods -o wide
kubectl describe pod POD
kubectl logs -f POD
kubectl exec -it POD -- sh
kubectl scale deployment APP --replicas=6
kubectl set image deployment/APP CONTAINER=IMAGE:TAG
kubectl rollout status deployment/APP
kubectl rollout history deployment/APP
kubectl rollout undo deployment/APP
kubectl delete -f k8s/
13. Ansible
What is Ansible?
Ansible is an automation tool for configuration management, application deployment, orchestration, and repeatable administrative tasks. It commonly connects over SSH and applies modules to managed hosts.
Why do we use it?
Instead of manually installing and configuring Nginx on 50 servers, you describe the desired configuration once and apply it consistently.
Ansible control node
|
| SSH / supported connection
v
+-------+-------+-------+
| Web 1 | Web 2 | DB 1 |
+-------+-------+-------+
Inventory
An inventory defines managed hosts and groups.
# inventory.ini
[web]
web1 ansible_host=192.168.1.21
web2 ansible_host=192.168.1.22
[db]
db1 ansible_host=192.168.1.31
[all:vars]
ansible_user=automation
ansible_ssh_private_key_file=~/.ssh/automation
ansible-inventory -i inventory.ini --graph
ansible all -i inventory.ini -m ansible.builtin.ping
Playbook
A playbook is a YAML automation blueprint containing one or more plays. Each play maps hosts to tasks.
---
- name: Configure web servers
hosts: web
become: true
gather_facts: true
tasks:
- name: Install Nginx
ansible.builtin.package:
name: nginx
state: present
- name: Start and enable Nginx
ansible.builtin.service:
name: nginx
state: started
enabled: true
ansible-playbook -i inventory.ini web.yml
ansible-playbook -i inventory.ini web.yml --check --diff
ansible-playbook -i inventory.ini web.yml --syntax-check
Modules
Modules perform actions such as package installation, file copying, user management, service control, cloud operations, and API calls.
- name: Create application directory
ansible.builtin.file:
path: /srv/myapp
state: directory
owner: myapp
group: myapp
mode: '0750'
Prefer a purpose-built module over shell or command when one exists because modules better support idempotence and structured results.
Variables
Variables make automation reusable.
---
- name: Demonstrate variables
hosts: web
vars:
app_name: myapp
app_port: 8080
tasks:
- name: Show application port
ansible.builtin.debug:
msg: "{{ app_name }} listens on {{ app_port }}"
Variable sources include inventory, group variables, host variables, role defaults/vars, play vars, facts, registered results, and extra vars. Precedence matters; keep the design simple.
Facts
Facts are collected information about managed hosts.
- name: Show operating system
ansible.builtin.debug:
msg: "{{ ansible_facts.distribution }} {{ ansible_facts.distribution_version }}"
ansible web1 -i inventory.ini -m ansible.builtin.setup
Templates
Templates use Jinja to generate files from variables.
# templates/myapp.conf.j2
server {
listen 80;
server_name {{ server_name }};
location / {
proxy_pass http://127.0.0.1:{{ app_port }};
}
}
- name: Install Nginx virtual host
ansible.builtin.template:
src: myapp.conf.j2
dest: /etc/nginx/conf.d/myapp.conf
owner: root
group: root
mode: '0644'
notify: Reload Nginx
Handlers
Handlers run when notified by a changed task, commonly to restart or reload a service.
handlers:
- name: Reload Nginx
ansible.builtin.service:
name: nginx
state: reloaded
If the template does not change, the handler is not notified.
Roles
Roles organize tasks, handlers, templates, files, variables, and defaults in a reusable structure.
roles/
└── webserver/
├── defaults/main.yml
├── files/
├── handlers/main.yml
├── tasks/main.yml
├── templates/
├── vars/main.yml
└── meta/main.yml
---
- name: Apply webserver role
hosts: web
become: true
roles:
- webserver
Practical playbook: deploy a static site
---
- name: Deploy static website
hosts: web
become: true
vars:
web_root: /var/www/example
tasks:
- name: Install Nginx
ansible.builtin.package:
name: nginx
state: present
- name: Create web root
ansible.builtin.file:
path: "{{ web_root }}"
state: directory
owner: root
group: root
mode: '0755'
- name: Publish website
ansible.builtin.copy:
src: site/
dest: "{{ web_root }}/"
owner: root
group: root
mode: '0644'
notify: Reload Nginx
- name: Install site configuration
ansible.builtin.template:
src: nginx-site.conf.j2
dest: /etc/nginx/conf.d/example.conf
owner: root
group: root
mode: '0644'
validate: nginx -t -c %s
notify: Reload Nginx
- name: Ensure Nginx is running and enabled
ansible.builtin.service:
name: nginx
state: started
enabled: true
handlers:
- name: Reload Nginx
ansible.builtin.service:
name: nginx
state: reloaded
The exact Nginx validation command and configuration location can differ by distribution. Test the template validation approach in the target OS.
Ansible Vault
Encrypt sensitive Ansible data rather than committing it as plaintext.
ansible-vault create group_vars/production/vault.yml
ansible-vault edit group_vars/production/vault.yml
ansible-playbook -i inventory.ini site.yml --ask-vault-pass
For production automation, integrate Vault password retrieval with a secure secret-management method rather than sharing a password manually.
Common mistakes
- Using
shellfor everything. - Writing non-idempotent tasks.
- Putting secrets in plaintext variables.
- Using
latestpackage state without a controlled update policy. - Mixing every application into one huge playbook.
- Ignoring check mode limitations.
- Failing to validate generated configuration before reloading a service.
Best practices
- Use fully qualified collection names such as
ansible.builtin.copy. - Make tasks idempotent and clearly named.
- Use roles for reusable components.
- Store inventory variables by environment.
- Encrypt secrets and limit access.
- Run
--syntax-check, linting, and tests in CI. - Use
--check --diffas a preview, while understanding modules may not fully support check mode. - Pin tested collection versions.
Interview questions
- What is an inventory?
- What is the difference between a play, playbook, task, and module?
- Explain Ansible idempotence.
- When does a handler run?
- What is the difference between
copyandtemplate? - Why are roles useful?
- How do you protect secrets?
- Why prefer modules over shell commands?
Ansible cheat sheet
ansible-inventory -i inventory.ini --graph
ansible all -i inventory.ini -m ansible.builtin.ping
ansible-playbook -i inventory.ini site.yml --syntax-check
ansible-playbook -i inventory.ini site.yml --check --diff
ansible-playbook -i inventory.ini site.yml
ansible-vault edit secret.yml
14. Terraform
What is Terraform?
Terraform is an Infrastructure as Code tool. You describe infrastructure in configuration files, Terraform compares the desired configuration with known state and provider APIs, and then proposes or applies changes.
Why do we use it?
Infrastructure becomes reviewable, repeatable, version-controlled, and easier to reproduce across environments.
Terraform configuration (.tf)
|
terraform plan
|
Desired vs current state
|
terraform apply
|
Cloud/provider APIs
|
Infrastructure resources
Providers
A provider plugin communicates with an external API such as AWS, Azure, OCI, Google Cloud, Kubernetes, or GitHub.
terraform {
required_version = ">= 1.8.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 6.0"
}
}
}
provider "aws" {
region = var.aws_region
}
Choose provider and Terraform constraints according to versions tested by your organization. Run terraform init -upgrade deliberately, review lock-file changes, and test upgrades.
Resources
A resource declares an infrastructure object Terraform should manage.
resource "aws_s3_bucket" "artifacts" {
bucket = var.artifact_bucket_name
tags = {
Name = "Build artifacts"
Environment = var.environment
}
}
The resource address is aws_s3_bucket.artifacts.
Variables
Variables make configurations reusable.
variable "aws_region" {
description = "AWS region for resources"
type = string
default = "ap-south-1"
}
variable "environment" {
description = "Deployment environment"
type = string
validation {
condition = contains(["dev", "staging", "production"], var.environment)
error_message = "Environment must be dev, staging, or production."
}
}
Example terraform.tfvars:
environment = "dev"
artifact_bucket_name = "replace-with-globally-unique-name"
Do not commit secrets in .tfvars files.
Outputs
Outputs expose useful values after apply and can be consumed by other automation.
output "artifact_bucket_arn" {
description = "ARN of the artifact bucket"
value = aws_s3_bucket.artifacts.arn
}
terraform output
terraform output -raw artifact_bucket_arn
Modules
A module is a reusable group of Terraform configuration. The current directory is the root module; called modules are child modules.
module "network" {
source = "./modules/network"
environment = var.environment
vpc_cidr = "10.20.0.0/16"
}
Example structure:
terraform/
├── main.tf
├── variables.tf
├── outputs.tf
├── versions.tf
├── environments/
└── modules/
└── network/
├── main.tf
├── variables.tf
└── outputs.tf
State
Terraform state maps configuration resource addresses to real infrastructure objects and stores attributes needed for planning.
Default local state:
terraform.tfstate
State can contain sensitive values. Do not commit it to Git. Protect it with access controls, encryption, backups/versioning, and state locking where supported.
Backend
A backend determines where Terraform stores state and performs related operations such as locking.
Example S3 backend configuration:
terraform {
backend "s3" {
bucket = "company-terraform-state"
key = "dev/network/terraform.tfstate"
region = "ap-south-1"
encrypt = true
use_lockfile = true
}
}
Backend authentication should come from secure environment/identity configuration, not hard-coded credentials.
Backend features and arguments evolve. Validate the configuration against the Terraform version and backend documentation used by your team.
Terraform command workflow
terraform fmt
Formats Terraform files.
terraform fmt
terraform fmt -recursive
terraform fmt -check -recursive
terraform init
Initializes a working directory, configures the backend, downloads providers, and downloads modules.
terraform init
terraform init -upgrade
terraform init -reconfigure
terraform init -migrate-state
terraform validate
Checks configuration syntax and internal consistency after initialization.
terraform validate
terraform plan
Builds an execution plan showing proposed changes.
terraform plan
terraform plan -var-file=dev.tfvars
terraform plan -out=tfplan
terraform show tfplan
Typical symbols:
+create.~update in place.-/+replace.-destroy.
terraform apply
Executes an approved plan.
terraform apply
terraform apply tfplan
Applying a saved plan is safer in CI because the reviewed plan is the one executed, provided the plan is stored and handled securely and has not become invalid.
terraform destroy
Plans and destroys resources managed by the configuration.
terraform plan -destroy
terraform destroy
terraform destroy can remove production infrastructure and data. Use access controls, protected workflows, backups, and explicit approvals.
AWS example: VPC and EC2 instance
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 6.0"
}
}
}
provider "aws" {
region = var.aws_region
}
data "aws_ami" "linux" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["al2023-ami-2023.*-x86_64"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
}
resource "aws_vpc" "main" {
cidr_block = "10.20.0.0/16"
enable_dns_support = true
enable_dns_hostnames = true
tags = {
Name = "${var.environment}-vpc"
}
}
resource "aws_subnet" "public" {
vpc_id = aws_vpc.main.id
cidr_block = "10.20.1.0/24"
map_public_ip_on_launch = true
tags = {
Name = "${var.environment}-public"
}
}
resource "aws_security_group" "web" {
name = "${var.environment}-web"
description = "Allow application traffic"
vpc_id = aws_vpc.main.id
ingress {
description = "HTTP"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
resource "aws_instance" "web" {
ami = data.aws_ami.linux.id
instance_type = "t3.micro"
subnet_id = aws_subnet.public.id
vpc_security_group_ids = [aws_security_group.web.id]
tags = {
Name = "${var.environment}-web"
Environment = var.environment
}
}
This is a learning example, not a complete production network. It omits an Internet gateway, routes, private subnets, restricted administration, load balancing, TLS, monitoring, backup, and many security controls.
Terraform workflow for teams
Developer branch
|
terraform fmt -check
terraform validate
security/lint checks
|
terraform plan
|
Peer review + approval
|
Apply saved plan using protected credentials
|
Post-apply tests and monitoring
Common mistakes
- Committing
terraform.tfstateor credentials. - Editing cloud resources manually and creating drift.
- Applying without reviewing a plan.
- Using one state file for unrelated environments.
- Hard-coding account IDs, regions, or secrets everywhere.
- Copying a module without understanding destructive changes.
- Running
terraform importor state commands without backups and review. - Treating Terraform state as a normal text file to edit manually.
Best practices
- Use remote encrypted state with locking and restricted access.
- Separate state by environment and blast radius.
- Commit
.terraform.lock.hclfor applications/root configurations according to team policy. - Pin/test Terraform and provider versions.
- Run formatting, validation, linting, and policy/security checks in CI.
- Review saved plans before apply.
- Use modules with clear interfaces, documentation, and versioning.
- Use cloud identity roles instead of long-lived static keys.
- Import existing resources before managing them; do not blindly recreate them.
- Back up state and test recovery procedures.
Interview questions
- What is Terraform state and why is it required?
- What does
terraform initdo? - What is the difference between a provider and a resource?
- What is a backend?
- Why save a plan using
-out? - How do you handle configuration drift?
- How do modules improve infrastructure code?
- How do you protect sensitive state?
- What is the difference between
terraform validateandterraform plan? - How would you separate dev, staging, and production?
Terraform cheat sheet
terraform fmt -recursive
terraform init
terraform validate
terraform plan -out=tfplan
terraform show tfplan
terraform apply tfplan
terraform output
terraform state list
terraform plan -destroy
terraform destroy
15. Suggested hands-on learning path
Lab 1: Linux filesystem
- Create
/tmp/devops-lab/{config,data,logs}. - Create configuration files with
touchand Vim. - Copy and rename them.
- Search content using
grepand files usingfind. - Set ownership and permissions.
- Delete only the lab directory after checking
pwdandls.
Lab 2: Linux service
- Create a small script or Java JAR.
- Create a dedicated service user.
- Create a systemd unit.
- Start, enable, inspect, and follow logs.
- Test failure and restart behavior.
Lab 3: Networking and DNS
- Record
ip link,ip addr, andip routeoutput. - Use
ip route getfor a public address. - Add a temporary
/etc/hostsentry in a VM. - Compare
getent hosts,dig, andnslookup. - Remove the test entry.
Lab 4: Java and Jenkins
- Create a minimal Java Maven project.
- Run
./mvnw clean verify. - Package the JAR.
- Create a Jenkinsfile with checkout, test, package, and artifact stages.
- Add an agent rather than building on the controller.
Lab 5: Docker
- Create a multi-stage Dockerfile.
- Build a versioned image.
- Run it as a non-root user.
- Connect the application and PostgreSQL through Compose.
- Persist database data in a named volume.
- Verify logs and health.
Lab 6: Kubernetes
- Create a namespace.
- Deploy the application using a Deployment.
- Add ConfigMap and Secret references.
- Expose it through ClusterIP and test with port-forwarding.
- Scale to three replicas.
- Roll out a new immutable image tag.
- Inspect history and perform rollback.
Lab 7: Ansible
- Create two Linux VMs.
- Build an inventory.
- Test connectivity with
ansible.builtin.ping. - Create a role that installs and configures Nginx.
- Use a template and handler.
- Run syntax check, check mode, and actual apply.
Lab 8: Terraform
- Configure a remote state design for a non-production lab.
- Create an AWS provider configuration using a role/profile.
- Create a small network or S3 resource.
- Run format, initialize, validate, and plan.
- Review and apply a saved plan.
- Verify the resource and then destroy the lab safely.
Final learning project
Build this complete flow:
Git repository
|
Jenkins Pipeline
|-- test Java application
|-- build immutable JAR
|-- build and scan Docker image
|-- push image to registry
|-- update Kubernetes deployment
|-- verify rollout and health
|
Terraform provisions infrastructure
Ansible configures supporting Linux hosts
Monitoring confirms availability
Final production checklist
Official documentation references
- GNU Coreutils manual
- Linux manual pages and iproute2 documentation
- Oracle/OpenJDK tools documentation
- Jenkins User Documentation
- Docker Documentation
- Kubernetes Documentation and kubectl reference
- Ansible Community Documentation
- HashiCorp Terraform Documentation
Product behavior and flags can change. For production work, verify commands against the exact operating-system, Java, Jenkins, Docker, Kubernetes, Ansible, Terraform, cloud-provider, and plugin versions used in your environment.