240710 젠킨스 파이프라인 사용하기
젠킨스 파이프라인 사용하기
젠킨스 파이프라인
- 코드로서의 파이프라인이다.
- 빌드, 배포, 테스트 등 소프트웨어 개발 프로세스를 코드로 정의한다.
파이프라인의 구성
1) pipline
파이프라인 블록으로 스크립트 시작과 끝을 정의한다.
pipeline {
...
}
2) agent
파이프라인의 각 단계를 실행할 노드를 정의한다.
아래와 같이 any로 정의하면 나중에 젠킨스 클러스터를 구성했을 때 어떤 노드로 실행해도 좋다는 의미이다.
agent any
3) stages
파이프라인을 여러 단계로 나눈다.
빌드, 테스트, 배포 등 특정 작업을 수행한다.
stages {
stage('Build') {
steps {
echo 'Building...'
}
}
stage('Test') {
steps {
echo 'Testing...'
}
}
stage('Deploy') {
steps {
echo 'Deploying...'
}
}
}
4) steps
각 단계에서 실행될 구체적인 명령어를 작성한다.
steps {
echo 'Hello, World!'
}
실습
새 아이템을 pipline으로 생성한다.
젠킨스 파이프라인은 groovy 언어로 작성한다.
pipeline 구조
샘플 스크립트 저장 후
빌드하면 두 stage가 순서대로 실행된다.
파이프라인 콘솔에서 각 단계별로 출력 결과를 볼 수 있다.
deploy 단계 출력 결과
pipeline {
agent any
stages {
stage('Compile') {
steps {
echo "Compiled successfully!";
}
}
stage('Test') {
steps {
echo "Test passed successfully!";
}
}
stage('Code Analysis') {
steps {
echo "Code Analysis completed successfully!";
}
}
stage('Deploy') {
steps {
echo "Deployed successfully!";
}
}
}
post {
always {
echo "This will always run"
}
success {
echo "This will run when the run finished successfully"
}
failure {
echo "This will run if failed"
}
unstable {
echo "This will run when the run was marked as unstable"
}
changed {
echo "This will run when the state of the pipeline has changed"
}
}
}
작성 및 빌드 후 pipeline - stage view 플러그인 설치
always
항상 실행할 내용
success
정상적으로 종료되면 출력될 내용
failure
실패 시 출력될 내용
unstable
실행은 되었으나 포그라운드를 잡고 있던지 할 때 나오는 내용
changed
파이프라인 변경 시 출력될 내용
플러그인을 설치한 후 다시 stage view에 들어가면
스테이지별 소요시간과 로그를 쉽게 볼 수 있다.
이제 cpuboundapp 애플리케이션을 pipeline으로 배포해 볼 것이다.
파이프라인 하단에 pipeline syntax로 들어가면
스크립트를 쉽게 작성할 수 있다.
pipeline {
tools {
gradle "GRADLE" // Jenkins에서 설정한 Gradle의 이름
}
agent any
stages {
stage('Clone') {
steps {
git branch: 'main', url: 'https://github.com/계정명/레포지토리명.git'
}
}
stage('Build') {
steps {
sh 'pwd'
sh 'ls'
sh './gradlew clean build'
sh 'ls ./build/libs'
}
}
}
}
총 두 개의 stage를 만들었다.
clone 단계에서는 애플리케이션을 클론하고
build 단계에서는 셸 스크립트로 빌드 명령을 내린다.
이렇게 바로 빌드를 했더니 오류가 나서
gradle tool 설정을 했다.
name은 GRADLE로 작성하고
version은 8.6으로 했다.
그러고 나서 빌드에 성공했다.
그다음으로 ssh 전송을 하기 위해 ssh agent 플러그인을 설정했다.
그리고 ssh agent가 동작하기 위해 젠킨스가 비공개키를 쓰도록 설정해야 한다.
위 탭으로 들어가 credentials를 생성한다.
위 경로에서 cat으로 비밀키 확인 후 credentails에 비밀키를 저장한다.
파이프라인 스크립트에 deploy stage를 추가하고
위와 같이 작성했다.
빌드했더니 publickey 오류가 뜬다.
왜 publickey 오류가 떴냐면
스크립트에서 ssh로 jar 파일을 전송하는 구문에서
sshagent {} 블록을 사용하지 않아서였다.
현재 스크립트에서는 젠킨스 인스턴스에서 배포 인스턴스에 비공개키를 보내는 구문이 없었기 때문에
배포 인스턴스가 신뢰할 수 없는 송신자라고 파악해 jar 파일을 받을 수 없었던 것이다.
stage('Deploy') {
steps {
script {
// gradle 빌드로 생성된 jar 파일의 위치
def jarPath = 'build/libs/파일명.jar'
// 원격 서버(배포)의 IP 주소 및 배포 경로
def targetServerIp = 'xxx.xxx.xxx.xxx' // instance-2의 private 주소
def deployPath = '배포 경로'
def runAppCommand = "java -jar $deployPath/파일명.jar"
// 서버에 파일을 SCP로 전송
sshagent(['비공개키명']) { // 'server-ssh-credentials'는 Jenkins에서 설정한 credentials ID
sh "scp -o StrictHostKeyChecking=no $jarPath 계정명@$targetServerIp:$deployPath/"
}
// 원격 서버에서 애플리케이션 실행
// sshagent(['비공개키명']) {
// sh "ssh -o StrictHostKeyChecking=no ubuntu@$targetServerIp '$runAppCommand'"
// }
}
}
}
그래서 파일 전송 구문을 sshagent로 감쌌다.
배포 인스턴스에 접속해 ls를 해보니 .jar 파일이 수신된 것을 확인할 수 있었다.
이제 배포 구문 주석을 풀고 2번 인스턴스에 배포가 되나 빌드를 해볼 것이다.
2번 인스턴스의 공개주소:8080으로 접속이 되면 배포된 것이다!
def runAppCommand = "nohup java -jar $deployPath/파일명.jar > nohup.out 2>&1 &"
현재 실행 구문은 포그라운드로 실행하는데 백그라운드로 실행하려면 위와 같이 앞에 nohup을 붙여주면 된다.
표준 출력이나 오류 출력을 저장할 nohup.out 파일도 만들었다.
여전히 페이지에 접속이 잘 되며 인스턴스 디렉토리에 nohup 파일도 추가되었다.
그리고 두 인스턴스에 모두 배포하고 코드 중복을 최소화하기 위해 리팩토링을 했다.
stage('Deploy') {
steps {
script {
// gradlew 빌드로 생성된 jar 파일의 위치
def jarPath = 'build/libs/파일명.jar'
// 배포 경로
def deployPath = '경로'
def deployToServer = { serverIp ->
def runAppCommand = "nohup java -jar $deployPath/파일명.jar > nohup.out 2>&1 &"
sshagent(['credentailID']) { // 'server-ssh-credentials'는 Jenkins에서 설정한 credentials ID
// 서버에 파일을 SCP로 전송
sh "scp -o StrictHostKeyChecking=no $jarPath ubuntu@$serverIp:$deployPath/"
// 원격 서버에서 애플리케이션 실행
sh "ssh -o StrictHostKeyChecking=no ubuntu@$serverIp '$runAppCommand'"
}
}
// 원격(배포) 서버의 IP 주소
def targetServer1Ip = 'ip' // instance-1의 private 주소
def targetServer2Ip = 'ip' // instance-2의 private 주소
deployToServer(targetServer1Ip)
deployToServer(targetServer2Ip)
}
}
}
}
}
deployToServer 함수에서 사용하는 화살표(->)는 Groovy의 클로저(Closure)를 정의하는 문법이다.
클로저는 코드 블록을 함수처럼 정의할 수 있게 해주고 변수와 같은 이름으로 할당할 수 있다.
위 파이프라인 스크립트에서 클로저는 서버 IP 주소를 받아서 해당 서버에 파일을 전송하고 애플리케이션을 실행하는 기능을 수행한다.