Deploy Helm charts into Kubernetes with Jenkins job - jenkins

I want to create a Jenkins job which deploys Helm chart into Kubernetes cluster.
Helm charts are stored into Bitbucket repository.
pipeline {
agent any
stages {
stage('Download Helm Charts') {
steps {
sh "echo 'Downloading Helm Charts from Bitbucket repository...'"
git checkout http://192.168.1.30:7990/scm/jen/helm.git
// not sure do I need ot point the root folder of the Helm repository or only the single chart
}
}
stage('Test Kubernetes version') {
steps {
sh "echo 'Checking Kubernetes version..'"
// How to do remote test of kubernetes version
}
}
stage('Push Helm Charts to Kubernetes') {
steps {
sh "echo 'building..'"
// push here helm chart from Jenkins server to Kubernetes cluster
}
}
stage('Build Image') {
steps {
sh "echo 'building..'"
git checkout http://192.168.1.30:7990/scm/jen/spring-boot-microservice.git
// execute Java -jar ... and build docker image
}
}
stage('Push Image into Nexus registry') {
steps {
sh "echo 'building..'"
// push compiled docker image into Nexus repository
}
}
stage('Deploy Image from Nexus registry into Kubernetes') {
steps {
sh "echo 'building..'"
}
}
stage('Test'){
steps {
sh "echo 'Testing...'"
// implement a check here is it deployed sucessfully
}
}
}
}
What configuration I need to add into this Jenkins file in order to download Heml chart repository from bitbucket and apply the configuration into Kubernetes cluster?
Can you give me an example for such a Jenkins file?

Assuming your Pipeline is already in Bitbucket repo where Helm charts reside. Following is a example structure of the repo.
jenkins
├── app1-charts
│   ├── Chart.yaml
│   ├── templates
│   │   ├── app1.yml
│   │   └── _helpers.tpl
│   └── values.yaml
└── Jenkinsfile
The Jenkinsfile in the root directory would have a simple Pipeline like below.
pipeline {
agent any
stages {
stage('Build1') {
steps {
echo "Doing some build here if you need"
}
}
stage('Applying helm charts') {
steps {
echo "Running Helm"
sh "helm upgrade --wait --timeout 60 --set image.tag=${SOME_INPUT} app1-name ./app1-charts"
}
}
}
}
The above Pipeline assumes that you have Helm setup in the Jenkins agents. Now in Jenkins, you can create a New Pipeline Job and select the option Pipeline Script from SCM, and then provide the Bitbucket configurations.
Make sure the Script Path is set to point to your Jenkinsfile. Also, make sure Lightweight checkout is unchecked.
Once you add the configurations this will clone the repo with your helm charts and run the Pipeline in the repo which will execute the Helm charts.
Update: Pipeline to checkout bitbucket repo
Check the following Pipeline example. You may have to generate an access token with the necessary permissions to checkout the repo if the repo is Private.
pipeline {
agent any
stages {
stage('checkout') {
steps {
echo 'Checking out code from bitbucket'
git(url: 'https://x-token-auth:REPO_ACCESS_TOKEN#bitbucket.org/ORG_NAME/your-repo.git', branch: 'master')
sh """
cd your-helm-directory
helm install .............. Or whatever command you need
"""
}
}
}
}

Related

Jenkins pipeline and Docker multi-stage builds howto

Question
I have to configure CI/CD for number of Git repositories with help of Jenkins (and DockerHub as CD target). I did that with help of Docker multi-stage build (see Considerations). I'm afraid to misunderstand/overcomplicate a simple idea.
Is Jenkins + Docker multi-stage build = best/good practice? Am I applying the idea in the correct way?
Considerations
From this presentation I assume using Docker inside Jenkins is a good idea. After reading an article Using Multi-Stage Builds to Simplify and Standardize Build Processes, Docker multi-stage builds looks to be the next step of using Jenkins + Docker.
Answers to similar question also say Docker multi-stage makes sense, but doesn't provide an example of realisation.
Implementation
Jenkins creates pipeline from SCM repository.
Git repository
Dockerfile
Jenkinsfile
project-folder
|-src
|-pom.xml
Dockerfile
FROM alpine as source
RUN apk --update --no-cache add git
COPY project-folder repo
FROM maven:3.6.3-jdk-8 as test
COPY --from=source repo repo
WORKDIR repo
RUN mvn clean test
FROM maven:3.6.3-jdk-8 as build
COPY --from=test repo repo
WORKDIR repo
RUN mvn clean package
FROM openjdk:8 as final
MAINTEINER xxx <xxx#gmail.com>
LABEL owner="xxx"
COPY --from=build repo/target/some-lib-1.8.jar /usr/local/some-lib.jar
ENTRYPOINT ["java", "-jar", "/usr/local/some-lib.jar"]
Jenkinsfile
I used docker build --target for more granularity on Jenkins UI.
#!/usr/bin/env groovy
def imageId = "use-name/image-name:1.$BUILD_NUMBER"
pipeline {
agent {
label 'docker' # separate agent (launched as JAR on host machine) to avoid running docker inside docker
}
stages {
stage('Test') {
steps {
script {
sh "docker build --no-cache --target test -t ${imageId} ."
}
}
}
stage('Build') {
steps {
script {
sh "docker build --target build -t ${imageId} ."
}
}
}
stage('Image') {
steps {
script {
sh "docker build --target final -t ${imageId} ."
}
}
}
stage('Deploy') {
steps {
script {
docker.withRegistry('' , 'dockerhub') {
dockerImage = docker.build("${imageId}")
dockerImage.push()
}
}
}
}
stage('Clean') {
steps{
sh "docker rmi ${imageId}"
}
}
}
}
following taleodor's answer I would suggest next jenkinsfile:
pipeline {
agent {
label 'docker' # separate agent (launched as JAR on host machine) to avoid running docker inside docker
}
environment {
imageId = 'use-name/image-name:1.$BUILD_NUMBER'
docker_registry = 'your_docker_registry'
docker_creds = credentials('your_docker_registry_creds')
}
stages {
stage('Docker build') {
steps {
sh "docker build --no-cache --force-rm -t ${imageId} ."
}
}
stage('Docker push') {
steps {
sh'''
docker login $docker_registry --username $docker_creds_USR --password $docker_creds_PSW
docker push $imageId
docker logout
'''
}
}
stage('Clean') {
steps{
sh "docker rmi ${imageId}"
}
}
}
}

How to use helm commands in jenkins pipeline script

I have been trying to deploy the image built on jenkins by docker to helm charts, i have referred couple of documents on website https://dev.to/sword-health/seamless-ci-cd-with-jenkins-helm-and-kubernetes-5e00
and https://cloudcompilerr.wordpress.com/2018/06/03/docker-jenkins-kubernetes-run-jenkins-on-kubernetes-cluster/ and managed till the point where docker image gets pushed into dockerhub but i get stuck at helm
i'm not getting what the error exactly is.
JENKINS ERROR
+ helm list
/var/lib/jenkins/workspace/01#tmp/durable-68e91f76/script.sh: 1: /var/lib/jenkins/workspace/01#tmp/durable-68e91f76/script.sh: helm: not found
PIPELINESCRIPT
pipeline {
environment {
registry = "hemanthpeddi/springboot"
registryCredential = 'dockerhub'
}
agent any
tools {maven "maven" }
stages {
stage('Cloning Git') {
steps {
git 'https://github.com/hrmanth/game-of-life.git'
}
}
stage('Build'){
steps{
sh script: 'mvn clean package'
}
}
stage('Building image') {
steps{
script {
dockerImage = docker.build registry + ":$BUILD_NUMBER"
}
}
}
stage('Deploy Image') {
steps{
script {
docker.withRegistry( '', registryCredential ) {
dockerImage.push()
}
}
}
}
stage('Remove Unused docker image') {
steps{
sh "docker rmi $registry:$BUILD_NUMBER"
}
}
stage('Run Helm') {
steps {
script {
container('helm') {
sh "helm ls"
}
}
}
}
}
}
Is there any specific configuration that i'm missing before i use helm in jenkins? And i have configured my kubernetes IP in the cloud configuration in jenkins, Please help
Plugins Installed
Kubernetes Plugin
Docker Plugin
You need helm, it is not available by default. You could add helm as a tool in Jenkins and use it.
https://www.jenkins.io/doc/book/pipeline/syntax/#tools
you can install helm in the container itself by adding an extra stage
stage("install helm"){
steps{
sh 'wget https://get.helm.sh/helm-v3.6.1-linux-amd64.tar.gz'
sh 'ls -a'
sh 'tar -xvzf helm-v3.6.1-linux-amd64.tar.gz'
sh 'sudo cp linux-amd64/helm /usr/bin'
sh 'helm version'
}
}
I am not so familiar with that, but when you are using the "container('helm')" step, I think it refers to
Kubernetes Plugin.
So, reading this docs, I think that the "podTemplate" is missing in your configuration.
Thus what you need to do is to configure a Helm container in the "podTemplate" and put the name "helm". You can try to use, for example, the "alpine/helm" image.
See you later.

Missing Required Parameter in Docker File

I'm learning how to use Jenkins and jenkinsfile for my CI/CD project, and when trying to run a docker image to run my selenium tests against, an error is thrown saying that the docker image param is missing.
I've followed the docks on the jenkins site for a tutorial and I'm now trying to fit that for my own purposes.
pipeline {
agent any
stages {
stage('Build') {
steps {
echo 'Building..'
sh 'npm install'
}
}
stage('Test') {
steps {
echo 'Testing..'
docker {
image 'selenium/standalone-firefox:3.141.59-gold'
args '-p 4444:4444'
}
sh 'npm test'
}
}
stage('Deploy') {
steps {
echo 'Deploying....'
}
}
}
}
Docker should run on my Ubuntu server with port 4444 of the docker exposed and mapped to port 4444 of the server.
You used Declarative Pipeline for your Jenkinsfile, not Scripted Pipeline. For Declarative Pipeline, the docker is a directive which can only be used to specify agent for entire pipeline or stage as following:
pipeline {
agent { // specify docker container for entire pipeline
docker {
image ''
args ''
}
}
}
stage('test') {
agent { // all steps of this stage will be executed inside this docker container
docker {
image ''
args ''
}
}
}
You can't use this docker directive as pipeline step, like sh, 'echo'.
Jenkins indeed supply a docker DSL which can be directly used in Scripted Pipeline.
Declarative Pipeline supply a step script in where we can put Scripted Pipeline-liked script as following:
stage('test') {
steps {
script {
def version = ....
def img = docker.build(...)
img.push()
docker.image(...).inside(){}
}
}
}
Thus you can change your Jenkinsfile as following and give a trying.
pipeline {
agent any
stages {
stage('Build') {
steps {
echo 'Building..'
sh 'npm install'
}
}
stage('Test') {
steps {
echo 'Testing..'
script {
docker.image('selenium/standalone-firefox:3.141.59-gold')
.inside('-p 4444:4444'){}
}
sh 'npm test'
}
}
stage('Deploy') {
steps {
echo 'Deploying....'
}
}
}
}
By default the Docker Pipeline integrates assumes the default Docker Registry of Docker Hub.
If you intend to use use a custom Docker Registry, you can use docker.withRegistry to specify the custom Registry URL and Credentials as following:
stage('Test') {
steps {
echo 'Testing..'
script {
docker.withRegistry('<custom docker registry>',
'<credentialsId for custom docker registry if required>') {
docker.image('selenium/standalone-firefox:3.141.59-gold')
.inside('-p 4444:4444'){}
}
}
sh 'npm test'
}
}
Note: If the custom docker registry need credentails, you have to add your account for custom docker registry into Jenkins via Jenkins Credentials. After adding, Jenkins will assign a id for your account, the id called credentialsId which used in above code.

Uploading non maven projects to nexus

I'm new with docker and jenkins. I'm trying to upload a non maven project to nexus using the jenkins pipeline. Below is a snippet of my jenkinsfile script. I want to do a maven upload of the resulting docker build image. any help?
node {
def app
stage('Clone repository') {
checkout scm
}
stage('Build image') {
app = bat "docker build -t myapp ."
}
stage('Test image') {
bat 'echo "Tests successful"'
}
stage('Deploy image') {
"
}
}
I haven't used this plugin before so this is my best guess. I am thinking the below plugin might help you do what you are looking for.
https://github.com/spotify/dockerfile-maven
Configure your pom.xml to point to nexus repository
Usage - https://github.com/spotify/dockerfile-maven/blob/master/docs/usage.md
dockerfile:build ------> Builds a Docker image from a Dockerfile.
dockerfile:tag ---------> Tags a Docker image.
dockerfile:push -------->Pushes a Docker image to a repository.

Best solution to deploy (copy) the last version to the server using Jenkins Pipline

Here is my Jenkins Pipeline:
pipeline {
agent {
docker {
image 'node:6-alpine'
args '-p 3000:3000'
}
}
environment {
CI = 'true'
}
stages {
stage('Build') {
steps {
sh 'npm install'
sh 'npm build'
}
}
stage('Deliver') {
steps {
sh './jenkins/scripts/deliver.sh'
input message: 'Finished using the web site? (Click "Proceed" to continue)'
sh './jenkins/scripts/kill.sh'
}
}
stage('Deploy') {
steps {
sh './jenkins/scripts/deploy.sh'
}
}
} }
I use Docker and jenkinsci/blueocean image to run Jenkins. The first two stages are kind of standard to build a NodeJS app, the third one, however, is the part that I want to Jenkins copy new files to the server. Here is the deploy.sh files:
#!/usr/bin/env sh
set -x
scp -o StrictHostKeyChecking=no -r dist/* deviceappstore:/var/www/my_website/static/
There are two problems, first jenkinsci/blueocean does not have scp (not setup) and second, the ~/.ssh/config does not exist inside of the Jankins docker image then SCP will fail to authenticate. My solution was to build a custom image extends from jenkinsci/blueocean, setup SCP and copy config file and SSH key into it.
There are some plugins like Publish Over SSH but it seems it's not useful for Pipeline projects.
Is there any better solution? It the whole scenario right or I'm doing something wrong? I'm looking for most secure and standard solution for this problem.
OK, I think I found a good solution.
Thanks to SSH Agent plugin I can easily pass the credentials to the SCP command and copy the files to the server. Something like this:
...
stage('Deploy') {
steps {
sshagent(['my SSH']) {
echo 'this works...'
sh 'scp -o StrictHostKeyChecking=no -r dist/* my_server:/var/www/my_site/static/'
}
}
}
...
This is perfect because all the credentials are inside of Jenkins server and there's nothing about it in the repo.
And to be able to use this, there's just one solution. You need to use apk inside of the jenkinsci/blueocean (alpine) image and setup openssh:
apk add openssh
Or better solution create a new Dockerfile and build your own version.

Resources