본문 바로가기
DevOps

Kubernetes 입문 가이드: 컨테이너 오케스트레이션의 모든 것

by devcomet 2025. 5. 28.
728x90
반응형

Kubernetes 입문 가이드: 컨테이너 오케스트레이션의 모든 것

 

쿠버네티스(Kubernetes)는 현대 DevOps 환경에서 가장 중요한 컨테이너 오케스트레이션 플랫폼입니다.

구글에서 개발된 이 오픈소스 시스템은 컨테이너화된 애플리케이션의 배포, 확장, 관리를 자동화하여 개발팀과 운영팀의 생산성을 혁신적으로 향상시켰습니다.

이 가이드에서는 쿠버네티스 초보자부터 중급자까지 단계별로 학습할 수 있는 실무 중심의 내용을 다룹니다.

쿠버네티스란 무엇인가?

쿠버네티스는 컨테이너 오케스트레이션 플랫폼으로, 여러 서버에 분산된 컨테이너들을 효율적으로 관리하는 시스템입니다.

Docker 컨테이너를 대규모로 운영할 때 발생하는 복잡성을 해결하기 위해 설계되었으며, 자동 스케일링, 로드 밸런싱, 서비스 디스커버리, 롤링 업데이트 등의 기능을 제공합니다.

쿠버네티스의 핵심 특징

자동화된 컨테이너 배포 및 스케줄링
쿠버네티스는 사용자가 정의한 리소스 요구사항과 제약 조건을 기반으로 컨테이너를 최적의 노드에 자동으로 배치합니다.

CPU, 메모리, 스토리지 등의 리소스를 효율적으로 활용하여 시스템 전체의 성능을 최적화합니다.

선언적 구성 관리
YAML이나 JSON 형식의 매니페스트 파일을 통해 원하는 상태를 선언하면, 쿠버네티스가 현재 상태를 목표 상태로 수렴시킵니다.

이러한 선언적 접근 방식은 인프라스트럭처 코드화(Infrastructure as Code)의 핵심 원칙을 실현합니다.

쿠버네티스 아키텍처 이해하기

쿠버네티스 클러스터는 마스터 노드와 워커 노드로 구성되며, 각각 고유한 역할과 컴포넌트를 가지고 있습니다.

마스터 노드 컴포넌트

API 서버 (kube-apiserver)
모든 쿠버네티스 API 요청을 처리하는 중앙 관리 컴포넌트입니다.

kubectl 명령어, 대시보드, 그리고 다른 쿠버네티스 컴포넌트들이 API 서버를 통해 클러스터와 상호작용합니다.

etcd
쿠버네티스 클러스터의 모든 구성 데이터와 상태 정보를 저장하는 분산 키-값 저장소입니다.

클러스터의 두뇌 역할을 하며, 고가용성과 일관성을 보장합니다.

컨트롤러 매니저 (kube-controller-manager)
다양한 컨트롤러들을 실행하여 클러스터의 상태를 지속적으로 모니터링하고 원하는 상태로 유지합니다.

레플리케이션 컨트롤러, 엔드포인트 컨트롤러, 네임스페이스 컨트롤러 등이 포함됩니다.

스케줄러 (kube-scheduler)
새로 생성된 파드를 적절한 워커 노드에 할당하는 역할을 담당합니다.

리소스 요구사항, 정책 제약, 친화성 규칙 등을 고려하여 최적의 배치 결정을 내립니다.

워커 노드 컴포넌트

kubelet
각 워커 노드에서 실행되는 에이전트로, 파드의 생명주기를 관리합니다.

API 서버로부터 파드 스펙을 받아 컨테이너 런타임과 협력하여 컨테이너를 실행하고 상태를 보고합니다.

kube-proxy
클러스터 내 네트워킹을 담당하며, 서비스 디스커버리와 로드 밸런싱을 구현합니다.

iptables나 IPVS를 이용하여 트래픽을 적절한 파드로 라우팅합니다.

컨테이너 런타임
실제 컨테이너를 실행하는 소프트웨어입니다.

Docker, containerd, CRI-O 등이 지원되며, 컨테이너 런타임 인터페이스(CRI)를 통해 kubelet과 통신합니다.

쿠버네티스 핵심 오브젝트 완벽 가이드

쿠버네티스에서 애플리케이션을 배포하고 관리하기 위해서는 다양한 오브젝트들을 이해해야 합니다.

각 오브젝트는 특정한 목적과 기능을 가지고 있으며, 이들을 조합하여 복잡한 애플리케이션 아키텍처를 구성할 수 있습니다.

파드(Pod) - 쿠버네티스의 기본 단위

파드는 쿠버네티스에서 배포 가능한 가장 작은 단위로, 하나 이상의 컨테이너를 포함합니다.

같은 파드 내의 컨테이너들은 네트워크와 스토리지를 공유하며, 항상 동일한 노드에 스케줄링됩니다.

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.21
    ports:
    - containerPort: 80
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"

위 예제는 nginx 컨테이너를 실행하는 간단한 파드 정의입니다.

리소스 요청량과 제한량을 명시하여 클러스터 리소스를 효율적으로 관리할 수 있습니다.

디플로이먼트(Deployment) - 애플리케이션 배포 관리

디플로이먼트는 파드의 선언적 업데이트를 제공하며, 레플리카 수, 롤링 업데이트 전략 등을 정의할 수 있습니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.21
        ports:
        - containerPort: 80
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 1

이 디플로이먼트는 nginx 파드 3개를 유지하며, 롤링 업데이트 시 최대 1개의 파드가 사용 불가능하고 최대 1개의 추가 파드를 생성할 수 있도록 설정합니다.

서비스(Service) - 네트워크 추상화

서비스는 파드 집합에 대한 안정적인 네트워크 엔드포인트를 제공합니다.

파드는 언제든지 재생성될 수 있지만, 서비스를 통해 일관된 접근 방법을 유지할 수 있습니다.

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
  type: ClusterIP

ClusterIP 타입의 서비스는 클러스터 내부에서만 접근 가능한 가상 IP를 제공합니다.

외부 접근이 필요한 경우 LoadBalancer나 NodePort 타입을 사용할 수 있습니다.

쿠버네티스 설치 및 환경 구성

쿠버네티스를 학습하고 실습하기 위해서는 적절한 환경을 구성해야 합니다.

개발 환경부터 프로덕션 환경까지 다양한 설치 옵션이 있으며, 각각의 장단점을 이해하고 상황에 맞는 선택을 해야 합니다.

로컬 개발 환경 구성

Minikube를 이용한 단일 노드 클러스터
Minikube는 로컬 환경에서 쿠버네티스를 학습하기에 가장 적합한 도구입니다.

VirtualBox, VMware, Docker 등 다양한 드라이버를 지원하며, 간단한 명령어로 클러스터를 시작할 수 있습니다.

# Minikube 설치 (macOS 기준)
brew install minikube

# 클러스터 시작
minikube start --driver=docker --cpus=2 --memory=4096

# 대시보드 실행
minikube dashboard

# 클러스터 상태 확인
kubectl cluster-info

Docker Desktop의 쿠버네티스 기능
Docker Desktop을 사용하는 경우 설정에서 쿠버네티스를 활성화하면 별도 설치 없이 사용할 수 있습니다.

Windows와 macOS에서 GUI를 통해 쉽게 관리할 수 있어 초보자에게 추천됩니다.

Kind (Kubernetes in Docker)
Kind는 Docker 컨테이너를 노드로 사용하여 쿠버네티스 클러스터를 생성하는 도구입니다.

멀티 노드 클러스터 구성이 가능하며, CI/CD 파이프라인에서도 자주 사용됩니다.

# Kind 설치
go install sigs.k8s.io/kind@latest

# 멀티 노드 클러스터 생성
cat <<EOF | kind create cluster --config=-
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
- role: worker
EOF

kubectl 설치 및 설정

kubectl은 쿠버네티스 클러스터와 상호작용하기 위한 명령줄 도구입니다.

모든 쿠버네티스 운영 작업은 kubectl을 통해 수행되므로, 설치와 기본 사용법을 숙지해야 합니다.

# kubectl 설치 (Linux 기준)
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x kubectl
sudo mv kubectl /usr/local/bin/

# 버전 확인
kubectl version --client

# 클러스터 연결 확인
kubectl cluster-info

# 현재 컨텍스트 확인
kubectl config current-context

# 사용 가능한 컨텍스트 목록
kubectl config get-contexts

쿠버네티스 실습 예제 - 웹 애플리케이션 배포

실제 웹 애플리케이션을 쿠버네티스에 배포하는 전체 과정을 단계별로 살펴보겠습니다.

이 예제를 통해 쿠버네티스의 핵심 개념들이 실제로 어떻게 작동하는지 이해할 수 있습니다.

1단계: 애플리케이션 컨테이너화

먼저 간단한 Node.js 애플리케이션을 생성하고 Docker 이미지로 빌드합니다.

// app.js
const express = require('express');
const app = express();
const port = 3000;

app.get('/', (req, res) => {
  res.json({
    message: 'Hello Kubernetes!',
    timestamp: new Date().toISOString(),
    hostname: process.env.HOSTNAME
  });
});

app.get('/health', (req, res) => {
  res.status(200).json({ status: 'OK' });
});

app.listen(port, () => {
  console.log(`App running on port ${port}`);
});
# Dockerfile
FROM node:16-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node", "app.js"]
# Docker 이미지 빌드
docker build -t my-k8s-app:v1.0 .

# 로컬 레지스트리에 푸시 (실습용)
docker tag my-k8s-app:v1.0 localhost:5000/my-k8s-app:v1.0
docker push localhost:5000/my-k8s-app:v1.0

2단계: 쿠버네티스 매니페스트 작성

애플리케이션을 쿠버네티스에 배포하기 위한 YAML 파일들을 작성합니다.

# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-k8s-app
  labels:
    app: my-k8s-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-k8s-app
  template:
    metadata:
      labels:
        app: my-k8s-app
    spec:
      containers:
      - name: app
        image: localhost:5000/my-k8s-app:v1.0
        ports:
        - containerPort: 3000
        env:
        - name: NODE_ENV
          value: "production"
        livenessProbe:
          httpGet:
            path: /health
            port: 3000
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /health
            port: 3000
          initialDelaySeconds: 5
          periodSeconds: 5
        resources:
          requests:
            memory: "128Mi"
            cpu: "100m"
          limits:
            memory: "256Mi"
            cpu: "200m"
---
apiVersion: v1
kind: Service
metadata:
  name: my-k8s-app-service
spec:
  selector:
    app: my-k8s-app
  ports:
  - protocol: TCP
    port: 80
    targetPort: 3000
  type: LoadBalancer

3단계: 애플리케이션 배포 및 확인

작성한 매니페스트 파일을 사용하여 애플리케이션을 배포합니다.

# 애플리케이션 배포
kubectl apply -f deployment.yaml

# 배포 상태 확인
kubectl get deployments
kubectl get pods
kubectl get services

# 파드 로그 확인
kubectl logs -l app=my-k8s-app

# 서비스 포트 포워딩으로 접근 테스트
kubectl port-forward service/my-k8s-app-service 8080:80

# 다른 터미널에서 테스트
curl http://localhost:8080

4단계: 스케일링 및 업데이트

쿠버네티스의 핵심 기능인 스케일링과 롤링 업데이트를 실습해봅니다.

# 수평 확장
kubectl scale deployment my-k8s-app --replicas=5

# 스케일링 확인
kubectl get pods -w

# 이미지 업데이트
kubectl set image deployment/my-k8s-app app=localhost:5000/my-k8s-app:v1.1

# 롤아웃 상태 확인
kubectl rollout status deployment/my-k8s-app

# 롤아웃 히스토리 확인
kubectl rollout history deployment/my-k8s-app

# 이전 버전으로 롤백
kubectl rollout undo deployment/my-k8s-app

쿠버네티스 네트워킹 심화 이해

쿠버네티스의 네트워킹은 복잡하지만 매우 강력한 기능을 제공합니다.

클러스터 내 통신부터 외부 노출까지 다양한 네트워킹 개념을 이해해야 효과적으로 애플리케이션을 운영할 수 있습니다.

클러스터 네트워킹 모델

파드 네트워킹
모든 파드는 고유한 IP 주소를 가지며, NAT 없이 직접 통신할 수 있습니다.

같은 파드 내의 컨테이너는 localhost를 통해 통신하며, 포트만으로 구분됩니다.

서비스 네트워킹
서비스는 파드 집합에 대한 안정적인 네트워크 인터페이스를 제공합니다.

클러스터 DNS를 통해 서비스 이름으로 접근할 수 있으며, 자동으로 로드 밸런싱이 수행됩니다.

인그레스(Ingress) - HTTP/HTTPS 라우팅

인그레스는 클러스터 외부에서 내부 서비스로의 HTTP/HTTPS 라우팅을 관리합니다.

도메인 기반 라우팅, SSL 터미네이션, 로드 밸런싱 등의 기능을 제공합니다.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-app-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
  tls:
  - hosts:
    - myapp.example.com
    secretName: myapp-tls
  rules:
  - host: myapp.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: my-k8s-app-service
            port:
              number: 80
      - path: /api
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 8080

네트워크 정책(Network Policy)

네트워크 정책을 통해 파드 간 통신을 제어하고 보안을 강화할 수 있습니다.

마이크로서비스 아키텍처에서 서비스 간 통신을 세밀하게 제어하는 데 필수적입니다.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all-ingress
spec:
  podSelector: {}
  policyTypes:
  - Ingress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend-to-backend
spec:
  podSelector:
    matchLabels:
      app: backend
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: frontend
    ports:
    - protocol: TCP
      port: 8080

쿠버네티스 스토리지 관리

상태를 가진 애플리케이션을 쿠버네티스에서 운영하기 위해서는 영구 스토리지에 대한 이해가 필요합니다.

볼륨, 영구 볼륨, 스토리지 클래스 등의 개념을 통해 데이터의 지속성을 보장할 수 있습니다.

볼륨(Volume) 타입별 활용법

emptyDir 볼륨
파드 내 컨테이너 간 임시 데이터 공유에 사용됩니다.

파드가 삭제되면 데이터도 함께 사라지므로 캐시나 임시 파일 저장에 적합합니다.

hostPath 볼륨
노드의 파일시스템을 직접 마운트하여 사용합니다.

로그 수집이나 시스템 모니터링 도구에서 주로 사용되지만, 포터빌리티가 떨어지는 단점이 있습니다.

persistentVolume과 persistentVolumeClaim
영구 스토리지를 추상화하여 관리하는 쿠버네티스의 핵심 스토리지 개념입니다.

apiVersion: v1
kind: PersistentVolume
metadata:
  name: mysql-pv
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: fast-ssd
  hostPath:
    path: /mnt/data/mysql
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  storageClassName: fast-ssd
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:8.0
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-secret
              key: password
        ports:
        - containerPort: 3306
        volumeMounts:
        - name: mysql-storage
          mountPath: /var/lib/mysql
      volumes:
      - name: mysql-storage
        persistentVolumeClaim:
          claimName: mysql-pvc

스토리지 클래스와 동적 프로비저닝

스토리지 클래스를 통해 다양한 스토리지 타입을 정의하고 자동으로 볼륨을 생성할 수 있습니다.

클라우드 환경에서는 각 제공업체의 스토리지 서비스와 연동하여 효율적인 스토리지 관리가 가능합니다.

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast-ssd
provisioner: kubernetes.io/aws-ebs
parameters:
  type: gp3
  iops: "3000"
  throughput: "125"
  encrypted: "true"
allowVolumeExpansion: true
reclaimPolicy: Delete

쿠버네티스 보안 강화 방법

쿠버네티스 클러스터의 보안은 다층적 접근 방식을 통해 구현해야 합니다.

인증, 권한 부여, 네트워크 보안, 파드 보안 등 다양한 측면에서 보안을 강화해야 합니다.

RBAC (Role-Based Access Control)

RBAC를 통해 사용자와 서비스 계정의 권한을 세밀하게 제어할 수 있습니다.

최소 권한 원칙을 적용하여 보안을 강화하는 것이 중요합니다.

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: development
  name: pod-reader
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "watch", "list"]
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods
  namespace: development
subjects:
- kind: User
  name: developer
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

파드 보안 표준(Pod Security Standards)

파드 보안 표준을 통해 컨테이너의 보안 설정을 강제할 수 있습니다.

Privileged, Baseline, Restricted 등의 보안 레벨을 정의하여 클러스터 전반의 보안을 향상시킵니다.

apiVersion: v1
kind: Pod
metadata:
  name: secure-pod
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    fsGroup: 2000
  containers:
  - name: app
    image: nginx:1.21
    securityContext:
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true
      capabilities:
        drop:
        - ALL
    volumeMounts:
    - name: tmp-volume
      mountPath: /tmp
  volumes:
  - name: tmp-volume
    emptyDir: {}

시크릿(Secret) 관리

민감한 정보는 시크릿 오브젝트를 통해 안전하게 관리해야 합니다.

데이터베이스 패스워드, API 키, TLS 인증서 등을 암호화하여 저장하고 파드에 주입할 수 있습니다.

apiVersion: v1
kind: Secret
metadata:
  name: app-secrets
type: Opaque
data:
  database-password: cGFzc3dvcmQxMjM=  # base64 encoded
  api-key: YWJjZGVmZ2hpams=
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: secure-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: secure-app
  template:
    metadata:
      labels:
        app: secure-app
    spec:
      containers:
      - name: app
        image: my-secure-app:latest
        env:
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: app-secrets
              key: database-password
        - name: API_KEY
          valueFrom:
            secretKeyRef:
              name: app-secrets
              key: api-key

쿠버네티스 모니터링 및 로깅

운영 환경에서 쿠버네티스 클러스터를 안정적으로 관리하기 위해서는 종합적인 모니터링과 로깅 시스템이 필요합니다.

Prometheus, Grafana, ELK 스택 등을 활용하여 가시성을 확보하고 문제를 사전에 감지할 수 있습니다.

Prometheus와 Grafana를 이용한 메트릭 모니터링

Prometheus는 쿠버네티스 환경에서 가장 널리 사용되는 모니터링 솔루션입니다.

시계열 데이터베이스를 기반으로 하며, 강력한 쿼리 언어인 PromQL을 제공하여 복잡한 메트릭 분석이 가능합니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: prometheus
spec:
  replicas: 1
  selector:
    matchLabels:
      app: prometheus
  template:
    metadata:
      labels:
        app: prometheus
    spec:
      containers:
      - name: prometheus
        image: prom/prometheus:v2.40.0
        ports:
        - containerPort: 9090
        volumeMounts:
        - name: config-volume
          mountPath: /etc/prometheus
        - name: storage-volume
          mountPath: /prometheus
        args:
          - '--config.file=/etc/prometheus/prometheus.yml'
          - '--storage.tsdb.path=/prometheus'
          - '--web.console.libraries=/etc/prometheus/console_libraries'
          - '--web.console.templates=/etc/prometheus/consoles'
      volumes:
      - name: config-volume
        configMap:
          name: prometheus-config
      - name: storage-volume
        persistentVolumeClaim:
          claimName: prometheus-pvc

ServiceMonitor를 통한 자동 서비스 디스커버리
Prometheus Operator를 사용하면 ServiceMonitor 리소스를 통해 자동으로 모니터링 대상을 발견하고 설정할 수 있습니다.

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: app-metrics
  labels:
    app: my-k8s-app
spec:
  selector:
    matchLabels:
      app: my-k8s-app
  endpoints:
  - port: metrics
    interval: 30s
    path: /metrics

중앙화된 로깅 시스템 구축

Fluentd를 이용한 로그 수집
Fluentd는 DaemonSet으로 배포하여 모든 노드의 로그를 수집하고 중앙 저장소로 전송합니다.

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd
  namespace: kube-system
spec:
  selector:
    matchLabels:
      name: fluentd
  template:
    metadata:
      labels:
        name: fluentd
    spec:
      serviceAccount: fluentd
      tolerations:
      - key: node-role.kubernetes.io/master
        effect: NoSchedule
      containers:
      - name: fluentd
        image: fluent/fluentd-kubernetes-daemonset:v1-debian-elasticsearch
        env:
        - name: FLUENT_ELASTICSEARCH_HOST
          value: "elasticsearch.logging.svc.cluster.local"
        - name: FLUENT_ELASTICSEARCH_PORT
          value: "9200"
        volumeMounts:
        - name: varlog
          mountPath: /var/log
        - name: varlibdockercontainers
          mountPath: /var/lib/docker/containers
          readOnly: true
      volumes:
      - name: varlog
        hostPath:
          path: /var/log
      - name: varlibdockercontainers
        hostPath:
          path: /var/lib/docker/containers

알림 및 경고 시스템

Alertmanager 설정
Prometheus와 연동하여 메트릭 기반 알림을 관리합니다.

Slack, 이메일, PagerDuty 등 다양한 채널로 알림을 전송할 수 있습니다.

apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: kubernetes-alerts
spec:
  groups:
  - name: kubernetes.rules
    rules:
    - alert: PodCrashLooping
      expr: rate(kube_pod_container_status_restarts_total[15m]) > 0
      for: 5m
      labels:
        severity: warning
      annotations:
        summary: "Pod {{ $labels.pod }} is crash looping"
        description: "Pod {{ $labels.pod }} in namespace {{ $labels.namespace }} is restarting frequently"

    - alert: HighMemoryUsage
      expr: (container_memory_usage_bytes / container_spec_memory_limit_bytes) > 0.9
      for: 10m
      labels:
        severity: critical
      annotations:
        summary: "High memory usage detected"
        description: "Container {{ $labels.container }} in pod {{ $labels.pod }} is using {{ $value | humanizePercentage }} of its memory limit"

쿠버네티스 CI/CD 파이프라인 구축

쿠버네티스와 CI/CD를 통합하면 애플리케이션의 지속적 배포와 운영이 가능합니다.

GitOps, Helm, ArgoCD 등의 도구를 활용하여 현대적인 배포 파이프라인을 구성할 수 있습니다.

GitOps 워크플로우 구현

ArgoCD를 이용한 선언적 배포
ArgoCD는 Git 저장소의 매니페스트를 기준으로 쿠버네티스 클러스터의 상태를 동기화합니다.

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-k8s-app
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/company/k8s-manifests
    targetRevision: HEAD
    path: production/my-app
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
    - CreateNamespace=true
  revisionHistoryLimit: 10

Helm을 이용한 패키지 관리

Helm은 쿠버네티스의 패키지 매니저로, 복잡한 애플리케이션을 템플릿화하여 관리할 수 있습니다.

# values.yaml
replicaCount: 3

image:
  repository: my-k8s-app
  pullPolicy: IfNotPresent
  tag: "1.0.0"

service:
  type: ClusterIP
  port: 80

ingress:
  enabled: true
  className: "nginx"
  annotations:
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
  hosts:
    - host: myapp.example.com
      paths:
        - path: /
          pathType: ImplementationSpecific
  tls:
    - secretName: myapp-tls
      hosts:
        - myapp.example.com

resources:
  limits:
    cpu: 500m
    memory: 512Mi
  requests:
    cpu: 250m
    memory: 256Mi

autoscaling:
  enabled: true
  minReplicas: 3
  maxReplicas: 10
  targetCPUUtilizationPercentage: 80

Helm 차트 구조

my-app/
├── Chart.yaml
├── values.yaml
├── templates/
│   ├── deployment.yaml
│   ├── service.yaml
│   ├── ingress.yaml
│   ├── configmap.yaml
│   ├── secret.yaml
│   ├── hpa.yaml
│   └── _helpers.tpl
└── charts/

GitHub Actions을 이용한 자동화 파이프라인

# .github/workflows/deploy.yml
name: Build and Deploy to Kubernetes

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write

    steps:
    - name: Checkout repository
      uses: actions/checkout@v3

    - name: Log in to Container Registry
      uses: docker/login-action@v2
      with:
        registry: ${{ env.REGISTRY }}
        username: ${{ github.actor }}
        password: ${{ secrets.GITHUB_TOKEN }}

    - name: Extract metadata
      id: meta
      uses: docker/metadata-action@v4
      with:
        images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
        tags: |
          type=ref,event=branch
          type=ref,event=pr
          type=sha,prefix={{branch}}-

    - name: Build and push Docker image
      uses: docker/build-push-action@v4
      with:
        context: .
        push: true
        tags: ${{ steps.meta.outputs.tags }}
        labels: ${{ steps.meta.outputs.labels }}

    - name: Set up Kubectl
      uses: azure/setup-kubectl@v3
      with:
        version: 'v1.28.0'

    - name: Configure kubectl
      run: |
        echo "${{ secrets.KUBE_CONFIG }}" | base64 -d > kubeconfig
        export KUBECONFIG=kubeconfig

    - name: Deploy to Kubernetes
      run: |
        export KUBECONFIG=kubeconfig
        helm upgrade --install my-app ./helm/my-app \
          --set image.tag=${{ github.sha }} \
          --set image.repository=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} \
          --namespace production \
          --create-namespace \
          --wait

쿠버네티스 성능 최적화 및 트러블슈팅

운영 환경에서 쿠버네티스 클러스터의 성능을 최적화하고 문제를 해결하는 것은 매우 중요합니다.

리소스 관리, 스케줄링 최적화, 네트워크 튜닝 등 다양한 측면에서 성능을 개선할 수 있습니다.

리소스 관리 최적화

Horizontal Pod Autoscaler (HPA) 설정
CPU, 메모리, 커스텀 메트릭을 기반으로 파드를 자동으로 확장하거나 축소할 수 있습니다.

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: my-app-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-k8s-app
  minReplicas: 3
  maxReplicas: 20
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80
  - type: Pods
    pods:
      metric:
        name: requests_per_second
      target:
        type: AverageValue
        averageValue: "100"
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
      - type: Percent
        value: 10
        periodSeconds: 60
    scaleUp:
      stabilizationWindowSeconds: 0
      policies:
      - type: Percent
        value: 100
        periodSeconds: 15
      - type: Pods
        value: 4
        periodSeconds: 15
      selectPolicy: Max

Vertical Pod Autoscaler (VPA) 활용
VPA는 파드의 CPU와 메모리 요청량을 자동으로 조정하여 리소스 효율성을 높입니다.

apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: my-app-vpa
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-k8s-app
  updatePolicy:
    updateMode: "Auto"
  resourcePolicy:
    containerPolicies:
    - containerName: app
      maxAllowed:
        cpu: 1
        memory: 2Gi
      minAllowed:
        cpu: 100m
        memory: 128Mi
      controlledResources: ["cpu", "memory"]

일반적인 문제 해결 방법

파드 스케줄링 문제 해결
파드가 Pending 상태에 머물러 있을 때의 일반적인 원인과 해결 방법을 알아봅시다.

# 파드 상태 확인
kubectl get pods -o wide

# 파드 이벤트 확인
kubectl describe pod <pod-name>

# 노드 리소스 상태 확인
kubectl top nodes
kubectl describe nodes

# 리소스 부족 시 노드 추가 또는 파드 리소스 요청량 조정
# PVC 문제 시 스토리지 클래스 및 볼륨 상태 확인
kubectl get pv,pvc
kubectl describe pvc <pvc-name>

네트워크 연결 문제 디버깅
서비스 간 통신 문제를 해결하는 체계적인 접근 방법입니다.

# 서비스 및 엔드포인트 확인
kubectl get svc,endpoints
kubectl describe svc <service-name>

# DNS 해석 테스트
kubectl run debug --image=busybox -it --rm -- nslookup <service-name>

# 네트워크 정책 확인
kubectl get networkpolicies
kubectl describe networkpolicy <policy-name>

# 파드 간 연결 테스트
kubectl exec -it <source-pod> -- wget -qO- <target-service>:80

성능 모니터링 및 분석

클러스터 성능 메트릭 수집

# 노드 리소스 사용량 확인
kubectl top nodes

# 파드별 리소스 사용량 확인
kubectl top pods --all-namespaces

# 네임스페이스별 리소스 사용량
kubectl top pods -n <namespace>

# 컨테이너별 상세 메트릭 (metrics-server 필요)
kubectl get --raw "/apis/metrics.k8s.io/v1beta1/nodes" | jq .

애플리케이션 성능 최적화

# 효율적인 리소스 설정 예시
apiVersion: apps/v1
kind: Deployment
metadata:
  name: optimized-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: optimized-app
  template:
    metadata:
      labels:
        app: optimized-app
    spec:
      containers:
      - name: app
        image: my-app:latest
        resources:
          requests:
            memory: "128Mi"
            cpu: "100m"
          limits:
            memory: "256Mi"
            cpu: "200m"
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10
          timeoutSeconds: 5
          failureThreshold: 3
        readinessProbe:
          httpGet:
            path: /ready
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 5
          timeoutSeconds: 3
          failureThreshold: 3
        env:
        - name: JAVA_OPTS
          value: "-Xmx128m -XX:+UseG1GC -XX:MaxGCPauseMillis=200"
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                  - optimized-app
              topologyKey: kubernetes.io/hostname

쿠버네티스 마이그레이션 전략

기존 애플리케이션을 쿠버네티스로 마이그레이션하는 것은 신중한 계획과 단계적 접근이 필요합니다.

레거시 시스템부터 클라우드 네이티브 애플리케이션까지 다양한 시나리오에 대한 마이그레이션 전략을 살펴보겠습니다.

마이그레이션 계획 수립

현재 상태 평가 (Assessment)
기존 인프라스트럭처와 애플리케이션을 분석하여 마이그레이션 우선순위를 결정합니다.

종속성 매핑, 리소스 사용량 분석, 보안 요구사항 검토 등을 통해 체계적인 계획을 수립해야 합니다.

단계적 마이그레이션 접근법

1단계: Lift and Shift (재호스팅)
- 기존 애플리케이션을 최소한의 변경으로 컨테이너화
- 모놀리식 애플리케이션을 단일 컨테이너로 패키징

2단계: Re-platforming (재플랫폼화)
- 쿠버네티스 네이티브 기능 활용
- ConfigMap, Secret, Service 등 도입

3단계: Refactoring (리팩토링)
- 마이크로서비스 아키텍처로 분해
- 클라우드 네이티브 패턴 적용

데이터베이스 마이그레이션

StatefulSet을 이용한 상태 있는 애플리케이션 배포
데이터베이스와 같은 상태 있는 애플리케이션은 StatefulSet을 사용하여 안정적으로 운영할 수 있습니다.

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql
spec:
  serviceName: mysql
  replicas: 3
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:8.0
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-secret
              key: root-password
        ports:
        - containerPort: 3306
          name: mysql
        volumeMounts:
        - name: mysql-data
          mountPath: /var/lib/mysql
        - name: mysql-config
          mountPath: /etc/mysql/conf.d
      volumes:
      - name: mysql-config
        configMap:
          name: mysql-config
  volumeClaimTemplates:
  - metadata:
      name: mysql-data
    spec:
      accessModes: ["ReadWriteOnce"]
      resources:
        requests:
          storage: 100Gi
      storageClassName: fast-ssd

마이크로서비스 분해 전략

도메인 주도 설계 (Domain-Driven Design) 적용
비즈니스 도메인을 기준으로 모놀리식 애플리케이션을 마이크로서비스로 분해합니다.

각 서비스는 독립적인 데이터베이스를 가지고, API를 통해 통신합니다.

# 사용자 서비스
apiVersion: apps/v1
kind: Deployment
metadata:
  name: user-service
  labels:
    app: user-service
    version: v1
spec:
  replicas: 3
  selector:
    matchLabels:
      app: user-service
  template:
    metadata:
      labels:
        app: user-service
        version: v1
    spec:
      containers:
      - name: user-service
        image: user-service:v1.0
        ports:
        - containerPort: 8080
        env:
        - name: DATABASE_URL
          valueFrom:
            secretKeyRef:
              name: user-db-secret
              key: url
        - name: ORDER_SERVICE_URL
          value: "http://order-service:8080"
---
# 주문 서비스
apiVersion: apps/v1
kind: Deployment
metadata:
  name: order-service
  labels:
    app: order-service
    version: v1
spec:
  replicas: 3
  selector:
    matchLabels:
      app: order-service
  template:
    metadata:
      labels:
        app: order-service
        version: v1
    spec:
      containers:
      - name: order-service
        image: order-service:v1.0
        ports:
        - containerPort: 8080
        env:
        - name: DATABASE_URL
          valueFrom:
            secretKeyRef:
              name: order-db-secret
              key: url
        - name: PAYMENT_SERVICE_URL
          value: "http://payment-service:8080"

쿠버네티스 고급 패턴 및 운영 전략

엔터프라이즈 환경에서 쿠버네티스를 안정적으로 운영하기 위한 고급 패턴과 전략을 다룹니다.

멀티 클러스터 관리, 재해 복구, 보안 강화 등 프로덕션 환경에서 필요한 실무 지식을 제공합니다.

멀티 클러스터 아키텍처

클러스터 페더레이션과 관리
여러 클러스터를 효율적으로 관리하기 위해 GitOps와 클러스터 API를 활용합니다.

# Cluster API를 이용한 클러스터 정의
apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
  name: production-cluster
  namespace: default
spec:
  clusterNetwork:
    pods:
      cidrBlocks: ["192.168.0.0/16"]
    services:
      cidrBlocks: ["10.128.0.0/12"]
  infrastructureRef:
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: AWSCluster
    name: production-cluster
  controlPlaneRef:
    kind: KubeadmControlPlane
    apiVersion: controlplane.cluster.x-k8s.io/v1beta1
    name: production-cluster-control-plane

재해 복구 및 백업 전략

Velero를 이용한 클러스터 백업
Velero는 쿠버네티스 클러스터의 리소스와 영구 볼륨을 백업하고 복원하는 도구입니다.

apiVersion: velero.io/v1
kind: Schedule
metadata:
  name: daily-backup
spec:
  schedule: "0 2 * * *"  # 매일 오전 2시
  template:
    includedNamespaces:
    - production
    - staging
    excludedResources:
    - events
    - events.events.k8s.io
    storageLocation: default
    volumeSnapshotLocations:
    - default
    ttl: 720h0m0s  # 30일 보관

보안 강화를 위한 고급 설정

Pod Security Policy 및 OPA Gatekeeper
Open Policy Agent (OPA) Gatekeeper를 사용하여 클러스터 전반의 보안 정책을 강제할 수 있습니다.

apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
  name: k8srequiredsecuritycontext
spec:
  crd:
    spec:
      names:
        kind: K8sRequiredSecurityContext
      validation:
        openAPIV3Schema:
          type: object
          properties:
            runAsNonRoot:
              type: boolean
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8srequiredsecuritycontext

        violation[{"msg": msg}] {
          container := input.review.object.spec.containers[_]
          not container.securityContext.runAsNonRoot
          msg := "Container must run as non-root user"
        }

        violation[{"msg": msg}] {
          not input.review.object.spec.securityContext.runAsNonRoot
          msg := "Pod must run as non-root user"
        }
---
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredSecurityContext
metadata:
  name: must-run-as-nonroot
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
    excludedNamespaces: ["kube-system", "gatekeeper-system"]
  parameters:
    runAsNonRoot: true

쿠버네티스 학습 로드맵 및 인증

쿠버네티스 전문가가 되기 위한 체계적인 학습 경로와 실무에서 인정받는 인증 과정을 안내합니다.

단계별 학습 목표를 설정하고 지속적인 성장을 위한 가이드라인을 제시합니다.

단계별 학습 경로

초급 단계 (1-3개월)

  • 컨테이너와 Docker 기초 이해
  • 쿠버네티스 아키텍처 및 핵심 개념 학습
  • kubectl 기본 명령어 숙달
  • Pod, Service, Deployment 실습

중급 단계 (3-6개월)

  • 고급 워크로드 관리 (StatefulSet, DaemonSet, Job)
  • 네트워킹 및 스토리지 심화 학습
  • RBAC 및 보안 설정
  • Helm을 이용한 패키지 관리

고급 단계 (6-12개월)

  • 클러스터 운영 및 모니터링
  • CI/CD 파이프라인 구축
  • 커스텀 리소스 및 오퍼레이터 개발
  • 멀티 클러스터 관리

인증 프로그램

CKA (Certified Kubernetes Administrator)
클러스터 관리, 네트워킹, 스토리지, 보안 등 운영 측면에 중점을 둔 인증입니다.

CKAD (Certified Kubernetes Application Developer)
애플리케이션 개발자를 위한 인증으로, 애플리케이션 배포 및 관리에 집중합니다.

CKS (Certified Kubernetes Security Specialist)
쿠버네티스 보안 전문가를 위한 고급 인증으로, 클러스터 보안 강화에 특화되어 있습니다.

실습 환경 추천

온라인 실습 플랫폼

  • Play with Kubernetes (labs.play-with-k8s.com)
  • Katacoda 쿠버네티스 시나리오
  • Kubernetes 공식 튜토리얼

로컬 개발 환경

  • Docker Desktop + Kubernetes
  • Minikube
  • Kind (Kubernetes in Docker)

클라우드 기반 실습

  • Google Kubernetes Engine (GKE) 무료 티어
  • Amazon EKS
  • Azure AKS

마치며: 쿠버네티스로 시작하는 클라우드 네이티브 여정

쿠버네티스는 단순한 컨테이너 오케스트레이션 도구를 넘어서 현대적인 애플리케이션 개발과 운영의 패러다임을 바꾸고 있습니다.

이 가이드에서 다룬 내용들은 쿠버네티스 여정의 시작점일 뿐이며, 지속적인 학습과 실습을 통해 전문성을 기를 수 있습니다.

성공적인 쿠버네티스 도입을 위한 핵심 원칙

점진적 접근 방식
한 번에 모든 것을 바꾸려 하지 말고, 작은 프로젝트부터 시작하여 경험을 쌓아가는 것이 중요합니다.

팀의 역량과 조직의 준비도를 고려하여 단계적으로 도입하세요.

자동화 우선 사고
수동 작업을 최소화하고, Infrastructure as Code와 GitOps를 통해 모든 것을 자동화하려 노력하세요.

이는 오류를 줄이고 운영 효율성을 크게 향상시킵니다.

보안을 처음부터 고려
Security by Design 원칙에 따라 처음부터 보안을 염두에 두고 설계하세요.

RBAC, 네트워크 정책, 파드 보안 표준 등을 적극 활용하여 방어 계층을 구축해야 합니다.

관찰 가능성 확보
로깅, 메트릭, 트레이싱을 통해 시스템의 상태를 지속적으로 모니터링하고 문제를 사전에 감지할 수 있는 체계를 구축하세요.

미래 전망과 발전 방향

쿠버네티스 생태계는 빠르게 발전하고 있으며, 새로운 기술과 패턴들이 지속적으로 등장하고 있습니다.

서비스 메시 (Service Mesh)
Istio, Linkerd와 같은 서비스 메시 기술이 마이크로서비스 간 통신을 더욱 안전하고 효율적으로 만들어 가고 있습니다.

서버리스 및 FaaS
Knative, OpenFaaS 등을 통해 쿠버네티스에서도 서버리스 컴퓨팅이 가능해지고 있습니다.

AI/ML 워크로드
Kubeflow, MLflow 등을 활용하여 쿠버네티스에서 머신러닝 파이프라인을 구축하는 사례가 증가하고 있습니다.

엣지 컴퓨팅
K3s, MicroK8s 등 경량화된 쿠버네티스 배포판을 통해 엣지 환경에서도 컨테이너 오케스트레이션이 확산되고 있습니다.

실무 적용을 위한 마지막 조언

쿠버네티스를 학습할 때는 이론과 실습의 균형을 맞추는 것이 중요합니다.

공식 문서를 정기적으로 확인하고, 커뮤니티의 베스트 프랙티스를 따라가며, 실제 프로젝트에 적용해보는 경험을 쌓아가세요.

또한 DevOps 문화와 함께 쿠버네티스를 도입해야 진정한 효과를 얻을 수 있음을 잊지 마세요.

기술적인 도구는 수단일 뿐이며, 팀워크와 협업, 지속적인 개선 문화가 성공의 핵심입니다.

쿠버네티스와 함께하는 클라우드 네이티브 여정이 여러분의 개발 및 운영 역량을 한 단계 더 발전시키는 계기가 되기를 바랍니다.

728x90
반응형