쿠버네티스
는 컨테이너 런타임을 통해 컨테이너를 다루는 도구를 말한다. 여러 서버에 컨테이너를 분산 배치하거나 문제가 생긴 컨테이너를 교체하는 등의 일을 해주며, 이를 컨테이너 오케스트레이션
이라고 한다.
Pod
Kubernetes의 기본 실행 단위이다.
하나 이상의 컨테이너로 구성되며, 같은 네트워크 환경에서 실행된다.
각 Pod는 자체 IP 주소를 가지며, 컨테이너들 간의 내부 통신이 가능하다.
Service
Pod들을 외부와 연결하거나 클러스터 내에서 접근할 수 있게 한다.
로드 밸런싱, 서비스 디스커버리 등을 제공하여 여러 Pod들을 단일 IP로 묶어 관리한다.
Deployment
애플리케이션의 상태를 정의하고, 업데이트를 관리한다.
애플리케이션의 버전 관리와 자동 롤백, 확장 등을 지원한다.
ReplicaSet
특정 수의 Pod 복제본을 항상 유지하기 위해 사용한다.
Deployment에 의해 관리되며, Pod의 수를 자동으로 조정한다.
Namespace
클러스터 내에서 리소스를 논리적으로 분리할 수 있는 방법이다.
여러 환경에서 동일한 리소스 이름을 사용하면서도 충돌을 방지할 수 있다.
Node
Kubernetes 클러스터 내에서 애플리케이션을 실행하는 서버이다.
각 Node는 컨테이너를 실행할 수 있는 하나 이상의 Kubelet 프로세스를 실행하고 있다.
Ingress
외부 HTTP/HTTPS 요청을 클러스터 내부 서비스로 라우팅하는 규칙을 정의한다.
일반적으로 로드 밸런서와 함께 사용되며, URL 경로 기반으로 요청을 처리할 수 있다.
ConfigMap과 Secret
애플리케이션에 대한 설정 정보를 저장하는 방법입니다.
ConfigMap은 텍스트 기반 설정 정보를, Secret은 암호화된 민감한 정보를 저장합니다.
자동화
: 컨테이너의 배포, 확장, 복구를 자동으로 처리한다.확장성
: 애플리케이션의 요구 사항에 맞게 클러스터 리소스를 동적으로 확장할 수 있다.자원 최적화
: 클러스터 내 리소스를 효율적으로 분배하고, 여러 애플리케이션을 격리하여 실행할 수 있다.운영 간소화
: 상태 관리, 모니터링, 로깅 등을 중앙에서 처리할 수 있어 운영 효율성이 높다.# 미니쿠베 시작 (단일노드)
minikube start
minikube start -n 2 # 다중노드
minikube start --driver=docker # 도커를 가상 드라이버로 설정
minikube start -p helloworld # helloworld라는 이름의 프로필로 생성
# 미니쿠베 프로필 목록 확인
minikube profile list
# 현재 사용중인 프로필 확인
minikube profile
# 프로필 변경
minikube profile helloworld # helloword로 변경
# 미니쿠베 상태 확인
minikube status
# 미니쿠베 일시정지
minikube pause
# 미니쿠베 종료
minikube stop
# 미니쿠베 삭제
minikube delete # 미니쿠베 삭제하기
> brew install minikube
==> Auto-updating Homebrew...
Adjust how often this is run with HOMEBREW_AUTO_UPDATE_SECS or disable with
HOMEBREW_NO_AUTO_UPDATE. Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).
.
.
.
==> minikube
zsh completions have been installed to:
/opt/homebrew/share/zsh/site-functions
> minikube start
>
😄 Darwin 15.2 (arm64) 의 minikube v1.34.0
✨ 자동적으로 docker 드라이버가 선택되었습니다
📌 Using Docker Desktop driver with root privileges
👍 Starting "minikube" primary control-plane node in "minikube" cluster
🚜 Pulling base image v0.0.45 ...
💾 쿠버네티스 v1.31.0 을 다운로드 중 ...
> preloaded-images-k8s-v18-v1...: 307.61 MiB / 307.61 MiB 100.00% 21.89 M
> gcr.io/k8s-minikube/kicbase...: 441.45 MiB / 441.45 MiB 100.00% 12.76 M
🔥 Creating docker container (CPUs=2, Memory=7789MB) ...
🐳 쿠버네티스 v1.31.0 을 Docker 27.2.0 런타임으로 설치하는 중
▪ 인증서 및 키를 생성하는 중 ...
▪ 컨트롤 플레인을 부팅하는 중 ...
▪ RBAC 규칙을 구성하는 중 ...
🔗 bridge CNI (Container Networking Interface) 를 구성하는 중 ...
🔎 Kubernetes 구성 요소를 확인...
▪ Using image gcr.io/k8s-minikube/storage-provisioner:v5
🌟 애드온 활성화 : storage-provisioner, default-storageclass
🏄 끝났습니다! kubectl이 "minikube" 클러스터와 "default" 네임스페이스를 기본적으로 사용하도록 구성되었습니다.
# 실행 상태 확인
> minikube status
>
minikube
type: Control Plane
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured
# 기존 실행 중인 미니쿠베 종료
> minikube stop
>
✋ "minikube" 노드를 중지하는 중 ...
🛑 "minikube"를 SSH로 전원을 끕니다 ...
🛑 1개의 노드가 중지되었습니다.
# testProfile 이라는 이름의 프로필 생성 및 시작
> minikube start -p testProfile
>
😄 [testProfile] Darwin 15.2 (arm64) 의 minikube v1.34.0
✨ 자동적으로 docker 드라이버가 선택되었습니다
📌 Using Docker Desktop driver with root privileges
👍 Starting "testProfile" primary control-plane node in "testProfile" cluster
🚜 Pulling base image v0.0.45 ...
🔥 Creating docker container (CPUs=2, Memory=7789MB) ...
🐳 쿠버네티스 v1.31.0 을 Docker 27.2.0 런타임으로 설치하는 중
▪ 인증서 및 키를 생성하는 중 ...
▪ 컨트롤 플레인을 부팅하는 중 ...
▪ RBAC 규칙을 구성하는 중 ...
🔗 bridge CNI (Container Networking Interface) 를 구성하는 중 ...
🔎 Kubernetes 구성 요소를 확인...
▪ Using image gcr.io/k8s-minikube/storage-provisioner:v5
🌟 애드온 활성화 : storage-provisioner, default-storageclass
🏄 끝났습니다! kubectl이 "testProfile" 클러스터와 "default" 네임스페이스를 기본적으로 사용하도록 구성되었습니다.
# 생성된 프로필 리스트 확인
> minikube profile list
>
|-------------|-----------|---------|--------------|------|---------|---------|-------|----------------|--------------------|
| Profile | VM Driver | Runtime | IP | Port | Version | Status | Nodes | Active Profile | Active Kubecontext |
|-------------|-----------|---------|--------------|------|---------|---------|-------|----------------|--------------------|
| minikube | docker | docker | ---.---.--.- | 8443 | v1.31.0 | Stopped | 1 | * | |
| testProfile | docker | docker | ---.---.--.- | 8443 | v1.31.0 | Running | 1 | | * |
|-------------|-----------|---------|--------------|------|---------|---------|-------|----------------|--------------------|
# 프로필 변경
> minikube profile minikube
> ✅ minikube profile was successfully set to minikube
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-web
spec:
replicas: 1
selector:
matchLabels:
app: my-web
template:
metadata:
labels:
app: my-web
spec:
containers:
- name: my-web
image: my-web:1.0
ports:
- containerPort: 3000
---
apiVersion: v1
kind: Service
metadata:
name: my-web-service
spec:
selector:
app: my-web
ports:
- protocol: TCP
port: 80
targetPort: 3000
type: NodePort
eval $(minikube docker-env)
# 미니쿠베 도커 활성화
> eval $(minikube docker-env)
# 도커 이미지 빌드
> docker build -t my-web:1.0 .
> [+] Building 19.2s (12/12) FINISHED
# 이미지 전송
> minikube image load my-web:1.0
# kubectl 컨텍스트 확인
> kubectl config current-context
> minikube
# 컨텍스트가 미니쿠베가 아니라면 미니쿠베로 변경 필요
> kubectl config use-context minikube
# 쿠버네티스 배포
> kubectl apply -f deployment.yaml
>
deployment.apps/my-web created
service/my-web-service created
kubectl get all
# minikube 리소스 확인
> kubectl get all
>
NAME READY STATUS RESTARTS AGE
pod/my-web-57bc889df4-zc84r 0/1 ImagePullBackOff 0 29m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/my-web-service NodePort 10.101.36.165 <none> 80:32136/TCP 29m
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 163m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/my-web 0/1 1 0 29m
NAME DESIRED CURRENT READY AGE
replicaset.apps/my-web-57bc889df4 1 1 0 29m
Node Port
는 외부에서 접근할 수 있도록 포트를 개방한다. Node Port
를 사용하면 외부에서 지정된 포트를 통해 서비스에 접속할 수 있다.
apiVersion: v1
kind: Service
metadata:
name: my-web-service
spec:
type: NodePort
selector:
app: my-web
ports:
- protocol: TCP
port: 8080 # 외부에서 접근할 기본 포트
targetPort: 3000 # 컨테이너의 포트
nodePort: 30001 # 외부에서 접근할 NodePort (범위: 30000-32767)
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
> kubectl apply -f deployment.yaml
> deployment.apps/my-web created
> kubectl apply -f service.yaml
> service/my-web-service configured
http://<Minikube IP>:<NodePort>
url로 접근 가능하게 된다
kubectl get pods
# Pod 상태 확인. Running으로 표시되어야 정상 실행중인 것
> kubectl get pods
>
NAME READY STATUS RESTARTS AGE
my-web-78f96cb845-8fhlw 1/1 Running 0 12s
# 미니쿠베 ip 확인
> minikube ip
> 192.168.49.2
# service 확인. 접근 가능 url 출력
> minikube service my-web-service
>
|-----------|------------------|-------------|---------------------------|
| NAMESPACE | NAME | TARGET PORT | URL |
|-----------|------------------|-------------|---------------------------|
| default | my-web-service | 8080 | http://192.168.49.2:30001 |
|-----------|------------------|-------------|---------------------------|
🏃 my-web-service 서비스의 터널을 시작하는 중
|-----------|------------------|-------------|------------------------|
| NAMESPACE | NAME | TARGET PORT | URL |
|-----------|------------------|-------------|------------------------|
| default | my-web-service | | http://127.0.0.1:64487 |
|-----------|------------------|-------------|------------------------|
🎉 Opening service default/my-web-service in default browser...
❗ darwin 에서 Docker 드라이버를 사용하고 있기 때문에, 터미널을 열어야 실행할 수 있습니다
kubectl get deployment
kubectl describe pod <POD_NAME>
kubectl delete service city-web-service
kubectl delete all --all
# deployment 확인
> kubectl get deployment
>
NAME READY UP-TO-DATE AVAILABLE AGE
my-web 1/1 1 1 15m
# pod 로그 확인
> kubectl describe pod my-web-57bc889df4-lh2dh
>
Name: my-web-57bc889df4-lh2dh
Namespace: default
Priority: 0
Service Account: default
Node: minikube/192.168.49.2
Start Time: Mon, 30 Dec 2024 10:57:12 +0900
Labels: app=my-web
pod-template-hash=57bc889df4
Annotations: <none>
Status: Pending
IP: 10.244.0.7
IPs:
IP: 10.244.0.7
Controlled By: ReplicaSet/my-web-57bc889df4
Containers:
my-web:
Container ID:
Image: my-web:1.0
Image ID:
Port: 3000/TCP
Host Port: 0/TCP
State: Waiting
Reason: ImagePullBackOff
Ready: False
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-wlpqw (ro)
.
.
.
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 2m20s default-scheduler Successfully assigned default/my-web-57bc889df4-lh2dh to minikube
Normal Pulling 41s (x4 over 2m20s) kubelet Pulling image "my-web:1.0"
Warning Failed 39s (x4 over 2m17s) kubelet Failed to pull image "my-web:1.0": Error response from daemon: pull access denied for my-web, repository does not exist or may require 'docker login': denied: requested access to the resource is denied
Warning Failed 39s (x4 over 2m17s) kubelet Error: ErrImagePull
Warning Failed 25s (x6 over 2m17s) kubelet Error: ImagePullBackOff
Normal BackOff 13s (x7 over 2m17s) kubelet Back-off pulling image "my-web:1.0"
Port Forwarding
은 로컬 머신에서 쿠버네티스 Pod으로 트래픽을 포워딩하는 방법이다. 외부에서 서비스에 바로 접근할 수 없고 개발 환경에 사용한다.
항목 | NodePort | Port Forwarding |
---|---|---|
접속 범위 | 외부에서 접근 가능 | 로컬 머신에서만 접속 가능 |
설정 위치 | service.yaml 파일에 포트(NodePort ) 지정 | kubectl port-forward 명령어로 설정 |
용도 | 프로덕션 환경, 다른 시스템에서 접근할 때 사용 | 개발 및 테스트 환경에서 임시로 연결할 때 사용 |
kubectl port-forward pod/<POD_NAME> <LOCAL_PORT>:<POD_PORT>
> kubectl port-forward pod/my-web-78f96cb845-8fhlw 8080:3000
>
Forwarding from 127.0.0.1:8080 -> 3000
Forwarding from [::1]:8080 -> 3000
Handling connection for 8080
Handling connection for 8080
Handling connection for 8080
...
http://localhost:<LOCAL_PORT>
로 접근 가능하다.
볼륨
: pod 내의 컨테이너에서 데이터를 저장하거나 공유할 수 있도록 하는 스토리지
컨테이너는 일시적인 파일 시스템을 사용하므로, 컨테이너가 재시작되거나 삭제되면 데이터가 사라진다. 이러한 문제를 해결하기 위해 볼륨을 사용한다.
볼륨 특징
- pod 내의 여러 컨테이너에서 동시에 접근할 수 있다. 이를 통해 컨테이너 간 데이터 공유가 가능하다.
- 볼륨은 pod의 라이프사이클 동안 유지가 된다. 데이터 영속성을 제공한다.
볼륨 주요 타입
volumes:
- name: my-empty-dir
emptyDir: {}
volumes:
- name: my-host-path
hostPath:
path: /path/on/host
type: Directory
volumes:
- name: my-pvc
persistentVolumeClaim:
claimName: my-pvc
mkdir -p /Users/unknown/k8sData
# 실행 중인 컨테이너 확인
> docker ps
>
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
73b86b6b2209 gcr.io/k8s-minikube/kicbase:v0.0.45 "/usr/local/bin/entr…" 3 days ago Up 24 hours 127.0.0.1:55674->22/tcp, 127.0.0.1:55675->2376/tcp, 127.0.0.1:55677->5000/tcp, 127.0.0.1:55678->8443/tcp, 127.0.0.1:55676->32443/tcp minikube
# 컨테이너 쉘 실행
> docker exec -it 73b86b6b2209 /bin/bash
# 내부 경로 확인
> ls /
CHANGELOG Release.key bin boot data dev docker.key etc home kic.txt kind lib media mnt opt proc root run sbin srv sys tmp usr var version.json
> ls /mnt
> data
로컬의 /Users/unknown/k8sData
디렉토리를 컨테이너 /mnt/data
로 마운트
> minikube mount /Users/unknown/k8sData:/mnt/data
>
📁 Mounting host path /Users/unknown/k8sData into VM as /mnt/data ...
▪ Mount type: 9p
▪ User ID: docker
▪ Group ID: docker
▪ 버전: 9p2000.L
▪ 메시지 사이즈: 262144
▪ 옵션: map[]
▪ 연결된 주소: 127.0.0.1:51567
🚀 Userspace file server: ufs starting
✅ Successfully mounted /Users/unknown/k8sData to /mnt/data
hostPath 볼륨을 사용하여 /Users/unknown/k8sData 로컬 디렉토리를 컨테이너 내 /app/data 경로에 마운트
containers:
volumeMounts:
- mountPath: /mnt/data # 컨테이너 내 경로
name: my-web-volume
volumes:
- name: my-web-volume
hostPath:
path: /mnt/data # Minikube VM에서 마운트된 경로
type: Directory
수정한 deployment.yaml 파일을 쿠버네티스 클러스터에 적용하여 pod을 배포한다.
명령어 실행 시 쿠버네티스 클러스터 내에 pod이 생성되고, hostPath
볼륨이 설정되어 로컬 PC의 /Users/unknown/k8sData
디렉토리와 컨테이너의 /app/data
경로가 연결된다.
> kubectl apply -f deployment.yaml
> deployment.apps/my-web configured
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-web
spec:
replicas: 2 # replicas 2
selector:
matchLabels:
app: my-web
template:
metadata:
labels:
app: my-web
spec:
containers:
- name: my-web
image: my-web:1.0
imagePullPolicy: Never
ports:
- containerPort: 3000
volumeMounts:
- mountPath: /mnt/data
name: my-web-volume
volumes:
- name: my-web-volume
hostPath:
path: /mnt/data
type: Directory
> kubectl apply -f deployment.yaml
> deployment.apps/my-web configured
# pod이 2개 실행되고 있는지 확인 (status: Running이어야 정상 실행중)
> kubectl get pods
>
NAME READY STATUS RESTARTS AGE
my-web-54677cd5f6-ffftd 1/1 Running 0 8s
my-web-54677cd5f6-ht6fm 1/1 Running 0 8s
# pod 하나 죽여보기
> kubectl delete pod my-web-54677cd5f6-ffftd
> pod "my-web-54677cd5f6-ffftd" deleted
# 새로운 pod이 자동으로 생성되는지 확인
> kubectl get pods
>
NAME READY STATUS RESTARTS AGE
my-web-54677cd5f6-bchbh 1/1 Running 0 4s
my-web-54677cd5f6-ht6fm 1/1 Running 0 5m37s