쿠버네티스 요약 정리

Posted by Albert 67Day 8Hour 9Min 28Sec ago [2025-12-01]

1. 쿠버네티스란?

쿠버네티스(Kubernetes, 약칭 K8s)는 컨테이너화된 애플리케이션의 배포, 확장, 관리를 자동화하는 오픈소스 컨테이너 오케스트레이션 플랫폼입니다. 구글이 개발하여 2014년에 오픈소스로 공개했으며, 현재는 CNCF(Cloud Native Computing Foundation)에서 관리하고 있습니다.

주요 기능

  • 자동화된 배포 및 롤백: 애플리케이션의 새 버전을 자동으로 배포하고 문제 발생 시 이전 버전으로 롤백
  • 자동 스케일링: 부하에 따라 자동으로 Pod 수를 증감
  • 서비스 디스커버리 및 로드 밸런싱: 컨테이너에 고유 IP와 DNS 이름 제공
  • 스토리지 오케스트레이션: 로컬 스토리지, 클라우드 스토리지 등을 자동으로 마운트
  • 자가 치유: 실패한 컨테이너를 자동으로 재시작하고 교체
  • 시크릿 및 구성 관리: 민감한 정보를 안전하게 저장하고 관리

2. 쿠버네티스 아키텍처

컨트롤 플레인 컴포넌트

  • kube-apiserver: 쿠버네티스 API를 노출하는 컴포넌트
  • etcd: 모든 클러스터 데이터를 저장하는 키-값 저장소
  • kube-scheduler: 새로운 Pod를 실행할 노드를 선택
  • kube-controller-manager: 컨트롤러 프로세스를 실행
  • cloud-controller-manager: 클라우드 제공자와 상호작용

노드 컴포넌트

  • kubelet: 각 노드에서 실행되며 Pod가 실행되도록 보장
  • kube-proxy: 네트워크 규칙을 관리하고 트래픽을 라우팅
  • 컨테이너 런타임: Docker, containerd, CRI-O 등

주요 개념

  • Pod: 쿠버네티스의 가장 작은 배포 단위, 하나 이상의 컨테이너 그룹
  • Service: Pod의 논리적 집합과 접근 정책 정의
  • Deployment: Pod와 ReplicaSet의 선언적 업데이트 제공
  • Namespace: 클러스터 리소스를 논리적으로 분리

3. 설치 방법

3.1 Minikube 설치 (로컬 개발용)

Minikube는 로컬에서 단일 노드 쿠버네티스 클러스터를 실행할 수 있게 해줍니다.

Ubuntu/Linux에서 설치:

' Minikube 다운로드
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64

' 설치
sudo install minikube-linux-amd64 /usr/local/bin/minikube

' Minikube 시작
minikube start

' 상태 확인
minikube status

macOS에서 설치:

' Homebrew 사용
brew install minikube

' Minikube 시작
minikube start

Windows에서 설치:

' Chocolatey 사용
choco install minikube

' 또는 직접 다운로드
' https://minikube.sigs.k8s.io/docs/start/

3.2 kubectl 설치

kubectl은 쿠버네티스 클러스터와 상호작용하는 CLI 도구입니다.

' Linux
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl

' macOS
brew install kubectl

' Windows (Chocolatey)
choco install kubernetes-cli

' 설치 확인
kubectl version --client

3.3 프로덕션 환경 설치 (kubeadm)

사전 요구사항:

  • 2GB 이상 RAM
  • 2개 이상의 CPU
  • 네트워크 연결

고유한 hostname, MAC 주소, product_uuid

' 1. Docker 설치 (컨테이너 런타임)
sudo apt-get update
sudo apt-get install -y docker.io
sudo systemctl enable docker
sudo systemctl start docker

' 2. kubeadm, kubelet, kubectl 설치
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl

curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.28/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg

echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.28/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list

sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl

' 3. 클러스터 초기화 (마스터 노드에서)
sudo kubeadm init --pod-network-cidr=10.244.0.0/16

' 4. kubectl 설정
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

' 5. 네트워크 플러그인 설치 (Flannel)
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

' 6. 워커 노드 추가 (워커 노드에서 실행)
' kubeadm init 명령 후 출력된 join 명령을 실행
sudo kubeadm join <master-ip>:6443 --token <token> --discovery-token-ca-cert-hash sha256:<hash>

4. 기본 사용법

4.1 클러스터 정보 확인

' 클러스터 정보
kubectl cluster-info

' 노드 목록
kubectl get nodes

' 모든 리소스 확인
kubectl get all --all-namespaces

' 특정 네임스페이스의 리소스
kubectl get all -n default

4.2 Pod 생성 및 관리

' 간단한 Pod 실행
kubectl run nginx --image=nginx

' Pod 목록 확인
kubectl get pods

' Pod 상세 정보
kubectl describe pod nginx

' Pod 로그 확인
kubectl logs nginx

' Pod에 접속
kubectl exec -it nginx -- /bin/bash

' Pod 삭제
kubectl delete pod nginx

4.3 Deployment 생성

' Deployment 생성
kubectl create deployment nginx-deployment --image=nginx --replicas=3

' Deployment 확인
kubectl get deployments

' Deployment 상세 정보
kubectl describe deployment nginx-deployment

' Pod 목록 확인 (라벨로 필터링)
kubectl get pods -l app=nginx-deployment

' 스케일링
kubectl scale deployment nginx-deployment --replicas=5

' 롤링 업데이트
kubectl set image deployment/nginx-deployment nginx=nginx:1.21

' 롤아웃 상태 확인
kubectl rollout status deployment/nginx-deployment

' 롤백
kubectl rollout undo deployment/nginx-deployment

4.4 Service 생성

' Deployment를 외부에 노출
kubectl expose deployment nginx-deployment --type=LoadBalancer --port=80

' Service 확인
kubectl get services

' Service 상세 정보
kubectl describe service nginx-deployment

5. 실전 예제

예제 1: 간단한 웹 애플리케이션 배포

simple-webapp-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: webapp-deployment
  labels:
    app: webapp
spec:
  replicas: 3
  selector:
    matchLabels:
      app: webapp
  template:
    metadata:
      labels:
        app: webapp
    spec:
      containers:
      - name: webapp
        image: nginx:1.21
        ports:
        - containerPort: 80
        resources:
          requests:
            memory: "64Mi"
            cpu: "250m"
          limits:
            memory: "128Mi"
            cpu: "500m"
        livenessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 3
          periodSeconds: 3
        readinessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 5
          periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
  name: webapp-service
spec:
  type: LoadBalancer
  selector:
    app: webapp
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
    nodePort: 30080

배포,상태확인, 접속테스트

' 배포 적용
kubectl apply -f simple-webapp-deployment.yaml

' 상태 확인
kubectl get deployments
kubectl get pods
kubectl get services

' 접속 테스트 (Minikube 사용 시)
minikube service webapp-service

' 또는 포트 포워딩
kubectl port-forward service/webapp-service 8080:80
' 브라우저에서 http://localhost:8080 접속

예제 2: ConfigMap과 Secret 사용

configmap-secret-example.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  APP_ENV: "production"
  APP_DEBUG: "false"
  DATABASE_HOST: "mysql-service"
  DATABASE_PORT: "3306"
  config.json: |
    {
      "server": {
        "port": 8080,
        "host": "0.0.0.0"
      },
      "logging": {
        "level": "info"
      }
    }
---
apiVersion: v1
kind: Secret
metadata:
  name: app-secret
type: Opaque
data:
  ' Base64로 인코딩된 값
  ' echo -n 'admin' | base64
  DATABASE_USER: YWRtaW4=
  ' echo -n 'password123' | base64
  DATABASE_PASSWORD: cGFzc3dvcmQxMjM=
  ' echo -n 'my-secret-key' | base64
  API_KEY: bXktc2VjcmV0LWtleQ==
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-with-config
spec:
  replicas: 2
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: myapp
        image: nginx:alpine
        ports:
        - containerPort: 8080
        
        ' 환경 변수로 ConfigMap 사용
        env:
        - name: APP_ENV
          valueFrom:
            configMapKeyRef:
              name: app-config
              key: APP_ENV
        - name: APP_DEBUG
          valueFrom:
            configMapKeyRef:
              name: app-config
              key: APP_DEBUG
        
        ' 환경 변수로 Secret 사용
        - name: DATABASE_USER
          valueFrom:
            secretKeyRef:
              name: app-secret
              key: DATABASE_USER
        - name: DATABASE_PASSWORD
          valueFrom:
            secretKeyRef:
              name: app-secret
              key: DATABASE_PASSWORD
        
        ' ConfigMap을 볼륨으로 마운트
        volumeMounts:
        - name: config-volume
          mountPath: /etc/config
        
        ' Secret을 볼륨으로 마운트
        - name: secret-volume
          mountPath: /etc/secrets
          readOnly: true
      
      volumes:
      - name: config-volume
        configMap:
          name: app-config
      - name: secret-volume
        secret:
          secretName: app-secret


' ConfigMap과 Secret 배포
kubectl apply -f configmap-secret-example.yaml

' ConfigMap 확인
kubectl get configmap
kubectl describe configmap app-config

' Secret 확인
kubectl get secret
kubectl describe secret app-secret

' Pod 내부에서 환경 변수 확인
kubectl exec -it <pod-name> -- env | grep APP_

' 마운트된 파일 확인
kubectl exec -it <pod-name> -- cat /etc/config/config.json

예제 3: 퍼시스턴트 볼륨을 사용하는 MySQL 데이터베이스

mysql-persistent-volume.yaml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: mysql-pv
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: manual
  hostPath:
    path: "/mnt/data/mysql"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pvc
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
  storageClassName: manual
---
apiVersion: v1
kind: Secret
metadata:
  name: mysql-secret
type: Opaque
data:
  ' echo -n 'rootpassword' | base64
  mysql-root-password: cm9vdHBhc3N3b3Jk
  ' echo -n 'mydb' | base64
  mysql-database: bXlkYg==
  ' echo -n 'user' | base64
  mysql-user: dXNlcg==
  ' echo -n 'userpassword' | base64
  mysql-password: dXNlcnBhc3N3b3Jk
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:8.0
        ports:
        - containerPort: 3306
          name: mysql
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-secret
              key: mysql-root-password
        - name: MYSQL_DATABASE
          valueFrom:
            secretKeyRef:
              name: mysql-secret
              key: mysql-database
        - name: MYSQL_USER
          valueFrom:
            secretKeyRef:
              name: mysql-secret
              key: mysql-user
        - name: MYSQL_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-secret
              key: mysql-password
        volumeMounts:
        - name: mysql-storage
          mountPath: /var/lib/mysql
        resources:
          requests:
            memory: "256Mi"
            cpu: "250m"
          limits:
            memory: "512Mi"
            cpu: "500m"
        livenessProbe:
          exec:
            command:
            - mysqladmin
            - ping
            - -h
            - localhost
          initialDelaySeconds: 30
          periodSeconds: 10
          timeoutSeconds: 5
        readinessProbe:
          exec:
            command:
            - mysql
            - -h
            - localhost
            - -u
            - root
            - -p$MYSQL_ROOT_PASSWORD
            - -e
            - SELECT 1
          initialDelaySeconds: 10
          periodSeconds: 5
          timeoutSeconds: 1
      volumes:
      - name: mysql-storage
        persistentVolumeClaim:
          claimName: mysql-pvc
---
apiVersion: v1
kind: Service
metadata:
  name: mysql-service
spec:
  type: ClusterIP
  selector:
    app: mysql
  ports:
  - protocol: TCP
    port: 3306
    targetPort: 3306
' MySQL 배포
kubectl apply -f mysql-persistent-volume.yaml

' 상태 확인
kubectl get pv
kubectl get pvc
kubectl get pods

' MySQL에 접속하여 테스트
kubectl exec -it <mysql-pod-name> -- mysql -u root -p
' 패스워드: rootpassword

' MySQL 서비스를 통한 접속 테스트 (다른 Pod에서)
kubectl run -it --rm --image=mysql:8.0 --restart=Never mysql-client -- mysql -h mysql-service -u user -p
' 패스워드: userpassword

예제 4: Ingress를 사용한 HTTP 라우팅

' 먼저 두 개의 다른 애플리케이션 배포
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app1-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: app1
  template:
    metadata:
      labels:
        app: app1
    spec:
      containers:
      - name: app1
        image: hashicorp/http-echo
        args:
        - "-text=Hello from App 1"
        ports:
        - containerPort: 5678
---
apiVersion: v1
kind: Service
metadata:
  name: app1-service
spec:
  selector:
    app: app1
  ports:
  - protocol: TCP
    port: 80
    targetPort: 5678
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app2-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: app2
  template:
    metadata:
      labels:
        app: app2
    spec:
      containers:
      - name: app2
        image: hashicorp/http-echo
        args:
        - "-text=Hello from App 2"
        ports:
        - containerPort: 5678
---
apiVersion: v1
kind: Service
metadata:
  name: app2-service
spec:
  selector:
    app: app2
  ports:
  - protocol: TCP
    port: 80
    targetPort: 5678
---
' Ingress 리소스
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  rules:
  - host: myapp.example.com
    http:
      paths:
      - path: /app1
        pathType: Prefix
        backend:
          service:
            name: app1-service
            port:
              number: 80
      - path: /app2
        pathType: Prefix
        backend:
          service:
            name: app2-service
            port:
              number: 80
  ' 기본 백엔드 (선택사항)
  ' defaultBackend:
  '   service:
  '     name: default-service
  '     port:
  '       number: 80


' Ingress Controller 설치 (Minikube)
minikube addons enable ingress

' 또는 일반 클러스터에서 NGINX Ingress Controller 설치
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.1/deploy/static/provider/cloud/deploy.yaml

' Ingress 배포
kubectl apply -f ingress-example.yaml

' 상태 확인
kubectl get ingress
kubectl describe ingress example-ingress

' /etc/hosts 파일에 추가 (로컬 테스트)
' <Minikube-IP> myapp.example.com
' Minikube IP 확인: minikube ip

' 테스트
curl http://myapp.example.com/app1
curl http://myapp.example.com/app2

예제 5: HorizontalPodAutoscaler (자동 스케일링)

horizontal-pod-autoscaler.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: php-apache
spec:
  replicas: 1
  selector:
    matchLabels:
      app: php-apache
  template:
    metadata:
      labels:
        app: php-apache
    spec:
      containers:
      - name: php-apache
        image: registry.k8s.io/hpa-example
        ports:
        - containerPort: 80
        resources:
          requests:
            cpu: 200m
            memory: 128Mi
          limits:
            cpu: 500m
            memory: 256Mi
---
apiVersion: v1
kind: Service
metadata:
  name: php-apache
spec:
  selector:
    app: php-apache
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: php-apache-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: php-apache
  minReplicas: 1
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 50
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 70
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
      - type: Percent
        value: 50
        periodSeconds: 15
      - type: Pods
        value: 2
        periodSeconds: 15
      selectPolicy: Min
    scaleUp:
      stabilizationWindowSeconds: 0
      policies:
      - type: Percent
        value: 100
        periodSeconds: 15
      - type: Pods
        value: 4
        periodSeconds: 15
      selectPolicy: Max


' Metrics Server 설치 (필수)
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

' Minikube의 경우
minikube addons enable metrics-server

' HPA 배포
kubectl apply -f horizontal-pod-autoscaler.yaml

' HPA 상태 확인
kubectl get hpa
kubectl describe hpa php-apache-hpa

' 부하 테스트를 위한 별도 터미널에서 실행
kubectl run -i --tty load-generator --rm --image=busybox --restart=Never -- /bin/sh -c "while sleep 0.01; do wget -q -O- http://php-apache; done"

' 다른 터미널에서 HPA 동작 모니터링
kubectl get hpa php-apache-hpa --watch

' Pod 수 변화 확인
kubectl get pods --watch

6. 유용한 kubectl 명령어

' 리소스 생성
kubectl create -f <filename>.yaml
kubectl apply -f <filename>.yaml

' 리소스 조회
kubectl get pods
kubectl get deployments
kubectl get services
kubectl get all

' 상세 정보 확인
kubectl describe pod <pod-name>
kubectl describe deployment <deployment-name>

' 로그 확인
kubectl logs <pod-name>
kubectl logs -f <pod-name>  ' 실시간 로그
kubectl logs <pod-name> --previous  ' 이전 컨테이너 로그

' 리소스 수정
kubectl edit deployment <deployment-name>
kubectl scale deployment <deployment-name> --replicas=5

' 리소스 삭제
kubectl delete pod <pod-name>
kubectl delete deployment <deployment-name>
kubectl delete -f <filename>.yaml

' Pod 내부 접속
kubectl exec -it <pod-name> -- /bin/bash

' 포트 포워딩
kubectl port-forward <pod-name> 8080:80

' 컨텍스트 관리
kubectl config get-contexts
kubectl config use-context <context-name>

' 네임스페이스 관리
kubectl create namespace <namespace-name>
kubectl get pods -n <namespace-name>
kubectl config set-context --current --namespace=<namespace-name>

' 리소스 사용량 확인
kubectl top nodes
kubectl top pods

' 레이블 관리
kubectl label pods <pod-name> env=production
kubectl get pods -l env=production

' YAML 출력
kubectl get deployment <deployment-name> -o yaml
kubectl get pod <pod-name> -o json

7. 모범 사례

  1. 네임스페이스 사용: 리소스를 논리적으로 분리하여 관리
  2. 리소스 제한 설정: requests와 limits를 항상 설정
  3. Health Check 구현: livenessProbe와 readinessProbe 활용
  4. 레이블과 셀렉터 활용: 리소스 관리 및 필터링
  5. ConfigMap/Secret 사용: 설정과 코드 분리
  6. 버전 관리: 선언적 방식(YAML)으로 리소스 관리
  7. 롤링 업데이트 전략: 무중단 배포 구현
  8. 모니터링과 로깅: Prometheus, Grafana, ELK 스택 활용








LIST

Copyright © 2014 visionboy.me All Right Reserved.