# AWX Operator: AWX as a Kubernetes custom resource, reconciled by watches.yaml

> The AWX Operator installs and manages an AWX instance inside a Kubernetes namespace, built with Operator SDK and Ansible rather than in Go. Its Dockerfile shows a pure event driven reconcile loop, and its last tagged release was 2.19.1 in July 2024 while commits continue on the devel branch.

**ansible/awx-operator** — An Ansible AWX operator for Kubernetes built with Operator SDK and Ansible. 🤖

- Repository: https://github.com/ansible/awx-operator
- Website: https://www.github.com/ansible/awx
- Stars: 1,512 · Forks: 719
- Language: Jinja
- License: Apache-2.0
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/ansible-awx-operator

## One AWX instance per namespace, driven by a custom resource

The scope statement in the README is short and worth quoting for its precision: the operator is meant to be deployed in your Kubernetes cluster and can be used to install and manage the lifecycle of an AWX instance in the same namespace. So the unit of management is an AWX instance living in the namespace the operator runs in, not a platform wide controller fanning out across every namespace. What the operator is, mechanically, is the Ansible AWX operator for Kubernetes built with Operator SDK and Ansible, so the reconciliation logic is a set of Ansible roles rather than compiled Go. For a team that already reviews playbooks, that is a reviewable form of automation. For a team that has standardised on Helm or operators written in Go, it is a different shape than the one they expect.

## The entrypoint runs with a reconcile period of zero

The Dockerfile is the most informative file in the repository, and it is short. It starts from a pinned base image, adds openssl, installs the collection requirements at build time, and copies in watches.yaml, the roles directory and the playbooks directory before declaring what runs:

```dockerfile
FROM quay.io/operator-framework/ansible-operator:v1.42.3
```

```dockerfile
ENTRYPOINT ["/tini", "--", "/usr/local/bin/ansible-operator", "run", \
    "--watches-file=./watches.yaml", \
    "--reconcile-period=0s" \
    ]
```

Two details follow from that. The reconcile period is 0s, so the operator reacts to watch events rather than polling on a timer, and the logic lives in watches.yaml, which sits at the top level of the repository and is copied into the image verbatim. Editing behaviour means editing that file. The image also builds with a non root user, USER 1001, after an openssl update step.

## Ansible collections are baked in at image build time

The Dockerfile copies requirements.yml into the image home and installs it, then chmods the ansible directory so the runtime user can read the collections it just installed:

```dockerfile
COPY requirements.yml ${HOME}/requirements.yml
RUN ansible-galaxy collection install -r ${HOME}/requirements.yml \
 && chmod -R ug+rwx ${HOME}/.ansible
```

That ordering has a consequence for operators of this thing. Collection versions are resolved when the image is built, not when a user applies a custom resource, so rolling forward a collection means building and pushing a new operator image. The same applies to DEFAULT_AWX_VERSION and OPERATOR_VERSION, which are declared as build arguments and exported as environment variables, meaning the AWX version a new instance gets by default is decided by how the image was built. Nothing in the README documents how to override that per instance.

## Two demo manifests sit at the repository root

The root listing shows awx-demo.yml and awxmeshingress-demo.yml. Their names describe the two obvious starting points: a plain AWX instance, and an AWX instance behind an ingress. The README itself does not explain either file, so treat them as the reading material, not as documentation. The docs directory and the project documentation at ansible.readthedocs.io are where the resource fields are described. Note also what is in the root: a molecule/ directory for testing the operator itself, a dev/ directory, projects/, config/, makefiles/ and a noxfile.py, which tells you the project's own contribution loop is the Ansible automation toolchain rather than a Go build.

## Commits continue on devel, but no release since July 2024

Here is the maintenance picture in two dates. The default branch is devel, and the last push to the repository was on 2026-10-09, so code is moving. The newest tag is 2.19.1 from 2024-07-02, preceded by 2.19.0 and 2.18.0 in June 2024. The README does not explain the gap between the two, and there is a CHANGELOG.md at the root if you want the history. Practically, if you pin an operator image by release tag you are pinning code from mid 2024, and the newer work exists on the devel branch rather than in a versioned artefact.

## The Helm chart for AWX lives in a different repository

The README points at two documentation locations and they are not the same thing. Operator documentation sits at ansible.readthedocs.io/projects/awx-operator/, while the Helm chart documentation is at ansible-community.github.io/awx-operator-helm/. That separation is the practical point. Decide which install path your cluster policy prefers before you evaluate features.

## Against running AWX from your own playbooks

The alternative is a set of Ansible roles you write yourself that create the deployment, the services and the database behind AWX, applied by a scheduler, or a plain manifest set maintained in Git. The difference in approach is who owns the reconciliation. Your own roles run when you run them and tell you what happened last time; an operator watches state, reacts to changes, and treats the cluster as the source of truth for an instance that stays installed. What the operator cannot do is span namespaces or manage several AWX instances from one deployment, and it brings a build pipeline, an image registry and a bundle with it. For a single instance per cluster, a hand written role set is often less machinery for the same result.

## Conclusion

The AWX Operator fits a Kubernetes platform team that wants AWX installed and upgraded through the same declarative path as everything else in the cluster, and that reads Ansible roles as reviewable rather than as a black box. Before deploying, read watches.yaml and the demo manifests at the root of the repository, since the CRD fields that control your AWX instance are defined there and nowhere in the README. The last push was on 2026-10-09, the newest tag is 2.19.1 from 2024-07-02, and the repository is not archived.

## FAQ

### What does the AWX Operator manage in a Kubernetes cluster?

The README states it can be used to install and manage the lifecycle of an AWX instance in the same namespace as the operator. It is built with Operator SDK and Ansible.

### How does the AWX Operator decide what to reconcile?

The Dockerfile entrypoint runs ansible-operator with --watches-file=./watches.yaml and --reconcile-period=0s, so reconciliation is event driven from that watches file, which is copied into the image from the repository root.

### Where is the documentation for the AWX Operator and its Helm chart?

Operator documentation is at ansible.readthedocs.io/projects/awx-operator/ and Helm chart documentation is at ansible-community.github.io/awx-operator-helm/. The README does not describe the awx-demo.yml or awxmeshingress-demo.yml manifests at the repository root.

## Sources

- [ansible/awx-operator on GitHub](https://github.com/ansible/awx-operator)
- [License: Apache-2.0](https://github.com/ansible/awx-operator/blob/devel/LICENSE)
- [Project website](https://www.github.com/ansible/awx)
- [README](https://github.com/ansible/awx-operator/blob/devel/README.md)
- [Releases](https://github.com/ansible/awx-operator/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/ansible-awx-operator
