본문으로 건너뛰기

Personal Project - Kubernetes 아키텍처

On-Premise VMware 환경 기반 Kubernetes 3-Tier 고가용성 시스템

목차



디렉토리 구조

personal-project/
├── 프로젝트_계획서/ # 프로젝트 계획서 및 PPT 슬라이드
├── 프로젝트_산출물/ # 최종 산출물
│ ├── gition/ # Git + Notion 통합 협업 플랫폼 (FastAPI + React + MySQL)
│ └── k8s/ # Kubernetes 클러스터 구성 및 배포 매니페스트
├── day1-1224 ~ day12-0108/ # 일일 작업 기록 (K8s 클러스터 구축 과정)
└── docs/ # 참고 문서

🏗️ 전체 인프라 아키텍처


🌐 네트워크 구성

서버 IP 할당

호스트IP용도
GitLab172.100.100.8Git, CI/CD, Registry
Bastion172.100.100.9SSH 게이트웨이
NFS172.100.100.10공유 스토리지
MySQL172.100.100.11Primary (쓰기)
k8s-m172.100.100.12Master (Control Plane)
k8s-n1172.100.100.13Worker Node 1
k8s-n2172.100.100.14Worker Node 2
k8s-n3172.100.100.15Worker Node 3

MetalLB IP Pool

항목
Pool Nameingress-pool
IP 범위172.100.100.20 - 172.100.100.30
모드L2 (ARP)

서비스 포트

서비스호스트포트
Ingress (MetalLB)172.100.100.2080, 443
GitLab Web172.100.100.880
GitLab Registry172.100.100.85050
MySQL Master172.100.100.113306
NFS Server172.100.100.102049
MySQL Router R/Wmysql-cluster6446
MySQL Router R/Omysql-cluster6447

☸️ Kubernetes 클러스터 & Ingress 통합 구조 (mysql-cluster)

네트워크 흐름 요약

순서경로설명
1User → LoadBalancer172.100.100.20:80 접근
2LoadBalancer → IngressIngress Controller로 전달
3Ingress → Servicepath: / → Frontend, /api → API
4Service → Pod로드밸런싱
5API → mysql-operatormysql-cluster:6446 (Write)
6mysql-operator → MySQLPrimary(Write) / Secondary(Read)
7MySQL ↔ MySQLGroup Replication 동기화
8Operator → Cluster자동 Failover/복구 관리

📝 브랜치 노트 (Branch Notes) 기능

각 브랜치마다 Notion 스타일의 문서 페이지를 생성하여 관리

클러스터 환경에서의 브랜치 노트

데이터 흐름 순서

순서동작대상설명
1git checkoutNFS해당 브랜치로 전환
2SELECT (Read)mysql-cluster:6447branch_pages 조회
3INSERT/UPDATE (Write)mysql-cluster:6446branch_pages 저장

브랜치별 노트 작성 흐름

클러스터 구성 포인트

구성설명이유
API 3 replicas여러 Pod에서 동일 브랜치 노트 접근고가용성
NFS 공유 볼륨Git 저장소를 모든 Pod에서 공유git checkout 동기화
MySQL Masterbranch_pages 테이블 중앙 저장데이터 일관성
Ingress 로드밸런싱요청마다 다른 Pod 처리 가능부하 분산

API 엔드포인트

MethodPath설명
GET/api/pages/{user}/{repo}/{branch}브랜치 노트 조회
POST/api/pages/{user}/{repo}/{branch}브랜치 노트 저장
POST/api/git/checkout브랜치 전환 + 자동 페이지 생성

branch_pages 테이블

CREATE TABLE branch_pages (
id CHAR(36) PRIMARY KEY, -- UUID
user_id INT NOT NULL, -- FK → users
repo_id INT NOT NULL, -- FK → repositories
branch_name VARCHAR(255) NOT NULL, -- 브랜치명 (feat/login)
title VARCHAR(255), -- 페이지 제목
content JSON, -- 블록 에디터 데이터
created_at DATETIME DEFAULT NOW(),
updated_at DATETIME DEFAULT NOW() ON UPDATE NOW(),

UNIQUE KEY unique_user_repo_branch (user_id, repo_id, branch_name)
);

🔄 CI/CD 파이프라인 흐름

GitLab CI 이미지 빌드 과정

1. .gitlab-ci.yml 파이프라인 구조

stages:
- build
- deploy

variables:
DOCKER_HOST: tcp://docker:2375
DOCKER_TLS_CERTDIR: ""

# Backend 이미지 빌드
build-backend:
stage: build
image: docker:24.0.5
services:
- name: docker:24.0.5-dind
command: ["--insecure-registry=172.100.100.8:5050"]
before_script:
- echo '{"insecure-registries":["172.100.100.8:5050"]}' > /etc/docker/daemon.json
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
script:
- docker build --provenance=false -t $CI_REGISTRY_IMAGE/backend:latest ./backend
- docker push $CI_REGISTRY_IMAGE/backend:latest
when: manual

# Frontend 이미지 빌드
build-frontend:
stage: build
image: docker:24.0.5
services:
- name: docker:24.0.5-dind
command: ["--insecure-registry=172.100.100.8:5050"]
before_script:
- echo '{"insecure-registries":["172.100.100.8:5050"]}' > /etc/docker/daemon.json
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
script:
- docker build --provenance=false -t $CI_REGISTRY_IMAGE/frontend:latest -f frontend/Dockerfile .
- docker push $CI_REGISTRY_IMAGE/frontend:latest
when: manual

2. 빌드 흐름

3. 주요 설정 포인트

설정설명
Docker-in-Dockerdocker:24.0.5-dindRunner 내부에서 Docker 빌드
privilegedtrueDinD 필수 설정
insecure-registries172.100.100.8:5050HTTP Registry 허용
--provenance=falseBuildKit 옵션Registry 호환성
when: manual수동 트리거필요시에만 빌드

Kubernetes 배포 과정

1. Registry Secret 설정

# GitLab Registry 인증 Secret 생성
kubectl create secret docker-registry gitlab-registry \
--docker-server=172.100.100.8:5050 \
--docker-username=root \
--docker-password=<ACCESS_TOKEN> \
-n gition

2. Deployment에서 이미지 Pull

# fastapi-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
namespace: gition
spec:
replicas: 3
template:
spec:
imagePullSecrets:
- name: gitlab-registry # Registry 인증
containers:
- name: api
image: 172.100.100.8:5050/root/gition/backend:latest
imagePullPolicy: Always # 최신 이미지 Pull

3. 배포 명령어

# 이미지 업데이트 후 배포
kubectl rollout restart deployment/api -n gition
kubectl rollout restart deployment/frontend -n gition

# 배포 상태 확인
kubectl rollout status deployment/api -n gition
kubectl get pods -n gition -w

4. 전체 배포 흐름

5. containerd 설정 (K8s 노드)

# 모든 K8s 노드에서 실행 (insecure registry 허용)
sudo mkdir -p /etc/containerd/certs.d/172.100.100.8:5050
sudo tee /etc/containerd/certs.d/172.100.100.8:5050/hosts.toml > /dev/null <<EOF
server = "http://172.100.100.8:5050"

[host."http://172.100.100.8:5050"]
capabilities = ["pull", "resolve", "push"]
skip_verify = true
EOF

sudo systemctl restart containerd

🏢 3-Tier 애플리케이션 구조 (mysql-cluster)

데이터 흐름 순서

순서경로설명
1User → Ingressgition.local 접속
2Ingress → Frontendpath: / → React 앱
3Ingress → APIpath: /api, /auth → FastAPI
4API → mysql-operator:6446 (Write) 또는 :6447 (Read)
5mysql-operator → MySQLPrimary(Write) / Secondary(Read)
6MySQL ↔ MySQLGroup Replication 동기화
7MySQL → Local PV각 노드별 데이터 저장
8Operator → Cluster자동 Failover/복구 관리

MySQL Router 연결 정보

용도호스트포트설명
쓰기 (R/W)mysql-cluster6446Primary로 라우팅
읽기 (R/O)mysql-cluster6447Secondary들로 로드밸런싱

🗄️ MySQL InnoDB Cluster (Group Replication)

InnoDB Cluster 특징:

  • 자동 Failover: Primary 장애 시 Secondary 중 하나가 자동 승격
  • 동기 복제: Group Replication 기반 데이터 일관성 보장
  • MySQL Router: 애플리케이션 단일 엔드포인트 제공
  • Operator 관리: 자동 클러스터 생성/복구

자동 Failover 아키텍처

Failover 테스트 방법

# 1. 현재 Primary 확인
kubectl exec -it mysql-cluster-0 -n gition -c mysql -- \
mysql -uroot -p -e "SELECT member_host, member_role FROM performance_schema.replication_group_members"

# 2. Primary Pod 삭제
kubectl delete pod mysql-cluster-0 -n gition

# 3. 새 Primary 확인 (30초~1분 후)
kubectl exec -it mysql-cluster-1 -n gition -c mysql -- \
mysql -uroot -p -e "SELECT member_host, member_role FROM performance_schema.replication_group_members"

✅ 자동 Failover 성공 시 애플리케이션은 MySQL Router를 통해 무중단으로 새 Primary에 연결됩니다.

스토리지 아키텍처

스토리지용도특징
Local PVMySQL 데이터고성능, 노드별
NFSSQL Dump 백업공유, 7일 보관

🔗 네임스페이스 구조


🔐 보안 & 네트워크 정책


📊 리소스 할당

노드vCPURAM역할
Bastion21GBSSH Gateway
GitLab24GBCI/CD, Registry
NFS11GBPersistent Storage, Backup
MySQL24GBMaster Database (Docker)
k8s-m44GBControl Plane
k8s-n144GBWorker (Frontend, API, MySQL)
k8s-n244GBWorker (Frontend, API, MySQL)
k8s-n344GBWorker (API, MySQL)

📚 Quick Reference

IP 주소 정리

서비스IP포트
Ingress (External IP)172.100.100.2080, 443
GitLab Web172.100.100.880
GitLab Registry172.100.100.85050
MySQL Master172.100.100.113306
NFS Server172.100.100.102049

Pod 구성

Deployment/StatefulSetReplicasImagePort
frontend2172.100.100.8:5050/root/gition/frontend80
api3172.100.100.8:5050/root/gition/backend3001
mysql-cluster3mysql/mysql-server:8.03306, 6446, 6447
mysql-router2mysql/mysql-router:8.06446, 6447

Ingress 라우팅

PathServicePort
/frontend-svc80
/apiapi-svc3001
/auth/githubapi-svc3001
/healthapi-svc3001

kubectl 자주 사용 명령어

# 클러스터 상태 확인
kubectl get nodes -o wide
kubectl get pods -A

# gition 배포 상태
kubectl get all -n gition

# Ingress 확인
kubectl get ingress -n gition
kubectl get svc -n ingress-nginx

🦊 GitLab 로컬 서버 접속

접속 아키텍처

접속 방법

# 1. SSH 터널 설정 (Windows/Mac에서)
ssh -L 8080:172.100.100.8:80 -J pista@192.168.45.9 pista@172.100.100.12

# 2. 브라우저 접속
# http://localhost:8080

# 3. 로그인
# Username: root
# Password: (초기 비밀번호 또는 변경된 비밀번호)

GitLab 프로젝트 구조

경로설명
root/gition메인 프로젝트
root/gition/backendFastAPI 백엔드
root/gition/frontendReact 프론트엔드

Container Registry 이미지

이미지경로용도
backend172.100.100.8:5050/root/gition/backend:latestFastAPI API 서버
frontend172.100.100.8:5050/root/gition/frontend:latestReact + Nginx

CI/CD 트리거


관련 문서

그래프 뷰

그래프 데이터 로딩 중…
현재: Personal Project - Kubernetes 아키텍처
노드 클릭 → 이동 · 드래그 → 위치 조정