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: Automate K8s Cluster Management and Application Deployment

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

Use Ansible to manage Kubernetes clusters, deploy applications, configure namespaces, and automate Day 2 operations. Complete guide with kubernetes.core.

Introduction

Kubernetes has become the standard for container orchestration, but managing clusters, deploying applications, and handling Day 2 operations still requires significant automation. Ansible bridges the gap between infrastructure provisioning and Kubernetes management — using the same language and workflows your team already knows.

The kubernetes.core collection provides native Kubernetes modules that let you manage any K8s resource declaratively through Ansible playbooks.

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

Install the Collection

ansible-galaxy collection install kubernetes.core

# Python dependencies pip install kubernetes openshift PyYAML

Authentication

Kubeconfig (Default)

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

Explicit Configuration

- name: Connect to specific cluster
  kubernetes.core.k8s:
    host: https://k8s-api.example.com:6443
    api_key: "{{ k8s_token }}"
    validate_certs: true
    state: present
    definition:
      apiVersion: v1
      kind: Namespace
      metadata:
        name: myapp

Service Account Token (for AAP)

# In AAP: Create OpenShift/Kubernetes credential type
# Token from: kubectl create serviceaccount ansible -n kube-system
# Then:       kubectl create token ansible -n kube-system --duration=8760h

- name: Use service account kubernetes.core.k8s: host: "{{ lookup('env', 'K8S_AUTH_HOST') }}" api_key: "{{ lookup('env', 'K8S_AUTH_API_KEY') }}" validate_certs: "{{ lookup('env', 'K8S_AUTH_VERIFY_SSL') }}" state: present definition: "{{ resource }}"

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

Manage Namespaces

- name: Kubernetes namespace management
  hosts: localhost
  connection: local
  tasks:
    - name: Create namespaces
      kubernetes.core.k8s:
        state: present
        definition:
          apiVersion: v1
          kind: Namespace
          metadata:
            name: "{{ item.name }}"
            labels:
              environment: "{{ item.env }}"
              team: "{{ item.team }}"
      loop:
        - { name: app-production, env: production, team: platform }
        - { name: app-staging, env: staging, team: platform }
        - { name: app-dev, env: development, team: developers }

- name: Set resource quotas kubernetes.core.k8s: state: present definition: apiVersion: v1 kind: ResourceQuota metadata: name: compute-quota namespace: "{{ item.namespace }}" spec: hard: requests.cpu: "{{ item.cpu }}" requests.memory: "{{ item.memory }}" limits.cpu: "{{ item.cpu_limit }}" limits.memory: "{{ item.memory_limit }}" loop: - { namespace: app-production, cpu: "8", memory: 16Gi, cpu_limit: "16", memory_limit: 32Gi } - { namespace: app-staging, cpu: "4", memory: 8Gi, cpu_limit: "8", memory_limit: 16Gi }

Deploy Applications

From Inline YAML

- name: Deploy web application
  kubernetes.core.k8s:
    state: present
    definition:
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: webapp
        namespace: app-production
        labels:
          app: webapp
      spec:
        replicas: 3
        selector:
          matchLabels:
            app: webapp
        template:
          metadata:
            labels:
              app: webapp
          spec:
            containers:
              - name: webapp
                image: "{{ webapp_image }}:{{ webapp_version }}"
                ports:
                  - containerPort: 8080
                resources:
                  requests:
                    cpu: 250m
                    memory: 256Mi
                  limits:
                    cpu: 500m
                    memory: 512Mi
                livenessProbe:
                  httpGet:
                    path: /health
                    port: 8080
                  initialDelaySeconds: 30
                readinessProbe:
                  httpGet:
                    path: /ready
                    port: 8080
                  initialDelaySeconds: 10

From YAML Files

- name: Apply manifests from files
  kubernetes.core.k8s:
    state: present
    src: "{{ item }}"
  loop:
    - manifests/namespace.yml
    - manifests/configmap.yml
    - manifests/secret.yml
    - manifests/deployment.yml
    - manifests/service.yml
    - manifests/ingress.yml

From Templates

- name: Deploy with Jinja2 templates
  kubernetes.core.k8s:
    state: present
    definition: "{{ lookup('template', 'deployment.yml.j2') }}"
  vars:
    app_name: myapp
    replicas: 3
    image: registry.example.com/myapp:v2.1.0

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

Helm Chart Management

- name: Deploy with Helm
  kubernetes.core.helm:
    name: ingress-nginx
    chart_ref: ingress-nginx/ingress-nginx
    release_namespace: ingress-system
    create_namespace: true
    chart_version: "4.10.0"
    values:
      controller:
        replicaCount: 2
        service:
          type: LoadBalancer

- name: Deploy application Helm chart kubernetes.core.helm: name: myapp chart_ref: ./charts/myapp release_namespace: app-production values: image: repository: registry.example.com/myapp tag: "{{ app_version }}" resources: limits: cpu: 500m memory: 512Mi wait: true wait_timeout: 300s

Manage Secrets

- name: Create Kubernetes secret
  kubernetes.core.k8s:
    state: present
    definition:
      apiVersion: v1
      kind: Secret
      metadata:
        name: db-credentials
        namespace: app-production
      type: Opaque
      data:
        username: "{{ db_username | b64encode }}"
        password: "{{ db_password | b64encode }}"
  no_log: true

- name: Create TLS secret kubernetes.core.k8s: state: present definition: apiVersion: v1 kind: Secret metadata: name: tls-cert namespace: app-production type: kubernetes.io/tls data: tls.crt: "{{ lookup('file', 'certs/server.crt') | b64encode }}" tls.key: "{{ lookup('file', 'certs/server.key') | b64encode }}" no_log: true

Rolling Updates

- name: Rolling update with zero downtime
  hosts: localhost
  tasks:
    - name: Update deployment image
      kubernetes.core.k8s:
        state: present
        definition:
          apiVersion: apps/v1
          kind: Deployment
          metadata:
            name: webapp
            namespace: app-production
          spec:
            strategy:
              type: RollingUpdate
              rollingUpdate:
                maxSurge: 1
                maxUnavailable: 0
            template:
              spec:
                containers:
                  - name: webapp
                    image: "registry.example.com/webapp:{{ new_version }}"

- name: Wait for rollout to complete kubernetes.core.k8s_info: api_version: apps/v1 kind: Deployment name: webapp namespace: app-production register: deployment until: > deployment.resources[0].status.readyReplicas == deployment.resources[0].spec.replicas retries: 30 delay: 10

Query Cluster State

- name: Get cluster information
  kubernetes.core.k8s_info:
    api_version: v1
    kind: Pod
    namespace: app-production
    label_selectors:
      - app=webapp
  register: webapp_pods

- name: Display pod status ansible.builtin.debug: msg: "{{ item.metadata.name }}: {{ item.status.phase }}" loop: "{{ webapp_pods.resources }}"

- name: Find unhealthy pods kubernetes.core.k8s_info: api_version: v1 kind: Pod namespace: app-production field_selectors: - status.phase!=Running register: unhealthy_pods

Day 2 Operations

Scale Deployments

- name: Scale based on schedule
  kubernetes.core.k8s_scale:
    api_version: apps/v1
    kind: Deployment
    name: webapp
    namespace: app-production
    replicas: "{{ business_hours | ternary(5, 2) }}"
    wait: true
    wait_timeout: 120

Backup etcd

- name: Backup etcd
  hosts: k8s_control_plane
  tasks:
    - name: Create etcd snapshot
      ansible.builtin.command:
        cmd: >
          etcdctl snapshot save /backup/etcd-{{ ansible_date_time.date }}.db
          --endpoints=https://127.0.0.1:2379
          --cacert=/etc/kubernetes/pki/etcd/ca.crt
          --cert=/etc/kubernetes/pki/etcd/server.crt
          --key=/etc/kubernetes/pki/etcd/server.key

Best Practices

Use kubernetes.core collection — Not the deprecated community.kubernetes Service accounts with RBAC — Never use admin kubeconfig in production AAP no_log: true for secrets — Prevent credentials from appearing in job output Wait for readiness — Always verify deployments complete before proceeding Template manifests — Use Jinja2 for environment-specific values instead of separate YAML files Helm for complex apps — Use kubernetes.core.helm for chart-based deployments Label everything — Consistent labeling enables efficient queries and management Store manifests in Git — GitOps workflow with AAP webhooks for automated deployment

FAQ

Ansible vs kubectl/Helm directly?

Ansible orchestrates multi-step workflows — deploy infrastructure, configure apps, update DNS, run tests — in one playbook. kubectl/Helm handle individual steps. Use Ansible to tie them together.

Can I manage OpenShift with these modules?

Yes — kubernetes.core works with OpenShift. For OpenShift-specific resources (Routes, DeploymentConfigs), also install redhat.openshift.

EKS/GKE/AKS support?

Yes — authenticate with cloud credentials and point to the cluster's API endpoint. Use cloud-specific collections for cluster provisioning (amazon.aws, azure.azcollection, google.cloud).

Conclusion

Ansible provides a unified automation layer for Kubernetes — from cluster provisioning through application deployment to Day 2 operations. By managing K8s resources through playbooks, you get version control, idempotency, and integration with your existing Ansible workflows.

Related Articles

Ansible Docker Complete GuideAnsible AWS Complete GuideAnsible Automation Platform 2.6

Category: installation

Browse all Ansible tutorials · AnsiblePilot Home