이제 모든 준비가 끝났습니다.
그저 젠킨스 파이프라인 코드만 잘 작성해주시면 됩니다.
저는 스크립트에서 아래와 같은 변수들을 젠킨스에서 선언하고 사용합니다.
스크립트는 아래와 같습니다.
pipeline {
agent any
stages {
stage('Git Clone') {
steps {
script {
try {
git url: "https://$GIT_URL", branch: "master", credentialsId: "$GIT_CREDENTIALS_ID"
sh "sudo rm -rf ./.git"
env.cloneResult=true
} catch (error) {
print(error)
env.cloneResult=false
currentBuild.result = 'FAILURE'
}
}
}
}
stage('Build JAR') {
when {
expression {
return env.cloneResult ==~ /(?i)(Y|YES|T|TRUE|ON|RUN)/
}
}
steps {
script{
try {
sh """
rm -rf deploy
mkdir deploy
"""
sh "sudo sed -i \"s/module_name=.*/module_name=${env.JOB_NAME}\\:${env.BUILD_NUMBER}/g\" /var/lib/jenkins/workspace/${env.JOB_NAME}/src/main/resources/application.properties"
sh "cat /var/lib/jenkins/workspace/${env.JOB_NAME}/src/main/resources/application.properties"
sh 'mvn -Dmaven.test.failure.ignore=true clean install'
sh """
cd deploy
cp /var/lib/jenkins/workspace/${env.JOB_NAME}/target/*.jar ./${env.JOB_NAME}.jar
"""
env.mavenBuildResult=true
} catch (error) {
print(error)
echo 'Remove Deploy Files'
sh "sudo rm -rf /var/lib/jenkins/workspace/${env.JOB_NAME}/*"
env.mavenBuildResult=false
currentBuild.result = 'FAILURE'
}
}
}
post {
success {
slackSend channel: '#pipeline-deploy', color: 'good', message: "The pipeline ${currentBuild.fullDisplayName} stage Build JAR successfully."
}
failure {
slackSend channel: '#pipeline-deploy', color: 'danger', message: "The pipeline ${currentBuild.fullDisplayName} stage Build JAR failed."
}
}
}
stage('Docker Build'){
when {
expression {
return env.mavenBuildResult ==~ /(?i)(Y|YES|T|TRUE|ON|RUN)/
}
}
steps {
script{
try {
sh"""
#!/bin/bash
cd ./deploy
cat>Dockerfile<<-EOF
FROM ${ECR_BASE_URL}:latest
ADD ${env.JOB_NAME}.jar /home/${env.JOB_NAME}.jar
CMD nohup java -jar /home/${env.JOB_NAME}.jar 1> /dev/null 2>&1
EXPOSE 9000
EOF"""
sh"""
cd ./deploy
\$(aws ecr get-login --no-include-email --region ap-northeast-2)
docker build -t ${env.JOB_NAME.toLowerCase()} .
docker tag ${env.JOB_NAME.toLowerCase()}:latest ${ECR_TASK_URL}:ver${env.BUILD_NUMBER}
docker push ${ECR_TASK_URL}:ver${env.BUILD_NUMBER}
"""
echo 'Remove Deploy Files'
sh "sudo rm -rf /var/lib/jenkins/workspace/${env.JOB_NAME}/*"
env.dockerBuildResult=true
} catch (error) {
print(error)
echo 'Remove Deploy Files'
sh "sudo rm -rf /var/lib/jenkins/workspace/${env.JOB_NAME}/*"
env.dockerBuildResult=false
currentBuild.result = 'FAILURE'
}
}
}
post {
success {
slackSend channel: '#jenkins', color: 'good', message: "The pipeline ${currentBuild.fullDisplayName} stage Docker Build successfully."
}
failure {
slackSend channel: '#jenkins', color: 'danger', message: "The pipeline ${currentBuild.fullDisplayName} stage Docker Build failed."
}
}
}
stage('Push Yaml'){
when {
expression {
return env.dockerBuildResult ==~ /(?i)(Y|YES|T|TRUE|ON|RUN)/
}
}
steps {
script{
try {
git url: "https://$GIT_URL-yaml", branch: "master", credentialsId: "$GIT_CREDENTIALS_ID"
sh "rm -rf /var/lib/jenkins/workspace/${env.JOB_NAME}/*"
sh """
mkdir yaml
cd yaml
#!/bin/bash
cat>deployment.yaml<<-EOF
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: cb-test-api
namespace: prd-api
spec:
replicas: 1
template:
metadata:
labels:
app: cb-test-api
spec:
containers:
- image: ${ECR_TASK_URL}:ver${env.BUILD_NUMBER}
imagePullPolicy: Always
name: cb-test-api
ports:
- containerPort: 9000
EOF"""
sh "cat /var/lib/jenkins/workspace/${env.JOB_NAME}/yaml/deployment.yaml"
withCredentials([[$class: "UsernamePasswordMultiBinding", credentialsId: "$GIT_CREDENTIALS_ID", usernameVariable: "GIT_AUTHOR_NAME", passwordVariable: "GIT_PASSWORD"]]) {
sh """
git add .
git commit -m "Deploy ${env.JOB_NAME} ${env.BUILD_NUMBER}"
git push https://${GIT_AUTHOR_NAME}:${GIT_PASSWORD}@${GIT_URL}-yaml
"""
}
sh "sudo rm -rf /var/lib/jenkins/workspace/${env.JOB_NAME}/*"
env.pushYamlResult=true
} catch (error) {
print(error)
echo 'Remove Deploy Files'
withCredentials([[$class: "UsernamePasswordMultiBinding", credentialsId: "$GIT_CREDENTIALS_ID", usernameVariable: "GIT_AUTHOR_NAME", passwordVariable: "GIT_PASSWORD"]]) {
sh """
git reset --hard HEAD^
git push --force https://${GIT_AUTHOR_NAME}:${GIT_PASSWORD}@${GIT_URL}-yaml
"""
}
sh "sudo rm -rf /var/lib/jenkins/workspace/${env.JOB_NAME}/*"
env.pushYamlResult=false
currentBuild.result = 'FAILURE'
}
}
}
post {
success {
slackSend channel: '#jenkins', color: 'good', message: "The pipeline ${currentBuild.fullDisplayName} stage Push Yaml successfully."
}
failure {
slackSend channel: '#jenkins', color: 'danger', message: "The pipeline ${currentBuild.fullDisplayName} stage Push Yaml failed."
}
}
}
stage('Argo Deploy'){
when {
expression {
return env.pushYamlResult ==~ /(?i)(Y|YES|T|TRUE|ON|RUN)/
}
}
steps {
script{
try {
withEnv(["PATH=/usr/local/bin:$PATH"]) {
sh"""
#!/bin/bash
expect << EOF
spawn argocd login --grpc-web $ARGOCD_DOMAIN
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)
echo 'Remove Deploy Files'
sh "sudo rm -rf /var/lib/jenkins/workspace/${env.JOB_NAME}/*"
currentBuild.result = 'FAILURE'
}
}
}
post {
success {
slackSend channel: '#jenkins', color: 'good', message: "The pipeline ${currentBuild.fullDisplayName} successfully."
}
failure {
slackSend channel: '#jenkins', color: 'danger', message: "The pipeline ${currentBuild.fullDisplayName} failed."
}
}
}
}
}
보통 Push yaml까지 (모든 CI)가 끝나면 승인체계를 거치도록 작성하는데,
이는 DevOps 카테고리에서 추가적으로 게시하도록 하겠습니다.
ArgoCD CLI까지 모두 수행하게 되면,
ArgoCD에서 배포되는것을 실시간으로 UI를 통해 보실 수 있으며 이전 배포버전 내역도 볼 수 있습니다.
마지막으로 서버에 접속해보면 정상적으로 파이프라인의 잡 네임과 빌드넘버가 붙어서 배포가 잘 되었음을 확인할 수 있습니다.
이렇게, EKS에서의 GitOps 스타일의 기본 CICD 자동화를 알아봤습니다.
Canary배포나 블루그린 형태의 배포에 대한 부분을 좀 더 연구한 후 잘 수행되면 작성할 예정입니다.
'EKS > Jenkins & ArgoCD' 카테고리의 다른 글
EKS CICD Automation - 4. ArgoCD Blue/Green Deployment (0) | 2020.09.07 |
---|---|
EKS CICD Automation - 2. Install ArgoCD (0) | 2020.02.06 |
EKS CICD Automation - 1. Intro (0) | 2020.02.06 |