yeonghoon.kim

  • 게시판
  • 갤러리

관측 스택과 앱 배포 저장소 구조 정리

김영훈 2026.06.19 12:23 조회 수 : 23

ArgoCD가 GitLab repo를 읽기 시작한 뒤, 일반 앱을 바로 올리기 전에 기본 운영 구성을 먼저 정리함.

구축 매뉴얼 기준으로 11장부터 13장까지 진행.

  • Monitoring / Logging / Alerting
  • 앱 배포와 namespace 구조
  • Storage / PV / PVC / NFS / 백업 구조

먼저 관측 스택.

앱이 떠 있는지만 보는 걸로는 부족해서 metrics, logs, alerts를 나눠서 구성함.

Monitoring
= Prometheus, Grafana, kube-state-metrics, node-exporter

Logging
= Loki, Fluent Bit, Grafana

Alerting
= PrometheusRule, Alertmanager, Telegram

흐름은 대충 이 구조.

[Metrics]
Node / Pod / App
-> Prometheus
-> Grafana

[Logs]
Pod / Container logs
-> Fluent Bit
-> Loki
-> Grafana

[Alerts]
PrometheusRule
-> Prometheus
-> Alertmanager
-> Telegram

일반 앱보다 관측 스택을 먼저 올림.

문제가 생겼을 때 Pod 상태, 로그, 알림을 볼 수 있어야 하기 때문.

중요한 순서.

1. monitoring namespace와 Secret 준비
2. kube-prometheus-stack CRD 선설치
3. monitoring Application sync
4. Loki PV/PVC 준비
5. Loki sync
6. Loki ready 확인
7. Fluent Bit sync
8. PrometheusRule / AlertmanagerConfig / ScrapeConfig 반영
9. Prometheus, Loki, Alertmanager 검증

monitoring Application 설정 확인.

# monitoring Application Helm values에 crds.enabled=false와 ServerSideApply=true가 있는지 확인한다.
cd /home/ioniere/gitlab-project-clones/ioniere/cluster-apps
grep -nE 'values:|crds:|enabled: false|grafana:|ServerSideApply' apps/monitoring.yaml -A4 -B2

kube-prometheus-stack의 CRD는 크기가 커서 일반 apply로 처리하면 annotation 크기 문제가 날 수 있음.

그래서 CRD는 server-side apply로 먼저 넣고, Helm chart 쪽에서는 CRD 설치를 끔.

monitoring namespace 생성.

# monitoring namespace를 먼저 생성한다.
kubectl create namespace monitoring --dry-run=client -o yaml | kubectl apply -f -

monitoring 쪽 Secret은 SOPS로 복구.

값은 출력하지 않음.

대상은 Grafana admin, Alertmanager Telegram Secret.

그 다음 ArgoCD에서 monitoring, loki, fluent-bit 순서로 sync.

Loki가 준비되기 전에 Fluent Bit을 먼저 올리면 로그 전송 실패가 쌓일 수 있어서 순서를 나눔.

Loki ready 확인.

# Loki가 ready 상태인지 확인한다.
kubectl -n monitoring get pods -l app.kubernetes.io/name=loki
# Loki ready endpoint를 확인한다.
kubectl -n monitoring port-forward svc/loki 3100:3100
# Loki ready 응답을 확인한다.
curl -sS http://127.0.0.1:3100/ready

이제 앱 배포 구조 정리.

ArgoCD root Application이 child Application을 만들고, child Application이 실제 앱을 배포하는 구조.

cluster-apps repo
  -> bootstrap/root-application.yaml
  -> ArgoCD root Application
  -> apps/*.yaml
  -> child Application
  -> 각 앱 namespace
  -> Deployment / StatefulSet / Service / Ingress / PVC

앱이 뜨려면 Application만 있어서는 부족함.

먼저 재료가 있어야 함.

namespace
registry Secret
app Secret
PV/PVC 또는 NFS 저장소
Deployment / StatefulSet
Service
Ingress

root Application과 child Application 확인.

# root Application과 child Application 생성 상태를 확인한다.
kubectl -n argocd get applications.argoproj.io \
  -o custom-columns=NAME:.metadata.name,SYNC:.status.sync.status,HEALTH:.status.health.status,REVISION:.status.sync.revision

일반 앱 namespace.

3004-uptime-kuma
3007-japan
3008-bingbingsubway
3009-yeonghoon-kim
3035-mbti-mini
money
waf-dashboard

앱 Helm values에는 namespace.create=false로 둔 경우가 있음.

즉, chart가 namespace를 만들지 않고 운영자가 먼저 namespace를 준비하는 방식.

namespace.create=false
= 앱 chart가 namespace를 만들지 않음
= sync 전에 namespace를 먼저 준비해야 함

Secret도 두 종류로 나눠서 봄.

registry Secret
= private registry에서 image를 받기 위한 인증 정보

app Secret
= 앱 실행에 필요한 DB password, app key, token 등

registry Secret이 없으면 이미지를 못 받아서 ImagePullBackOff가 날 수 있음.

app Secret이 없으면 이미지는 받았는데 앱이 DB 접속 실패 등으로 죽을 수 있음.

마지막으로 저장소 구조 정리.

Kubernetes에서 Pod는 언제든 다시 만들어질 수 있음.

그래서 DB, CMS 파일, Loki 데이터, Uptime Kuma 같은 데이터는 Pod 안에만 두면 안 됨.

이 환경에서는 주로 DGX host의 NFS 경로를 사용.

NFS root
= /mnt/k8s-nfs

daily backup root
= /backup/dgx/daily

구조는 이렇게 봄.

Pod
-> PVC
-> PV
-> NFS /mnt/k8s-nfs
-> backup /backup/dgx/daily
-> 원격지 백업서버

NFS와 백업 경로 확인.

# NFS root와 daily backup root가 존재하고, 어느 디스크에 붙어 있는지 확인한다.
df -h /mnt/k8s-nfs /backup/dgx/daily
# NFS root의 상위 구조를 확인한다. Secret 값이나 민감한 파일 내용은 출력하지 않는다.
find /mnt/k8s-nfs -maxdepth 2 -type d | sort | sed -n '1,80p'

PV/PVC 상태 확인.

# 클러스터 전체 PV 상태를 확인한다.
kubectl get pv
# 모든 namespace의 PVC 상태를 확인한다.
kubectl get pvc -A

PV가 실제 NFS 경로를 가리키는지 확인.

# PV가 어떤 NFS 서버와 경로를 바라보는지 확인한다.
kubectl get pv -o custom-columns=NAME:.metadata.name,STATUS:.status.phase,CLAIM:.spec.claimRef.name,SERVER:.spec.nfs.server,PATH:.spec.nfs.path,RECLAIM:.spec.persistentVolumeReclaimPolicy

중요한 데이터는 PVC/PV가 Bound인지 확인.

Pending이면 저장소가 아직 연결되지 않은 상태라서 앱 sync를 계속 밀면 안 됨.

Stateful 앱은 더 조심해서 봄.

# StatefulSet과 PVC를 함께 확인한다.
kubectl get statefulset -A
kubectl get pvc -A
# 비정상 Pod를 확인한다.
kubectl get pods -A --field-selector=status.phase!=Running,status.phase!=Succeeded

  • 추천 0

  • 비추천 0
이 게시물을
목록

댓글 0

번호 제목 글쓴이 날짜 조회 수
339 yeonghoon.kim php 업그레이드 new 김영훈 2026.07.09 0
338 GitLab Registry PAT 만료로 이미지 Pull 실패 김영훈 2026.07.08 14
337 Stateful과 Stateless 구분해보기 김영훈 2026.07.02 23
336 Git revert는 기록을 지우는 게 아니라 되돌리는 기록을 남기는 것 김영훈 2026.06.29 19
335 OutOfSync와 Degraded 구분하기 김영훈 2026.06.28 25
334 control-plane 장애 시나리오 관찰 김영훈 2026.06.27 12
333 worker 재부팅 전 drain 절차 정리 김영훈 2026.06.26 20
332 ImagePullBackOff와 registry pull secret 누락 김영훈 2026.06.22 17
331 ArgoCD 복구 중 GitLab 접근 문제 정리 김영훈 2026.06.22 26
» 관측 스택과 앱 배포 저장소 구조 정리 김영훈 2026.06.19 23
329 SOPS Secret 복구와 ArgoCD root Application 적용 김영훈 2026.06.18 28
328 복구 런북 초반 누락 사항 정리 김영훈 2026.06.17 15
327 CoreDNS로 GitLab Registry 내부 주소 고정 김영훈 2026.06.17 19
326 ArgoCD와 GitOps 구조 준비 김영훈 2026.06.16 16
325 SOPS age로 Kubernetes Secret 암복호화 김영훈 2026.06.15 23
324 yeonghoon.kim 배포 파일을 Helm Chart로 전환 [1] 김영훈 2026.06.12 18
323 Docker Compose 서비스를 Kubernetes로 이전(깃랩 도커 저장소 필요) [2] 김영훈 2026.06.10 20
322 Kubernetes 기본 클러스터, ingress-nginx 설치 김영훈 2026.06.09 15
321 DGX Kubernetes 구성 계획 김영훈 2026.06.08 25
320 2026년 일본 여행(21일) 요약 김영훈 2026.06.02 17
쓰기 태그
 첫 페이지 1 2 3 4 5 6 7 8 9 10 끝 페이지