실습환경
Jenkins, gogs 컨테이너 생성
# 작업 디렉토리 생성 후 이동
mkdir cicd-labs
cd cicd-labs
#
cat <<EOT > docker-compose.yaml
services:
jenkins:
container_name: jenkins
image: jenkins/jenkins
restart: unless-stopped
networks:
- cicd-network
ports:
- "8080:8080"
- "50000:50000"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- jenkins_home:/var/jenkins_home
gogs:
container_name: gogs
image: gogs/gogs
restart: unless-stopped
networks:
- cicd-network
ports:
- "10022:22"
- "3000:3000"
volumes:
- gogs-data:/data
volumes:
jenkins_home:
gogs-data:
networks:
cicd-network:
driver: bridge
EOT
# 배포
docker compose up -d
docker compose ps
# 기본 정보 확인
for i in gogs jenkins ; do echo ">> container : $i <<"; docker compose exec $i sh -c "whoami && pwd"; echo; done
# 도커를 이용하여 각 컨테이너로 접속
docker compose exec jenkins bash
exit
docker compose exec gogs bash
exit
세부 설정은 링크 참조
Repo 생성
- Repo Name : Dev-app2, ops-deploy
- Visibility : Private
- .gitignore : python
생성한 Repo에 코드 업로드
- Server.py
from http.server import ThreadingHTTPServer, BaseHTTPRequestHandler
from datetime import datetime
import socket
class RequestHandler(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header('Content-type', 'text/plain')
self.end_headers()
now = datetime.now()
hostname = socket.gethostname()
response_string = now.strftime("The time is %-I:%M:%S %p, VERSION 0.0.1\n")
response_string += f"Server hostname: {hostname}\n"
self.wfile.write(bytes(response_string, "utf-8"))
def startServer():
try:
server = ThreadingHTTPServer(('', 80), RequestHandler)
print("Listening on " + ":".join(map(str, server.server_address)))
server.serve_forever()
except KeyboardInterrupt:
server.shutdown()
if __name__ == "__main__":
startServer()
- Dockerfile 생성
FROM python:3.12
ENV PYTHONUNBUFFERED 1
COPY . /app
WORKDIR /app
CMD python3 server.py
- Version 파일 생성
0.0.1
- Repo에 배포
Docker Hub repo 생성 및 Token 발급
발급된 Token은 잊어버리지 않도록 복사해둡니다.
Jenkins CI + K8S (kind)
kind에 대한 설명은 링크를 참고
kind cluster 배포
- MYIP 환경 변수 등록
$ ifconfig | grep -A5 en0
## inet에 표기된 로컬 IP를 환경 변수에 등록
$ MYIP={IP}
- kind 배포
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
networking:
apiServerAddress: "$MYIP"
nodes:
- role: control-plane
extraPortMappings:
- containerPort: 30000
hostPort: 30000
- containerPort: 30001
hostPort: 30001
- containerPort: 30002
hostPort: 30002
- containerPort: 30003
hostPort: 30003
- role: worker
- role: worker
$ kind create cluster --config kind-node.yaml --name myk8s --image kindest/node:v1.30.6
## 확인
$ kind get nodes --name myk8s
myk8s-control-plane
myk8s-worker
myk8s-worker2
$ kubens
default
kube-node-lease
kube-public
kube-system
local-path-storage
$ kubens default
Context "kind-myk8s" modified.
Active namespace is "default".
- kind는 개별 도커 네트워크를 생성하여 사용
$ docker network ls
$ docker inspect kind
- 생성된 node 확인
- Kube ops view 생성
## kube ops view helm
$ helm repo add geek-cookbook https://geek-cookbook.github.io/charts/
$ helm install kube-ops-view geek-cookbook/kube-ops-view --version 1.2.2 --set service.main.type=NodePort,service.main.ports.http.nodePort=30001 --set env.TZ="Asia/Seoul" --namespace kube-system
## 설치 확인
$ k get eploy,pod,svc,ep -n kube-system -l app.kubernetes.io/instance=kube-ops-view
## kube-ops-view 접속 (for mac)
$ open "http://127.0.0.1:30001/#scale=2
Jenkins 설정
- Jenkins Plugin 설치
- pipeline stage view
- docker pipeline
- gogs
- 자격증명 설정 : Jenkins > Credentials > Globals > Add Credentials
- gogs repo 자격증명 설정
- kind : Username with password
- Username : devops
- password : <gogs token>
- ID : gogs-crd
- Docker Hub 자격증명 설정
- kind : Username with password
- Username : <docker hub ID >
- Password : <docker hub pw or token>
- ID : dockerhub-crd
- k8s 자격증명 설정 : k8s-crd
- kind : Secret file
- file : .kube/config 파일 업로드
- ID : k8s-crd
- gogs repo 자격증명 설정
Jenkins Item 생성
- Pipeline Script
pipeline {
agent any
environment {
DOCKER_IMAGE = 'tjdgns789/dev-app' // Docker 이미지 이름
}
stages {
stage('Checkout') {
steps {
git branch: 'main',
url: 'http://{IP}:3000/devops/dev-app2.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()
}
}
}
}
}
post {
success {
echo "Docker image ${DOCKER_IMAGE}:${DOCKER_TAG} has been built and pushed successfully!"
}
failure {
echo "Pipeline failed. Please check the logs."
}
}
}
- 지금 빌드 -> 콘솔 Output 확인
- 도커 허브 확인
Kubernetes에 Docker 이미지 배포하기
- 흔히 말하는 K8S manifest(.yaml) 파일의 구조는 아래와 같다.
쿠버네티스는 원하는 상태를 설정할 때 최대한 충족시키기 위해 노력한다.
Deployment 배포하기
간단하게 위 섹션에서 docker hub에 업로드한 이미지를 kind cluster에 배포해보겠습니다.
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/tjdgns789/dev-app:0.0.1
- Deployment 배포
$ k apply -f deploy.yaml
배포 후 자원 생성이 잘되었는지 확인해보면, 정상적으로 생성되지 않은 것을 확인할 수 있습니다.
위에서 해왔던 순서를 생각해보면 Docker hub의 repo를 Private로 만들었고,
우리는 K8S에 Priv repo에 접근할 수 있는 권한을 부여하지 않았고, 자격 증명 실패로 에러가 발생한 것 입니다.
- Docker Hub 자격 증명 설정하기
DHUSER=<도커 허브 계정>
DHPASS=<도커 허브 암호 혹은 토큰>
$ kubectl create secret docker-registry dockerhub-secret \
--docker-server=https://index.docker.io/v1/ \
--docker-username=$DHUSER \
--docker-password=$DHPASS
- secret 생성 확인
- 생성된 secret을 사용하여 다시 deploy 배포
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
imagePullSecrets:
- name: dockerhub-secret
- 배포 리소스 생성 확인
아래 캡처에서 확인할 수 있듯이 secret을 반영하여 priv repo에 접근할 수 있는 권한을 할당하니, 정상적으로 자원이 생성되는 것을 확인할 수 있습니다.
- POD 동작 확인
제 3의 테스트 POD를 생성하고, 해당 파드에서 pod ip를 통해 프로세스가 정상 동작하고 있는지 확인합니다.
## 테스트 파드 생성
$ kubectl run curl-pod --image=curlimages/curl:latest --command -- sh -c "while true; do sleep 3600; done"
## POD IP 확인
$ kubectl get pod -o wide | egrep "timeserver" | head -n 1 | awk '{print $6}'
## CURL 테스트
$ kubectl exec -it curl-pod -- curl {pod ip}
## 로그 확인
$ k logs pod/timeserver-pod1
Listening on 0.0.0.0:80
10.244.2.4 - - [22/Dec/2024 15:46:35] "GET / HTTP/1.1" 200 -
10.244.2.4 - - [22/Dec/2024 15:51:16] "GET / HTTP/1.1" 200 -
10.244.2.4 - - [22/Dec/2024 15:51:17] "GET / HTTP/1.1" 200 -
10.244.2.4 - - [22/Dec/2024 15:51:17] "GET / HTTP/1.1" 200 -
10.244.2.4 - - [22/Dec/2024 15:51:17] "GET / HTTP/1.1" 200 -
10.244.2.4 - - [22/Dec/2024 15:51:18] "GET / HTTP/1.1" 200 -
10.244.2.4 - - [22/Dec/2024 15:51:18] "GET / HTTP/1.1" 200 -
Service와 연동하기
POD는 휘발성 리소스 이므로 배포 시 재생성되기 때문에 IP와 같은 정보들이 수시로 변경됩니다.
따라서, deploy와 service를 통해 비고정적인 부분을 고정시켜 언제든 POD가 재생성되어도 영향이 없도록 대응합니다.
- service.yaml
apiVersion: v1
kind: Service
metadata:
name: timeserver
spec:
selector:
pod: timeserver-pod
ports:
- port: 80
targetPort: 80
protocol: TCP
nodePort: 30000
type: NodePort
- 배포 후 테스트 파드에서 서비스로 통신 테스트
$ kubectl get svc timeserver
- Service IP로 통신 테스트
## 테스트 파드에서 수행
$ kubectl exec -it curl-pod -- curl 10.96.47.81
Service로도 정상적으로 통신되는 것을 확인할 수 있습니다.
Gogs Webhooks 설정
- Gogs dev-app2 > Serttings > webhook에서 아래와 같이 webhook을 설정합니다.
- Payload URL : jenkins
- content type : application/json
- secret : 임의 지정
- Jenkins Item 생성(type: pipeline)
- REPO URL : http://{gogs IP 주소}:3000/{gogs user}/dev-app2
- Use gogs secret : {webhook 생성 시 사용한 secret}
- Build Triggers : Build when a change is pushed to gogs 체크
- Pipelinu script from SCM
- SCM : Git
- Repo URL : {위와 동일}
- Credentials(devops/***)
- Branch(*/man)
- Script Path : Jenkinsfile (파일 내용은 위에 있는 pipeline script와 동일)
- 변경 사항을 주기 위해 VERSION과 server.py의 버전을 0.0.4로 수정
- SCM : Git
$ git add . && git commit -m "VERSION $(cat VERSION) Changed" && git push -u origin main
PUSH가 일어날 때 설정한 Webhook이 호출되고 자연스레 빌드까지 이뤄진 것을 확인할 수 있습니다.
K8S에 신규 버전 이미지로 배포
$ kubectl set image deployment timeserver timeserver-container=$DHUSER/dev-app:0.0.4 && watch -d "kubectl get deploy,ep timeserver; echo; kubectl get rs,pod"
이전 old pod가 삭제되고 신규 pod가 생성되고 있는 것을 확인할 수 있고, service로 curl 테스트 시 신규 버전의 이미지가 호출되는 것을 확인할 수 있습니다.
- curl 테스트
$ kubectl exec -it curl-pod -- curl 10.96.47.81
- GOGS webook 기록 확인
Jenkins CI/CD + K8S(Kind)
지금까지는 jenkins로 배포를 제외한 CI부분 까지의 프로세스를 자동화했다면,
이제는 CD(Deploy)에 대한 부분도 클러스터에 바로 반영될 수 있는 실습을 진행합니다.
Jenkins 컨테이너 내부에 툴 설치 : kubectl, helm
$ docker compose exec --privileged -u root jenkins bash
$ curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/arm64/kubectl"
$ install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
$ kubectl version --client=true
$ curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
$ helm version
Jenkins Item 생성(Pipeline) : item name(k8s-cmd)
- Pipeline script
pipeline {
agent any
environment {
KUBECONFIG = credentials('k8s-crd')
}
stages {
stage('List Pods') {
steps {
sh '''
# Fetch and display Pods
kubectl get pods -A --kubeconfig "$KUBECONFIG"
'''
}
}
}
}
- 빌드 실행 결과
Jenkins 를 이용한 blue-green 배포 준비
#
cd dev-app
#
mkdir deploy
# echo-server-blue.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: echo-server-blue
spec:
replicas: 2
selector:
matchLabels:
app: echo-server
version: blue
template:
metadata:
labels:
app: echo-server
version: blue
spec:
containers:
- name: echo-server
image: hashicorp/http-echo
args:
- "-text=Hello from Blue"
ports:
- containerPort: 5678
# echo-server-service.yaml
apiVersion: v1
kind: Service
metadata:
name: echo-server-service
spec:
selector:
app: echo-server
version: blue
ports:
- protocol: TCP
port: 80
targetPort: 5678
nodePort: 30000
type: NodePort
## deploy/echo-server-green.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: echo-server-green
spec:
replicas: 2
selector:
matchLabels:
app: echo-server
version: green
template:
metadata:
labels:
app: echo-server
version: green
spec:
containers:
- name: echo-server
image: hashicorp/http-echo
args:
- "-text=Hello from Green"
ports:
- containerPort: 5678
#
git add . && git commit -m "Add echo server yaml" && git push -u origin main
$ while true; do curl -s --connect-timeout 1 http://127.0.0.1:30000 ; date ; echo "------------" ; sleep 1 ; done
위 명령어로 모니터링하면서 Jenkins에서 Switching을 허용하면 아래와 같이 Blue가 Green으로 전환되는 것을 확인할 수 있습니다.
Jenkins CI + Argo CD + K8S(Kind)
ArgoCD는 Kubernetes를 위한 선언적 Gitops CD 툴 입니다.
Gitops방식을 사용하며, git의 변경사항을 kubernetes 클러스터에 반영합니다.
멀티 클러스터 배포 관리가 가능하며, Auto Sync를 지원합니다.
또한 롤백과 버전 관리를 지원하고 WEB UI를 지원하여 편하게 작업도 가능합니다.
ArgoCD 설치
$ kubectl create ns argocd
## argocd-values.yaml (helm)
dex:
enabled: false
server:
service:
type: NodePort
nodePortHttps: 30002
# 설치
helm repo add argo https://argoproj.github.io/argo-helm
helm install argocd argo/argo-cd --version 7.7.10 -f argocd-values.yaml --namespace argocd
# 확인
kubectl get pod,svc,ep -n argocd
kubectl get crd | grep argo
- ArgoCD 최초 패스워드 확인
ID는 admin입니다.
$ kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d ;echo
- ArgoCD 웹 페이지 접속
open "https://127.0.0.1:30002"
- ops-deploy repo 등록
Settings > repositories > CONNECT REPO- connection method : VIA HTTPS
- Type : git
- Project : default
- Repo URL : http://192.168.219.106:3000/devops/ops-deploy (뒤에 .git은 제외합니다.)
- Usernaem : devops
- Password : {gogs token}
helm chart 를 통한 배포 실습
#
$ mkdir nginx-chart
$ cd nginx-chart
$ mkdir templates
## configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}
data:
index.html: |
{{ .Values.indexHtml | indent 4 }}
## deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: {{ .Release.Name }}
template:
metadata:
labels:
app: {{ .Release.Name }}
spec:
containers:
- name: nginx
image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
ports:
- containerPort: 80
volumeMounts:
- name: index-html
mountPath: /usr/share/nginx/html/index.html
subPath: index.html
volumes:
- name: index-html
configMap:
name: {{ .Release.Name }}
## service.yaml
apiVersion: v1
kind: Service
metadata:
name: {{ .Release.Name }}
spec:
selector:
app: {{ .Release.Name }}
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 30000
type: NodePort
## values.yaml
indexHtml: |
<!DOCTYPE html>
<html>
<head>
<title>Welcome to Nginx!</title>
</head>
<body>
<h1>Hello, Kubernetes!</h1>
<p>Nginx version 1.26.1</p>
</body>
</html>
image:
repository: nginx
tag: 1.26.1
replicaCount: 1
## Chart.yaml
apiVersion: v2
name: nginx-chart
description: A Helm chart for deploying Nginx with custom index.html
type: application
version: 1.0.0
appVersion: "1.26.1"
- helm을 이용한 배포
## helm install 및 배포 확인
$ helm install dev-nginx . -f values.yaml
$ helm list
$ kubectl get svc,deploy,ep,cm dev-nginx -o wide
## curl 테스트
$ curl http://127.0.0.1:30000
$ curl http://127.0.0.1:30000 | grep version
- values.yaml 값 변경 후 적용하기
indexHtml: |
<!DOCTYPE html>
<html>
<head>
┆ <title>Welcome to Nginx!</title>
</head>
<body>
┆ <h1>Hello, Kubernetes!</h1>
┆ <p>Nginx version 1.26.234</p>
</body>
</html>
image:
repository: nginx
tag: 1.26.2
replicaCount: 2
- helm upgrade
$ helm upgrade dev-nginx . -f values.yaml
- nginx 변경 사항 확인
Repo(ops-deploy) 에 nginx helm chart 를 Argo CD를 통한 배포
## ops-deploy git clone
$ git clone http://192.168.254.124:3000/devops/ops-deploy.git
$ cd ops-deploy
## 배포 파일 설정
$ VERSION=1.26.1
$ mkdir nginx-chart
$ mkdir nginx-chart/templates
## VERSION
echo $VERSION > nginx-chart/VERSION
## templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}
data:
index.html: |
{{ .Values.indexHtml | indent 4 }}
EOF
cat > nginx-chart/templates/deployment.yaml <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: {{ .Release.Name }}
template:
metadata:
labels:
app: {{ .Release.Name }}
spec:
containers:
- name: nginx
image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
ports:
- containerPort: 80
volumeMounts:
- name: index-html
mountPath: /usr/share/nginx/html/index.html
subPath: index.html
volumes:
- name: index-html
configMap:
name: {{ .Release.Name }}
## templates/service.yaml
apiVersion: v1
kind: Service
metadata:
name: {{ .Release.Name }}
spec:
selector:
app: {{ .Release.Name }}
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 30000
type: NodePort
## values-dev.yaml
indexHtml: |
<!DOCTYPE html>
<html>
<head>
<title>Welcome to Nginx!</title>
</head>
<body>
<h1>Hello, Kubernetes!</h1>
<p>DEV : Nginx version 1.26.1</p>
</body>
</html>
image:
repository: nginx
tag: 1.26.1
replicaCount: 1
## values.prd.yaml
indexHtml: |
<!DOCTYPE html>
<html>
<head>
<title>Welcome to Nginx!</title>
</head>
<body>
<h1>Hello, Kubernetes!</h1>
<p>PRD : Nginx version 1.26.1</p>
</body>
</html>
image:
repository: nginx
tag: 1.26.1
replicaCount: 2
## Chart.yaml
apiVersion: v2
name: nginx-chart
description: A Helm chart for deploying Nginx with custom index.html
type: application
version: 1.0.0
appVersion: "1.26.1"
- git 배포
$ git add . && git commit -m "init commit" && git push origin main
- Argo CD에 App 등록 : Application → NEW APP
- GENERAL
- App Name : dev-nginx
- Project Name : default
- SYNC POLICY : Manual
- SYNC OPTIONS : AUTO-CREATE NAMESPACE
- Source
- Repo URL : 설정되어 있는 것 선택
- Revision : HEAD
- PATH : nginx-chart
- DESTINATION
- Cluster URL : <기본값>
- NAMESPACE : dev-nginx
- HELM
- Values files : values-dev.yaml
- GENERAL
Create를 클릭하면 Missing 상태의 앱이 생성됩니다.
SYNC 버튼을 클릭하여 자원을 생성합니다.
생성된 자원이 클러스터에서도 잘 생성되었는지 확인합니다.
클러스터에서도 명령어를 통해 app의 상태를 확인할 수 있습니다.
$ kubectl describe applications -n argocd dev-nginx
코드 수정
VERSION을 변경하고 다시 배포해 봅니다.
VERSION=1.26.2
## values-dev.yaml
indexHtml: |
<!DOCTYPE html>
<html>
<head>
<title>Welcome to Nginx!</title>
</head>
<body>
<h1>Hello, Kubernetes!</h1>
<p>DEV : Nginx version 1.26.2</p>
</body>
</html>
image:
repository: nginx
tag: 1.26.2
replicaCount: 2
## values-prd.yaml
indexHtml: |
<!DOCTYPE html>
<html>
<head>
<title>Welcome to Nginx!</title>
</head>
<body>
<h1>Hello, Kubernetes!</h1>
<p>PRD : Nginx version 1.26.2</p>
</body>
</html>
image:
repository: nginx
tag: 1.26.2
replicaCount: 2
- 배포
$ git status && git add . && git commit -m "Update nginx version $(cat nginx-chart/VERSION)" && git push -u origin main
- Argo CD 웹 확인
- 웹에서 REFRESH를 클릭하면 Sync status가 OutOfSync로 변경된 것을 확인할 수 있습니다.
- DIFF를 통해 AS-IS <> TO-BE의 변경 사항을 확인할 수 있습니다.
- SYNC 클릭 후 오브젝트 확인
생성 시간을 확인하면 sync 클릭 직후 재배포가 이뤄진 것을 확인할 수 있습니다.
- 변경 사항 확인
ArgoCD 애플리케이션 자체를 yaml로 생성
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: dev-nginx
namespace: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
source:
helm:
valueFiles:
- values-dev.yaml
path: nginx-chart
repoURL: http://192.168.219.106:3000/devops/ops-deploy
targetRevision: HEAD
syncPolicy:
automated:
prune: true
syncOptions:
- CreateNamespace=true
destination:
namespace: dev-nginx
server: https://kubernetes.default.svc
- 배포 확인
- 웹 페이지 접근 확인
ops-deploy ➤ curl http://127.0.0.1:30000 git:main
<!DOCTYPE html>
<html>
<head>
<title>Welcome to Nginx!</title>
</head>
<body>
<h1>Hello, Kubernetes!</h1>
<p>DEV : Nginx version 1.26.2</p>
</body>
</html>
위에서 만든 Docker Image를 클러스터에 배포하기
$ VERSION=0.0.1
$ echo $VERSION > VERSION
## timeserver.yaml
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/tjdgns789/dev-app:0.0.1
imagePullSecrets:
- name: dockerhub-secret
## service.yaml
apiVersion: v1
kind: Service
metadata:
name: timeserver
spec:
selector:
pod: timeserver-pod
ports:
- port: 80
targetPort: 80
protocol: TCP
nodePort: 30000
type: NodePort
- 코드 배포
$ git status && git add . && git commit -m "Add dev-app deployment yaml" && git push -u origin main
- Argo CD app 생성
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: timeserver
namespace: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
source:
path: dev-app
repoURL: http://192.168.219.106:3000/devops/ops-deploy
targetRevision: HEAD
syncPolicy:
automated:
prune: true
syncOptions:
- CreateNamespace=true
destination:
namespace: default
server: https://kubernetes.default.svc
- Object 생성 확인
- ArogoCD 웹에서 확인
dev-app2의 version 업데이트 시 > ops-deploy repo의 version 동기화
- dev-app2 repo의 jenkinsfile 수정
pipeline {
agent any
environment {
DOCKER_IMAGE = 'tjdgns789/dev-app' // Docker 이미지 이름
GOGSCRD = credentials('gogs-crd')
}
stages {
stage('Checkout') {
steps {
git branch: 'main',
url: 'http://192.168.219.106:3000/devops/dev-app2.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-credentials') {
// DOCKER_TAG 사용
def appImage = docker.build("${DOCKER_IMAGE}:${DOCKER_TAG}")
appImage.push()
appImage.push("latest")
}
}
}
}
stage('ops-deploy Checkout') {
steps {
git branch: 'main',
url: 'http://192.168.254.124:3000/devops/ops-deploy.git', // Git에서 코드 체크아웃
credentialsId: 'gogs-crd' // Credentials ID
}
}
stage('ops-deploy version update push') {
steps {
sh '''
OLDVER=$(cat dev-app/VERSION)
NEWVER=$(echo ${DOCKER_TAG})
sed -i -e "s/$OLDVER/$NEWVER/" dev-app/timeserver.yaml
sed -i -e "s/$OLDVER/$NEWVER/" dev-app/VERSION
git add ./dev-app
git config user.name "devops"
git config user.email "a@a.com"
git commit -m "version update ${DOCKER_TAG}"
git push http://${GOGSCRD_USR}:${GOGSCRD_PSW}@192.168.254.124:3000/devops/ops-deploy.git
'''
}
}
}
post {
success {
echo "Docker image ${DOCKER_IMAGE}:${DOCKER_TAG} has been built and pushed successfully!"
}
failure {
echo "Pipeline failed. Please check the logs."
}
}
}
- server.py, version 수정
"0.0.8" - dev-app2 repo git push
$ git add . && git commit -m "VERSION $(cat VERSION) Changed" && git push -u origin main
- ArgoCD 재배포
일정 시간이 지나고 argocd가 변경 내역을 감지해 OutOfSync > Auto Sync로 재배포되는 것을 확인할 수 있습니다.
- 배포 전후를 비교해도 dev-app2 레포에만 수정했지만 pipeline 설정으로 인해 ops-deploy의 version도 변경된 것을 확인했습니다.
'Cloud > CICD' 카테고리의 다른 글
GitHub Actions CI/CD (1) | 2024.12.15 |
---|---|
Jenkins CI/CD + Docker (1) | 2024.12.08 |