Ansible and Pulumi: Two Automation Philosophies Coexisting
Table of contents
- Key takeaways
- The natural split
- Pulumi — infrastructure
- Ansible — configuration
- Concrete example: full stack
- Pulumi versus Terraform
- Dynamic inventory from Pulumi
- Productive CI/CD flow
- Antipatterns to avoid
- Cases where one tool suffices
- Secrets
- Typical ROI for adopting IaC + Config Management
- Conclusion
Actualizado: 2026-05-03
Ansible and Pulumi are often compared but solve different problems. Ansible is configuration management: what is installed on a server, config files, users, services. Pulumi is Infrastructure as Code: what cloud resources exist (VPCs, instances, load balancers, buckets). Using them together is a mature and productive pattern. This article covers how to combine without duplicating work.
Key takeaways
- Ansible controls state inside a server; Pulumi controls which servers exist.
- Both address automation, but at different stack layers.
- For pure cloud-native greenfield, Pulumi alone sometimes suffices; for legacy hybrid, Ansible remains a fundamental piece.
- Dynamic inventory from Pulumi outputs is the natural glue between the two tools.
- Do not pick both Terraform and Pulumi: they are alternatives, not complements.
The natural split
Pulumi — infrastructure
- Create VPCs, subnets, security groups.
- Provision instances, databases, buckets.
- Configure DNS and certificates.
- Managed services (RDS, Redshift, Kubernetes clusters).
Ansible — configuration
- Install packages on servers.
- Deploy applications.
- Manage users and SSH keys.
- Config files (nginx.conf, postgresql.conf).
- Orchestrate operations (rolling restarts, patches).
Both address automation, but at different layers. Combining them is natural; duplicating them is an antipattern.
Concrete example: full stack
Pulumi creates infrastructure in TypeScript:
import * as aws from "@pulumi/aws";
const vpc = new aws.ec2.Vpc("main", { cidrBlock: "10.0.0.0/16" });
const subnet = new aws.ec2.Subnet("private", {
vpcId: vpc.id,
cidrBlock: "10.0.1.0/24",
});
const instance = new aws.ec2.Instance("web", {
ami: "ami-xxx",
instanceType: "t3.medium",
subnetId: subnet.id,
});
export const instanceIp = instance.publicIp;Ansible configures what runs on it:
- hosts: web
tasks:
- apt:
name: [nginx, postgresql-client]
state: present
- template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify: restart nginx
handlers:
- name: restart nginx
systemd:
name: nginx
state: restartedBoth together cover the complete stack without either invading the other’s territory.
Pulumi versus Terraform
Pulumi is a Terraform alternative with real code (TypeScript, Python, Go, .NET) instead of HCL:
Pulumi advantages:
- Native language loops and conditionals.
- Reusable abstractions (classes, functions).
- Testing with the language’s standard test framework.
- Full IDE autocomplete.
Disadvantages:
- Higher cognitive load (programming vs. declaring).
- Smaller community than Terraform.
- Some new features reach Terraform or OpenTofu first.
Pulumi vs Terraform/OpenTofu is a team preference. Both do cloud-agnostic IaC competently.
Dynamic inventory from Pulumi
The glue between the two tools is dynamic inventory: Ansible reads IPs and endpoints from Pulumi outputs instead of maintaining a static file.
# pulumi_inventory.py
import pulumi.automation as auto
stack = auto.select_stack(...)
outputs = stack.outputs()
print({
"web": {
"hosts": [o.value for o in outputs["instance_ips"].value]
}
})Ansible consumes this dynamically with ansible -i pulumi_inventory.py all -m ping. The CI/CD pipeline stays clean: Pulumi applies first, Ansible picks up the outputs and configures.
Productive CI/CD flow
- Pulumi creates or updates infrastructure.
- Pulumi exports outputs (IPs, endpoints, credentials).
- Ansible receives outputs as dynamic inventory.
- Ansible configures apps, users and services.
- Both run in the same pipeline:
tofu/pulumi plan → apply → ansible-playbook.
Antipatterns to avoid
- Pulumi configuring things inside the VM: complicated
user-datascripts. Ansible is better for that. - Ansible creating AWS resources:
amazon.aws.*modules exist but for more than ten resources, Pulumi is more maintainable. - Terraform + Pulumi together: pick one IaC. Two tools for the same layer is duplication, not complement.
Cases where one tool suffices
Ansible alone:
- Legacy on-premise with no cloud infra to provision.
- Static VMs where infra does not change.
- Network devices (Cisco, Juniper): Ansible has excellent modules.
Pulumi alone:
- Everything runs on managed services or containers.
- Kubernetes-native where generated manifests cover configuration.
- VM-less cloud-only.
Secrets
Ansible Vault encrypts YAML files natively. For serious production, integrating with an external secret manager (HashiCorp Vault, AWS SSM) is the right path.
Pulumi encrypts secrets in state with Config.setSecret() and integrates with AWS SSM, Azure Key Vault and HashiCorp Vault. The pattern is the same: never plaintext secrets in the repository.
Typical ROI for adopting IaC + Config Management
The return is time-asymmetric:
- First month: negative (setup time).
- Three months: break-even.
- One year: 40–60 % saved on repetitive operations.
- Two years onward: disaster recovery in minutes instead of days.
Value accumulates. Not starting is an invisible cost that grows every week.
Conclusion
Ansible and Pulumi are complementary, not competitors: Pulumi (or Terraform/OpenTofu) for infrastructure, Ansible for configuration management. For cloud infrastructure with servers, combining them is the cleanest and most maintainable stack. Teams that understand this division have more predictable automation and fewer operational incidents. If you already manage CrowdSec or another component on your nodes, Ansible is the natural tool for that layer.