티스토리 뷰
환경 구성
- Jenkins에 DinD방식으로 구성했고, socket을 mount해서 사용한다.


Jenkins에 git과 dockerhub credential을 넣어준다.
git은 코드를 불러와서 build하는 역할으하며, 여기서 나온 결과물을 docker hub에 image로 저장한다.

CI (Jenkins)
Jenkins Pipeline
pipeline {
agent any
environment {
VAR_NAME = "value"
}
stages {
stage('Stage Name') {
steps {
// 실행할 명령
}
}
}
post {
success {
echo "Pipeline succeeded"
}
failure {
echo "Pipeline failed"
}
}
}
Jenkins의 pipeline은 위와 같은 구조를 띈다.
- agent : 이 파이프라인을 실행할 jenkins 노드 (쉽계 얘기하면 runner를 의미하는)
- stages : 내가 수행하고 싶은 실제 Action을 순서대로 정의
- 이 안에서 stages(name), steps를 통해서 내가 원하는 실제 동작을 수행하게 한다.
- post : 파이프라인 동작 후 success/fail 에 따른 결과 처리 (slack같은 곳에 알림을 보내는)
그래서 stages에 아래처럼 git을 통해 코드를 가져오고, docker hub에 push하는 방식으로 구성하면, docker hub에 images가 build된 채로 upload 된다.
...
stage('Checkout') {
steps {
git branch: 'main',
url: 'http://172.19.117.230:3000/devops/dev-app.git', // Git에서 코드 체크아웃
credentialsId: 'gogs-crd' // Credentials ID
}
}
...
stage('Docker Build and Push') {
steps {
script {
docker.withRegistry('https://index.docker.io/v1/', 'dockerhub-crd') {
def appImage = docker.build("${DOCKER_IMAGE}:${DOCKER_TAG}")
appImage.push()
appImage.push("latest")
}
}
}
...

위에 이미지를 Kubernetes에 적용하기 위해서 사용하는 방법은 Kubernetes Secrets에 Docker Credential을 넣어야한다.(Repo가 Priavte임)
혹시...? 라는 기대감에 kubernetes에 안넣고 docker login해서 kubectl 명령어를 날려도 Image를 가져올 수는 없다.
(⎈|kind-myk8s:default) cand0@localhost /var/lib $ docker login
Authenticating with existing credentials... [Username: cand0]
i Info → To login with a different account, run 'docker logout' followed by 'docker login'
Login Succeeded
(⎈|kind-myk8s:default) cand0@localhost /var/lib $ cat <<EOF | kubectl apply -f -
...
EOF
deployment.apps/timeserver created
(⎈|kind-myk8s:default) cand0@localhost /var/lib $ k get pods
NAME READY STATUS RESTARTS AGE
timeserver-7db8b6748-lzn9p 0/1 ImagePullBackOff 0 85s
timeserver-7db8b6748-t22pc 0/1 ImagePullBackOff 0 85s
그래서 kubernetes secret에 docker hub 관련 key를 넣고 imagePullSecrets에 해당 Secrets을 넣어주면 된다.
(⎈|kind-myk8s:default) cand0@localhost /var/lib $ kubectl create secret docker-registry dockerhub-secret \
--docker-server=https://index.docker.io/v1/ \
--docker-username=$DHUSER \
--docker-password=$DHPASS
secret/dockerhub-secret created
(⎈|kind-myk8s:default) cand0@localhost /var/lib $ cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
...
spec:
...
imagePullSecrets:
- name: dockerhub-secret
EOF
deployment.apps/timeserver created
(⎈|kind-myk8s:default) cand0@localhost /var/lib $ k get pods
NAME READY STATUS RESTARTS AGE
timeserver-645cdc9bdb-gbf9k 1/1 Running 0 58s
timeserver-645cdc9bdb-wwqbd 1/1 Running 0 58s
지금까지의 설정은 Version을 Update하거나, Git에서 변경이 일어나면 Jenkins에서 Trigger하지 않고, Jenkins에서 직접 Build를 다시하고, Kubernetes에서도 Rolling을 다시해야한다.
Webhook 설정
git에 push가 되면 자동으로 Jenkins Build가 돌아가게 하기 위해서 아래 설정들을 진행한다.
Jenkins
Pipeline script from SCM으로 하면 git에서 Pipeline에 대한 Script를 같이 관리할 수 있다.

gogs(git)
gogs에서는 push같은 이벤트가 발생하면 Webhook을 설정할 수 있는데, 아래처럼 Allow List로 IP를 설정해줘야한다.

Jenkins에 SCM-Pipeline 이라는 job으로 push가 일어나면 보내게 한다.

그래서 이제는 그냥 Version만 아래처럼 바꿔도 자동으로 Jenkins에서 build가 된다.
e26293aeec28:/data/dev-app# vi VERSION
e26293aeec28:/data/dev-app# git add .
e26293aeec28:/data/dev-app# git commit -m 'test'
[main c9c959b] test
1 file changed, 1 insertion(+), 1 deletion(-)
e26293aeec28:/data/dev-app# git push
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 12 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 244 bytes | 244.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0), pack-reused 0 (from 0)
To http://172.19.117.230:3000/devops/dev-app.git
c698e5b..c9c959b main -> main


아직은 Kubernetes에서 직접 Rolling 해야한다.
CD (Jenkins로 해보기)
Jenkins에서 CD를 구성하기 위해서는 Kubernetes에 접근할 수 있어야한다.
먼저 Jenkins에 Kubeconfig를 Secrets을 넣어준다. (Jenkins에 kubectl도 넣어야함)

그렇게 저 Credential 가지고 CD를 구성할 수 있다.
아래 처럼 구성하면 되고, input message를 통해서 rollback도 구현할 수 있다.
...
stages {
...
stage('k8s deployment blue version') {
steps {
sh "kubectl apply -f ./deploy/echo-server-blue.yaml --kubeconfig $KUBECONFIG"
sh "kubectl apply -f ./deploy/echo-server-service.yaml --kubeconfig $KUBECONFIG"
}
}
...
stage('approve version switching') {
steps {
script {
returnValue = input message: 'Green switching?', ok: "Yes", parameters: [booleanParam(defaultValue: true, name: 'IS_SWITCHED')]
if (returnValue) {
sh "kubectl patch svc echo-server-service -p '{\"spec\": {\"selector\": {\"version\": \"green\"}}}' --kubeconfig $KUBECONFIG"
}
}
}
}
stage('Blue Rollback') {
steps {
script {
returnValue = input message: 'Blue Rollback?', parameters: [choice(choices: ['done', 'rollback'], name: 'IS_ROLLBACk')]
if (returnValue == "done") {
sh "kubectl delete -f ./deploy/echo-server-blue.yaml --kubeconfig $KUBECONFIG"
}
if (returnValue == "rollback") {
sh "kubectl patch svc echo-server-service -p '{\"spec\": {\"selector\": {\"version\": \"blue\"}}}' --kubeconfig $KUBECONFIG"
}
}
}
}
}
}


하면서 느꼇지만, 하나하나 스크립트를 그냥 때려박는.... ArgoCD는 뭐가 다를까?
CD(ArgoCD)
ArgoCD에서는 아래처럼 Git을 설정할 수 있다.

그러면 해당 git에 Kubernetes의 yaml파일들을 올리면 ArgoCD에서는 아래처럼 설정할 수 있다. (잘 연결되면 아래처럼 ArgoCD에서 dir을 인지한다.)

이게 원래는 ArgoCD에서 3분마다 되는데, 아까처럼 아래에 Webhook을 넣어주고, ArgoCD에 요청을 보내면 바로바로 Udpate하게 할 수 있다.

확실히 Jenkins에서는 kubectl apply 이런거를 하나씩 넣었던 것에 비해서, 간단해지는 것을 확인할 수 있다.
'스터디 > CICD' 카테고리의 다른 글
| 5주차 - Argo CD 2/3 (0) | 2025.11.14 |
|---|---|
| 4주차 - Argo CD 1/3 (1) | 2025.11.08 |
| 2주차 - Helm, Tekton (0) | 2025.10.25 |
| helm이 만든 secret에는 어떤 정보가 있을까? (0) | 2025.10.25 |
| 1주차 - Image Build (0) | 2025.10.18 |
