1. 프로젝트 flow
step 1) K8SE 클러스터 생성
step 2) 노드 풀 생성
step 3) 파일스토리지 생성 및 NFS Client Provisioner 설정
step 4) CR에 이미지 저장하고, 저장된 이미지로 웹 서비스 띄우기
CR - KC 서비스 / 각 파드별 볼륨 마운트는 hostpath가 아닌 nfs로 생성한 pvc
step 5) CR에 저장된 이미지로 pod 띄우기
step 6) HPA설정으로 위에 생성된 pod를 최소 1개, 최대 3개로 HPA 구성
설정 후 부하를 발생시켜서 자동 확장, 축소가 제대로 되는지 체크
2. K8SE 클러스터 및 노드풀 생성
1. 클러스터 생성
아래 링크를 참조하여 클러스터를 생성한다.
쿠버네티스 버전 : 1.29 / CNI : Calico / 노드풀 : 3개
3. 파일스토리지 생성 및 NFS Client Provisioner 설정
1. 파일 스토리지 생성
https://docs.kakaocloud.com/service/container-pack/k8se/how-to-guides/k8se-nfs
2. Helm으로 NFS Client Provisioner 배포
helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/
3. NFS Client Provisioner 설치
helm install --kubeconfig=$KUBE_CONFIG nfs-subdir-external-provisioner nfs-subdir-external-provisioner/nfs-subdir-external-provisioner --set nfs.server=[File Storage IP] --set nfs.path=[File Storage Mount Path]
4. StorageClass 확인
kubectl --kubeconfig=$KUBE_CONFIG get sc
5. PersistentVolumeClaim 생성 및 자동 프로비저닝 테스트
PVC 생성 예제 파일
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: test-claim
spec:
storageClassName: nfs-client
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Mi
6. File Storage 할당하기
kubectl --kubeconfig=$KUBE_CONFIG get pvc // PVC 확인
kubectl --kubeconfig=$KUBE_CONFIG get pv // PV 확인
4. CR에 이미지 저장하고, 저장된 이미지로 웹 서비스 띄우기
https://docs.kakaocloud.com/tutorial/container/cr-basic
1. Container Registry 생성
구분 | 리포지토리 설정값 |
공개 여부 | 비공개 |
리포지토리 이름 | cr-felix-test |
태그 덮어쓰기 | 가능 |
이미지 스캔 | 자동 |
2. 예제 프로젝트 도커 이미지 빌드
예제 프로젝트를 설치할 디렉터리를 생성하고 작업 디렉터리를 생성한 디렉터리로 설정
mkdir -p ~/Downloads/kakaocloud-library
cd ~/Downloads/kakaocloud-library
예제 프로젝트를 설치
git clone -b kakaocloud-library https://github.com/kakaoenterprise/kakaocloud-tutorials
작업 디렉터리를 예제 프로젝트 경로로 이동합니다.
예제 프로젝트 파일을 확인합니다.
cd kakaocloud-tutorials
ls
3. 예제 프로젝트 빌드
Docker 실행 환경 확인
docker info
서버 프로젝트를 linux/amd64 환경으로 빌드합니다.
빌드된 서버 컨테이너 이미지를 카카오클라우드 환경에 맞게 태그를 설정합니다.
클라이언트 프로젝트를 linux/amd64 환경으로 빌드합니다.
빌드된 클라이언트 컨테이너 이미지를 카카오클라우드 환경에 맞게 태그를 설정합니다.
docker build -t kakaocloud-library-server:latest --platform linux/amd64 -f ./server/deploy/Dockerfile ./server
docker tag kakaocloud-library-server:latest {PROJECT_NAME}.kr-central-2.kcr.dev/{REPOSITORY_NAME}/kakaocloud-library-server:latest
docker build -t kakaocloud-library-client:latest --platform linux/amd64 -f ./client/deploy/Dockerfile ./client
docker tag kakaocloud-library-client:latest {PROJECT_NAME}.kr-central-2.kcr.dev/{REPOSITORY_NAME}/kakaocloud-library-client:latest
4.예제 프로젝트 이미지 업로드
1. Container Registry 로그인
docker login {PROJECT_NAME}.kr-central-2.kcr.dev \
--username {ACCESS_KEY} \
--password {ACCESS_SECRET_KEY}
2. 서버 컨테이너 이미지를 업로드합니다.
클라이언트 컨테이너 이미지를 업로드합니다.
docker push {PROJECT_NAME}.kr-central-2.kcr.dev/{REPOSITORY_NAME}/kakaocloud-library-server:latest
docker push {PROJECT_NAME}.kr-central-2.kcr.dev/{REPOSITORY_NAME}/kakaocloud-library-client:latest
3. 업로드된 이미지는 아래 명령어를 통해 다운로드할 수 있습니다. 로컬 머신에 입력하여 이미지를 설치합니다.
서버 이미지 클라이언트 이미지 다운로드
docker pull {PROJECT_NAME}.kr-central-2.kcr.dev/{REPOSITORY_NAME}/kakaocloud-library-server:latest
docker pull {PROJECT_NAME}.kr-central-2.kcr.dev/{REPOSITORY_NAME}/kakaocloud-library-client:latest
4. docker images로 이미지 다운로드 확인
5. CR에 저장된 이미지로 pod 띄우기
각 파드별 볼륨 마운트는 hostpath가 아닌 nfs로 생성한 pvc로 설정해주기 위해서
마운트 패스를 hostpath가 아닌 /root로 잡아주었고, 편리한 작업을 위해서 네임스페이스는 felix로 통일
서버 배포
apiVersion: apps/v1
kind: Deployment
metadata:
name: server-deployment
namespace: felix
spec:
replicas: 2
selector:
matchLabels:
app: server
template:
metadata:
labels:
app: server
spec:
containers:
- name: server
image: {PROJECT_NAME}.kr-central-2.kcr.dev/tutorial/kakaocloud-library-server:latest
env:
- name: PROFILE
value: "local"
ports:
- containerPort: 8080
volumeMounts:
- name: root-volume
mountPath: /root
imagePullSecrets:
- name: kc-cr-secret
volumes:
- name: root-volume
hostPath:
path: /root
type: Directory
---
apiVersion: v1
kind: Service
metadata:
name: server-service
namespace: felix
spec:
type: ClusterIP
selector:
app: server
ports:
- protocol: TCP
port: 8080
targetPort: 8080
서버 service 배포
apiVersion: v1
kind: Service
metadata:
name: server-service
namespace: felix
spec:
type: ClusterIP
selector:
app: server
ports:
- protocol: TCP
port: 8080
targetPort: 8080
클라이언트 deployment 배포
apiVersion: apps/v1
kind: Deployment
metadata:
name: client-deployment
namespace: felix
spec:
replicas: 2
selector:
matchLabels:
app: client
template:
metadata:
labels:
app: client
spec:
containers:
- name: client
image: {PROJECT_NAME}.kr-central-2.kcr.dev/tutorial/kakaocloud-library-client:latest
env:
- name: SERVER_ENDPOINT
value: "http://server-service.felix.svc.cluster.local:8080"
ports:
- containerPort: 80
volumeMounts:
- name: root-volume
mountPath: /root
imagePullSecrets:
- name: kc-cr-secret
volumes:
- name: root-volume
hostPath:
path: /root
type: Directory
클라이언트 service 배포
apiVersion: v1
kind: Service
metadata:
name: client-service
namespace: felix
spec:
type: LoadBalancer
selector:
app: client
ports:
- protocol: TCP
port: 80
targetPort: 80
콘솔에서 로드 밸런서 설정
예제 프로젝트 클라이언트의 service를 LoadBalancer 유형으로 배포하면서, 카카오클라우드 콘솔에서 Load Balancer 서비스의 로드 밸런서 목록에도 추가된 것을 확인할 수 있습니다. 로드 밸런서 목록 > [더 보기] > 퍼블릭 IP 연결을 클릭해 외부에서 서비스에 접근할 수 있게 만들 수 있습니다.
서비스 접속 확인
브라우저에서 등록한 퍼블릭 IP로 접속하여 서비스를 확인합니다. 정상적으로 연결된 경우, '카카오클라우드 도서관' 서비스 화면을 볼 수 있습니다.

6. HPA 설정 및 부하 테스트
HPA(HorizontalPodAutoscale)를 Cluster Autoscaler와 함께 설정하면 더욱 효과적으로 리소스를 관리
1. HPA 설정하기 전, Helm client를 설치합니다. 운영체제별 Helm 설치에 대한 자세한 설명은 Helm 공식 문서 > 헬름 설치하기를 참고하시기 바랍니다.
2. HPA 부하 테스트를 위해 파드를 모니터링하는 metrics-server를 설치합니다.
# metrics-server 설치 명령어
helm repo add metrics-server https://kubernetes-sigs.github.io/metrics-server/
helm upgrade --install metrics-server metrics-server/metrics-server --set hostNetwork.enabled=true --set containerPort=4443
3. 노드의 리소스 사용량을 정상적으로 모니터링하는지 확인합니다. metrics-server 설치 후 모니터링 정보가 수집되기까지 최대 5분 정도 소요될 수 있습니다.
# 노드의 리소스 사용량 확인 명령어
kubectl top node
4. HPA와 Cluster Autoscaler을 설정한 후, 부하 테스트를 진행하기 위한 php-server를 배포합니다.
# php-server App 배포 명령어
apiVersion: apps/v1
kind: Deployment
metadata:
name: php-apache
spec:
selector:
matchLabels:
run: php-apache
template:
metadata:
labels:
run: php-apache
spec:
containers:
- name: php-apache
image: ke-container-registry.kr-central-2.kcr.dev/ke-cr/hpa-example:latest
ports:
- containerPort: 80
resources:
limits:
cpu: 500m
requests:
cpu: 500m
---
apiVersion: v1
kind: Service
metadata:
name: php-apache
labels:
run: php-apache
spec:
ports:
- port: 80
selector:
run: php-apache
5. 부하 테스트를 위해 HPA를 생성합니다.
# HPA 생성 명령어
kubectl autoscale deployment php-apache --cpu-percent=10 --min=1 --max=10 // HPA 생성
kubectl get hpa // HPA 설정 확인
실행 결과
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
php-apache Deployment/php-apache 46%/50% 1 10 5 28m
6. 테스트를 위해 부하를 일으키는 파드를 실행합니다.
# 파드 실행 명령어
kubectl run -i --tty load-generator --rm --image=ke-container-registry.kr-central-2.kcr.dev/ke-cr/busybox:latest --restart=Never -- /bin/sh -c "while sleep 0.01; do wget -q -O- http://php-apache; done"
7. 부하가 커지며 파드와 노드 개수가 정상적으로 증가하는 것을 확인합니다.
- php-apache 서버 HPA가 발생하며, 리소스가 부족하여 스케줄링 되지 못한 일부 파드들은 Pending 상태가 됩니다.
- 일부 파드가 스케줄링 되지 못하므로 리소스 추가를 위해 노드가 3개로 자동 확장됩니다.
# HPA 및 자동 확장 동작 결과 확인 명령어
kubectl get pods -w // 파드 개수 변경 확인
kubectl get nodes -w // 노드 개수 변경 확인
실행 결과
NAME READY STATUS RESTARTS AGE
php-apache-766d5cdd5b-2t5p8 0/1 Pending 0 44s
php-apache-766d5cdd5b-5mhlk 0/1 Pending 0 29s
php-apache-766d5cdd5b-5vjt6 0/1 Pending 0 14s
php-apache-766d5cdd5b-74z87 1/1 Running 0 44s
php-apache-766d5cdd5b-d49g9 0/1 Pending 0 29s
php-apache-766d5cdd5b-fnlld 1/1 Running 0 44s
php-apache-766d5cdd5b-nr5f2 0/1 Pending 0 29s
php-apache-766d5cdd5b-t7zr8 0/1 Pending 0 29s
php-apache-766d5cdd5b-vjjlz 1/1 Running 0 2m49s
php-apache-766d5cdd5b-whjhw 0/1 Pending 0 14s
NAME STATUS ROLES AGE VERSION
host-10-187-5-177 Ready <none> 51s v1.24.6
host-10-187-5-189 Ready <none> 9m5s v1.24.6
host-10-187-5-98 Ready <none> 69s v1.24.6
7. CI/CD with K8SE(GitHub Actions, ArgoCD)
1. GitHub에서 Private 레포지토리 생성
GitHub에서 Private 레포지토리를 생성한다.
퍼블릭으로 만들어서 하는 방법도 가능하나, 실무 환경에 가깝게 구성하기 위해서 프라이빗으로 레포지토리를
생성해주고 별도 인증을 통해서 접속하도록 구성한다.
수동 토큰 발급이 필요한 경우 아래 과정을 참고하면 되고,
야물 배포 시 시크릿 부분을 자동화 하였기때문에 본 프로젝트에서는 별도 토근 발급과정이 필요하지 않습니다.
[레포지토리 생성]
GitHub 접속 → 우측 상단 + → New repository
Repository name: my-k8s-app
Private 선택
README, .gitignore는 체크 안 함
Create repository
2. GitHub Personal Access Token 발급
ArgoCD가 Private 레포에 접근하려면 토큰이 필요하기 때문에 토큰을 발급해준다.
[토큰 발급]
GitHub 우측 상단 프로필 → Settings
왼쪽 메뉴에서 Developer settings 클릭
Personal access tokens > Tokens (classic) 클릭
Generate new token (classic) 버튼 클릭
[설정 예시]
Note: argo-git-token
체크: repo (read access to private repos)
만료 기간: 90일 또는 custom
Generate 후 토큰 값 복사 (다시 못 봄!)
토큰 값을 다시 보는게 불가능하기 때문에 꼭 별도 저장하는것을 권장한다.
3. Kubernetes에 Git 인증용 Secret 생성
먼저 argocd 라는 네임스페이스를 생성한다.
kubectl create namespace argocd
Git 인증용 Secret을 생성한다.
kubectl create secret generic github-creds \
--namespace argocd \
--from-literal=username=<your_github_username> \
--from-literal=password=<your_generated_token>
4. ArgoCD 설치하기 (Helm 사용)
Helm 리포지터리를 추가한다.
helm repo add argo https://argoproj.github.io/argo-helm
helm repo update
ArgoCD 설치 (Helm)
helm install argocd argo/argo-cd \
--namespace argocd
설치확인
kubectl get pods -n argocd
5. ArgoCD 웹 UI 접속
포트포워딩으로 로컬에서 접속
kubectl port-forward svc/argocd-server -n argocd 8080:443
브라우저에서 열기
(주의: https, 인증서 경고 뜰 수 있음 → 무시하고 계속)
https://localhost:8080
기본 로그인 정보
아이디 : admin
비밀번호 : 아래 명령어로 확인
kubectl get secret argocd-initial-admin-secret -n argocd \
-o jsonpath="{.data.password}" | base64 -d
'카카오클라우드' 카테고리의 다른 글
카카오클라우드 미니 프로젝트 2(쿠버네티스 CI CD 구축하기/ Github Action, argo) (0) | 2025.04.20 |
---|---|
카카오클라우드 CDN으로 서비스 웹서버 오프로딩 (0) | 2025.03.05 |
카카오클라우드 Object Storage & CDN으로 정적 웹사이트 호스팅 (0) | 2025.03.05 |
카카오클라우드 S3 API로 Object Storage 사용 (0) | 2024.12.07 |
카카오클라우드 Object Storage와 CDN으로 HTTP Live Streaming 구현 (0) | 2024.11.09 |