쿠버네티스 요약 정리
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. 모범 사례
- 네임스페이스 사용: 리소스를 논리적으로 분리하여 관리
- 리소스 제한 설정: requests와 limits를 항상 설정
- Health Check 구현: livenessProbe와 readinessProbe 활용
- 레이블과 셀렉터 활용: 리소스 관리 및 필터링
- ConfigMap/Secret 사용: 설정과 코드 분리
- 버전 관리: 선언적 방식(YAML)으로 리소스 관리
- 롤링 업데이트 전략: 무중단 배포 구현
- 모니터링과 로깅: Prometheus, Grafana, ELK 스택 활용