이번 프로젝트에서는 local, dev 등 애플리케이션 실행 환경을 프로파일별로 분리하기 위해 kustomization 을 사용했습니다.
프로젝트 구조는 다음과 같습니다.
base 에는 deployment, service 등 애플리케이션 구동에 필요한 resource 를 넣었고 (pdb 는 파드 업데이트 중에도 최소 하나의 파드는 동작하도록 해 무중단 배포가 가능하도록 했습니다)
network 에는 ingress 를 넣어 alb나 ExternalDNS 관련 설정이 들어가도록 했습니다.
overlays 에는 각 profile 별 동작을 위한 yaml 을 넣었습니다.
📁 home-protector-infra
├── 📁 base/
│ ├── 📁 ai/
│ │ ├── 📄 deploy
│ │ ├── 📄 hpa
│ │ ├── 📄 pdb
│ │ ├── 📄 service
│ │ └── 📄 kustomization
│ └── 📁 backend/
│ ├── 📄 deploy
│ ├── 📄 hpa
│ ├── 📄 pdb
│ ├── 📄 service
│ └── 📄 kustomization
├── 📁 network/
│ ├── 📄 app-ingress.yaml
│ └── 📄 kustomization
└── 📁 overlays/
├── 📁 local/
│ └── 📁 backend/
│ ├── 📄 patch-env.yaml
│ ├── 📄 sealed-secret.yaml
│ └── 📄 kustomization.yaml
└── 📁 develop/
├── 📁 ai/
│ ├── 📄 patch-image.yaml
│ └── 📄 kustomization
├── 📁 backend/
│ ├── 📄 secret-workspace
│ ├── 📄 patch-env.yaml
│ ├── 📄 patch-image.yaml
│ ├── 📄 sealed-secret.yaml
│ └── 📄 kustomization.yaml
└── 📄 kustomization
backend base 의 각 resource 이다. 사용을 위해서 kustomization 에 각 manifest 를 등록했다
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- backend-deployment.yaml
- backend-service.yaml
- backend-pdb.yaml
- backend-hpa.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend-application
labels:
app: backend-application
spec:
replicas: 2
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
maxSurge: 1
selector:
matchLabels:
app: backend-application
template:
metadata:
name: backend-application
labels:
app: backend-application
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "8080"
prometheus.io/path: "/actuator/prometheus"
spec:
containers:
- name: backend-application
image: han16935/protector-be
imagePullPolicy: IfNotPresent
ports:
- name : http
containerPort: 8080
# resources:
# requests:
# cpu: "500m"
# memory: "256Mi"
# limits:
# cpu: "1000m" # 최대 1 CPU 코어 제한
# memory: "512Mi"
envFrom:
- configMapRef:
name: backend-configmap
restartPolicy: Always
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: backend-pdb
spec:
minAvailable: 1 # 최소 1개 파드는 항상 실행 상태 유지
selector:
matchLabels:
app: backend-application
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: backend-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: backend-application
minReplicas: 2 # 최소 pod 개수
maxReplicas: 4 # 최대 pod 개수
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 70
다음으로는 ingress 이다. 이도 마찬가지로 network 폴더 내부의 kustomization 에 등록해야 한다. external-dns.alpha.xxx 어노테이션을 통해 Route 53 에 관련 도메인을 등록할 수 있다. 아래 certificate-arn 의 경우 저 값 그대로 들어가면 ArgoCD 통해 애플리케이션을 배포할 때 에러를 일으키니 주의하자
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: home-protector-ingress
annotations:
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: instance
alb.ingress.kubernetes.io/group.name: home-protector
alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS": 443}]'
alb.ingress.kubernetes.io/certificate-arn: "${AWS_HTTPS_CERT}" # 실제 값으로 바뀌어야
alb.ingress.kubernetes.io/ssl-redirect : '443'
external-dns.alpha.kubernetes.io/hostname: be.home-protector.click,prometheus.home-protector.click
spec:
ingressClassName: alb
rules:
- host: "be.home-protector.click"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: backend-service
port:
number: 80
- host: "prometheus.home-protector.click"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: prometheus-service
port:
number: 80
overlays/develop/backend/kustomization.yaml 의 경우 우리는 base/backend 를 기반으로 애플리케이션 metadata 를 수정할 것이고, patch-xx 를 통해 값을 수정할 것이기에 kustomization 은 다음과 같이 작성한다
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../../base/backend
- sealed-secret.yaml
patches:
- path: patch-image.yaml
- path: patch-env.yaml
generatorOptions:
disableNameSuffixHash: true
patch-env 파일이다. 우리는 dev 환경에서 이 애플리케이션을 실행할 것이기에, 다음처럼 patch-env를 작성했다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend-application
spec:
template:
spec:
containers:
- name: backend-application
envFrom:
- secretRef:
name: backend-secret
env:
- name: SPRING_PROFILES_ACTIVE
value: dev
patch-image.yaml 파일이다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend-application
spec:
template:
spec:
containers:
- name: backend-application
image: 637423458012.dkr.ecr.ap-northeast-2.amazonaws.com/home-protector:be039674777e3b04d51ea18408a59b9c68a045c4
우리는 base 내 deploy 내 이미지가 아닌, ECR 내 이미지를 사용할 것이기에 Github Actions workflow 에 태그 최신화 step 을 추가했다.
- name : Checkout k8s repository
uses : actions/checkout@v4
with:
repository : GCU-Home-Protector/protector-infra
ref : main
token : ${{secrets.ACTION_TOKEN}}
path : home-protector-infra
- name : Update backend image
if : success()
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
IMAGE_TAG: ${{ github.sha }}
run : |
cd home-protector-infra/overlays/develop/backend
sed -i "s|image: ${ECR_REGISTRY}/${ECR_REPOSITORY}.*$|image: ${ECR_REGISTRY}/${ECR_REPOSITORY}:${IMAGE_TAG}|" patch-image.yaml
cat patch-image.yaml
- name : Push updated manifest
run : |
cd home-protector-infra
git config --global user.email "github-actions@github.com"
git config --global user.name "github-actions"
if [[ -n "$(git status --porcelain)" ]]; then
git add overlays/develop/backend/patch-image.yaml
git commit -m "chore : Update backend image tag to ${{ github.sha }}"
else
echo "No changes detected, creating empty commit to trigger ArgoCD"
git commit --allow-empty -m "chore : Tag update fail"
fi
git push origin main
overlays/kustomization.yaml 은 다음과 같이 작성했다
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../overlays/develop/ai
- ../../overlays/develop/backend
- ../../network
실행을 위해 다음 명령어를 사용했다. 실행 되는 걸 확인하고 위에서부터 복붙한 거여서 잘못 복붙햇을 수도 잇다... 그러면 미안...
# Bastion <-> EKS 연결
aws eks update-kubeconfig --region $AWS_DEFAULT_REGION --name $CLUSTER_NAME
# 필요한 값 환경변수로 세팅
# Sealed Secret Controller 생성
helm repo add sealed-secrets https://bitnami-labs.github.io/sealed-secrets
helm repo update
helm install sealed-secrets-controller sealed-secrets/sealed-secrets \
--namespace kube-system \
--create-namespace
kubectl wait --namespace kube-system \
--for=condition=available deployment/sealed-secrets-controller \
--timeout=180s
kubectl get secret sealed-secrets-key -n kube-system \
-o jsonpath="{.data.tls\.crt}" | base64 -d > sealed-secrets-key.pem
# kubeseal 설치
curl -LO "https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.30.0/kubeseal-0.30.0-linux-amd64.tar.gz"
tar -xvzf "kubeseal-0.30.0-linux-amd64.tar.gz" kubeseal
chmod +x kubeseal
sudo mv kubeseal /usr/local/bin/
cd "$ORIGIN_DIR"
rm -rf "$TMP_DIR"
# env 생성
cd protector-infra/overlays/backend/secret-workspace
chmod +x generate-env-file.sh
./generate-env-file.sh
# Sealed Secret 생성
export SEALED_SECRETS_CERT=~/protector-infra/overlays/develop/backend/secret-workspace/sealed-secrets-key.pem
chmod +x generate-sealed-secret.sh
./generate-sealed-secret.sh
# ECR 로그인
aws ecr get-login-password \
--region ${AWS_DEFAULT_REGION} | docker login \
--username AWS \
--password-stdin ${ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com
kubectl apply -k overlays/develop


AI 서버도 제대로 연결되고 있는 걸 볼 수 있다!

'프로젝트 > 졸업작품 - 인프라' 카테고리의 다른 글
| 10. 좋아요 음악 조회 API 성능 개선 - 캐싱 적용 (1) | 2025.07.07 |
|---|---|
| 8. ArgoCD 세팅 (0) | 2025.07.02 |
| 5. Terraform 을 통한 EKS 및 DB 구축 (0) | 2025.07.02 |
| 4. TroubleShooting - dev 환경에서 로그 미출력 현상 발생 (1) | 2025.07.02 |
| 3. SealedSecret 을 통한 애플리케이션 환경변수 관리 (0) | 2025.06.27 |