You finish a playbook on Friday. On your laptop it is green every time: collections resolve, modules behave, the change lands cleanly. Monday morning someone launches the same job from Ansible Automation Platform (AAP) — and it dies on a missing collection, the wrong Python package, or a system library that never existed on the controller workers.
That pattern is not bad luck. It is a packaging problem dressed up as an automation problem. If the job only works where you installed the tools by hand, you do not yet have a platform capability — you have a laptop demo.
What actually changes between your laptop and AAP
Local Ansible and Automation Controller do not share an environment by default. Your laptop quietly carries years of pip install, ansible-galaxy collection install, and OS packages. Controllers run jobs in a defined runtime. When that runtime does not match what the playbook assumes, you get failures that look random:
- A collection version that exists in your user home but not on the worker
- A Python library a module needs (boto3, google-auth, kubernetes, and friends)
- A system package for crypto, Kerberos, or cloud CLIs
- Different Ansible core or ansible-runner versions than you tested against
Teams often “fix” this by installing more packages onto the controller host. That works once, then breaks the next upgrade, the next colleague’s job, or the next environment that was never patched the same way. You have traded a one-off failure for shared, invisible state.
Execution environments: ship the runtime with the playbook
An execution environment (EE) is a container image that holds everything the job needs to run: Ansible, collections, Python dependencies, and selected system packages. Automation Controller pulls that image and runs the job inside it. The playbook no longer depends on whatever happened to be installed on the worker last quarter.
Think of it the same way application teams think about shipping a service: if the app only runs on one developer’s machine, it is not ready. If the automation only runs on one consultant’s laptop, it is not ready either.
A practical path that survives contact with production
1. Write down what the playbook actually needs
Start from failure, not from a wish list. Capture the collections and Python packages your roles import. Prefer pinned versions over “latest”. If a cloud module needs a vendor SDK, that SDK belongs in the EE definition — not in a sticky note on the wiki.
A minimal dependency file for ansible-builder usually looks like a short list of collections plus a requirements.txt (or equivalent) for Python. Keep it next to the playbook in git so reviews can see runtime changes the same way they see YAML changes.
2. Build a small EE, then prove it outside the laptop story
Use ansible-builder (or your platform’s supported build path) to produce an image from that definition. Run the playbook from that image before you attach it to a Controller job template. If it only passes with your personal virtualenv, you have not finished the build.
Push the image to a registry your AAP instance can reach. Tag by purpose and version (network-ee:1.4.0), not by a person’s name. Named images age badly the week that person leaves the project.
3. Pin the EE on the job template
In Automation Controller, point the job template (or the organization default, when that fits) at the EE you just published. Re-run the same inventory and extra vars you used in testing. The goal is boring: identical inputs, identical runtime, predictable result.
When something still fails, you now have a useful question: is the bug in the playbook, the inventory data, or the EE definition? Without an EE, every failure looks like “Ansible is flaky.” With an EE, you can reproduce the runtime on a fresh machine.
Patterns that keep EEs maintainable
- Prefer a few shared EEs over one per playbook. Group by domain (cloud provisioning, network, Windows, Linux baseline). Too many images become another inventory problem.
- Rebuild on a schedule, not only on pain. Base images and security fixes move. A quarterly rebuild with a changelog beats an emergency rebuild during an outage.
- Keep credentials out of the image. Secrets belong in Controller credentials, vault, or your secrets manager — never baked into layers “just for the pipeline.”
- Document the contract. One page: which job templates use which EE tag, who owns the definition, and how to request a new collection.
Where this shows up in real delivery
On client engagements, the first “it works on my machine” incident often appears right when automation leaves a proof of concept and enters shared Controller. Cloud playbooks are frequent offenders because SDKs and auth libraries change quickly. If you are already automating instance lifecycle in the public cloud, the same discipline applies whether you started from a tutorial like our walkthrough of Ansible automation on Google Cloud or from an internal role library.
The payoff is operational, not decorative. On-call engineers can re-run a job without cloning someone’s laptop. New team members get a green path without a two-hour setup script. Upgrades become deliberate image bumps instead of archaeology on a controller host.
A short checklist before you call the automation “done”
- Dependencies are declared and pinned in an EE definition in git
- The playbook has been run successfully from that image, not only from a local venv
- The Controller job template pins the EE tag you tested
- Someone other than the author can launch the job and get the same result
- There is an owner for rebuilding the EE when collections or base images change
If any line on that list is missing, treat the work as unfinished delivery — even if the ticket is green. Automation that only one person can run is still a project, not a platform.
Bottom line
When Ansible fails in AAP after succeeding locally, start with the runtime, not with blame. Execution environments turn “works on my laptop” into a versioned, reviewable artifact that Controller can trust. That is how you move from clever playbooks to automation other people can operate.
If you are shaping an AAP rollout or cleaning up controller jobs that only work for one engineer, our automation consulting services cover the same ground: make the path reproducible, then make it owned.



Leave a Reply