AnsiblePilot — Master Ansible Automation

AnsiblePilot is the leading resource for learning Ansible automation, DevOps, and infrastructure as code. Browse over 1,400 tutorials covering Ansible modules, playbooks, roles, collections, and real-world examples. Whether you are a beginner or an experienced engineer, our step-by-step guides help you automate Linux, Windows, cloud, containers, and network infrastructure.

Popular Topics

About Luca Berton

Luca Berton is an Ansible automation expert, author of 8 Ansible books published by Apress and Leanpub including "Ansible for VMware by Examples" and "Ansible for Kubernetes by Example", and creator of the Ansible Pilot YouTube channel. He shares practical automation knowledge through tutorials, books, and video courses to help IT professionals and DevOps engineers master infrastructure automation.

Ansible for Kubernetes: Deploy, Manage, and Automate K8s Clusters Complete Guide

By Luca Berton · Published 2024-01-01 · Category: installation

Complete guide to using Ansible with Kubernetes. Deploy pods, services, and deployments with the kubernetes.core collection.

Ansible automates Kubernetes the same way it automates everything else — with YAML playbooks, idempotent modules, and no agent on the cluster. The kubernetes.core collection gives you modules for deployments, services, Helm charts, RBAC, and custom resources. Here's how to use them.

Setup

Install the Collection

ansible-galaxy collection install kubernetes.core

Dependencies

# Python kubernetes client (required)
pip install kubernetes

# For Helm support pip install kubernetes helm

# For dynamic inventory pip install kubernetes

Authentication

The kubernetes.core modules use your kubeconfig by default:

# Uses ~/.kube/config automatically
- kubernetes.core.k8s:
    state: present
    definition: "{{ lookup('file', 'deployment.yml') }}"

Or specify explicitly:

# Explicit kubeconfig
- kubernetes.core.k8s:
    kubeconfig: /path/to/kubeconfig
    context: production-cluster
    state: present
    definition: "{{ deployment }}"

# Or use host/token - kubernetes.core.k8s: host: https://k8s-api.example.com:6443 api_key: "{{ k8s_token }}" validate_certs: true state: present definition: "{{ deployment }}"

See also: Ansible for Kubernetes: Automate K8s Cluster Management and Application Deployment

Deploying Resources

Create a Deployment

---
- name: Deploy application to Kubernetes
  hosts: localhost
  connection: local
  tasks:
    - name: Create namespace
      kubernetes.core.k8s:
        state: present
        definition:
          apiVersion: v1
          kind: Namespace
          metadata:
            name: production
            labels:
              environment: production

- name: Deploy web application kubernetes.core.k8s: state: present definition: apiVersion: apps/v1 kind: Deployment metadata: name: web-app namespace: production labels: app: web spec: replicas: 3 selector: matchLabels: app: web template: metadata: labels: app: web spec: containers: - name: web image: "nginx:1.27" ports: - containerPort: 80 resources: requests: memory: "128Mi" cpu: "100m" limits: memory: "256Mi" cpu: "200m" livenessProbe: httpGet: path: /healthz port: 80 initialDelaySeconds: 10 periodSeconds: 30

- name: Create service kubernetes.core.k8s: state: present definition: apiVersion: v1 kind: Service metadata: name: web-app namespace: production spec: selector: app: web ports: - port: 80 targetPort: 80 type: ClusterIP

Load Manifests from Files

- name: Apply manifest from file
  kubernetes.core.k8s:
    state: present
    src: manifests/deployment.yml

- name: Apply all manifests in directory kubernetes.core.k8s: state: present src: "{{ item }}" loop: "{{ lookup('fileglob', 'manifests/*.yml', wantlist=True) }}"

- name: Apply from template kubernetes.core.k8s: state: present definition: "{{ lookup('template', 'deployment.yml.j2') }}"

ConfigMaps and Secrets

- name: Create ConfigMap
  kubernetes.core.k8s:
    state: present
    definition:
      apiVersion: v1
      kind: ConfigMap
      metadata:
        name: app-config
        namespace: production
      data:
        DATABASE_HOST: "db.internal"
        LOG_LEVEL: "info"
        MAX_CONNECTIONS: "100"

- name: Create Secret kubernetes.core.k8s: state: present definition: apiVersion: v1 kind: Secret metadata: name: app-secrets namespace: production type: Opaque stringData: DATABASE_PASSWORD: "{{ vault_db_password }}" API_KEY: "{{ vault_api_key }}"

Helm Chart Management

Install a Helm Chart

- name: Add Helm repository
  kubernetes.core.helm_repository:
    name: ingress-nginx
    repo_url: https://kubernetes.github.io/ingress-nginx

- name: Install ingress-nginx kubernetes.core.helm: name: ingress-nginx chart_ref: ingress-nginx/ingress-nginx release_namespace: ingress-nginx create_namespace: true values: controller: replicaCount: 2 service: type: LoadBalancer resources: requests: cpu: 100m memory: 128Mi

Upgrade and Rollback

- name: Upgrade application chart
  kubernetes.core.helm:
    name: my-app
    chart_ref: ./charts/my-app
    release_namespace: production
    values:
      image:
        tag: "{{ app_version }}"
      replicas: "{{ replica_count | default(3) }}"
    wait: true
    timeout: 10m0s

- name: Rollback on failure kubernetes.core.helm: name: my-app release_namespace: production state: absent when: deploy_failed | default(false)

Full Helm Workflow

---
- name: Deploy application stack with Helm
  hosts: localhost
  connection: local
  vars:
    app_version: "2.1.0"
    environment: production
  tasks:
    - name: Add required repositories
      kubernetes.core.helm_repository:
        name: "{{ item.name }}"
        repo_url: "{{ item.url }}"
      loop:
        - { name: bitnami, url: "https://charts.bitnami.com/bitnami" }
        - { name: prometheus, url: "https://prometheus-community.github.io/helm-charts" }

- name: Deploy PostgreSQL kubernetes.core.helm: name: postgresql chart_ref: bitnami/postgresql release_namespace: "{{ environment }}" create_namespace: true values: auth: postgresPassword: "{{ vault_pg_password }}" database: myapp primary: persistence: size: 20Gi

- name: Deploy application kubernetes.core.helm: name: my-app chart_ref: ./charts/my-app release_namespace: "{{ environment }}" values: image: tag: "{{ app_version }}" database: host: postgresql.{{ environment }}.svc.cluster.local wait: true

- name: Deploy monitoring kubernetes.core.helm: name: prometheus chart_ref: prometheus/kube-prometheus-stack release_namespace: monitoring create_namespace: true values: grafana: adminPassword: "{{ vault_grafana_password }}"

See also: Ansible Kubernetes (k8s) Module: Manage K8s Resources (Guide)

RBAC Management

---
- name: Configure RBAC
  hosts: localhost
  connection: local
  tasks:
    - name: Create service account
      kubernetes.core.k8s:
        state: present
        definition:
          apiVersion: v1
          kind: ServiceAccount
          metadata:
            name: deploy-bot
            namespace: production

- name: Create role kubernetes.core.k8s: state: present definition: apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: deployer namespace: production rules: - apiGroups: ["apps"] resources: ["deployments", "replicasets"] verbs: ["get", "list", "watch", "create", "update", "patch"] - apiGroups: [""] resources: ["pods", "services", "configmaps"] verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

- name: Bind role to service account kubernetes.core.k8s: state: present definition: apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: deploy-bot-deployer namespace: production subjects: - kind: ServiceAccount name: deploy-bot namespace: production roleRef: kind: Role name: deployer apiGroup: rbac.authorization.k8s.io

Querying Cluster State

Get Resource Info

- name: Get all pods in namespace
  kubernetes.core.k8s_info:
    kind: Pod
    namespace: production
  register: pod_list

- name: Show running pods ansible.builtin.debug: msg: "{{ item.metadata.name }} - {{ item.status.phase }}" loop: "{{ pod_list.resources }}" when: item.status.phase == "Running"

- name: Get specific deployment kubernetes.core.k8s_info: api_version: apps/v1 kind: Deployment name: web-app namespace: production register: deployment_info

- name: Check replica count ansible.builtin.debug: msg: "Ready: {{ deployment_info.resources[0].status.readyReplicas | default(0) }}/{{ deployment_info.resources[0].spec.replicas }}"

Wait for Resources

- name: Wait for deployment to be ready
  kubernetes.core.k8s_info:
    api_version: apps/v1
    kind: Deployment
    name: web-app
    namespace: production
    wait: true
    wait_condition:
      type: Available
      status: "True"
    wait_timeout: 300

- name: Wait for pod to be running kubernetes.core.k8s_info: kind: Pod namespace: production label_selectors: - app=web wait: true wait_condition: type: Ready status: "True" wait_timeout: 120

See also: Kubernetes Core 6.4.0: Helm v4 Support & k8s_drain Improvements

Dynamic Inventory

Use the Kubernetes inventory plugin to target pods or nodes:

# k8s_inventory.yml
plugin: kubernetes.core.k8s
connections:
  - kubeconfig: ~/.kube/config
    namespaces:
      - production
      - staging

# Then use in playbook # ansible-playbook -i k8s_inventory.yml playbook.yml

Scaling and Rolling Updates

- name: Scale deployment
  kubernetes.core.k8s:
    state: present
    definition:
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: web-app
        namespace: production
      spec:
        replicas: "{{ desired_replicas }}"

- name: Rolling update (change image) kubernetes.core.k8s: state: present definition: apiVersion: apps/v1 kind: Deployment metadata: name: web-app namespace: production spec: template: spec: containers: - name: web image: "myapp:{{ new_version }}" wait: true wait_timeout: 600

Execute Commands in Pods

- name: Run database migration
  kubernetes.core.k8s_exec:
    namespace: production
    pod: "{{ migration_pod }}"
    command: python manage.py migrate
  register: migration_result

- name: Show migration output ansible.builtin.debug: msg: "{{ migration_result.stdout }}"

Common Patterns

Blue-Green Deployment

---
- name: Blue-green deployment
  hosts: localhost
  connection: local
  vars:
    new_color: "{{ 'green' if current_color == 'blue' else 'blue' }}"
  tasks:
    - name: Deploy new version ({{ new_color }})
      kubernetes.core.k8s:
        state: present
        definition:
          apiVersion: apps/v1
          kind: Deployment
          metadata:
            name: "web-{{ new_color }}"
            namespace: production
          spec:
            replicas: 3
            selector:
              matchLabels:
                app: web
                color: "{{ new_color }}"
            template:
              metadata:
                labels:
                  app: web
                  color: "{{ new_color }}"
              spec:
                containers:
                  - name: web
                    image: "myapp:{{ new_version }}"

- name: Wait for new deployment kubernetes.core.k8s_info: api_version: apps/v1 kind: Deployment name: "web-{{ new_color }}" namespace: production wait: true wait_condition: type: Available status: "True" wait_timeout: 300

- name: Switch service to new color kubernetes.core.k8s: state: present definition: apiVersion: v1 kind: Service metadata: name: web namespace: production spec: selector: app: web color: "{{ new_color }}" ports: - port: 80

- name: Scale down old deployment kubernetes.core.k8s: state: present definition: apiVersion: apps/v1 kind: Deployment metadata: name: "web-{{ current_color }}" namespace: production spec: replicas: 0

FAQ

Should I use Ansible or kubectl for Kubernetes?

Use Ansible when you need reproducible, version-controlled deployments that integrate with your existing automation. Use kubectl for quick debugging and ad-hoc commands. For CI/CD, Ansible playbooks are more maintainable than shell scripts full of kubectl commands.

How does Ansible compare to ArgoCD or Flux for GitOps?

ArgoCD/Flux continuously sync cluster state with a Git repo (pull-based GitOps). Ansible runs on-demand (push-based). For continuous reconciliation, use ArgoCD/Flux. For orchestrated deployments that need to coordinate with non-Kubernetes systems, Ansible is more flexible.

Can Ansible manage multiple Kubernetes clusters?

Yes. Use different kubeconfig files or contexts per task. You can deploy the same application across dev, staging, and production clusters in a single playbook by parameterizing the context.

Do I need Ansible if I already use Helm?

Ansible adds orchestration around Helm — install charts in order, wait for dependencies, configure secrets from Vault, and coordinate with non-Kubernetes systems. If your entire stack is Helm charts with no external dependencies, you might not need Ansible.

What about Ansible on Kubernetes (AWX/AAP)?

AWX (open-source) and Ansible Automation Platform (enterprise) run on Kubernetes themselves. This gives you Ansible-managed Kubernetes managing the Ansible that manages other things — it's automation all the way down.

Conclusion

The kubernetes.core collection gives Ansible full control over Kubernetes — deployments, Helm charts, RBAC, scaling, and cluster queries. Use it when you need orchestrated, reproducible K8s operations that integrate with your broader infrastructure automation. For pure GitOps, consider ArgoCD alongside Ansible for the best of both worlds.

Related Articles

Ansible vs Terraform in 2026Ansible CI/CD Pipeline IntegrationAnsible for Docker Container ManagementAnsible Check Mode and Diff ModeAnsible OpenShift Automation GuideExtend K8s API with Custom Resource DefinitionsFixing Kubernetes PersistentVolume Configuration Error

Category: installation

Browse all Ansible tutorials · AnsiblePilot Home