top of page
  • Writer's pictureRafael Natali

Deploying Applications in Kubernetes Engine Made Easy with Ansible

Ansible infrastructure-as-code to automate Nginx deployment in Google Kubernetes Cluster (GKE) on Google Cloud Platform (GCP).


Automate application deployments in Kubernetes using Ansible - Image from author
Automate application deployments in Kubernetes using Ansible - Image from author

Prerequisite


This tutorial is a continuation of my previous article called Automate your Kubernetes Cluster Setup Using Ansible. This article aimed to help you use Ansible¹ to create a Kubernetes Cluster in Google Cloud Platform (GCP)². Therefore, if you didn’t do it already, review the mentioned article before proceeding.


The code used to create this tutorial is available in this repository.


From this point on, I assume you already have an up and running GKE cluster.


Manage Kubernetes Objects with Ansible


We will use the kubernetes.core.k8s³ plugin to manage objects within our GKE cluster. As for our Nginx example, we will work with two Kubernetes objects: Namespace⁴ and Pod⁵.

Ansible Directory Layout


Follow is the directory structure we will be working with through this tutorial.

.
├── LICENSE                        # license file
├── README.md                      # main documentation file
└── ansible                        # top-level folder
    ├── ansible.cfg                # config file
    ├── create-k8s.yml             # playbook to provision env
    ├── deploy-app-k8s.yml         # playbook to deploy Nginx 
    ├── destroy-k8s.yml            # playbook to destroy env
    ├── undeploy-app-k8s.yml       # playbook to remove Nginx
    ├── inventory             
    │   └── gcp.yml                # inventory file
    └── roles
        ├── destroy_k8s            # role to remove k8s cluster        
        │   └── tasks
        │       └── main.yml
        ├── destroy_k8s_deployment # role to remove Nginx 
        │       └── tasks
        │           └── main.yml
        ├── destroy_network        # role to remove VPC
        │   └── tasks
        │       └── main.yml
        ├── k8s                    # role to create k8s cluster
        │   └── tasks
        │       └── main.yml
        ├── k8s-deployment         # role to deploy Nginx
        │   ├── tasks
        │   │   └── main.yml
        │   └── vars
        │       └── main.yml
        └── network                # role to create VPC
            └── tasks
                └── main.yml

Ansible Inventory

In the Ansible inventory⁶ file add a variable named namespace.

...
# use the section below to enter k8s namespaces to manage
# this namespace is used in the Deploying an Application section
namespace: nginx

Ansible Roles


Create a new Ansible role⁷ on ansible/roles/k8s-deployment with the following main.yml file under tasks. This role will be responsible for creating the namespace and deploy the Pod with Nginx.

---
- name: Create a k8s namespace  
  kubernetes.core.k8s:    
    state: present    
    definition:      
      apiVersion: v1      
      kind: Namespace      
      metadata:        
        name: "{{ namespace }}"
        
- name: Create k8s pod for nginx  
  kubernetes.core.k8s:    
    state: present    
    definition:      
      apiVersion: v1      
      kind: Pod      
      metadata:        
        name: "{{ app }}"        
        namespace: "{{ namespace }}"        
        labels:          
          app: "{{ app }}"      
      spec:        
        containers:          
          - name: "{{ app }}"            
            image: "{{ image }}"            
            imagePullPolicy: Always    

You can group several actions within the same task. In the task file above, it will first create the namespace and then it will create the Pod.

Notice that the kubernetes.core.k8s plugin uses the standard Kubernetes object yaml configuration to create the resources.

Investigating the role directory structure, we noticed that there is a vars folder. We set variables in roles to ensure a value is used in that role and is not overridden by inventory variables.

Refer to Ansible Using Variables documentation for more details.

Create a main.yml file under the vars folder to set the Nginx variables. We are using these values to replace {{ app }} and {{ image }} variables.

---
app: nginx
image: nginx:1.19.9-alpine

Ansible Playbook

The last step is to create an Ansible playbook⁸ to execute the k8s-deployment role. In the ansible folder, I created a file called deploy-app-k8s.yml:

---
- name: deploy application
  hosts: localhost  
  gather_facts: false  
  environment:    
    GOOGLE_CREDENTIALS: "{{ credentials_file }}"
  
  roles:    
    - k8s-deployment    

Deploying an application


Execute the following command to deploy the Nginx web-server:

ansible-playbook ansible/deploy-app-k8s.yml -i ansible/inventory/<your-inventory-filename>

Output:

PLAY [deploy application] *****************************************************************

TASK [k8s-deployment : Create a k8s namespace] ******************
changed: [localhost]

TASK [k8s-deployment : Create a k8s service to expose nginx] ****
changed: [localhost]

PLAY RECAP *******************************************************
localhost: ok=2  changed=2  unreachable=0  failed=0  skipped=0  rescued=0  ignored=0

Accessing the Nginx

Execute the following commands and then access the Nginx using this URL.

export POD_NAME=$(kubectl get pods --namespace nginx -l "app=nginx" -o jsonpath="{.items[0].metadata.name}")
kubectl --namespace nginx port-forward $POD_NAME 8080:80

Cleaning up


To remove all resources created in this tutorial all we need is a role that removes the namespace object created initially.

The ansible/roles/destroy_k8s_deployment role has this configuration.

---
- name: Destroy a k8s namespace
  kubernetes.core.k8s:
    name: "{{ namespace }}"
    api_version: v1
    kind: Namespace
    state: absent

Execute the following command to remove the Nginx resources created but, keep the Kubernetes cluster:

ansible-playbook ansible/undeploy-app-k8s.yml -i ansible/inventory/<your-inventory-filename>

Output:

PLAY [undeploy application] **************************************

TASK [destroy_k8s_deployment : Destroy a k8s namespace] *********
changed: [localhost]

PLAY RECAP *****************************************************************
localhost: ok=1  changed=1  unreachable=0  failed=0  skipped=0  rescued=0  ignored=0

Conclusion

This tutorial has demonstrated how to use Infrastructure as Code to deploy an Nginx web-server in a Kubernetes cluster on Google Cloud Platform. With the kubernetes.core.k8s plugin provided by Ansible, it’s possible to manage Kubernetes objects such as Namespaces and Pods using standard Kubernetes object yaml configuration.

Much more is possible with Ansible. Use this tutorial as the first step to manage your Kubernetes objects as code. Access the Ansible Documentation page for more information and to expand your Ansible knowledge and usage.

References










10 views0 comments

Comments


bottom of page