해당 글은 일프로 님의 인프런 강의 쿠버네티스 어나더 클래스 (지상편) - Sprint 1, 2의 내용을 정리한 글입니다.
해당 글에 사용된 내용, 사진 및 그림은 모두 강의와 강의 자료에 포함된 내용입니다.
pipeline {
agent any
tools {
gradle 'gradle-7.6.1'
jdk 'jdk-17'
}
// 빌드 시 같이 지정할 파라미터
parameters {
choice(choices: ['dev', 'qa', 'prod'], name: 'PROFILE')
}
environment {
// 본인의 username으로 하실 분은 수정해주세요.
DOCKERHUB_USERNAME = '1pro'
GITHUB_URL = 'https://github.com/k8s-1pro/kubernetes-anotherclass-sprint2.git'
// 실습 넘버링
CLASS_NUM = '2222'
}
stages {
stage('소스파일 체크아웃') {
steps {
// 소스코드를 가져올 Github 주소
git branch: 'main', url: 'https://github.com/k8s-1pro/kubernetes-anotherclass-api-tester.git'
}
}
stage('소스 빌드') {
steps {
// 755권한 필요 (윈도우에서 Git으로 소스 업로드시 권한은 644)
echo "chmod +x ./gradlew"
echo "gradle clean build"
}
}
stage('릴리즈파일 체크아웃') {
steps {
checkout scmGit(branches: [[name: '*/main']],
extensions: [[$class: 'SparseCheckoutPaths',
sparseCheckoutPaths: [[path: "/${CLASS_NUM}"]]]],
userRemoteConfigs: [[url: "${GITHUB_URL}"]])
}
}
stage('컨테이너 빌드') {
steps {
// jar 파일 복사
echo "cp ./build/libs/app-0.0.1-SNAPSHOT.jar ./${CLASS_NUM}/build/docker/app-0.0.1-SNAPSHOT.jar"
// 도커 빌드
echo "docker build -t ${DOCKERHUB_USERNAME}/api-tester:v1.0.0 ./${CLASS_NUM}/build/docker"
}
}
stage('컨테이너 업로드') {
steps {
// DockerHub로 이미지 업로드
echo "docker push ${DOCKERHUB_USERNAME}/api-tester:v1.0.0"
}
}
stage('커스터마이즈 템플릿 확인') {
steps {
// K8S 배포
sh "kubectl kustomize ./${CLASS_NUM}/deploy/kustomize/api-tester/overlays/${params.PROFILE}"
}
}
stage('커스터마이즈 배포') {
steps {
// K8S 배포
input message: '배포 시작', ok: "Yes"
// 빌드 시 지정한 PROFILE
// kubectl을 통해 배포 진행
sh "kubectl apply -f ./${CLASS_NUM}/deploy/kubectl/namespace-${params.PROFILE}.yaml"
// -k 옵션을 통해 Kustomize 배포
sh "kubectl apply -k ./${CLASS_NUM}/deploy/kustomize/api-tester/overlays/${params.PROFILE}"
}
}
}
}
pipeline {
agent any
tools {
gradle 'gradle-7.6.1'
jdk 'jdk-17'
}
parameters {
choice(choices: ['dev', 'qa', 'prod'], name: 'PROFILE')
}
environment {
// 본인의 username으로 하실 분은 수정해주세요.
DOCKERHUB_USERNAME = '1pro'
GITHUB_URL = 'https://github.com/k8s-1pro/kubernetes-anotherclass-sprint2.git'
// 실습 넘버링
CLASS_NUM = '2223'
}
stages {
stage('소스파일 체크아웃') {
steps {
// 소스코드를 가져올 Github 주소
git branch: 'main', url: 'https://github.com/k8s-1pro/kubernetes-anotherclass-api-tester.git'
}
}
stage('소스 빌드') {
steps {
// 755권한 필요 (윈도우에서 Git으로 소스 업로드시 권한은 644)
echo "chmod +x ./gradlew"
echo "gradle clean build"
}
}
stage('릴리즈파일 체크아웃') {
steps {
checkout scmGit(branches: [[name: '*/main']],
extensions: [[$class: 'SparseCheckoutPaths',
sparseCheckoutPaths: [[path: "/${CLASS_NUM}"]]]],
userRemoteConfigs: [[url: "${GITHUB_URL}"]])
}
}
stage('컨테이너 빌드') {
steps {
// jar 파일 복사
echo "cp ./build/libs/app-0.0.1-SNAPSHOT.jar ./${CLASS_NUM}/build/docker/app-0.0.1-SNAPSHOT.jar"
// 도커 빌드
echo "docker build -t ${DOCKERHUB_USERNAME}/api-tester:v1.0.0 ./${CLASS_NUM}/build/docker"
}
}
stage('컨테이너 업로드') {
steps {
// DockerHub로 이미지 업로드
echo "docker push ${DOCKERHUB_USERNAME}/api-tester:v1.0.0"
}
}
stage('헬름 템플릿 확인') {
steps {
// K8S 배포
// -f 옵션을 통해 values-{profile}.yaml을 만들어서 배포 환경마다 별도의 값들을 세팅하는 방식
sh "helm template api-tester-${CLASS_NUM} ./${CLASS_NUM}/deploy/helm/api-tester" +
" -f ./${CLASS_NUM}/deploy/helm/api-tester/values-${params.PROFILE}.yaml -n anotherclass-222-${params.PROFILE}"
// 배포 시마다 값을 동적으로 지정해야 하는 경우에 set 사용
// --set replicaCount='3' --set port='80' --set profile='dev' --set nodeport='32223'
}
}
stage('헬름 배포') {
steps {
input message: '배포 시작', ok: "Yes"
// 네임스페이스를 분리해 배포
sh "kubectl apply -f ./${CLASS_NUM}/deploy/kubectl/namespace-${params.PROFILE}.yaml"
// 최초 실행이면 install 아니면 upgrade
sh "helm upgrade api-tester-${CLASS_NUM} ./${CLASS_NUM}/deploy/helm/api-tester" +
" -f ./${CLASS_NUM}/deploy/helm/api-tester/values-${params.PROFILE}.yaml" +
" -n anotherclass-222-${params.PROFILE} --install" // --create-namespace
}
}
}
}
// Docker 사용
steps {
script{
withCredentials([usernamePassword(credentialsId: 'docker_password', passwordVariable: 'PASSWORD', usernameVariable: 'USERNAME')]) {
sh "echo " + '${PASSWORD}' + " | docker login -u " + '${USERNAME}' + " --password-stdin"
// Kubernetes config 사용
steps {
withCredentials([file(credentialsId: 'k8s_master_config', variable: 'KUBECONFIG')]) { // 암호화로 관리된 config가 들어감
sh "kubectl apply -f ./2224/deploy/kubectl/namespace-dev.yaml --kubeconfig " + '${KUBECONFIG}'
sh "helm upgrade api-tester-2224 ./2224/deploy/helm/api-tester -f ./2224/deploy/helm/api-tester/values-dev.yaml" +
" -n anotherclass-222-dev --install --kubeconfig " + '${KUBECONFIG}'
# 도커 로그아웃
docker logout
# 도커 로그인 정보 삭제 하ㅗㄱ인
cat ~/.docker/config.json
# kubeconfig 파일명 변경
mv ~/.kube/config ~/.kube/config_bak
# 인증서인 kubeconfig 파일을 찾을 수 없으므로 실패
kubectl get pods -A
environment {
APP_VERSION = '1.0.1'
BUILD_DATE = sh(script: "echo `date +%y%m%d.%d%H%M`", returnStdout: true).trim()
TAG = "${APP_VERSION}-" + "${BUILD_DATA}"
stage('컨테이너 빌드 및 업로드') {
steps {
script{
// 도커 빌드
sh "docker build ./2224/build/docker -t 1pro/api-tester:${TAG}"
sh "docker push 1pro/api-tester:${TAG}"
stage('헬름 배포') {
steps {
withCredentials([file(credentialsId: 'k8s_master_config', variable: 'KUBECONFIG')]) {
sh "helm upgrade api-tester-2224 ./2224/deploy/helm/api-tester -f ./2224/deploy/helm/api-tester/values-dev.yaml" +
...
" --set image.tag=${TAG}" // Deployment의 Image에 태그 값 주입
docker tag 1pro/api-tester:1.0.1-231220.171834 1pro/api-tester:latest
docker push 1pro/api-tester:latest
stage('컨테이너 빌드 및 업로드') {
steps {
script{
// 도커 빌드
sh "docker build ./${CLASS_NUM}/build/docker -t ${DOCKERHUB_USERNAME}/api-tester:${TAG}"
sh "docker push ${DOCKERHUB_USERNAME}/api-tester:${TAG}"
sh "docker rmi ${DOCKERHUB_USERNAME}/api-tester:${TAG}" // 이미지 삭제
...
}
}
}
stage('네임스페이스 생성') { // 배포시 apply로 Namespace 생성 or 배포와 별개로 미리 생성 (추후 삭제시 별도 삭제)
steps {
withCredentials([file(credentialsId: 'k8s_master_config', variable: 'KUBECONFIG')]) {
sh "kubectl apply -f ./2224/deploy/kubectl/namespace-dev.yaml --kubeconfig " + '"${KUBECONFIG}"'
...
stage('헬름 배포') {
steps {
apiVersion: apps/v1
kind: Deployment
spec:
template:
metadata:
annotations:
rollme: {{ randAlphaNum 5 | quote }} // 항상 새 배포를 위해 랜덤값 적용
stage('헬름 배포') {
steps {
withCredentials([file(credentialsId: 'k8s_master_config', variable: 'KUBECONFIG')]) {
sh "helm upgrade api-tester-2224 ./2224/deploy/helm/api-tester -f ./2224/deploy/helm/api-tester/values-dev.yaml" +
...
" --wait --timeout=10m" + // 최대 10분으로 설정
# GC 속성 관련 설정 파일
vi /var/lib/kubelet/config.yaml
# 변경한 설정 적용을 위한 재시작
systemctl restart kubelet
pipeline {
agent any
tools {
gradle 'gradle-7.6.1'
jdk 'jdk-17'
}
parameters {
// 배포 환경 선택
choice(choices: ['dev', 'qa', 'prod'], name: 'PROFILE', description: '배포 환경 선택')
}
environment {
// 본인의 username으로 하실 분은 수정해주세요.
DOCKERHUB_USERNAME = '1pro'
GITHUB_URL = 'https://github.com/k8s-1pro/kubernetes-anotherclass-sprint2.git'
// [2] 잦은 배포 - versioning 무의미, 계획된 배포 - versioning 필수
APP_VERSION = '1.0.1'
BUILD_DATE = sh(script: "echo `date +%y%m%d.%d%H%M`", returnStdout: true).trim()
TAG = "${APP_VERSION}-" + "${BUILD_DATE}"
// 실습 넘버링
CLASS_NUM = '2224'
}
stages {
stage('소스파일 체크아웃') {
steps {
// 소스코드를 가져올 Github 주소
git branch: 'main', url: 'https://github.com/k8s-1pro/kubernetes-anotherclass-api-tester.git'
}
}
stage('소스 빌드') {
steps {
// 실제 소스 빌드 수행
// 755권한 필요 (윈도우에서 Git으로 소스 업로드시 권한은 644)
sh "chmod +x ./gradlew"
sh "gradle clean build"
}
}
stage('릴리즈파일 체크아웃') {
steps {
checkout scmGit(branches: [[name: '*/main']],
extensions: [[$class: 'SparseCheckoutPaths',
sparseCheckoutPaths: [[path: "/${CLASS_NUM}"]]]],
userRemoteConfigs: [[url: "${GITHUB_URL}"]])
}
}
stage('컨테이너 빌드 및 업로드') {
steps {
// jar 파일 복사
sh "cp ./build/libs/app-0.0.1-SNAPSHOT.jar ./${CLASS_NUM}/build/docker/app-0.0.1-SNAPSHOT.jar"
script{
// 도커 빌드 - [1] 중요 데이터 암호화 관리
withCredentials([usernamePassword(credentialsId: 'docker_password', passwordVariable: 'PASSWORD', usernameVariable: 'USERNAME')]) {
sh "echo " + '${PASSWORD}' + " | docker login -u " + '${USERNAME}' + " --password-stdin"
}
if (DOCKERHUB_USERNAME == "1pro") {
TAG = "1.0.1-231220.175735" // 1pro useranme 수강생을 위한 고정 태그명
// 도커 빌드
sh "docker build ./${CLASS_NUM}/build/docker -t ${DOCKERHUB_USERNAME}/api-tester:${TAG}"
} else {
// 도커 빌드
sh "docker build ./${CLASS_NUM}/build/docker -t ${DOCKERHUB_USERNAME}/api-tester:${TAG}"
// [2] 잦은 배포 - versioning 무의미, 계획된 배포 - versioning 필수
sh "docker push ${DOCKERHUB_USERNAME}/api-tester:${TAG}"
}
// [3] 업로드 후 CI/CD Server에 만들어진 이미지 삭제
sh "docker rmi ${DOCKERHUB_USERNAME}/api-tester:${TAG}"
}
}
post {
always {
sh "docker logout"
}
}
}
// [4] 네임스페이스는 배포와 별도로 관리
stage('네임스페이스 생성') { // 배포시 apply로 Namespace 생성 or 배포와 별개로 미리 생성 (추후 삭제시 별도 삭제)
steps {
// kubectl 명령 사용 - [1] 중요 데이터 암호화 관리
withCredentials([file(credentialsId: 'k8s_master_config', variable: 'KUBECONFIG')]) {
sh "kubectl apply -f ./${CLASS_NUM}/deploy/kubectl/namespace-${params.PROFILE}.yaml --kubeconfig " + '${KUBECONFIG}'
}
}
}
stage('헬름 배포') {
steps {
// helm 명령 사용 - [1] 중요 데이터 암호화 관리
// Jenkins 빌드 전 profile 동적 지정
withCredentials([file(credentialsId: 'k8s_master_config', variable: 'KUBECONFIG')]) {
sh "helm upgrade api-tester-${CLASS_NUM} ./${CLASS_NUM}/deploy/helm/api-tester -f ./${CLASS_NUM}/deploy/helm/api-tester/values-${params.PROFILE}.yaml" +
" -n anotherclass-222-${params.PROFILE} --install --kubeconfig " + '${KUBECONFIG}' +
// [5] Helm 부가기능
" --wait --timeout=10m" + // 최대 10분으로 설정
// [2] 잦은 배포 - versioning 무의미, 계획된 배포 - versioning 필수
" --set image.tag=${TAG}" +
" --set image.repository=${DOCKERHUB_USERNAME}/api-tester"
}
}
}
}
}