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 PyYAMLAuthentication
Kubeconfig (Default)
- name: Use default kubeconfig
kubernetes.core.k8s:
state: present
definition: "{{ lookup('file', 'deployment.yml') }}"
# Uses ~/.kube/config automaticallyExplicit 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: myappService 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: 10From 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.ymlFrom 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.0See 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: 300sManage 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: trueRolling 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: 10Query 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_podsDay 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: 120Backup 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.keyBest Practices
- Use
kubernetes.corecollection — Not the deprecatedcommunity.kubernetes - Service accounts with RBAC — Never use admin kubeconfig in production AAP
no_log: truefor 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.helmfor 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
Further reading
To go deeper, managing Kubernetes with Ansible playbooks expands on these patterns in production.
Category: installation