Introduction
Resources Used
- Privately Hosted Jenkins
- Google developer console
- Ngrok
Setup 1: Setup Ngrok
ngrok http 8080
A blog site on our Real life experiences with various phases of DevOps starting from VCS, Build & Release, CI/CD, Cloud, Monitoring, Containerization.
ngrok http 8080
Although, the coding language used here is groovy but Jenkins does not allow us to use Groovy to its fullest, so we can say that Jenkins Pipelines are not exactly groovy. Classes that you may write in src, they are processed in a “special Jenkins way” and you have no control over this. Depending on the various scenarios objects in Groovy don’t behave as you would expect objects to work.
Our thought is putting all pipeline functions in vars is much more practical approach, while there is no other good way to do inheritance, we wanted to use Jenkins Pipelines the right way but it has turned out to be far more practical to use vars for global functions.
Practical Strategy
As we know Jenkins Pipeline’s shared library support allows us to define and develop a set of shared pipeline helpers in this repository and provides a straightforward way of using those functions in a Jenkinsfile.This simple example will just illustrate how you can provide input to a pipeline with a simple YAML file so you can centralize all of your pipelines into one library. The Jenkins shared library example:And the example app that uses it:
You would have the following folder structure in a git repo:
└── vars ├── opstreePipeline.groovy ├── opstreeStatefulPipeline.groovy ├── opstreeStubsPipeline.groovy └── pipelineConfig.groovy
This repo would be configured in under Manage Jenkins > Configure System in the Global Pipeline Libraries section. In that section Jenkins requires you give this library a Name. Example opstree-library
Let’s assume that project repository would have a pipeline.yaml file in the project root that would provide input to the pipeline:Pipeline.yaml
ENVIRONMENT_NAME: test SERVICE_NAME: opstree-service DB_PORT: 3079 REDIS_PORT: 6079
Then, to utilize the shared pipeline library, the Jenkinsfile in the root of the project repo would look like:
@Library ('opstree-library@master') _ opstreePipeline()
So how does it all work? First, the following function is called to get all of the configuration data from the pipeline.yaml file:
def call() { Map pipelineConfig = readYaml(file: "${WORKSPACE}/pipeline.yaml") return pipelineConfig }
You can see the call to this function in opstreePipeline(), which is called by the Jenkinsfile.
def call() { node('Slave1') { stage('Checkout') { checkout scm } def p = pipelineConfig() stage('Prerequistes'){ serviceName = sh ( script: "echo ${p.SERVICE_NAME}|cut -d '-' -f 1", returnStdout: true ).trim() } stage('Build & Test') { sh "mvn --version" sh "mvn -Ddb_port=${p.DB_PORT} -Dredis_port=${p.REDIS_PORT} clean install" } stage ('Push Docker Image') { docker.withRegistry('https://registry-opstree.com', 'dockerhub') { sh "docker build -t opstree/${p.SERVICE_NAME}:${BUILD_NUMBER} ." sh "docker push opstree/${p.SERVICE_NAME}:${BUILD_NUMBER}" } } stage ('Deploy') { echo "We are going to deploy ${p.SERVICE_NAME}" sh "kubectl set image deployment/${p.SERVICE_NAME} ${p.SERVICE_NAME}=opstree/${p.SERVICE_NAME}:${BUILD_NUMBER} " sh "kubectl rollout status deployment/${p.SERVICE_NAME} -n ${p.ENVIRONMENT_NAME} " } }
You can see the logic easily here. The pipeline is checking if the developer wants to deploy on which environment what db_port needs to be there.
The benefits of this approach are many, some of them are as mentioned below:
Jenkinsfiles could actually just look more commonly, like this:
@Library ('opstree-library@master') _ opstreePipeline()
and opstreePipeline() would just read the the project type from pipeline.yaml and dynamically run the exact function, like opstreeStatefulPipeline(), opstreeStubsPipeline.groovy() . since pipeline are not exactly groovy, this isn’t possible. So one of the drawback is that each project would have to have a different-looking Jenkinsfile. The solution is in progress!So, what do you think?
Reference links:
Image: Google image search (jenkins.io)
Prerequisites
Ansible Installation
Before starting with installing Jenkins using Ansible, you need to have Ansible installed in your system.
$ curl https://raw.githubusercontent.com/OpsTree/AnsiblePOC/alok/scripts/Setup/setup_ansible.sh | sudo bash
Setup jenkins using Ansible
Install jenkins ansible roles
Once we have ansible installed in our system, we can start installing the jenkins using ansible. To install we will use an already available ansible role to setup jenkins
Ansible roles default directory path is /etc/ansible/roles
Make ansible playbook file
$ cd ~/MyPlaybook/jenkins
$ ansible-playbook -i hosts site.yml
Now that Jenkins is running, go to http://192.168.33.15:8080. You’ll be welcome by the default Jenkins screen.
The reason behind this issue is that if you are using git with ssh protocol it tries to use your private key to perform git operations over ssh protocol & the location it expects is the .ssh folder at home directory of user. To fix this issue you have to create a HOME environment variable and point to your home directory where your .ssh folder exists after that restart Jenkins & now it should work fine.