Skip to content

Deploy application to Kubernetes with Ansible

This tutorial contains a pipeline that deploys an simple hello-world application to a Kubernetes cluster.

Prerequisites

You will need a running Kubernetes cluster, that supports services with LoadBalancer type, and a kubeconfig file that can be used to deploy application (a deployment and a service) into the cluster.

Preparing the Jenkins instance

The pipeline provided by this tutorial can be added to any Jenkins instance you have administrator access and can run pipeline stages with docker agent. For example, Jenkins configuration from Jenkins with access to hosts Docker engine tutorial can be used.

We will use secret file to configure credentials for managing the target Kubernetes cluster. To create the secret file credential, open Global credentials from Jenkins credentials store from Manage Jenkins > Manage Credentials and click Add Credentials from the left side menu.

In the New credentials form:

  1. Select Secret file as the credential kind
  2. Upload your kubeconfig to the file input
  3. Configure ID for the credential. Jenkinsfile uses kubeconfig as the ID.
  4. (Optionally) add a description.

Configure the pipeline

First, create a new pipeline via New Item button in the rigth side menu of the Jenkins dashboard. The name of the pipeline could be for example Animals and it should be an pipeline.

In the configure pipeline view, scroll to the bottom and under Pipeline sub-header select Pipeline script from SCM. SCM type should be Git and Repository URL the url of this repository: https://github.com/cicd-tutorials/cicd-tutorials.net.git. Ensure that branch specifier includes main branch of the repository and modify the Script Path to be docs/tutorials/jenkins/ansible-kubernetes/Jenkinsfile.

The pipeline deploys an example application to a Kubernetes cluster using Ansible playbook. The playbook selects a container image tag based on Jenkins build parameter.

Jenkinsfile
String d = "docs/tutorials/jenkins/ansible-kubernetes"

pipeline {
    agent any
    parameters {
        choice(name: 'ANIMAL', choices: ['cat', 'cow', 'dog', 'lion', 'pig'], description: 'Tag to use for deployment image')
    }
    stages {
        stage("deploy") {
            agent {
                dockerfile {
                    dir "$d"
                    reuseNode true
                }
            }
            environment {
                K8S_AUTH_KUBECONFIG = credentials('kubeconfig')
                KUBECONFIG = credentials('kubeconfig')
            }
            steps {
                sh """
                    ansible-playbook $d/deploy-to-kubernetes.yml --extra-vars "animal=${params.ANIMAL}"
                    ./$d/wait-until-service-up.sh
                """
            }
        }
    }
}

After you have created the pipeline, try to execute it by clicking Build Now. The pipeline should have deployed the example application into the Kubernetes cluster with the default image tag (cow) defined in the deploy-to-kubernetes.yml Ansible playbook.

deploy-to-kubernetes.yml
- name: Deploy and expose application
  hosts: localhost
  gather_facts: no
  vars:
    animal: cow
  tasks:
  - name: Create a deployment
    kubernetes.core.k8s:
      definition:
        apiVersion: apps/v1
        kind: Deployment
        metadata:
          labels:
            app: animals
          name: animals
          namespace: default
        spec:
          replicas: 3
          selector:
            matchLabels:
              app: animals
          template:
            metadata:
              labels:
                app: animals
            spec:
              containers:
              - image: ghcr.io/cicd-tutorials/animals:{{ animal }}
                name: animals
  - name: Expose the deployment
    kubernetes.core.k8s:
      definition:
        apiVersion: v1
        kind: Service
        metadata:
          labels:
            app: animals
          name: animals
          namespace: default
        spec:
          ports:
          - port: 80
            protocol: TCP
            targetPort: 80
          selector:
            app: animals
          type: LoadBalancer

After the Ansible playbook has been executed, the pipeline runs wait-until-service-up.sh script. The script waits until the load-balancer created by the Kubernetes service has reached running state and parses the URL where the example application is running.

#!/bin/sh -xe

# Wait until hostname is available
until kubectl get service animals -o json | jq -re .status.loadBalancer.ingress[0].hostname; do
    sleep 15;
done;

# Wait until animals application is up
hostname=$(kubectl get service animals -o json | jq -re .status.loadBalancer.ingress[0].hostname)
until curl -sSf $hostname; do
    sleep 15;
done;

echo "Load-balancer URL: $hostname"

You can find the URL of the created load-balancer from the console output of the build. Open the application with your browser or user curl to see the application response.

In addition, after the first execution Jenkins should have updated the project configuration to contain parameters defined in the pipeline and we can configure the image tag in Build with Parameters menu.