์ƒ์„ธ ์ปจํ…์ธ 

๋ณธ๋ฌธ ์ œ๋ชฉ

[ํ† ์ด ํ”„๋กœ์ ํŠธ] ์‹ค์ œ ๊ธฐ์—…์—์„œ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ธํ”„๋ผ ์•„ํ‚คํ…์ฒ˜ ํ•™์Šต

AWS CLOUD SCHOOL 9๊ธฐ

by AI Engineer crystal 2025. 4. 17. 09:48

๋ณธ๋ฌธ

๐Ÿงฑ 1๋‹จ๊ณ„: K8s ํด๋Ÿฌ์Šคํ„ฐ ์•„ํ‚คํ…์ฒ˜ ์„ค๊ณ„

โœ… ๋ชฉํ‘œ ์š”์•ฝ

  • Master 3๋Œ€ ๊ตฌ์„ฑ → HA(High Availability) ํด๋Ÿฌ์Šคํ„ฐ (.100)
  • Node 3๋Œ€ ๊ตฌ์„ฑ (.101 ~ .103)
  • NFS + DNS 1๋Œ€ ๊ตฌ์„ฑ (.99)
  • Harbor 1๋Œ€ ๊ตฌ์„ฑ ← Docker + Compose (.98)
  • etcd ๋ฐฑ์—… ๋ฐ ๋ณต์›
  • LB ๊ตฌ์„ฑ ํ•„์š” (master API ์ ‘์† ์œ„ํ•œ ๋‹จ์ผ ์ง„์ž…์ )

โœ… ํ•ต์‹ฌ ๊ฐœ๋… ์„ค๋ช…

โ–ถ๏ธ ์™œ Master๋Š” 3๋Œ€ ์ด์ƒ์ด์–ด์•ผ ํ•˜๋‚˜์š”?

  • etcd๋Š” quorum ๊ธฐ๋ฐ˜์˜ ๋ถ„์‚ฐ DB์ž…๋‹ˆ๋‹ค.
    quorum์ด๋ž€, ํด๋Ÿฌ์Šคํ„ฐ ๋‚ด์—์„œ ๊ณผ๋ฐ˜์ˆ˜ ์ด์ƒ์ด ํ•ฉ์˜๋ฅผ ํ•ด์•ผ ์“ฐ๊ธฐ ์ž‘์—…์ด ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค.
  • Master 2๋Œ€๋ฅผ ๊ตฌ์„ฑํ•  ๊ฒฝ์šฐ, ํ•˜๋‚˜๊ฐ€ ์žฅ์• ๋‚˜๋ฉด ๋‚จ์€ 1๋Œ€๋Š” quorum์„ ๋งŒ์กฑํ•˜์ง€ ๋ชปํ•˜์—ฌ ์“ฐ๊ธฐ ์ž‘์—…์ด ์ค‘๋‹จ๋ฉ๋‹ˆ๋‹ค.
  • 3๋Œ€๋ฅผ ๊ตฌ์„ฑํ•˜๋ฉด 1๋Œ€๊ฐ€ ์ฃฝ์–ด๋„ quorum(2/3)์ด ์œ ์ง€๋˜์–ด ์‹œ์Šคํ…œ์ด ์ •์ƒ์ ์œผ๋กœ ์šด์˜๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

โ–ถ๏ธ HA๋ฅผ ์œ„ํ•œ Load Balancer

  • Master๊ฐ€ ์—ฌ๋Ÿฌ ๋Œ€์ผ ๊ฒฝ์šฐ, ํด๋Ÿฌ์Šคํ„ฐ์— ์ ‘์†ํ•  ๋•Œ๋งˆ๋‹ค ์–ด๋А master์— ๋ถ™์„์ง€ ๋ถ„์‚ฐ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
  • ์ด๋ฅผ ์œ„ํ•ด ํด๋Ÿฌ์Šคํ„ฐ ์ง„์ž…์ ์œผ๋กœ HAProxy ๋˜๋Š” Keepalived + Nginx ๊ฐ™์€ L4/L7 LB๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
  • kubeadm ์„ค์ • ์‹œ controlPlaneEndpoint: "lb-address:6443" ๊ฐ™์€ ํ˜•ํƒœ๋กœ LB ์ฃผ์†Œ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ—‚๏ธ 2๋‹จ๊ณ„: NFS + DNS ๊ตฌ์„ฑ

โœ… ๋ชฉํ‘œ ์š”์•ฝ

  • NFS: Pod์˜ ์˜์† ๋ฐ์ดํ„ฐ๋ฅผ ์œ„ํ•œ ๋™์  PV ํ”„๋กœ๋น„์ €๋‹
  • DNS: Harbor ๋„๋ฉ”์ธ hub.aws9.pri, Ingress์šฉ www.aws9.pri ๋“ฑ ๋‚ด๋ถ€ ๋„๋ฉ”์ธ ๋„ค์ž„ ๋งคํ•‘

โœ… ๊ฐœ๋… ์„ค๋ช…

โ–ถ๏ธ NFS๋กœ ๋™์  ํ”„๋กœ๋น„์ €๋‹์ด ๊ฐ€๋Šฅํ•˜๋ ค๋ฉด?

  1. NFS ์„œ๋ฒ„๋ฅผ ๋ณ„๋„๋กœ ๊ตฌ์ถ•
  2. /shared ๊ฒฝ๋กœ๋ฅผ export
  3. Kubernetes์— NFS-CSI ๋“œ๋ผ์ด๋ฒ„ ์„ค์น˜
  4. StorageClass๋ฅผ ์ •์˜ (Provisioner๊ฐ€ NFS๋ฅผ ํ™œ์šฉ)
  5. ์ดํ›„ PVC ์ƒ์„ฑ ์‹œ StorageClass๋ฅผ ์ง€์ •ํ•˜๋ฉด ๋™์ ์œผ๋กœ PV๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-sc
provisioner: nfs.csi.k8s.io
parameters:
  server: nfs.aws9.pri
  share: /shared
reclaimPolicy: Retain
mountOptions:
  - nfsvers=4.1

โ–ถ๏ธ DNS ์„ค์ • ํฌ์ธํŠธ

  • CoreDNS์— hosts ๋ฐฉ์‹ ๋˜๋Š” forward ์„ค์ •์œผ๋กœ ์‚ฌ์„ค ๋„๋ฉ”์ธ ๋งคํ•‘
  • hub.aws9.pri → Harbor IP
  • www.aws9.pri → Ingress Controller (์˜ˆ: nginx-ingress) IP
  • ์™ธ๋ถ€์—์„œ ์ ‘๊ทผํ•˜์ง€ ์•Š์•„๋„ ๋˜๋ฏ€๋กœ CoreDNS๋งŒ์œผ๋กœ ํ•ด๊ฒฐ ๊ฐ€๋Šฅ

๐Ÿš€ 3๋‹จ๊ณ„: Harbor ๊ตฌ์„ฑ

โœ… ๋ชฉํ‘œ ์š”์•ฝ

  • Harbor๋ฅผ hub.aws9.pri๋กœ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•˜๊ฒŒ ๊ตฌ์„ฑ
  • ์‚ฌ์šฉ์ž๋ณ„ private repo ์ƒ์„ฑ
  • TLS๋Š” ์‚ฌ์„ค ํ™˜๊ฒฝ์ด๋ฏ€๋กœ self-signed ์ธ์ฆ์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅ

โœ… ์ฃผ์š” ์„ค์ • ํฌ์ธํŠธ

  • DNS ์„ค์ •์ด ์™„๋ฃŒ๋˜์–ด์•ผ docker login hub.aws9.pri ๊ฐ€๋Šฅ
  • Harbor์˜ harbor.yml ์„ค์ •์— hostname์„ hub.aws9.pri๋กœ ๋ณ€๊ฒฝ ํ›„ ๋‹ค์‹œ prepare → start
  • ์‚ฌ์šฉ์ž ๊ณ„์ • ๋ฐœ๊ธ‰ ํ›„, ํ”„๋กœ์ ํŠธ(Repo)๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ์ ‘๊ทผ ๊ถŒํ•œ ๋ถ€์—ฌ

๐Ÿ› ๏ธ 4๋‹จ๊ณ„: ArgoCD + Namespace ๊ธฐ๋ฐ˜ GitOps

โœ… ๋ชฉํ‘œ ์š”์•ฝ

  • ๊ฐœ๋ฐœ์ž๋งˆ๋‹ค ๋…๋ฆฝ๋œ GitHub ์ €์žฅ์†Œ ์‚ฌ์šฉ
  • ๊ฐ ๊ฐœ๋ฐœ์ž๋Š” ์ž์‹ ๋งŒ์˜ namespace์—์„œ ์•ฑ์„ ๊ด€๋ฆฌ
  • ArgoCD App์„ Namespace ๋‹จ์œ„๋กœ ๊ด€๋ฆฌ

โœ… ๊ฐœ๋… ์ •๋ฆฌ

  • ArgoCD๋Š” GitOps ๊ธฐ๋ฐ˜ ๋„๊ตฌ๋กœ, Git์— ์„ ์–ธ๋œ ์ƒํƒœ๋ฅผ ํด๋Ÿฌ์Šคํ„ฐ์— ๋™๊ธฐํ™”ํ•ฉ๋‹ˆ๋‹ค.
  • Namespace์™€ RBAC๋ฅผ ์กฐํ•ฉํ•˜์—ฌ ์‚ฌ์šฉ์ž ๊ฒฉ๋ฆฌ ๊ฐ€๋Šฅ
  • ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ๊ตฌ์„ฑ:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: blog-app
  namespace: argocd
spec:
  destination:
    namespace: team-blog
    server: https://kubernetes.default.svc
  source:
    repoURL: https://github.com/user/blog-yamls
    targetRevision: HEAD
    path: manifests
  project: default
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

โš–๏ธ 5๋‹จ๊ณ„: HPA + KEDA ์Šค์ผ€์ผ๋ง

โœ… ๋ชฉํ‘œ ์š”์•ฝ

  • ์‹œ๊ฐ„ ๊ธฐ๋ฐ˜: 9์‹œ~18์‹œ → 3๊ฐœ, ๊ทธ ์™ธ → 1๊ฐœ
  • CPU ๊ธฐ๋ฐ˜: 60% ์ด์ƒ → max 10๊ฐœ๊นŒ์ง€ ํ™•์žฅ

โœ… ๊ตฌํ˜„ ๋ฐฉํ–ฅ

  • KEDA๋Š” Cron ๊ธฐ๋ฐ˜ ์Šค์ผ€์ผ๋ง์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค
  • HPA๋Š” CPU ์‚ฌ์šฉ๋Ÿ‰ ๊ธฐ๋ฐ˜์œผ๋กœ ๋™์ž‘
  • KEDA + HPA๋ฅผ ํ•จ๊ป˜ ์„ค์ •ํ•˜์—ฌ ์‹œ๊ฐ„ ๊ธฐ๋ฐ˜ ๊ธฐ๋ณธ๊ฐ’๊ณผ ๋ถ€ํ•˜ ๊ธฐ๋ฐ˜ ํ™•์žฅ ๋‘˜ ๋‹ค ๊ฐ€๋Šฅ
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: shop-scaler
  namespace: team-shop
spec:
  scaleTargetRef:
    name: shop-deployment
  minReplicaCount: 1
  maxReplicaCount: 10
  triggers:
  - type: cron
    metadata:
      timezone: Asia/Seoul
      start: "09:00"
      end: "18:00"
      desiredReplicas: "3"
  - type: cpu
    metadata:
      type: Utilization
      value: "60"

๐ŸŒ 6๋‹จ๊ณ„: Ingress ๊ตฌ์„ฑ

โœ… ๋ชฉํ‘œ

  • www.aws9.pri/shop, .../blog, .../news ๋“ฑ Path ๊ธฐ๋ฐ˜ Routing
  • ๋ชจ๋“  ๋ผ์šฐํŒ…์€ Ingress๋กœ ํ†ตํ•ฉ
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: main-ingress
  namespace: team-shop
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  rules:
  - host: www.aws9.pri
    http:
      paths:
      - path: /shop(/|$)(.*)
        pathType: Prefix
        backend:
          service:
            name: shop-svc
            port:
              number: 80

๊ฐ ์„œ๋น„์Šค(blog/news ๋“ฑ)๋Š” namespace์™€ svc ์ด๋ฆ„๋งŒ ๋ฐ”๊ฟ”์„œ ๋™์ผ ๊ตฌ์กฐ๋กœ ์ž‘์„ฑํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.


๐Ÿ”„ 7๋‹จ๊ณ„: etcd ๋ฐฑ์—…/๋ณต์›

โœ… ์ ˆ์ฐจ ์š”์•ฝ

  1. etcd ๋ฐฑ์—…:
ETCDCTL_API=3 etcdctl snapshot save /backup/etcd-snapshot.db \
--endpoints=https://127.0.0.1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key
  1. pod ๋˜๋Š” deployment ์‚ญ์ œ
  2. ๋ณต์› ์ ˆ์ฐจ (ํ…Œ์ŠคํŠธ ํด๋Ÿฌ์Šคํ„ฐ๋‚˜ ์žฌ๋ถ€ํŒ… ํ•„์š”):
ETCDCTL_API=3 etcdctl snapshot restore /backup/etcd-snapshot.db \
--data-dir /var/lib/etcd-from-backup
  1. kubelet์„ ์žฌ์‹œ์ž‘ํ•˜๊ฑฐ๋‚˜ etcd๋ฅผ ๋ณต์›๋œ ๋””๋ ‰ํ† ๋ฆฌ๋กœ ๊ต์ฒด

๐Ÿ“ฆ 8๋‹จ๊ณ„: ๊ธฐํƒ€ ์‚ฌํ•ญ (Node Label / Taint / Toleration ๋“ฑ)

  • ํŠน์ • Pod๊ฐ€ ํŠน์ • ๋…ธ๋“œ์—๋งŒ ๋ฐฐ์น˜๋˜๋„๋ก ํ•˜๋ ค๋ฉด:
kubectl label node node1 disktype=ssd

Pod ์„ค์ •:

spec:
  nodeSelector:
    disktype: ssd
  • taint๊ฐ€ ์žˆ๋Š” ๋…ธ๋“œ์— ๋ฐฐ์น˜ํ•˜๋ ค๋ฉด:
kubectl taint node node2 dedicated=group1:NoSchedule

Pod toleration ์„ค์ •:

tolerations:
- key: "dedicated"
  operator: "Equal"
  value: "group1"
  effect: "NoSchedule"

๊ด€๋ จ๊ธ€ ๋”๋ณด๊ธฐ