50% OFF on All Courses!

Popular:

Your cart is empty

Your cart is empty

Ansible Interview Questions: 120 Real Ones With Answers

120 Ansible interview questions with worked answers, YAML you can run, and the ansible-core 2.19 and 2.20 changes interviewers are actually asking about in 2026.
Business interview between a woman and a man in a modern office setting.

Most Ansible interview questions lists were written for Ansible 2.9 and quietly reprinted every January.

You can spot them fast. They still say include instead of import_tasks. They still tell you facts live in ansible_distribution. And not one of them mentions that ansible-core 2.19 made non-boolean conditionals a hard error, or that 2.20 deprecated the setting that put those facts in your top-level namespace in the first place.

Here’s the deal. If your interviewer runs a current cluster, they know. And a candidate quoting 2019 behaviour sounds exactly like a candidate who has never upgraded anything.

So this is 120 Ansible interview questions with answers that match ansible-core 2.20 and the Ansible 13 community package. Every section tells you what the interviewer is actually checking. The YAML runs. And there’s a full section on the 2.19 and 2.20 breaking changes, because that’s the part nobody else covers and the part that separates you from the other four candidates.

Skip around. Freshers start below. Experienced engineers, jump to question 71.

Short on playbook practice? Our 20 Ansible playbook examples you can copy and run covers the patterns most of these questions are built on. Read that first if your hands-on time is thin.

How Ansible interviews actually run in 2026

Three rounds, usually.

Round one is a screen. Twenty minutes, often with a recruiter reading from a sheet. Pure definitions. What’s a playbook, what’s idempotency, agentless versus agent-based. You pass this by being fast and clear, not deep.

Round two is the real one. An engineer, 45 to 60 minutes, and the Ansible interview questions here are mostly “tell me about a time” plus live troubleshooting. They’ll describe a broken run and ask what you’d check. Variable precedence comes up in maybe half of these.

Round three is design. Senior roles only. Structure the automation for 400 servers across three environments, or explain how you’d roll a change with zero downtime.

One thing that’s changed since 2024: more teams ask about Event-Driven Ansible now, even when they don’t run it. They want to know you’ve read past the basics.

And one thing that hasn’t changed at all. Most candidates fail on variable precedence and idempotency. Not on anything exotic.

Three-column diagram of the Ansible interview process. Round 1 is a 20 minute recruiter screen on definitions. Round 2 is a 45 to 60 minute engineer deep dive on precedence and real incidents. Round 3 is a design round for senior roles.

Sara had six years on RHEL and applied for a platform role in Toronto in March. She sailed through the screen. Round two, the interviewer asked her to explain why a playbook that worked in staging was picking up the wrong http_port in production. She said “extra vars probably” and stopped. He waited. She didn’t have the rest of the ladder, couldn’t name where group_vars sat relative to host_vars, and the interview cooled from there. She got the rejection two days later with one line of feedback: “strong ops background, gaps in Ansible fundamentals.” Six years of experience, lost to a question worth about four minutes of study.

Don’t be Sara. Question 34 is the ladder.

Ansible interview questions for freshers

What they’re checking: can you describe Ansible to someone who doesn’t already know it, and do you understand the architecture well enough to debug it later. Answers here should be short. Rambling on a definition question reads as padding.

Architecture and how Ansible connects

1. What is Ansible?

An open-source automation tool that configures systems, deploys software, and orchestrates multi-step tasks. You describe the state you want in YAML, and Ansible makes the machines match it. No agent on the target, no central daemon required.

2. What does agentless mean, and why does it matter?

Ansible connects over SSH for Linux and WinRM or PSRP for Windows. Nothing gets installed on the managed node. It matters because there’s no agent to patch, no agent port to firewall, and no chicken-and-egg problem bootstrapping a fresh box. Puppet and Chef both need an agent running before they can do anything.

3. What are the main components of Ansible?

Control node (where you run ansible-playbook), managed nodes (the targets), inventory (the list of targets), modules (the units of work), plugins (connection, lookup, filter, callback), playbooks (YAML files describing plays), and roles (packaged, reusable content).

4. What is idempotency?

Running the same playbook twice produces the same end state, and the second run reports no changes. It matters because you can run Ansible on a schedule against production without fear. Most modules are idempotent by design. shell and command are not.

5. How do you make shell or command idempotent?

Use creates, removes, or a changed_when that reflects reality.

- name: Extract the archive once
  ansible.builtin.command: tar -xzf /tmp/app.tar.gz -C /opt/app
  args:
    creates: /opt/app/bin/server

If /opt/app/bin/server exists, the task is skipped. That’s the whole trick, and it’s a very common follow-up.

Comparison diagram. An unguarded command task reports changed on all three runs. The same task with a creates guard reports changed once then ok twice. Below, the three causes of a permanent changed status.

6. What’s the difference between an ad hoc command and a playbook?

An ad hoc command is a one-liner for a single module against a host pattern. A playbook is a saved, version-controlled YAML file with multiple plays and tasks. Ad hoc is for “check something right now”. Playbooks are for anything you’ll do twice.

ansible webservers -m ansible.builtin.ping
ansible webservers -m ansible.builtin.service -a "name=nginx state=restarted" -b

7. What is an inventory?

The list of hosts Ansible can talk to, plus their grouping and variables. It can be a static INI or YAML file, a dynamic script, or an inventory plugin that queries AWS, NetBox, or vCentre at runtime.

8. Static or dynamic inventory, when do you pick which?

Static for a fixed, small estate. Dynamic for anything where machines come and go, which is most cloud environments. A static file starts rotting the moment someone builds a server without telling you. We wrote up the trade-off in detail in static vs dynamic Ansible inventory.

9. What is ansible.cfg and where does Ansible look for it?

The config file. Ansible checks, in order: ANSIBLE_CONFIG environment variable, ./ansible.cfg in the current directory, ~/.ansible.cfg, then /etc/ansible/ansible.cfg. First one found wins completely. It does not merge them.

10. What is a module?

A unit of work Ansible ships to the target and runs. ansible.builtin.copy, ansible.builtin.yum, ansible.builtin.service. Modules return JSON, and Ansible uses that to decide changed, ok, or failed.

11. What’s an FQCN and why should you use one?

Fully Qualified Collection Name. ansible.builtin.copy instead of copy. Since collections split out of core, short names can resolve to different modules depending on what’s installed. FQCNs remove the ambiguity, and ansible-lint will flag you if you skip them.

12. What is a play?

A mapping of hosts to tasks. One playbook file can hold several plays, each targeting a different group with different privilege settings.

13. What is a task?

A single call to a module with its arguments, plus optional conditions, loops, and a name.

14. What are handlers?

Tasks that only run when notified, and only once at the end of the play no matter how many times they were notified. Classic use is restarting a service after a config change.

tasks:
  - name: Push nginx config
    ansible.builtin.template:
      src: nginx.conf.j2
      dest: /etc/nginx/nginx.conf
    notify: Restart nginx

handlers:
  - name: Restart nginx
    ansible.builtin.service:
      name: nginx
      state: restarted

15. When do handlers actually run?

At the end of the play, or wherever you put meta: flush_handlers. Not immediately. And if the play fails before the handler section, the handler never fires, which trips people up during outages.

16. What are facts?

System information Ansible gathers from the target at the start of a play: OS family, IP addresses, memory, mounted filesystems. Collected by the setup module.

17. How do you turn fact gathering off, and why would you?

gather_facts: false on the play. You’d do it for speed when you don’t need any facts, or against network devices that can’t run the setup module.

18. What is Ansible Galaxy?

The public hub for community roles and collections, and also the ansible-galaxy CLI you use to install them. ansible-galaxy collection install community.general.

19. What’s a collection?

A packaged bundle of roles, modules, plugins, and playbooks with its own versioning. Since ansible-core 2.10, almost everything outside a small builtin set ships as a collection.

20. What’s the difference between ansible-core and the Ansible community package?

ansible-core is the engine plus ansible.builtin. The Ansible community package is ansible-core bundled with several hundred collections. Ansible 13 is the current community package and ships ansible-core 2.20, per the Ansible releases and maintenance page.

21. What Python versions does Ansible need?

For Ansible 13 with ansible-core 2.20: Python 3.12 to 3.14 on the control node, 3.9 to 3.14 on managed nodes. Both floors moved in 2.20. Python 3.11 stopped being a supported control node version, and Python 3.8 stopped being a supported remote version, which retires Ubuntu 20.04 as a managed node. Get this the wrong way round in an interview and it’s obvious you read a summary rather than the porting guide.

22. Can the control node run on Windows?

Not natively. Use WSL, a Linux VM, or a container. Windows is fine as a managed node.

23. What’s ansible-playbook --check?

Dry run. Modules that support check mode report what they would change without changing it. Modules that don’t support it get skipped. Pair it with --diff to see the actual text changes.

24. What’s --limit for?

Restricting a run to a subset of the inventory. --limit web-03 or --limit 'webservers:!web-03'. This is the flag that saves you during an incident.

25. How do you test that Ansible can reach your hosts?

ansible all -m ansible.builtin.ping
ansible all -m ansible.builtin.setup -a "filter=ansible_distribution*"

The first checks SSH and Python. The second confirms fact gathering works, which is a different failure mode.

Ansible playbook interview questions

What they’re checking: whether you’ve written playbooks or only read about them. Playbook Ansible interview questions live or die on variable precedence and loop syntax, and those two expose the difference in about thirty seconds.

Variables, facts, and precedence

26. Where can you define variables?

Command line extra vars, play vars, vars_files, vars_prompt, host_vars, group_vars, role defaults, role vars, inventory files, registered variables, set_fact, and facts themselves. Twenty-two places officially. Knowing the top and bottom of that list matters more than reciting all of it.

27. What wins: group_vars, host_vars, or --extra-vars?

--extra-vars beats everything. Always. Then, working down: role vars beat play vars, which beat host_vars, which beat group_vars, which beat role defaults. Role defaults are the weakest thing in Ansible, on purpose, so users can override them.

28. Why are role defaults almost the weakest thing in Ansible and role vars so much stronger?

Because they serve opposite purposes. defaults/main.yml is a suggestion the role author expects you to override. vars/main.yml is an internal constant the author doesn’t want you touching. Same role, opposite intent. In the documented 22-level ladder, role defaults sit at level 2 and role vars at level 15. Interviewers love this one because it separates people who’ve written roles from people who’ve run them.

Ansible variable precedence ladder showing nine of the 22 documented levels, strongest at the top. Extra vars at level 22 win everything, role defaults at level 2 are weakest, with role vars, play vars, host_vars and group_vars in between.

29. Two groups define the same variable. Which wins?

Whichever group has the higher ansible_group_priority. If priorities match, they merge alphabetically by group name, so the last name alphabetically wins. Child groups always beat parent groups regardless of priority.

30. What’s set_fact?

Sets a variable at runtime, scoped to the host, that persists for the rest of the play. Higher precedence than almost everything except extra vars.

- name: Build the config path
  ansible.builtin.set_fact:
    app_config: "/etc/{{ app_name }}/{{ env }}.conf"

31. What’s register?

Captures a task’s return value into a variable. You then branch on .rc, .stdout, .changed, or .failed.

- name: Check the service
  ansible.builtin.command: systemctl is-active nginx
  register: nginx_state
  changed_when: false
  failed_when: false

- name: Report it
  ansible.builtin.debug:
    msg: "nginx says {{ nginx_state.stdout }}"

Note changed_when: false. A read-only check should never report changed. Leaving that off is the single most common idempotency bug in real codebases.

32. What’s the difference between ansible_facts['distribution'] and ansible_distribution?

Same value, two access paths. The bare ansible_distribution form exists because INJECT_FACTS_AS_VARS defaults to true and copies every fact into the top-level namespace. That default is deprecated in ansible-core 2.20 and flips to false in 2.24. Write ansible_facts['distribution'] in anything new. More on this at question 108.

33. What’s a magic variable?

A variable Ansible provides about the run itself rather than the host’s hardware. inventory_hostname, groups, hostvars, play_hosts, ansible_play_batch. They’re not facts and gathering doesn’t affect them.

34. How do you read another host’s variable?

Through hostvars.

- name: Point the app at the database
  ansible.builtin.debug:
    msg: "DB is at {{ hostvars[groups['databases'][0]]['ansible_default_ipv4']['address'] }}"

This needs facts gathered for that other host, which is why it fails when you run with --limit on just the app servers.

35. What’s vars_prompt?

Interactive input at playbook start. Fine for a one-off, terrible in CI, since it hangs forever waiting for a human.

36. How do you set a default for a variable that might not exist?

{{ some_var | default('fallback') }}. Use | default(omit) when you want the module parameter dropped entirely rather than set to an empty value.

37. What’s the omit placeholder for?

Telling a module “pretend I didn’t pass this argument”. Useful when one loop iteration should set an option and another shouldn’t. Worth knowing that 2.19 changed how omit propagates: values resolving to omit inside a loop are now dropped immediately instead of leaking through.

38. How do you keep a variable out of the log?

no_log: true on the task. It also suppresses the entire return value, which makes debugging painful, so turn it off deliberately when you’re troubleshooting and never commit it off.

Loops, conditionals, and templates

39. How do you loop over a list?

- name: Install the base packages
  ansible.builtin.package:
    name: "{{ item }}"
    state: present
  loop:
    - git
    - curl
    - vim

Though for package modules, passing the whole list at once is faster. One transaction instead of three.

40. loop or with_items, which should you use?

loop. The with_* family still works but has been the older style since 2.5, and with_items silently flattens nested lists in a way that surprises people. Use loop plus a filter when you need flattening.

41. How do you loop over a dictionary?

- name: Create the users
  ansible.builtin.user:
    name: "{{ item.key }}"
    shell: "{{ item.value.shell }}"
  loop: "{{ users | dict2items }}"

42. What’s loop_control good for?

Renaming item with loop_var (needed when you nest loops through include_tasks), setting a label so the output isn’t a wall of JSON, adding a pause, or exposing index_var.

43. How do conditionals work?

when, with a bare Jinja expression and no curly braces.

- name: RHEL-only task
  ansible.builtin.dnf:
    name: httpd
    state: present
  when: ansible_facts['os_family'] == "RedHat"

44. Can when return a non-boolean?

Not since ansible-core 2.19. when: inventory_hostname used to pass because a non-empty string is truthy. Now it raises: “Conditional result was ‘localhost’ of type ‘str’, which evaluates to True. Conditionals must have a boolean result.” Write when: some_list | length > 0 instead. This is one of the most common breakages when teams upgrade, and a great question to raise yourself if the interviewer asks whether you have questions.

45. Difference between when and failed_when?

when decides whether the task runs at all. failed_when decides whether a task that ran counts as a failure. Different stages entirely.

46. What’s block, rescue, always?

Try/catch/finally for tasks.

- block:
    - name: Try the upgrade
      ansible.builtin.command: /opt/app/upgrade.sh
  rescue:
    - name: Roll back
      ansible.builtin.command: /opt/app/rollback.sh
  always:
    - name: Re-enable monitoring
      ansible.builtin.command: /usr/bin/unsilence-alerts

47. What’s the difference between ignore_errors and failed_when: false?

ignore_errors: true marks the task failed but carries on, and the failure still shows red in output. failed_when: false means it was never a failure at all. Use the second for checks whose non-zero exit is expected.

48. template or copy, which one?

copy ships a file as-is. template renders Jinja2 first. If the file has a single {{ }} in it, you need template.

49. What Jinja2 filters do you actually use?

default, to_nice_json, to_nice_yaml, from_json, join, map, select, selectattr, regex_replace, b64encode, combine, dict2items, ipaddr from ansible.utils. If you name five without hesitating you sound like someone who writes templates.

50. Can you nest a template inside an expression?

No, not since 2.19. Multi-pass templating is gone. {{ 1 + {{ value }} }} used to work by accident and now raises a syntax error. Reference the variable directly: {{ 1 + value }}.

Ansible roles and collections interview questions

What they’re checking: whether your automation would survive being handed to someone else. Anyone can write a 400-line playbook. Roles are how you prove you’ve maintained one, and Ansible interview questions on roles are where that shows.

51. What is a role?

A directory structure that packages tasks, handlers, templates, files, variables, and metadata into something reusable and independently testable.

52. What’s in a role directory?

tasks/, handlers/, templates/, files/, vars/, defaults/, meta/, tests/, and library/ for role-local modules. Ansible auto-loads main.yml from each.

53. defaults/ or vars/, where does this variable go?

If a user should be able to override it, defaults/. If changing it would break the role, vars/. Anything that looks like configuration belongs in defaults.

54. What’s meta/main.yml for?

Role dependencies, supported platforms, minimum Ansible version, author info, and Galaxy tags. Dependencies listed there run before the role does.

55. How do you call a role?

Three ways. The roles: key at play level (runs before tasks), import_role (static), and include_role (dynamic).

56. Static or dynamic, what’s the real difference?

import_* is resolved at parse time. Tags and when apply to every task inside it, and --list-tasks shows them all. include_* is resolved at runtime, so it can take a variable filename or sit inside a loop, but tags on it don’t reach the child tasks. Rule of thumb: import unless you need a loop or a runtime-determined name.

57. Why is import_playbook different from import_tasks?

import_playbook pulls in a whole playbook file with its own plays and hosts. import_tasks pulls in a task list into the current play. Different levels.

58. What replaced the old include?

include_tasks and import_tasks. The bare include was ambiguous about static versus dynamic behaviour and is gone. If a study guide still teaches include, it predates 2.4 and you should stop reading it.

59. How do you share a role across teams?

Publish it to a private Automation Hub or Galaxy, or pin it from Git in requirements.yml.

roles:
  - src: https://github.com/acme/ansible-role-nginx
    scm: git
    version: v2.3.1

Pin the version. Always. main is not a version.

60. What’s requirements.yml?

The manifest of external roles and collections your project needs, installed with ansible-galaxy install -r requirements.yml. It’s how you get repeatable builds.

61. How do you pin a collection version?

collections:
  - name: community.general
    version: ">=9.0.0,<10.0.0"

62. What is Ansible Automation Hub?

Red Hat’s curated, supported collection registry, part of Ansible Automation Platform. Content there carries a support commitment. Galaxy content does not.

63. What’s an execution environment?

A container image holding ansible-core, collections, and Python dependencies, built with ansible-builder. It fixes the “works on my laptop” problem by making the whole runtime a versioned artifact.

64. How do roles get their variables at runtime?

Through defaults, then anything the caller passes, then group and host vars. When you call with include_role you can pass vars: inline, which lands at high precedence.

65. Can a role depend on another role?

Yes, through meta/main.yml dependencies. Be careful. Deps run every time the role is called unless allow_duplicates: false is set, and deep dependency chains get hard to reason about fast.

66. What’s ansible-galaxy init?

Scaffolds an empty role with the standard directory layout. Use ansible-galaxy collection init for a collection skeleton.

67. How do you tag tasks inside a role?

Tag the role at call site with tags: and every task inherits it, or tag individual tasks inside. Remember tags don’t propagate through include_role the way they do through import_role.

68. What’s the difference between a role and a collection?

A role is one reusable unit of configuration. A collection is a distribution package that can hold many roles, plus modules, plugins, and playbooks, with its own version number and namespace.

69. How do you test a role?

Molecule. It spins up a container or VM, converges the role, runs a verifier (usually Testinfra or Ansible’s own assertions), then runs converge again to prove idempotency. That second converge is the point.

70. What does a good role look like in review?

Sensible defaults, no hardcoded paths, works on at least two distros or explicitly says it doesn’t, has a README with a variables table, passes ansible-lint, and has a Molecule scenario. If a candidate mentions the idempotence check unprompted, that’s usually someone who’s been burned.

Building this properly, not just for the interview? Our Automation Engineer programme runs live, and every student writes and reviews real roles with an instructor in the room. That review loop is the part you can’t get from a video.

Ansible interview questions for experienced engineers

What they’re checking: scale and failure. Everything above works fine on five servers. These questions ask what happens at 500, and what you do when it breaks at 2am.

Performance and execution control

71. A playbook takes 40 minutes across 300 hosts. Where do you start?

Profile before you guess. Turn on the timing callbacks:

[defaults]
callbacks_enabled = ansible.posix.profile_tasks, ansible.posix.profile_roles

Then look at the top five tasks by time. Usually it’s fact gathering, a serialised loop that should be one call, or a wait_for with a generous timeout. Fix the measured problem, not the suspected one.

72. How does forks work?

Number of hosts Ansible works on in parallel. Default is 5, which is far too low for 300 hosts. Raise it in ansible.cfg and watch control-node CPU and file descriptors, because each fork is a process.

73. What’s serial and how is it different from forks?

forks is parallelism. serial is batching. serial: 10 processes ten hosts through the entire play, then the next ten. That’s what gives you rolling updates. You can pass a list, serial: [1, 5, 20], for a canary that widens.

74. What are strategies?

linear (default): every host finishes task 1 before anyone starts task 2. free: each host runs ahead as fast as it can. host_pinned: a worker sticks with one host until it’s done. Use free when hosts vary wildly in speed and the tasks don’t depend on each other.

75. What’s fact caching and when is it worth it?

Storing gathered facts in Redis, memcached, or JSON files so subsequent runs skip the setup module. Worth it when you run against the same estate repeatedly and facts don’t change much. Set gathering = smart plus a cache plugin and a sane fact_caching_timeout.

76. What’s gather_subset for?

Gathering only the fact categories you need. gather_subset: ['!all', '!min', 'network'] cuts setup time a lot on machines with many mounts or interfaces.

77. What’s pipelining and why isn’t it on by default?

It reduces SSH operations per task by sending the module over the existing connection instead of copying a file. Big speed win. It’s off by default because it breaks when requiretty is set in sudoers, which used to be common on RHEL.

78. What’s async and poll?

Fire-and-forget or fire-and-check-later. async: 3600, poll: 0 starts a long job and moves on. You then use async_status to check it. This is how you handle a task that outlives your SSH timeout.

79. What’s run_once?

Runs a task on the first host in the batch only, and can share the result with the rest through delegate_facts. Used for database migrations, where running it on all ten app servers would be a disaster.

80. What’s delegate_to?

Runs the task somewhere other than the current host, while keeping the current host’s variables in scope. Classic use is pulling a node out of a load balancer from the control node, or from the balancer itself, before touching the node.

- name: Drain from the load balancer
  community.general.haproxy:
    state: disabled
    host: "{{ inventory_hostname }}"
    backend: app_pool
  delegate_to: lb-01.example.com

81. How do you do a zero-downtime rolling deploy?

serial for the batch size, max_fail_percentage to abort if too many fail, drain from the balancer with delegate_to, deploy, health check with wait_for or a uri call against the app’s own endpoint, put it back in the pool. The health check is the part people skip, and it’s the part that makes it zero-downtime rather than zero-downtime-shaped.

82. What’s max_fail_percentage?

Aborts the play if more than that share of hosts in a batch fail. Without it, serial: 10 will happily break all 300 machines one batch at a time.

83. What does any_errors_fatal do?

Any host failing stops the play for every host, immediately. Use it when a partial rollout is worse than no rollout.

84. How do you debug a playbook that’s misbehaving?

-vvv for the module arguments and the raw return. --check --diff to see the intended change. --start-at-task to skip to the problem. The debug module with var: to print what a variable actually holds, which is usually not what you assumed. And ansible-playbook --syntax-check before you waste a run.

85. What’s the debugger keyword?

Drops you into an interactive prompt on task failure where you can inspect task_vars, change task.args, and redo the task. debugger: on_failed on a task or play. Almost nobody uses it and it’s genuinely useful.

Vault, secrets, and security

86. What is Ansible Vault?

Symmetric encryption for variables and files, so secrets can live in Git. ansible-vault encrypt, decrypt, edit, view, rekey, and encrypt_string for a single value.

87. Encrypt the whole file or just the value?

Just the value, usually. ansible-vault encrypt_string gives you an inline blob you can paste into a normal, readable vars file. A fully encrypted file means every diff in code review is a wall of base64.

88. How do you use more than one vault password?

Vault IDs. --vault-id dev@prompt --vault-id prod@~/.vault_prod. Different secrets for different environments, so a developer with the dev password can’t decrypt production.

89. How do you supply the vault password in CI?

A password file with tight permissions, or better, a vault password script that fetches the key from HashiCorp Vault, AWS Secrets Manager, or Azure Key Vault at runtime. Never an environment variable in a shared runner, and never committed.

90. Is Vault enough for secrets management on its own?

For a small team, usually. At scale, no. Vault has no rotation, no audit trail, and no fine-grained access control. Mature setups pull secrets at runtime from a real secrets manager through a lookup plugin and use Ansible Vault only for the bootstrap credential. Saying this unprompted marks you as senior.

91. How do you stop secrets leaking into logs?

no_log: true on tasks handling them, and be aware that a failed task with no_log gives you nothing to debug with. Also check your callback plugins, because a JSON callback shipping to a log aggregator will happily forward whatever it’s given.

92. What’s the security concern with become?

Password-based become sends the password over the connection, and become_user to a non-root user has a known permissions problem writing temp files. Use pipelining plus ANSIBLE_REMOTE_TEMP correctly, or a passwordless sudo rule scoped to what you actually need.

Testing, CI, and platform

93. What does ansible-lint catch?

Deprecated syntax, missing FQCNs, unnamed tasks, shell where a module exists, permissions left implicit, and idempotency smells. Run it in CI as a gate, not as a suggestion.

94. What does a real Ansible CI pipeline look like?

Lint, syntax check, Molecule converge and idempotence in a container, then a run against a staging inventory in check mode, then a gated apply. The idempotence step is the one that catches actual bugs.

95. What’s Event-Driven Ansible?

The piece that lets an event trigger automation instead of a human or a cron. You write a rulebook in YAML with three parts: sources (Kafka, webhook, Alertmanager, a Kafka topic), conditions, and actions (run a playbook, run a job template, set a fact).

- name: Restart the service on a critical alert
  hosts: all
  sources:
    - ansible.eda.webhook:
        host: 0.0.0.0
        port: 5000
  rules:
    - name: Handle the down event
      condition: event.payload.alertname == "ServiceDown"
      action:
        run_playbook:
          name: restart_service.yml

Ansible Automation Platform 2.6 added an event_splitter filter for nested events, multi-topic and wildcard support in the Kafka source, and external secret management for EDA, per Red Hat’s release notes. Knowing that EDA exists puts you ahead of most candidates. Knowing what a rulebook contains puts you ahead of nearly all of them.

Ansible interview questions for network automation

What they’re checking: whether you understand that network devices break most of Ansible’s assumptions. These are a different set of Ansible interview questions from the server ones, and candidates who prepared for the server version get caught out here.

Dev came to us in January with four years of Cisco experience and a CCNP. He’d done the reading, could recite variable precedence cold, and then got asked in a round two: “why does gather_facts fail on a Catalyst switch?” He didn’t know. He’d never run Ansible against a device that couldn’t execute Python. It’s a fifteen-second answer and it cost him the round. He took our CCIE Automation track, sat the same company’s interview again in June, and started in July.

96. Why does gather_facts: true fail against a switch?

The setup module is a Python script that runs on the target. A Catalyst or Nexus box in normal mode has no Python runtime you can use that way. Set gather_facts: false and use the platform’s own facts module, cisco.ios.ios_facts, instead.

97. What’s the network_cli connection plugin?

It runs the module on the control node and drives the device over SSH in an interactive CLI session, sending commands and parsing responses. That’s the opposite of the normal model, where the module is shipped to the target.

Two-row diagram. On a Linux server the module is shipped over SSH and Python runs it on the target, returning JSON facts. On a switch the module runs on the control node and drives the CLI, because the device has no Python to run.

98. network_cli, netconf, or httpapi?

network_cli for CLI-driven gear, which is most of it. netconf for devices with a proper NETCONF and YANG stack, like Junos. httpapi for REST-based platforms, like Nexus NX-API or Meraki. Pick based on what the device supports, and prefer structured over screen-scraped when you have the choice.

99. How does idempotency work with ios_config?

It compares your lines against the running config and pushes only the difference. But it’s line-matching, not semantic, so ordering and exact syntax matter. ios_config will happily re-push a line that’s functionally already there if the string doesn’t match. This is why network idempotency is genuinely harder than server idempotency, and saying that out loud is the answer they want.

100. How do you back up a config before you change it?

- name: Back up running config
  cisco.ios.ios_config:
    backup: true
    backup_options:
      dir_path: ./backups/{{ inventory_hostname }}
      filename: "{{ ansible_date_time.date }}.cfg"

Then push the change. If your answer to “how do you handle a bad change” doesn’t start with a backup, that’s a red flag to a network team.

101. What’s ios_command for and how is it different from ios_config?

ios_command runs show commands and returns output. ios_config changes configuration. Use ios_command with wait_for to assert state before and after a change.

102. How do you handle credentials for 200 devices?

ansible_user and ansible_password from Vault or a secrets manager, per group not per host, and use ansible_network_os in group vars to pick the right platform modules. TACACS with a service account beats local credentials, and your automation account should have a scoped privilege level.

103. What’s a dynamic inventory for network gear?

Pull from your source of truth rather than a static file. NetBox is the usual answer, through the netbox.netbox.nb_inventory plugin, which gives you groups by site, role, platform, and tenant for free. We wrote the full setup in NetBox dynamic inventory.

104. How do you push a VLAN to 40 switches safely?

Batch it. serial: 5, back up first, push, run a ios_command verification against show vlan brief, and max_fail_percentage: 0 so the first failure stops the rollout. Then have a rollback playbook that restores the backup, tested before you need it.

105. Ansible or a vendor controller like DNA Center?

Ansible when you want one tool across mixed vendors and full control of the change. A controller when you’re single-vendor and want the vendor’s intent model and compliance reporting. Most real networks run both, with Ansible doing the things the controller can’t express. Answering “it depends, here’s the split” beats picking a side.

Working on network automation specifically? Our CCIE Automation track covers exactly this: network_cli, structured data from devices, NetBox as source of truth, and change safety on production gear. Live sessions, and you keep the lab access.

Ansible interview questions about 2.19 and 2.20 changes

What they’re checking: whether you’ve upgraded anything recently. This section doesn’t exist in any other Ansible interview questions list, which is exactly why it’s worth reading. If a team runs ansible-core 2.19 or later, they hit these. If they haven’t upgraded yet, they’re about to, and a candidate who can describe the migration is immediately useful.

106. What’s the current version and what’s supported?

ansible-core 2.20 went GA on 2025-11-03 and is supported to May 2027. The community package built on it is Ansible 13. ansible-core 2.19 is in security-only maintenance until 2026-11-02. The community team maintains one major community package at a time, so 12.x is already past its date. Source: the Ansible releases and maintenance page.

Version timeline from ansible-core 2.19 to 2.24 with two columns. The left lists what 2.19 broke including non-boolean conditionals and nested templates. The right lists what 2.20 deprecated or removed including injected facts and smart transport.

107. What is Data Tagging?

The headline feature of 2.19. Ansible now tracks the provenance of a value: which file it came from, which line, which column. When something goes wrong, the error tells you where the value was defined instead of just what blew up. It also lets modules tag return values as deprecated with help text attached.

108. What’s happening to INJECT_FACTS_AS_VARS?

It defaults to true today, which is why ansible_distribution works as a bare variable alongside ansible_facts['distribution']. In 2.20 that default is deprecated, and it flips to false in 2.24. You’ll see deprecation warnings on any playbook reading injected facts. The migration is mechanical: replace ansible_<fact> with ansible_facts['<fact>'], dropping the prefix. Confirmed in the ansible-core 2.20 porting guide.

Worth flagging: ansible-lint didn’t catch this deprecation when it landed, so a clean lint run doesn’t mean you’re clear. Grep for it.

109. What broke in 2.19 templating?

Four things, roughly in order of how often they bite:

  1. Non-boolean conditionals now error. Covered at question 44.
  2. No embedded templates in expressions. {{ 1 + {{ x }} }} is a syntax error now.
  3. Native Jinja is the only mode. The old final-pass literal evaluation is gone, so things that used to get stringified stay typed.
  4. Filters stop silently coercing. replace on a non-string fails instead of quietly converting. Use map() across list elements.

Full list in the ansible-core 2.19 porting guide.

110. What’s the inverted trust model for templates?

Before 2.19, everything was templatable and you marked untrusted data unsafe. Now it’s the other way round: only strings from trusted sources, meaning playbooks, roles, and vars files, get templated. A template string that arrives from a remote system’s output is ignored by default. It’s a real security improvement and it also means some clever tricks people relied on quietly stop working.

111. What else did 2.20 remove?

DEFAULT_TRANSPORT = smart is gone, so you pick ssh or paramiko explicitly. The vault and unvault filters no longer take the deprecated vaultid parameter. And ansible-galaxy dropped support for the v2 Galaxy server API, which matters if you’re pointing at an old internal mirror.

112. How would you plan a 2.9 to 2.20 upgrade?

Not in one jump. Read the porting guide for every version in between, because breaking changes are cumulative and each guide only lists its own. Then: pin your current version so nothing moves under you, get the whole codebase passing ansible-lint, convert short module names to FQCNs, move to import_tasks/include_tasks, migrate off injected facts, then upgrade one minor at a time with Molecule running against each. Budget weeks, not an afternoon. Anyone who says “just upgrade and fix the errors” has not done it on a real codebase.

Ansible scenario based interview questions

What they’re checking: how you think when there isn’t a clean answer. Scenario based Ansible interview questions are the ones that decide the offer. Talk through your reasoning out loud, ask clarifying questions, and say what you’d check first.

113. A playbook works in staging and fails in production. Where do you look?

Variables first. Different group_vars, an extra var set in the pipeline, a host_vars file nobody remembers. Run with -vvv and compare the resolved values, or add a debug task dumping the specific variable early in the play. Then check OS version drift, and whether production has a different become policy. Nine times out of ten it’s precedence.

114. Your playbook reports “changed” on every run. Why?

Something isn’t idempotent. Usually a shell or command task without creates or changed_when. Sometimes a template where the rendered output has a timestamp or a dict rendering in a different order each time. Sometimes a file task with a mode expressed as 755 instead of '0755', so YAML reads it as an integer.

115. Half your hosts failed mid-deploy. What now?

Stop the run. Work out whether the failed half are actually broken or just skipped, since those need different responses. Use --limit @/path/to/retry to target only the failures once you’ve fixed the cause. And then go add max_fail_percentage so it stops itself next time.

116. You need to deploy to 500 servers in three regions with different configs. Design it.

Inventory grouped by region and by role, with group_vars/region_* for the regional differences and group_vars/role_* for the functional ones. One playbook, roles per function, no regional logic in the tasks. serial sized per region and a max_fail_percentage. If regions must not affect each other, run three separate invocations against three limits rather than one play, so a failure in one is contained.

117. A team wants secrets in the repo. What do you propose?

Ansible Vault as the floor, with per-environment vault IDs so dev credentials can’t open production. Then push toward a real secrets manager with a lookup at runtime, keeping only the bootstrap credential in Vault. Set out the trade-off honestly: Vault is simple and gives you no rotation or audit.

118. How do you roll back a failed Ansible change?

Depends what changed. Config files: you took a backup, restore it. Packages: pin the previous version and re-run. Anything stateful: you don’t roll back, you roll forward, and this is why database changes shouldn’t be in the same playbook as app deploys. The honest senior answer is that rollback is a design decision made before the change, not a command you run after.

119. Ansible or Terraform for this?

Terraform for creating infrastructure that doesn’t exist yet, with state tracking what it owns. Ansible for configuring what’s already there. Day 0 is Terraform, day 1 and day 2 are Ansible. Ansible can create cloud resources through modules, but without state it can’t reliably tell you what it created, and destroying things gets ugly. If you want the certification angle on this, we covered it in the Terraform certification guide.

120. How would you convert 200 bash scripts to Ansible?

Don’t, not all of them. Sort by how often each runs and how much damage it does when it goes wrong, and start at the top of that list. Wrap the rest in command with proper creates guards as a holding position, then rewrite as modules where a module exists. A big-bang rewrite of 200 scripts fails. Picking the ten that page someone at night and doing those properly succeeds.

The 5 answers that fail candidates

These aren’t wrong facts. They’re the right-sounding answers to common Ansible interview questions, the kind that tell an interviewer you’ve read about Ansible rather than run it.

“Ansible is idempotent.” Ansible isn’t. Modules are, and some aren’t. Say “most modules are idempotent, shell and command aren’t unless you guard them” and you’ve answered a different, better question.

“Extra vars have the highest precedence” and then nothing. True but shallow. The follow-up is always “and what’s lowest”, and the answer is role defaults. Volunteering the two ends of the ladder unprompted is worth more than reciting all twenty-two levels.

“I’d use shell for that.” Sometimes right, usually a tell. If a module exists and you reach for shell, you’re bypassing check mode, idempotency, and the return structure. Say why no module fits before you use it.

“We don’t really test our playbooks.” Honest, and fine, as long as you follow it with what you’d do about it. “No Molecule where I am now, but I’d start with lint in CI and an idempotence check” turns a gap into a plan.

Silence on the upgrade question. If you’re asked what version you run and you don’t know, that’s a bigger problem than the version being old. Know your ansible-core version before the interview. It takes one command.

How to prepare for an Ansible interview

Run ansible --version on whatever you have access to. Know your version. It’s the fastest way to sound like someone who operates rather than reads.

Write three playbooks from memory, no docs. Install and configure a service. Roll a change across a group with serial. Template a config with variables and a handler. If you can’t do these without looking things up, that’s your study list.

Break something on purpose. Set a variable in two places and predict which wins before you run it. Get the conditional error from 2.19 to fire. Debugging things you broke deliberately is how the precedence ladder stops being a list you memorised.

Prepare two stories. One about automation that saved real time, with a number. One about a change that went wrong and what you did. Round two is mostly these, and no list of Ansible interview questions can write them for you.

Read the porting guides. Twenty minutes on the 2.19 and 2.20 guides gives you the single most differentiating thing you can say in this interview.

For the wider round, our full DevOps interview guide covers the CI/CD, Kubernetes, and cloud questions that sit either side of Ansible. If the role leans network, Python interview questions for network engineers is the sibling set, because most Ansible-heavy network roles ask about both.

For structured practice away from the screen, SMEnode Labs publishes automation workbooks with lab exercises at smenode-labs.com.

Frequently asked questions

How can I prepare for an Ansible interview?

Know your ansible-core version, be able to write a playbook with variables, a loop, a conditional, and a handler from memory, and be able to explain variable precedence from both ends. Then prepare two real stories about automation you’ve built. Most candidates fail on precedence and idempotency, not on anything advanced.

Is Ansible used for CI or CD?

CD, mostly. Ansible handles the deployment and configuration steps that come after the build. Your CI tool (Jenkins, GitLab CI, GitHub Actions) builds and tests, then calls Ansible to push the artifact and configure the target. Ansible can run inside CI too, for linting and Molecule tests against your own automation code.

How many Ansible interview questions should I actually prepare?

Twenty, properly. The 120 here are for finding your gaps, not for memorising. An interviewer can tell the difference between someone who knows twenty answers cold and someone who half-knows a hundred.

Do I need Red Hat certification to get an Ansible job?

No. RHCE is Ansible-based now and it helps in Red Hat shops and with government contracts, but most teams care more about what you’ve automated. A GitHub repo with three real roles and a Molecule scenario beats a certification with no working examples.

What’s the difference between Ansible and Ansible Automation Platform?

Ansible is the open-source engine. Automation Platform is Red Hat’s commercial product around it: automation controller (the old Tower) for RBAC and scheduling, private Automation Hub, execution environments, Event-Driven Ansible, and support. Interview questions about job templates, surveys, and inventories-with-a-capital-I are usually AAP questions.

Is Ansible still worth learning in 2026?

For infrastructure roles, yes. It’s still the default answer for configuration management and post-provision work in mixed estates, and it shows up in DevOps, platform, SRE, cloud, and network automation job descriptions. The pay picture for those roles is in our DevOps salary guide.

Bottom line

Three things decide this interview, and none of them are on most question lists.

Variable precedence. Know the top and the bottom. Most candidates who fail, fail here.

Idempotency, said precisely. Modules are idempotent, not Ansible. shell needs a guard.

Currency. Know your version, know that 2.19 made conditionals strict, know that INJECT_FACTS_AS_VARS is on its way out. This is the cheapest differentiator available to you, and almost nobody uses it.

Work through the 120 Ansible interview questions above and mark the ones you couldn’t answer out loud. That’s your list. It’ll be shorter than you think.

Want the version where someone checks your answers? SMEnode Academy’s DevOps Engineer programme is live and instructor-led, with mock interviews built into the final module and a real person in the room to tell you when an answer sounds thin. That feedback is the thing a question list can’t give you.

Go get it.