HomeAbout
[DevOps] Maven을 사용한 Java Application 빌드 및 배포 & DevSecOps Pipeline 통합 및 자동화 고도화
DevOps
[DevOps] Maven을 사용한 Java Application 빌드 및 배포 & DevSecOps Pipeline 통합 및 자동화 고도화
NASA1515
NASA1515
August 20, 2021
1 min

사용 할 툴을 다음과 같습니다.

  • Jenkins
  • maven
  • github
  • ArgoCD

✔ 통합 Jenkins Pipeline


파이프라인 스크립트

properties([
parameters([
    string(name: 'sonar.projectKey', defaultValue: 'com.appsecco:dvja'),
    string(name: 'sonar.host.url', defaultValue: 'http://34.64.237.112:9000'),
    string(name: 'sonar.login', defaultValue: '608cacd6bb83c50712ebb34c4cba377c841cdebb'),
    string(name: 'ARGOCD_DOMAIN', defaultValue: '34.67.162.44:30357'),
    string(name: 'ARGOCD_PW', defaultValue: 'argo-cd-argocd-server-6d5f98cf57-wmf46'),
    string(name: 'ARGOCD_APP_NAME', defaultValue: 'test'),
    string(name: 'tag_num', defaultValue: ''),
]) 
])
pipeline {
    environment {
        slack_channel = '#studying'
        REGISTRY = 'nasa1515/wonseok'
        REGISTRY_IP = '34.64.237.112'
        REGISTRYCREDENTIAL = 'harbor' 
        DOCKER_IMAGE = ''
        TAG_NUM = ''
    }
    agent any
    tools { 
        maven 'mvn' 
    }
    stages {
        stage('Git clone') {
            steps {
                git 'https://github.com/nasa1515/dvwa-web-was.git'
            }
        }
        stage('Build Test') {
            steps {
                sh 'mvn clean package -Dcheckstyle.skip -Dspotbugs.skip -Dpmd.skip'
            }
        }
        stage ('Dependency-Check Analysis') {
            steps {
                sh '/var/lib/jenkins/dependency-check/bin/dependency-check.sh --scan `pwd` --format XML --out /var/lib/jenkins/workspace/ci-build-pipeline/dependency-check-report --prettyPrint'
                
                dependencyCheckPublisher pattern: 'dependency-check-report/dependency-check-report.xml'
            }
        }
        stage('Sonarqube and Quality gate') {
            options {
                timeout(time: 5, unit: 'MINUTES')
                retry(2)
            }
            steps {
                withSonarQubeEnv('SonarQube Server') {
                    sh "mvn sonar:sonar"
                }
                script {
                    qualitygate = waitForQualityGate()
                    if (qualitygate.status != "OK") {
                        currentBuild.result = "FAILURE"
                    }
                }
            }
        }
        stage('Docker image build') { 
            steps{
                script {
                    DOCKER_IMAGE = docker.build registry
                
                }
            }
        } 
        stage('Docker image push to Harbor') {
            steps{
                script {
                    docker.withRegistry('http://$REGISTRY_IP', REGISTRYCREDENTIAL) {
                        DOCKER_IMAGE.push('${BUILD_NUMBER}')
                        DOCKER_IMAGE.push("latest")
                    }
                }
                sh 'docker rmi $REGISTRY:latest'
                sh 'docker rmi $REGISTRY_IP/$REGISTRY:$BUILD_NUMBER'
                sh 'docker rmi $REGISTRY_IP/$REGISTRY:latest'
            }
        }
        stage('Anchore analyse') {  
            steps {  
                catchError(buildResult: 'SUCCESS', stageResult: 'SUCCESS') {
                writeFile file: 'anchore_images', text: '34.64.237.112/nasa1515/wonseok'  
                anchore name: 'anchore_images'  
                }
            }
        }

        stage('Push Yaml'){
            steps {
                script{
                    try {
                        git url: "https://github.com/nasa1515/dvwa-helm", branch: "main", credentialsId: "github"
                        sh "rm -rf /var/lib/jenkins/workspace/${env.JOB_NAME}/helm-service/values.yaml"
                        sh """
                        cd helm-service
                        #!/bin/bash
                        cat>values.yaml<<-EOF
# Default values for ghost.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.

replicaCount: 3

image:
repository: nasa1515/dvwa-web-was
tag: $BUILD_NUMBER
pullPolicy: ""

value: ec95c258266b8e985848cae688effa2b

namespace: cd-test

name: 
app: app
EOF"""
                        sh "cat /var/lib/jenkins/workspace/${env.JOB_NAME}/helm-service/values.yaml"
                        withCredentials([usernamePassword(credentialsId: 'github', passwordVariable: 'GIT_PASSWORD', usernameVariable: 'GIT_USERNAME')]) {
                            sh """
                            git add --all .
                            git commit -m "Deploy ${env.JOB_NAME} ${env.BUILD_NUMBER}"
                            git push https://${GIT_USERNAME}:${GIT_PASSWORD}@github.com/nasa1515/dvwa-helm
                            """
                        }                      
                        env.pushYamlResult=true
                    } catch (error) {
                        print(error)
                        echo 'Remove Deploy Files'
                        withCredentials([usernamePassword(credentialsId: 'github', passwordVariable: 'GIT_PASSWORD', usernameVariable: 'GIT_USERNAME')]) {
                            sh """
                            git reset --hard HEAD^
                            git push --force https://${GIT_USERNAME}:${GIT_PASSWORD}@github.com/nasa1515/dvwa-helm
                            """
                        }
                        env.pushYamlResult=false
                        currentBuild.result = 'FAILURE'
                    }
                }
            }
        }

        stage('Argo Deploy'){
            steps {
                script{
                    try {
                        withEnv(["PATH=/usr/local/bin:$PATH"]) {
                            sh"""
#!/bin/bash
expect << EOF
spawn argocd login --grpc-web $ARGOCD_DOMAIN

expect "WARNING: server certificate had error: x509: cannot validate certificate for 34.67.162.44 because it doesn't contain any IP SANs. Proceed insecurely (y/n)?"
send "y\r";

expect "Username:"
send "admin\r";    

expect "Password:"
send "$ARGOCD_PW\r";    
                                    
expect eof
EOF
                                argocd app get $ARGOCD_APP_NAME
                                argocd app sync $ARGOCD_APP_NAME
                            """
                        }
                    } catch (error) {
                        print(error)
                        currentBuild.result = 'FAILURE'
                    }
                }
            }
        }
    }
    post { 
    success { 
        slackSend (channel: SLACK_CHANNEL, color: 'good', message: "SUCCESSFUL: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]' (${env.BUILD_URL})") 
    }
    failure {
        slackSend (channel: SLACK_CHANNEL, color: 'bad', message: "FAILURE: '${env.JOB_NAME} [${env.BUILD_NUMBER}]' (${env.BUILD_URL})")    
    }
    }
}

동영상 요약


파이프라인의 프로세스

  1. 소스코드를 Clone 해온 뒤 Build 테스트
  2. Dependency-Check Analysis 로 코드 정적분석
  3. Sonarqube and Quality gate 정적분석
  4. 위의 검사에서 에러가 없으면 Docker image build
  5. 빌드한 도커이미지를 HARBOR 저장소에 PUSH
  6. HARBOR에 저장된 이미지의 에러 검사
  7. 새로운 빌드 넘버로 메니페스트 수정 후 GITOPS 저장소로 푸시
  8. ArgoCD로 Sync 요청

DVWA! 빌드 소스 저장소!


DVWA 빌드소스 저장소는 아래와 같이 구성했습니다.

저장소링크

스크린샷, 2020-11-12 15-36-51

  • Jenkins 에서는 해당 저장소를 Clone 후 이미지를 빌드 할 예정입니다.


MAVEN 빌드 전 사전작업


아래 두 설정을 모두 만족해야 정상적인 빌드가 됩니다.


Jenkins에서 JDK 설정


Jenkins에서 MAVEN 설정



Build Pipeline Script


전체적인 파이프라인 스크립트에서 MAVEN 빌드 부분만 떼어냈습니다.

pipeline {
    agent any
    tools { 
        maven 'mvn' 
    }
    stages {
        stage('Git clone') {
            steps {
                git 'https://github.com/nasa1515/dvwa.git'
            }
        }
        stage('Build Test') {
            steps {
               sh 'mvn clean package -Dcheckstyle.skip -Dspotbugs.skip -Dpmd.skip'
            }
        }
    }
}

  • 스크립트에 대한 설명없이도 아마 대부분은 이해가 될 것입니다. 간단하게 설명하자면 Agent any로 jdk, mvn들의 툴을 선언해준 뒤
    빌드 소스의 저장소를 clone 한 뒤 해당 소스들을 MVN으로 빌드하는 간단한 구문입니다 문법이 궁금하신분들은 참고링크를 읽어보시면 빠르게 이해 될 것입니다.

Tags

#DevOps#GCP#Kubernetes#Jenkins
NASA1515

NASA1515

Data Engineer

Hello I'M Wonseok aka NASA1515

Expertise

Public Cloud
k8s/Docker
Python

Social Media

instagramwebsitelinkedingithub

Related Posts

[DevOps] Private Docker Registry Harbor 도입으로 DevOps 고도화 & Jenkins와 ArgoCD에 연동 및 통합
[DevOps] Private Docker Registry Harbor 도입으로 DevOps 고도화 & Jenkins와 ArgoCD에 연동 및 통합
2021-08-12
1 min

Topics

CloudDevelop

Social Media