Jenkins란
The open source automation server, support building deploying and automating any project
CI(지속적 제공)/CD(지속적 배포) 워크플로 예제 :
Continuous Integration Server + Continuous Development, Build, Test, Deploy - Link
Jenkins
Jenkins – an open source automation server which enables developers around the world to reliably build, test, and deploy their software
www.jenkins.io
- 최신 코드 가져오기 : 개발을 위해 중앙 코드 리포지터리에서 로컬 시스템으로 애플리케이션의 최신 코드를 가져옴
- 단위 테스트 구현과 실행 : 코드 작성 전 단위 테스트 케이스를 먼저 작성
- 코드 개발 : 실패한 테스트 케이스를 성공으로 바꾸면서 코드 개발
- 단위 테스트 케이스 재실행 : 단위 테스트 케이스 실행 시 통과(성공!)
- 코드 푸시와 병합 : 개발 소스 코드를 중앙 리포지터리로 푸시하고, 코드 병합
- 코드 병합 후 컴파일 : 변경 함수 코드가 병함되면 전체 애플리케이션이 컴파일된다
- 병합된 코드에서 테스트 실행 : 개별 테스트뿐만 아니라 전체 통합 테스트를 실행하여 문제 없는지 확인
- 아티팩트 배포 : 애플리케이션을 빌드하고, 애플리케이션 서버의 프로덕션 환경에 배포
- 배포 애플리케이션의 E-E 테스트 실행 : 셀레늄 Selenium과 같은 User Interface 자동화 도구를 통해 애플리케이션의 전체 워크플로가 정상 동작하는지 확인하는 종단간 End-to-End 테스트를 실행.
소프트웨어 개발 프로세스의 다양한 단계를 자동화하는 도구로서
중앙 소스 코드 리포지터리에서 최신 코드 가져오기, 소스 코드 컴파일, 단위 테스트 실행, 산출물을 다양한 유형으로
패키징, 산출물을 여러 종류의 환경으로 배포하기 등의 기능을 제공.
젠킨스는 아파치 톰캣처럼 서블릿 컨테이너 내부에서 실행되는 서버 시스템이다.
자바로 작성됐고, 소프트웨어 개발과 관련된 다양한 도구를 지원.
- 젠킨스는 DSL Domain Specific Language (jenkins file)로 E-E 빌드 수명 주기 단계를 구축한다.
- 젠킨스는 파이프라인이라고 부르는 스크립트를 작성할 수 있는데, 이를 사용해서 각 빌드 단계마다 젠킨스가 수행할 태스트 및 하위 태스크의 순서를 정의.
- 순차적이고 종속적인 단계가 시작부터 끝까지 실행되면 최종적으로 사용자가 실행할 수 있는 빌드가 생성됨.
- 만약 빌드 프로세스를 진행하는 중에 특정 단계에서 실패가 발생하며, 이 단계의 출력 결과를 사용하는 다음 단계는 실행되지 않으며 빌드 프로세스 전체가 실패한다.
파이프라인
CD 파이프라인을 구현하고 통합할 때 사용하는 플러그인 스크립트 모음

파이프라인의 장점은 아래와 같습니다.
코드 : 애플리케이션 CI/CD 프로세스를 코드 형식으로 작성할 수 있고, 해당 코드를 중앙 리포지터리에 저장하여 팀원과 공유 및 작업 가능
내구성 : 젠킨스 서비스가 의도적으로 또는 우발적으로 재시작되더라도 문제없이 유지됨
일시 중지 가능 : 파이프라인을 실행하는 도중 사람의 승인이나 입력을 기다리기 위해 중단하거나 기다리는 것이 가능
다양성 : 분기나 반복, 병렬 처리와 같은 다양한 CI/CD 요구 사항을 지원

파이프라인은 아래와 같은 용어를 가집니다.
- 파이프라인 : 전체 빌드 프로세스를 정의하는 코드.
- 노드 node = Agent : 파이프라인을 실행하는 시스템
- Stages : 순차 작업 명세인 stage 들의 묶음
- stage : 특정 단계에서 수행되는 작업들의 정의. (옵션) agents 설정
- steps : 파이프라인의 특정 단계에서 수행되는 단일 작업을 의미.
- post : 빌드 후 조치, 일반적으로 stages 작업이 끝난 후 추가적인 steps/step
파이프라인 3가지 형태
파이프라인은 아래와 같이 구성됩니다.
- Pipeline script : 일반적인 방식으로 Jenkins 파이프라인을 생성하여 Shell Script를 직접 생성하여 빌드하는 방식
- Through the classic UI - you can enter a basic Pipeline directly in Jenkins through the classic UI.
- Pipeline script from SCM :
- 사전 작성한 JenkinsFile을 형상관리 저장소에 보관하고, 빌드 시작 시 파이프라인 프로젝트에서 호출 실행하는 방식
- ex. Git 내 groovy 파일
- Blue Ocean 기반 : UI기반하여 시각적으로 파이프라인을 구성하면, JenkinsFile이 자동으로 생성되어 실행되는 방식

- 파이프라인 2가지 구문 : 선언형 파이프라인(권장)과 스크립트형 파이프라인
- 선언형 파이프라인 : 쉽게 작성 가능, 최근 문법이고 젠킨스에서 권장하는 방법, step 필수!
- 스크립트형 파이프라인 : 커스텀 작업에 용이, 복잡하여 난이도가 높음, step은 필수 아닙니다.
https://velog.io/@kku64r/pipeline
[CI/CD] Jenkins Pipeline 정리
CI/CD 파이프라인은 신버전의 SW를 제공하기 위해 수행해야 할 일련의 단계로 통합 및 테스트 단계와 배포 단계의 모니터링 및 자동화를 도입하여 개발 프로세스를 개선한다. CI/CD 구성 툴로 대표
velog.io
선언형 파이프라인
pipeline {
agent any # Execute this Pipeline or any of its stages, on any available agent.
stages {
stage('Build') { # Defines the "Build" stage.
steps {
// # Perform some steps related to the "Build" stage.
}
}
stage('Test') {
steps {
//
}
}
stage('Deploy') {
steps {
//
}
}
}
}
스크립트형 파이프라인
node { # Execute this Pipeline or any of its stages, on any available agent.
stage('Build') { # Defines the "Build" stage. stage blocks are optional in Scripted Pipeline syntax. However, implementing stage blocks in a Scripted Pipeline provides clearer visualization of each stage's subset of tasks/steps in the Jenkins UI.
// # Perform some steps related to the "Build" stage.
}
stage('Test') {
//
}
stage('Deploy') {
//
}
}
파이프라인 실습
새로운 Item > (이름 : First-Pipeline) > Pipeline


저장하고 지금빌드를 눌러 실행해봅니다.
실행된 #1 파이프라인 > Console Output 로그를 보면 실행 결과를 확인할 수 있습니다.

아래 처럼 수정 후 확인: 환경변수 사용, 문자열 보간 → Console Output 확인
pipeline {
agent any
environment {
CC = 'clang'
}
stages {
stage('Example') {
environment {
AN_ACCESS_KEY = 'abcdefg'
}
steps {
echo "${CC}";
sh 'echo ${AN_ACCESS_KEY}'
}
}
}
}
아래 처럼 수정 후 확인: 파이프라인 빌드 시작(트리거) → Console Output 확인
pipeline {
agent any
triggers {
cron('H */4 * * 1-5')
}
stages {
stage('Example') {
steps {
echo 'Hello World'
}
}
}
}
아래 처럼 수정 후 확인: 파라미터와 함께 빌드 → Console Output 확인 ⇒ 다시 한번 더 빌드 클릭 (변수 입력 칸 확인)
pipeline {
agent any
parameters {
string(name: 'PERSON', defaultValue: 'Mr Jenkins', description: 'Who should I say hello to?')
text(name: 'BIOGRAPHY', defaultValue: '', description: 'Enter some information about the person')
booleanParam(name: 'TOGGLE', defaultValue: true, description: 'Toggle this value')
choice(name: 'CHOICE', choices: ['One', 'Two', 'Three'], description: 'Pick something')
password(name: 'PASSWORD', defaultValue: 'SECRET', description: 'Enter a password')
}
stages {
stage('Example') {
steps {
echo "Hello ${params.PERSON}"
echo "Biography: ${params.BIOGRAPHY}"
echo "Toggle: ${params.TOGGLE}"
echo "Choice: ${params.CHOICE}"
echo "Password: ${params.PASSWORD}"
}
}
}
}

- 아래 처럼 수정 후 확인: post (빌드 후 조치) → Console Output 확인
- always: 항상 실행
- changed: 현재 빌드의 상태가 이번 빌드의 상태와 달라졌다면 실행
- success: 현재 빌드가 성공했다면 실행
- failure: 현재 빌드가 실패했다면 실행
- unstable: 현재 빌드의 상태가 불안하다면 실행
pipeline {
agent any
stages {
stage('Example') {
steps {
echo 'Hello World'
}
}
}
post {
always {
echo 'I will always say Hello again!'
}
}
}
아래 처럼 수정 후 확인
pipeline {
agent any
stages {
stage('Compile') {
steps {
echo "Compiled successfully!";
}
}
stage('JUnit') {
steps {
echo "JUnit passed successfully!";
}
}
stage('Code Analysis') {
steps {
echo "Code Analysis completed successfully!";
}
}
stage('Deploy') {
steps {
echo "Deployed successfully!";
}
}
}
}
Item : My-First-Pipeline , Pipeline(Pipeline script - 아래 내용 추가 복붙) post 항목 : 빌드 성공 실패 등 메시지 출력
pipeline {
agent any
stages {
stage('Compile') {
steps {
echo "Compiled successfully!";
}
}
stage('JUnit') {
steps {
echo "JUnit 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"
}
}
}
stage view가 보이지 않아서 Jenkins 관리 > 플러그인 > Stage view를 설치해주었습니다.

Declarative: Post Actions 가 이번 파이프라인에서 생성된 것을 확인할 수 있습니다.

Jenkins CI Pipeline
플러그인 및 자격증명 설정을 진행합니다.
아래 3개 플러그인을 설치합니다.
Pipeline Stage View
Docker Pipeline
Gogs : Webhook Plugin
그 후 Jenkins 관리 > Credentials 에서 Gogs와 Docker Hub 토큰을 등록해줍니다.
해당 정보는 파이프라인에서 사용됩니다.
Jenkins 관리 → Credentials → Globals → Add Credentials
- Gogs Repo 자격증명 설정 : gogs-crd
- Kind : Username with password
- Username : devops
- Password : <Gogs 토큰>
- ID : gogs-crd
- 도커 허브 자격증명 설정 : dockerhub-crd
- Kind : Username with password
- Username : <도커 계정명>
- Password : <도커 계정 암호 혹은 토큰>
- ID : dockerhub-crd

Jenkins Item 생성
item name(pipeline-ci) > pipeline 으로생성해준뒤 아래 스크립트를 넣어줍니다.
- Pipeline script : 아래 빨간색 부분은 자신의 환경에 맞게 수정 할 것!
- appImage.push 는 각각 ‘버전 tag, latest tag’ 수행한다
pipeline {
agent any
environment {
DOCKER_IMAGE = '<자신의 도커 허브 계정>/dev-app' // Docker 이미지 이름
}
stages {
stage('Checkout') {
steps {
git branch: 'main',
url: 'http://gogs:3000/devops/dev-app.git', // Git에서 코드 체크아웃
credentialsId: 'gogs-crd' // Credentials ID
}
}
stage('Read VERSION') {
steps {
script {
// VERSION 파일 읽기
def version = readFile('VERSION').trim()
echo "Version found: ${version}"
// 환경 변수 설정
env.DOCKER_TAG = version
}
}
}
stage('Docker Build and Push') {
steps {
script {
docker.withRegistry('https://index.docker.io/v1/', 'dockerhub-crd') {
// DOCKER_TAG 사용
def appImage = docker.build("${DOCKER_IMAGE}:${DOCKER_TAG}")
appImage.push()
appImage.push("latest")
}
}
}
}
}
post {
success {
echo "Docker image ${DOCKER_IMAGE}:${DOCKER_TAG} has been built and pushed successfully!"
}
failure {
echo "Pipeline failed. Please check the logs."
}
}
}
'http://gogs:3000/devops/dev-app.git'
여기서 gogs 부분을 IP로 넣어도됩니다.
실습에서는 gogs 는 Docker DNS 상에서 자동으로 172.19.0.3 으로 매핑되므로 그대로 사용하겠습니다.
지금 빌드 후 콘솔 Output을 확인해봅니다.

빌드된 이미지가 도커허브에 업로드 된것도 확인할 수 있습니다.

Deploying to Kubernetes
# 디플로이먼트 오브젝트 배포 : 리플리카(파드 2개), 컨테이너 이미지 >> 아래 도커 계정 부분만 변경해서 배포해보자
DHUSER=<도커 허브 계정명>
DHUSER=gasida
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: timeserver
spec:
replicas: 2
selector:
matchLabels:
pod: timeserver-pod
template:
metadata:
labels:
pod: timeserver-pod
spec:
containers:
- name: timeserver-container
image: docker.io/$DHUSER/dev-app:0.0.1
livenessProbe:
initialDelaySeconds: 30
periodSeconds: 30
httpGet:
path: /healthz
port: 80
scheme: HTTP
timeoutSeconds: 5
failureThreshold: 3
successThreshold: 1
EOF
watch -d kubectl get deploy,rs,pod -o wide
# 배포 상태 확인 : kube-ops-view 웹 확인
kubectl get events -w --sort-by '.lastTimestamp'
kubectl get deploy,pod -o wide
kubectl describe pod
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 53s default-scheduler Successfully assigned default/timeserver-7cf7db8f6c-mtvn7 to myk8s-worker
Normal BackOff 19s (x2 over 50s) kubelet Back-off pulling image "docker.io/gasida/dev-app:latest"
Warning Failed 19s (x2 over 50s) kubelet Error: ImagePullBackOff
Normal Pulling 4s (x3 over 53s) kubelet Pulling image "docker.io/gasida/dev-app:latest"
Warning Failed 3s (x3 over 51s) kubelet Failed to pull image "docker.io/gasida/dev-app:latest": failed to pull and unpack image "docker.io/gasida/dev-app:latest": failed to resolve reference "docker.io/gasida/dev-app:latest": pull access denied, repository does not exist or may require authorization: server message: insufficient_scope: authorization failed
Warning Failed 3s (x3 over 51s) kubelet Error: ErrImagePull
TROUBLESHOOTING : image pull error (ErrImagePull / ErrImagePullBackOff)
- 보통 컨테이너 이미지 정보를 잘못 기입하는 경우에 발생
- 혹은 이미지 저장소에 이미지가 없거나, 이미지 가져오는 자격 증명이 없는 경우에 발생
도커허브 비공개 이미지 pull을 위한 쿠버네티스 시크릿 설정을 진해하겠습니다.
쿠버네티스에서 imagePullSecrets 로 등록된 Secret 은
Pod가 Private Registry (예: Docker Hub, Harbor, Nexus 등)에서 이미지를 pull할 때 사용되는 도커 로그인 정보입니다.
즉, kubectl create secret docker-registry 명령은
docker login 과 동등한 인증 JSON 파일(.docker/config.json) 을 Secret으로 만들어줍니다
- --docker-server: DockerHub 주소 (항상 https://index.docker.io/v1/)
- --docker-username: 로그인 ID
- --docker-password: PAT 또는 비밀번호
- Secret 타입은 자동으로 kubernetes.io/dockerconfigjson 으로 생성됩니다.
# k8s secret : 도커 자격증명 설정
kubectl get secret -A # 생성 시 타입 지정
DHUSER=<도커 허브 계정>
DHPASS=<도커 허브 암호 혹은 토큰>
echo $DHUSER $DHPASS
DHUSER=gasida
DHPASS=dckr_pat_JLKruUO5Ee8BGWhqxgRz50_jmT0
echo $DHUSER $DHPASS
kubectl create secret docker-registry dockerhub-secret \
--docker-server=https://index.docker.io/v1/ \
--docker-username=$DHUSER \
--docker-password=$DHPASS
# 확인 : base64 인코딩 확인
kubectl get secret
kubectl get secrets -o yaml | kubectl neat
kubectl get secret dockerhub-secret -o jsonpath='{.data.\.dockerconfigjson}' | base64 -d | jq
# 디플로이먼트 오브젝트 업데이트 : 시크릿 적용 >> 아래 도커 계정 부분만 변경해서 배포해보자
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: timeserver
spec:
replicas: 2
selector:
matchLabels:
pod: timeserver-pod
template:
metadata:
labels:
pod: timeserver-pod
spec:
containers:
- name: timeserver-container
image: docker.io/$DHUSER/dev-app:0.0.1
livenessProbe:
initialDelaySeconds: 30
periodSeconds: 30
httpGet:
path: /healthz
port: 80
scheme: HTTP
timeoutSeconds: 5
failureThreshold: 3
successThreshold: 1
imagePullSecrets:
- name: dockerhub-secret
EOF
watch -d kubectl get deploy,rs,pod -o wide
# 확인
kubectl get events -w --sort-by '.lastTimestamp'
kubectl get deploy,pod
동작원리는 아래와 같습니다.
- kubelet이 Pod를 스케줄링할 때 imagePullSecrets 에 지정된 Secret을 읽음
- Secret 안의 인증정보를 /root/.docker/config.json 형태로 임시 파일로 생성
- 그 자격증명으로 docker pull 수행
- 이미지 pull 성공 후 Pod 생성
Publishing your Service
# 서비스 생성
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
name: timeserver
spec:
selector:
pod: timeserver-pod
ports:
- port: 80
targetPort: 80
protocol: TCP
nodePort: 30000
type: NodePort
EOF
#
kubectl get service,ep timeserver -owide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/timeserver NodePort 10.96.236.37 <none> 80:30000/TCP 25s pod=timeserver-pod
NAME ENDPOINTS AGE
endpoints/timeserver 10.244.1.2:80,10.244.2.2:80,10.244.3.2:80 25s
# Service(NodePort)로 접속 확인 "노드IP:NodePort"
curl http://127.0.0.1:30000
curl http://127.0.0.1:30000
curl http://127.0.0.1:30000/healthz
# 반복 접속 해두기 : 부하분산 확인
while true; do curl -s --connect-timeout 1 http://127.0.0.1:30000 ; sleep 1 ; done
for i in {1..100}; do curl -s http://127.0.0.1:30000 | grep name; done | sort | uniq -c | sort -nr
# 파드 복제복 증가 : service endpoint 대상에 자동 추가
kubectl scale deployment timeserver --replicas 4
kubectl get service,ep timeserver -owide
# 반복 접속 해두기 : 부하분산 확인
while true; do curl -s --connect-timeout 1 http://127.0.0.1:30000 ; sleep 1 ; done
for i in {1..100}; do curl -s http://127.0.0.1:30000 | grep name; done | sort | uniq -c | sort -nr
Updating your application : k8s Deploying an application with Jenkins(pipeline-ci)

샘플 앱 server.py 코드 변경 → 젠킨스(지금 빌드 실행) : 새 0.0.2 버전 태그로 컨테이너 이미지 빌드 → 컨테이너 저장소 Push ⇒ k8s deployment 업데이트 배포
# VERSION 변경 : 0.0.2
# server.py 변경 : 0.0.2
git add . && git commit -m "VERSION $(cat VERSION) Changed" && git push -u origin main
코드에서 위와같이 push 해도 되지만 gogs 웹에 접근해서 직접 수정하겠습니다.


Jenkins 빌드를 직접 실행하고 아래 명령어를 수행합니다.


# 반복 접속 해두기 : 부하분산 확인
while true; do curl -s --connect-timeout 1 http://127.0.0.1:30000 ; sleep 1 ; done
for i in {1..100}; do curl -s http://127.0.0.1:30000 | grep name; done | sort | uniq -c | sort -nr
#
kubectl set image deployment timeserver timeserver-container=$DHUSER/dev-app:0.0.2 && watch -d "kubectl get deploy,ep timeserver -owide; echo; kubectl get rs,pod"
# 롤링 업데이트 확인
watch -d kubectl get deploy,rs,pod,svc,ep -owide
kubectl get deploy,rs,pod,svc,ep -owide
# kubectl get deploy $DEPLOYMENT_NAME
kubectl get deploy timeserver
kubectl get pods -l pod=timeserver-pod
#
curl http://127.0.0.1:30000

Gogs Webhooks 설정
Jenkins Job Trigger를 위해 Gogs Webhook을 설정합니다.
gogs 에 conf/app.ini 파일 수정 후 컨테이너 재기동
[security]
INSTALL_LOCK = true
SECRET_KEY = j2xaUPQcbAEwpIu
LOCAL_NETWORK_ALLOWLIST = 192.168.254.110 # 각자 자신의 IP

docker compose restart gogs
gogs 에 Webhooks 설정
gogs 웹에 접근합니다.
Jenkins job Trigger - [dev-app] - Setting → Webhooks → Gogs 클릭

- Payload URL : http://192.168.254.110:8080/gogs-webhook/?job=SCM-Pipeline/ # 각자 자신의 IP
- Content Type : application/json
- Secret : qwe123
- When should this webhook be triggered? : Just the push event
- Active : Check
⇒ Add webhook → Test Delivery 시도 시, 현재는 Jenkins 미설정 상태로 404 실패
http://jenkins:8080/gogs-webhook/?job=SCM-Pipeline/ 를 사용하기 위해서 gogs 설정을 추가해줍니다.
[security]
INSTALL_LOCK = true
SECRET_KEY = NJUK15LRPdc1PVE
LOCAL_NETWORK_ALLOWLIST = jenkins,127.0.0.1,localhost
docker compose restart gogs

Jenkins Item 생성(Pipeline)
item name(SCM-Pipeline)
- GitHub project : http://<자신의 IP>:3000/<Gogs 계정명>/dev-app ← .git 은 제거
- GitHub project : http://192.168.254.110:3000/devops/dev-app
- Use Gogs secret : qwe123
- Build Triggers : Build when a change is pushed to Gogs 체크
- Pipeline script from SCM
- SCM : Git
- Repo URL(http://<mac IP>:3000/<Gogs 계정명>/dev-app)
- Credentials(devops/***)
- Branch(*/main)
- Script Path : Jenkinsfile
- SCM : Git
파이프라인을 새로 생성 후
이전에 설치한 gogs webhook 설정을 진행합니다.


Jenkinsfile 작성 후 Git push
Jenkinsfile 및 소스 코드 작업 -> 0.0.3
# Jenkinsfile 빈 파일 작성
tree
├── Dockerfile
├── README.md
├── VERSION
└── server.py
touch Jenkinsfile
# VERSION 파일 : 0.0.3 수정
# server.py 파일 : 0.0.3 수정
IDE(VSCODE..) 로 Jenkinsfile 파일 작성
pipeline {
agent any
environment {
DOCKER_IMAGE = '<자신의 도커 허브 계정>/dev-app' // Docker 이미지 이름
}
stages {
stage('Checkout') {
steps {
git branch: 'main',
url: 'http://<자신의 IP>:3000/devops/dev-app.git', // Git에서 코드 체크아웃
credentialsId: 'gogs-crd' // Credentials ID
}
}
stage('Read VERSION') {
steps {
script {
// VERSION 파일 읽기
def version = readFile('VERSION').trim()
echo "Version found: ${version}"
// 환경 변수 설정
env.DOCKER_TAG = version
}
}
}
stage('Docker Build and Push') {
steps {
script {
docker.withRegistry('https://index.docker.io/v1/', 'dockerhub-crd') {
// DOCKER_TAG 사용
def appImage = docker.build("${DOCKER_IMAGE}:${DOCKER_TAG}")
appImage.push()
appImage.push("latest")
}
}
}
}
}
post {
success {
echo "Docker image ${DOCKER_IMAGE}:${DOCKER_TAG} has been built and pushed successfully!"
}
failure {
echo "Pipeline failed. Please check the logs."
}
}
}
작성된 파일 push
git add . && git commit -m "VERSION $(cat VERSION) Changed" && git push -u origin main
gogs 웹에 접근하여 설정 - webhook을 확인하면 정상적으로 200 코드를 확인 가능합니다.

gogs 웹훅이 연결된 Jenkins도 정상적으로 동작합니다.

마찬가지로 도커 허브도 정상동작합니다.
현재는 배포가 되지않으므로 직접 수동적용합니다.
# 신규 버전 적용
kubectl set image deployment timeserver timeserver-container=$DHUSER/dev-app:0.0.3 && while true; do curl -s --connect-timeout 1 http://127.0.0.1:30000 ; sleep 1 ; done
# 확인
watch -d "kubectl get deploy,ep timeserver; echo; kubectl get rs,pod"

'devops > cicd' 카테고리의 다른 글
| [CI/CD] 5주차 - Argo CD 2/3 (0) | 2025.11.16 |
|---|---|
| [CI/CD] 4주차 - Argo CD 1/3 (1) (0) | 2025.11.09 |
| [CI/CD] 3주차 - 실습환경구성 (0) | 2025.11.02 |
| [CI/CD] 2주차 - Tekton (0) | 2025.10.25 |
| [CI/CD] 2주차 - Helm (0) | 2025.10.25 |