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
Usekubernetes.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 Guide • Ansible AWS Complete Guide • Ansible Automation Platform 2.6Category: installation