Ssoon
3주차 - Jenkins CI/ArgoCD + K8S : Full CI/CD 구성 본문
CloudNet@ 가시다님이 진행하는 CI/CD 맛보기 스터디
✅ Full CI/CD
🧿 ops-deploy Repo 코드 작업
- dev-app 디렉터리를 생성합니다.
- VERSION=0.0.1 값을 환경 변수로 설정합니다.
- dev-app/VERSION 파일을 생성하고 그 안에 버전 정보(0.0.1)를 저장합니다.
[ssoon@localhost ops-deploy]$ mkdir dev-app
[ssoon@localhost ops-deploy]$ DHUSER=kschoi728
[ssoon@localhost ops-deploy]$ VERSION=0.0.1
[ssoon@localhost ops-deploy]$ cat > dev-app/VERSION <<EOF
$VERSION
EOF
- Docker Hub 사용자 정보(DHUSER, DHPASS)를 환경 변수로 설정.
- Kubernetes Secret을 생성하여 Docker Hub에 접근할 수 있는 인증 정보를 저장.
- Secret은 이후 Kubernetes에서 이미지(Pod 생성 시)에 접근할 때 사용됩니다.
[ssoon@localhost dev-app]$ DHUSER=kschoi728
[ssoon@localhost dev-app]$ DHPASS=dckr_pat_qAvtuYOW9U4OEDevuW81CuluDk0
[ssoon@localhost dev-app]$ echo $DHUSER $DHPASS
kschoi728 dckr_pat_qAvtuYOW9U4OEDevuW81CuluDk0
[ssoon@localhost dev-app]$ kubectl get secret
No resources found in default namespace.
[ssoon@localhost dev-app]$ kubectl create secret docker-registry dockerhub-secret \
--docker-server=https://index.docker.io/v1/ \
--docker-username=$DHUSER \
--docker-password=$DHPASS
secret/dockerhub-secret created
[ssoon@localhost dev-app]$ kubectl get secret
NAME TYPE DATA AGE
dockerhub-secret kubernetes.io/dockerconfigjson 1 3s
- 이 YAML 파일은 Kubernetes 클러스터에서 timeserver라는 Deployment를 정의합니다.
- 이 Deployment는:
- docker.io/kschoi728/dev-app:0.0.1 이미지를 사용하여 Pod를 생성.
- dockerhub-secret 을 사용하여 Docker Hub에서 이미지를 다운로드.
- 동일한 Pod를 2개 생성하여 관리.
[ssoon@localhost ops-deploy]$ cat > dev-app/timeserver.yaml <<EOF
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:$VERSION
imagePullSecrets:
- name: dockerhub-secret
EOF
- 이 파일은 Kubernetes 클러스터에서 NodePort Service를 생성하여 외부에서 Deployment의 Pod에 접근할 수 있게 합니다.
- Service 이름: timeserver.
- 외부 요청 → 노드 IP + 포트(30000) → Pod의 컨테이너 포트(80번)으로 전달.
[ssoon@localhost ops-deploy]$ cat > dev-app/service.yaml <<EOF
apiVersion: v1
kind: Service
metadata:
name: timeserver
spec:
selector:
pod: timeserver-pod
ports:
- port: 80
targetPort: 80
protocol: TCP
nodePort: 30000
type: NodePort
EOF
- Git을 사용하여 현재 작업 내용을 커밋하고 원격 저장소(main 브랜치)에 푸시
[ssoon@localhost ops-deploy]$ git status && git add . && git commit -m "Add dev-app deployment yaml" && git push -u origin main
현재 브랜치 main
브랜치가 'origin/main'에 맞게 업데이트된 상태입니다.
추적하지 않는 파일:
(커밋할 사항에 포함하려면 "git add <파일>..."을 사용하십시오)
dev-app/
커밋할 사항을 추가하지 않았지만 추적하지 않는 파일이 있습니다 (추적하려면 "git
add"를 사용하십시오)
[main fad2437] Add dev-app deployment yaml
3 files changed, 33 insertions(+)
create mode 100644 dev-app/VERSION
create mode 100644 dev-app/service.yaml
create mode 100644 dev-app/timeserver.yaml
오브젝트 나열하는 중: 7, 완료.
오브젝트 개수 세는 중: 100% (7/7), 완료.
Delta compression using up to 4 threads
오브젝트 압축하는 중: 100% (5/5), 완료.
오브젝트 쓰는 중: 100% (6/6), 785 bytes | 785.00 KiB/s, 완료.
Total 6 (delta 0), reused 0 (delta 0), pack-reused 0
To http://192.168.56.105:3000/devops/ops-deploy.git
4e431c2..fad2437 main -> main
branch 'main' set up to track 'origin/main'.
- gogs 대시보드에서 내용을 확인합니다.
🧿Argo CD app 생성
finalizers: 리소스 삭제 시 추가 작업을 지정.
- 여기서 resources-finalizer.argocd.argoproj.io는 ArgoCD에서 리소스를 정리하는 데 사용됩니다.
- syncPolicy: 애플리케이션 동기화 정책을 정의.
- automated: 동기화 작업을 자동으로 수행.
- prune: true: Git 저장소에 없는 리소스를 자동으로 삭제.
- syncOptions:
- CreateNamespace=true: 네임스페이스가 없으면 자동으로 생성.
- automated: 동기화 작업을 자동으로 수행.
ArgoCD에 새로운 애플리케이션(timeserver)을 등록하여 GitOps 방식으로 Kubernetes 클러스터에 배포를 관리합니다.
[ssoon@localhost ops-deploy]$ cat <<EOF | kubectl apply -f -
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.56.105:3000/devops/ops-deploy
targetRevision: HEAD
syncPolicy:
automated:
prune: true
syncOptions:
- CreateNamespace=true
destination:
namespace: default
server: https://kubernetes.default.svc
EOF
Warning: metadata.finalizers: "resources-finalizer.argocd.argoproj.io": prefer a domain-qualified finalizer name to avoid accidental conflicts with other finalizer writers
application.argoproj.io/timeserver created
- ArgoCD 애플리케이션의 상태를 확인합니다.
[ssoon@localhost dev-app]$ kubectl get applications -n argocd timeserver
NAME SYNC STATUS HEALTH STATUS
timeserver Synced Healthy
[ssoon@localhost dev-app]$ kubectl get deploy,rs,pod
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/timeserver 2/2 2 2 56s
NAME DESIRED CURRENT READY AGE
replicaset.apps/timeserver-7fcbc89ff9 2 2 2 56s
NAME READY STATUS RESTARTS AGE
pod/timeserver-7fcbc89ff9-hd266 1/1 Running 0 56s
pod/timeserver-7fcbc89ff9-tbxck 1/1 Running 0 56s
[ssoon@localhost dev-app]$ kubectl get svc,ep timeserver
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/timeserver NodePort 10.96.150.246 <none> 80:30000/TCP 61s
NAME ENDPOINTS AGE
endpoints/timeserver 10.244.1.17:80,10.244.2.18:80 61s
- 애플리케이션이 정상적으로 배포되고 작동 중임을 확인합니다.
[ssoon@localhost dev-app]$ curl http://127.0.0.1:30000
The time is 2:55:06 PM, VERSION 0.0.1
Server hostname: timeserver-7fcbc89ff9-hd266
🧿 dev-app Repo 코드 작업
- Jenkinsfile 내용을 변경합니다.
pipeline {
agent any
environment {
DOCKER_IMAGE = 'kschoi728/dev-app' // Docker 이미지 이름
GOGSCRD = credentials('gogs-crd')
}
stages {
stage('dev-app Checkout') {
steps {
git branch: 'main',
url: 'http://192.168.56.105: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")
}
}
}
}
stage('ops-deploy Checkout') {
steps {
git branch: 'main',
url: 'http://192.168.56.105: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.56.105: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."
}
}
}
- VERSION 파일과 server.py 파일을 수정하고 repo 에 배포합니다.
git add . && git commit -m "VERSION $(cat VERSION) Changed" && git push -u origin main
- Jenkins 에서 pipeline 을 확인합니다.
🧿 동작 확인
- ops-deploy repo에서 변경된 내용을 확인합니다.
- ArgoCD 에서도 Sync 을 실행하여 업데이트 내용을 확인합니다.
'CICD 맛보기' 카테고리의 다른 글
3주차 - Jenkins CI/ArgoCD + K8S : Jenkins CI + Argo CD + K8S(Kind) (0) | 2024.12.16 |
---|---|
3주차 - Jenkins CI/ArgoCD + K8S : Jenkins CI/CD + K8S(Kind) (0) | 2024.12.16 |
3주차 - Jenkins CI/ArgoCD + K8S : Jenkins CI + K8S(Kind) (1) | 2024.12.16 |
3주차 - Jenkins CI/ArgoCD + K8S : 실습환경 (0) | 2024.12.16 |
2주 : GitHub Actions CI/CD : 2 (0) | 2024.12.12 |
Comments