4 min read

Tutorial: Automate infrastructure and deployment on Azure using Jenkins and Ansible

Both Ansible and Jenkins are powerful open source automation tools. Using Ansible, you can provision virtual machines, containers, network and complete cloud infrastructures on Azure. In addition, Ansible allows you to automate the deployment and configuration of resources in your environment. Jenkins provides hundreds of plugins to support building, deploying and automating any project, including a plugin for Ansible.

With the power of Ansible and Jenkins, and their deep integration with Azure, you can have a seamless CI/CD experience on Azure. Below is an example for a web app scenario. Jenkins is used to build and deploy, and Ansible is called to handle provisioning.

In the following sections, we will walk though how to use Jenkins to call Ansible to provision a web app and then continuously build and deploy a Java Spring Boot application to Azure Web Apps.

Build your Jenkins and Ansible environment

Set up the Jenkins host

It is easy to create a Jenkins server on an Azure Linux virtual machine from a solution template. You can learn more about this template from install-jenkins-solution-template.

Install Ansible on the Jenkins host

When your Jenkins host is created, let us SSH to your Jenkins server and set up Ansible on it.

## Install pre-requisite packages

$ sudo apt-get update
$ sudo apt-get install -y libssl-dev libffi-dev python-dev python-pip

## Install Ansible and Azure SDKs via pip

$ sudo pip install ansible[azure]==2.7.0rc2

or
## Install Azure preview modules

$ sudo ansible-galaxy install Azure.azure_preview_modules

$ sudo pip install -r ~/.ansible/roles/Azure.azure_preview_modules/files/requirements-azure.txt

Note: Ansible modules for Azure Web Apps are only available in Ansible 2.7. You could install Ansible 2.7 RC version here or install Azure role named azure_preview_modules which include latest modules. Ansible 2.7 will be released on Oct 4th. After that, you need not specify the version here because the default version will be 2.7.

Install Maven for a sample Java application

In this demo, we will directly use this Jenkins server to build our Java application. Here we also install Maven on it.

## Install maven

sudo apt-get install -y maven

Install Jenkins plugin for Ansible

The following three plugins will be used for this web app scenario.

  • azure-app-service: A Jenkins plugin to deploy a web app.
  • ansible:  This plugin allows to execute Ansible tasks as a job build step.
  • envinject: This plugin makes it possible to have an isolated environment for your jobs.

Connect to your Jenkins server by following connect-to-jenkins. After you unblock Jenkins, suggest you choose Install suggested plugins.” The Jenkins plugin for App Service will be installed here.

To install the other two plugins, click Manage Jenkins on the left bar and select Manage Plugins.” Select Available” tab, search and install Ansible plugin and Environment Injector plugin.

Prepare Application, Ansible playbook, and Jenkinsfile

Spring Boot application for Azure Web Apps

Here we forked a Spring Boot project from https://github.com/spring-guides/gs-spring-boot to https://github.com/VSChina/gs-spring-boot for the following tutorial. On the branch named”war-based-deployment,” we updated the application.java and pom.xml to package this project as an executable war file, which can be directly deployed to Azure Web Apps with a Tomcat container by default.

Ansible playbook to provision Azure Web Apps

The below Ansible playbook creates a resource group and a web app on App Service Linux with Java 8 with Tomcat container runtime.

- name: Create Azure VM
  hosts: localhost
  connection: local
  vars:
    resource_group: "{{ lookup('env', 'RES_GROUP') }}"
    webapp_name: "{{ lookup('env', 'WEB_APP_NAME') }}"
    location: eastus
  tasks:
    - name: Create a resource group
      azure_rm_resourcegroup:
        name: "{{ resource_group }}"
        location: "{{ location }}"
    - name: Create a linux web app with java framework
      azure_rm_webapp:
        resource_group: "{{ resource_group }}"
        name: "{{ webapp_name }}"
        plan:
          resource_group: "{{ resource_group }}"
          name: myappplan
          is_linux: true
          sku: S1
          number_of_workers: 1
        frameworks:
          - name: "java"
            version: "8"
            settings:
              java_container: tomcat
              java_container_version: 8.5

Jenkinsfile

Below Jenkinsfile defines 4 tasks as followings.

  1. Check out source code
  2. Build
  3. Call Ansible to provision web app
  4. Deploy application to created web app
node {
  stage('Init') {
    checkout scm
  }

  stage('Build') {
    sh '''
        cd complete
        mvn clean package
        mv target/*.war ROOT.war
    '''
  }

  stage('Deploy') {
    withCredentials([azureServicePrincipal(credentialsId: env.AZURE_CRED_ID,
                                    subscriptionIdVariable: 'AZURE_SUBSCRIPTION_ID',
                                    clientIdVariable: 'AZURE_CLIENT_ID',
                                    clientSecretVariable: 'AZURE_SECRET',
                                    tenantIdVariable: 'AZURE_TENANT')]) {
                                      
      ansiblePlaybook installation: 'ansible',
      playbook: 'complete/deploy/ansible/webapp.yml'
    }

    azureWebAppPublish azureCredentialsId: env.AZURE_CRED_ID,
                       resourceGroup: env.RES_GROUP, 
                       appName: env.WEB_APP_NAME, 
                       filePath: "ROOT.war"
  }
}

Define your Jenkins pipeline

Add Azure Service Principal in credentials

Authentication is required using Ansible modules to provision Azure resources. If you don’t have Service Principal, create an Azure service principal. Take note of the values for the subscription ID, Client ID, Secret, and Tenant ID.

On Jenkins dashboard, click Credentials on the left bar and then System item. Then you will see Global Credentials on the page. Select it and click Add Credentials. As for kind, select Microsoft Azure Service Principal here and fill in subscription ID, Client ID, Secret, and Tenant ID.

After you click ok, you will see a new item is added. Copy the name (here it is 542d982a-7614-4a3d-ae6b-ce321bfef5b0) which is your <azure-credentials-id>.

Create a Jenkins job

Select New Item from the Jenkins console, then fill in your project and select Pipeline project, then select OK.

In General section, select Prepare an environment for the run. In the Properties Content, fill in following content.

AZURE_CRED_ID=azure-credentials-id
WEB_APP_NAME=web-app-name
RES_GROUP=web-app-resource-group
JENKINS_ADMIN=Jenkins-server-username

In Pipeline section, select Git for Source Control Management, fill in `https://github.com/VSChina/gs-spring-boot.git` in Repository URL and change Branch Specifier to “*/war-based-deployment“. As for Script Path, fill in “complete/deploy/jenkins/jenkinsfile-ansible-webapp.”

Launch the Jenkins Job

Now it is time to click Build Now. After the deployment is complete, you can find your web app on the portal and you will see it at https://<web-app-name>.azurewebsites.net.

Conclusion

In this tutorial we demonstrated a simple flow that automates web app provisioning and application deployment to Azure Web Apps. If you want to try more with the combination of Jenkins and Ansible, check out Ansible on Azure and Jenkins on Azure.

Questions? Let us know in the comments.