Ci/CD pipeline architecture-
Description
In the Project, I have deployed Java application on Kubernetes cluster through Jenkins CI/CD pipeline.When the Application is pushed to Github repository you can manually trigger the CI pipeline with the help of Jenkins and it will run every stage given in the pipeline this also includes scanning of image using Sonarqube after every test stage has run successfully the docker image is been created and pushed to docker hub and version tag is updated in manifest.yml file for k8s deployment Argo CD is used for deployment through manifest.yml files to the kubernetes cluster
Github - https://github.com/iamabhijeet20/Java-k8s-cicd
Installation-
Fork the repo in your github
Setup Jenkins , Sonarqube and Docker on one instance/server.
In Jenkins add these 2 plugins -
Docker Pipeline
Sonarqube Scanner
Add Credentials to Jenkins - (Naming - type)
sonarqube - (secret text)Generate token after logging to sonarqube
docker-cred - Docker credentials username and Password
github - (secret text) Github token from your Github account where repo is forked
Edit the instance ip of SonarQube in Jenkins file -
stage('Static Code Analysis') {
environment {
SONAR_URL = "http://65.1.45.127:9000" // change the ip here
}
steps {
withCredentials([string(credentialsId: 'sonarqube', variable: 'SONAR_AUTH_TOKEN')]) {
sh 'mvn sonar:sonar -Dsonar.login=$SONAR_AUTH_TOKEN -Dsonar.host.url=${SONAR_URL}'
Run the Pipeline
(Note- Pipeline might fail sometime depending on how you configured but its a learning curve solving the errors is a good practice to be one of the best Devops Engineer)
Setup ArgoCD for K8s
Install Argo CD operator with the help of Operator.io
- https://operatorhub.io/operator/argocd-operator
for better understanding i am providing the commands here-
curl -sL https://github.com/operator-framework/operator-lifecycle-manager/releases/download/v0.28.0/install.sh | bash -s v0.28.0
kubectl create -f https://operatorhub.io/install/argocd-operator.yaml
Create a yaml file to deploy argocd on your cluster-
apiVersion: argoproj.io/v1alpha1
kind: ArgoCD
metadata:
name: example-argocd
labels:
example: basic
spec: {}
apply the yaml file on kubernetes with kubectl apply command
make sure to edit the service of argocd-server from ClusteriP to NodePort
ArgoCD saves the password in kubernetes cluster secrets
Argocd-cluster
The password is base64 encrypted so decrypt it with this command-
echo <unencrypted-password> | base64 -d
Jenkins File -
pipeline { agent { docker { image 'echo2000/maven-docker-agent:latest' args '--user root -v /var/run/docker.sock:/var/run/docker.sock' } } stages { stage('Checkout') { steps { sh 'echo passed' } } stage('Build and Test') { steps { sh 'ls -ltr' sh 'mvn clean package' } } stage('Static Code Analysis') { environment { SONAR_URL = "http://65.1.45.127:9000" } steps { withCredentials([string(credentialsId: 'sonarqube', variable: 'SONAR_AUTH_TOKEN')]) { sh 'mvn sonar:sonar -Dsonar.login=$SONAR_AUTH_TOKEN -Dsonar.host.url=${SONAR_URL}' } } } stage('Build and Push Docker Image') { environment { DOCKER_IMAGE = "echo2000/java-cicd:${BUILD_NUMBER}" REGISTRY_CREDENTIALS = credentials('docker-cred') } steps { script { sh 'docker build -t ${DOCKER_IMAGE} .' def dockerImage = docker.image("${DOCKER_IMAGE}") docker.withRegistry('https://index.docker.io/v1/', "docker-cred") { dockerImage.push() } } } } stage('Update Deployment File') { environment { GIT_REPO_NAME = "Java-K8s-CICD" GIT_USER_NAME = "iamabhijeet20" } steps { withCredentials([string(credentialsId: 'github', variable: 'GITHUB_TOKEN')]) { sh ''' git config user.email "iamabhijeetbhovar@gmail.com" git config user.name "Abhijeet Bhovar" BUILD_NUMBER=${BUILD_NUMBER} sed -i "s/replaceImageTag/${BUILD_NUMBER}/g" helm-app-manifests/deployment.yml git add helm-app-manifests/deployment.yml git commit -m "Update deployment image to version ${BUILD_NUMBER}" git push https://${GITHUB_TOKEN}@github.com/${GIT_USER_NAME}/${GIT_REPO_NAME} HEAD:main ''' } } } } }
Deployment.yaml-
apiVersion: apps/v1 kind: Deployment metadata: name: java-app labels: app: java-app spec: replicas: 2 selector: matchLabels: app: java-app template: metadata: labels: app: java-app spec: containers: - name: java-app image: echo2000/java-cicd::replaceImageTag ports: - containerPort: 8080
Service.yaml-
apiVersion: v1 kind: Service metadata: name: java-app-svc spec: type: NodePort ports: - name: http port: 80 targetPort: 8080 protocol: TCP selector: app: java-app
Thank-you for reading <3