쿠버네티스(Kubernetes, 줄여서 K8s)는 컨테이너화된 애플리케이션을 배포, 관리, 확장하는 데 필요한 대부분의 수동 프로세스를 자동화
하는 오픈소스 컨테이너 오케스트레이션 플랫폼입니다. 구글이 내부로 사용하던 Borg에서 발전하여 2015년에 공개한 이후로 사실상 표준 컨테이너 오케스트레이션 도구로 사용되고 있습니다.
쿠버네티스는 그리스어로 "조타수" 또는 "항해사"를 의미하는 Kybernetes에서 유래한 것처럼, 쿠버네티스는 컨테이너라는 바다에서 애플리케이션이라는 배를 안전하게 운항하도록 도와주는 역할을 합니다.
이에 쿠버네티스에서 사용되는 많은 도구들 또한 바다와 관련된 용어가 아이콘이 많습니다.
쿠버네티스는 애플리케이션의 코드, 구성 및 종속성을 번들링하는 컨테이너를 관리하기 위한 플랫폼으로, 자체 리소스를 사용하여 격리된 프로세스로 실행될 수 있습니다. 애플리케이션마다 쿠버네티스 파드(Pod)로 분류되는 컨테이너가 하나 또는 다수 제공됩니다.
가장 오래된 배포 방식은 물리적인 컴퓨터 한 대에 하나의 운영체제(OS)를 설치하고, 그 위에 여러 프로그램을 설치하는 방식이었습니다. 이 방식에는 다음과 같은 문제가 있었습니다.
이러한 문제를 해결하기 위해 가상화 개념이 등장했습니다. 가상머신(VM)을 기반으로 애플리케이션을 배포하는 방식입니다. 각 가상머신은 논리적으로 구분된 환경에서 실행되어 각기 다른 OS와 분리된 리소스를 가집니다.
그러나 VM이 많아질수록 성능과 실행 속도가 저하되고, 각 VM마다 게스트 OS를 설치해야 하는 부담이 있습니다.
VM의 한계를 극복하기 위해 컨테이너 기술이 발전했습니다. 컨테이너는 다음과 같은 특징을 가집니다.
도커(Docker)는 이러한 컨테이너화 기술을 구현한 플랫폼으로, 애플리케이션 실행에 필요한 환경을 하나의 이미지로 모아 다양한 환경에서 일관되게 실행할 수 있게 했습니다.
도커의 등장으로 컨테이너 기반 배포 방식이 보편화되었지만, 새로운 문제가 발생했습니다
이러한 배경에서 컨테이너 관리를 자동화할 도구의 필요성이 대두되었고, 이에 대한 해답으로 쿠버네티스가 등장하게 되었습니다.
쿠버네티스는 컨트롤 플레인 컴포넌트(마스터)와 노드 컴포넌트로 구성된 아키텍처를 가지고 있습니다.
Kubernetes 관리 서버
현재 상태와 원하는 상태를 지속적으로 확인하며 특정 이벤트에 따라 특정 동작을 수행하는 컨트롤
쿠버네티스 리소스 상태 변화를 감지하고 클러스터에 적용
ETCD 의 Desired State 와 쿠버네티스의 Current State 비교
Kube-Controller-Manager
대부분의 쿠버네티스 오브젝트 상태 관리
Cloud-Controller-Manager
클라우드 플랫폼(AWS, GCP, Azure 등)에 특화된 리소스를 제어하는 클라우드 컨트롤러
Control Plane과 통신하며 필요한 Pod와 볼륨을 생성하는 서버로, 실제 컨테이너가 동작합니다.
쿠버네티스의 배포 도구는 다양하게 존재하며, 운영환경/개발환경에 따라 선택하여 설치할 수 있습니다.
운영 환경에서는 주로 kubeadm
, kubespray, kops가 사용되며, 개발 환경에서는 minikube
, k3d, kind
, getdeck, kwok이 사용됩니다.
kind(Kubernetes In Docker)는 가볍고 빠르게 테스트하고 지울 수 있어 이를 사용하여 쿠버네티스 설치를 하겠습니다.
kind를 설치하기 전, 반드시 Docker가 설치되어 있어야합니다
설치는 MacOS를 기준으로 진행합니다.
# Install Kind
**brew install kind**
# Install kubectl
**brew install kubernetes-cli**
설치를 진행한 후 아래 명령어를 통해 설치가 정상적으로 되었는지 확인합니다.
kind --version
kubectl version --client=true
kind 설치가 완료되었으면 아래 명령어를 통해 Cluster를 생성합니다.
# Create a cluster with kind
**kind create cluster**
정상적으로 Cluster가 생성되었는지 확인합니다.
# 클러스터 배포 확인
kind get clusters # 현재 로컬 환경에 생성된 kind cluster 확인
kind get nodes # cluster 노드 확인
kubectl cluster-info # 현재 설정된 Kubernetes 클러스터의 기본 서비스 정보 확인
# 노드 정보 확인
kubectl get node -o wide # 현재 Kubernetes 클러스터의 노드 상태를 좀 더 상세하게(wide) 출력
# 파드 정보 확인
kubectl get pod -A # Kubernetes 클러스터 내의 모든 네임스페이스에서 실행 중인 모든 파드 목록을 조회
kind는 기본적으로 dokcer에 kubernetes 환경을 구성하는 도구로, 다음 명령어를 입력해보면 실제로 컨테이너가 배포되어 있는 것을 확인할 수 있습니다.
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3850ec297c1a kindest/node:v1.32.2 "/usr/local/bin/entr…" 31 minutes ago Up 31 minutes 127.0.0.1:57230->6443/tcp kind-control-plane
Kubectl(kubernetes + control)은 쿠버네티스를 제어하는 명령을 API Server 로 전달합니다.
아래 명령어를 통해 현재 쿠버네티스 클러스터에서 사용할 수 있는 API 리소스 목록을 출력하며, 리소스 약어를 확인할 수 있습니다.
kubectl api-resources
kubectl get <RESOURCE>
를 통해 Kubernetes에서 리소스의 현재 상태를 조회할 수 있습니다.
# 노드 조회
kubectl get node
kubectl get node -o wide
# 파드 조회
kubectl get pods
kubectl get pods -A
# 디플로이먼트 조회
kubectl get deployment
kubectl get deployment -A
# 네임스페이스 조회
kubectl get namespace
kubectl describe <RESOURCE> [NAME]
를 통해 Kubernetes 리소스에 대한 자세한 설명과 상태 정보를 출력합니다.
# 파드 상세 조회
kubectl describe pod -n kube-system coredns-668d6bf9bc-62k9k
# 디플로이먼트 조회
kubectl describe deployment -n kube-system coredns
# 네임스페이스 조회
kubectl describe namespace kube-system
Pod 상세 정보
Deployment 상세 정보
Namespace 상세 정보
kubectl
명령어를 실행할 때, 어떤 클러스터에 연결할지, 어떤 사용자 자격으로 접근할지, 어떤 네임스페이스를 기본으로 사용할지를 지정하는 설정을 컨텍스트(Context)라고 합니다.
컨텍스트는 Kubernetes에 접근하기 위한 인증(Authentication) 과정의 일부로, 특히 여러 개의 클러스터(멀티 클러스터)를 운영할 때 매우 유용합니다.
구성 요소 | 설명 |
---|---|
Cluster | 연결할 Kubernetes 클러스터 정보 |
User | 클러스터에 사용할 인증 방식 및 자격 증명 |
Namespace | 기본적으로 사용할 네임스페이스 |
컨텍스트는 아래 명령어를 통해 확인할 수 있습니다.
# 현재 설정된 컨텍스트 확인
kubectl config current-context
# 모든 컨텍스트 확인
kubectl config get-contexts
# 다른 컨텍스트 전환
kubectl config use-context <Context Name>
# 컨텍스트 삭제
kubectl config delete-context <Context Name>
컨텍스트의 정보는 ~/.kube/config
에서 확인할 수 있으며 이를 확인해보면 아래와 같은 구조로 되어있습니다.
apiVersion: v1
clusters:
- cluster: # API Server 정보
certificate-authority-data: LS0tLS1CRUdJTiBDRVJUS# API Server 인증서
server: https://127.0.0.1:57230 # API Server URL
name: kind-kind # Cluster 명칭
contexts:
- context:
cluster: kind-kind
user: kind-kind # Cluster 접근 유저
name: kind-kind
current-context: kind-kind
kind: Config
preferences: {}
users:
- name: kind-kind # Cluster 접근 유저에 대한
user:
client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS # Client 인증서
client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkF # Client Key
Kubernetes에서 Namespace(네임스페이스)는 클러스터 내부를 논리적으로 분리하기 위한 단위로, 하나의 클러스터 안에서 리소스를 구분하고 효율적으로 관리할 수 있게 해줍니다. kube-
접두사는 Kubernetes 시스템에서 사용하기 위해 예약되어 있으므로, 해당 접두사로 네임스페이스를 생성할 수 없습니다.
또한, Kubernetes의 모든 객체(Object)가 네임스페이스에 속하는 것은 아니며, 일부 리소스는 클러스터 전체 범위에서 관리됩니다.
# Namespace 에 속하는 리소스
kubectl api-resources --namespaced=true
# Namespace 에 속하지 않는 리소스
kubectl api-resources --namespaced=false
네임 스페이스 생성
# 네임스페이스 조회
kubectl get ns
# 네임스페이스 생성
kubectl create namespace k8s-test
kubectl get ns
파드 생성
# Default Namespace에 파드 생성
kubectl run nginx --image=nginx:alpine
kubectl get pods
kubectl describe pod nginx
kubectl describe pod nginx | grep Namespace
# k8s-test 네임스페이스에 파드 생성
kubectl run nginx --image=nginx:alpine -n k8s-test
kubectl get pods -n k8s-test
kubectl get pods -A
# k8s-test 네임스페이스에 다시 한 번 파드 배포
kubectl run nginx --image=nginx:alpine -n k8s-test
Error from server (AlreadyExists): pods "nginx" already exists
# 논리적으로 격리되어 있기 때문에 다른 네임스페이스에는 동일한 이름의 파드를 배포할 수 있지만,
# 같은 네임스페이스에는 동일한 파드를 배포할 수 없습니다.
테스트 파드 삭제
# 테스트 파드 삭제
kubectl delete pods nginx
kubectl delete pods nginx -n k8s-test
# 기본 네임스페이스 변경
## 현재 네임스페이스 정보 조회 (빈값: default)
kubectl config get-contexts
kubectl config view --minify
kubectl config view --minify --output 'jsonpath={..namespace}'
## 네임스페이스 변경
kubectl config set-context --current --namespace=k8s-test
kubectl config get-contexts
kubectl config view --minify
kubectl config view --minify --output 'jsonpath={..namespace}'
Kubernetes에서 Pod(파드)는 가장 작은 배포 단위이자 실행 단위입니다. 하나 이상의 컨테이너로 구성되며, 동일한 파드 내의 컨테이너들은 Storage와 Network를 공유합니다. 이들은 항상 함께 실행되며, Pod는 프로세스를 직접 실행하는 것이 아니라, 컨테이너를 실행하기 위한 환경을 제공합니다.
일반적으로 Pod를 직접 생성하지 않고, Deployment와 같은 상위 리소스를 통해 생성하고 관리하는 것이 권장됩니다. Pod를 단독으로 사용하면 고가용성 및 자가 치유가 불가합니다. 따라서 아래와 같은 배포 방식을 사용합니다.
배포 방식 | 특징 설명 | 사용 사례 |
---|---|---|
Deployment | 가장 일반적인 배포 방식, 다양한 배포 전략 사용 가능 | 웹 서버, API 서버 등 |
StatefulSets | 파드의 실행 순서 보장, 고정된 네트워크 이름(Stable Hostname), 고정된 볼륨 | DB, Kafka 등 상태 기반 서비스 |
DaemonSet | 클러스터의 모든 노드에 하나씩 파드를 배포 | 로그 수집기, 모니터링 에이전트 등 |
Job / CronJob | 일회성 또는 주기적인 배치 작업 수행 | DB 백업, 배치 처리 |
pod.yaml 생성
apiVersion: v1
kind: Pod # Pod 리소스 선언
metadata:
name: nginx # Pod Name
spec:
containers:
- name: nginx # Container Name
image: nginx:alpine # Container Image
ports: # Container Port
- containerPort: 80
pod 배포
# 현재 pod 상태 확인
kubectl get pods -A
# pod 배포
kubectl apply -f pod.yaml
kubectl get pods
kubectl describe pods nginx
# 삭제
kubectl delete -f pod.yaml
Pod 로그 확인
# 로그 조회
kubectl logs nginx
kubectl logs nginx -f # f : 로그 스트리밍 모드
multi.yaml 생성
apiVersion: v1
kind: Pod
metadata:
name: k8s-multi-pods
spec:
containers:
- name: nginx
image: nginx
- name: redis
image: redis
Pod 배포
# pod 배포
kubectl apply -f multi.yaml
kubectl get pods
kubectl describe pods k8s-multi-pods
컨테이너가 여러개인 경우, 컨테이너 갯수 / 원하는 컨테이너 갯수
로 아래와 같이 표시된다.
사이드카 패턴
sidecar.yaml 생성
apiVersion: v1
kind: Pod
metadata:
name: k8s-mart
spec:
volumes:
- emptyDir: {}
name: varlog
containers:
- name: k8s-mart
image: busybox
command:
- /bin/sh
- -c
- 'i=1; while :;do echo -e "$i: Price: $((RANDOM % 10000 + 1))" >> /var/log/k8s-mart.log; i=$((i+1)); sleep 2; done'
volumeMounts:
- mountPath: /var/log
name: varlog
- name: price
image: busybox
args: [/bin/sh, "-c", 'tail -n+1 -f /var/log/k8s-mart.log']
volumeMounts:
- mountPath: /var/log
name: varlog
Pod 배포
# pod 배포
kubectl apply -f sidecar.yaml
kubectl get pods
kubectl describe pods k8s-mart
# price 컨테이너 로그 조회
kubectl logs k8s-mart -c price -f # k8s-mart Pod에서 price라는 컨테이너의 로그를 출력
배포된 Pod 삭제
kubectl delete -f <file.yaml>
Deployment는 Kubernetes에서 파드와 레플리카셋을 선언적으로 업데이트할 수 있는 리소스로, 파드 배포에 있어 핵심적인 역할을 합니다.
Deployment는 내부적으로 ReplicaSet을 생성하고 관리하며, 이를 통해 명시된 파드 개수의 가용성을 자동으로 보장합니다. (예: 파드 2개 또는 3개 유지)
단, Deployment가 관리하는 ReplicaSet은 직접 수정하지 않는 것이 원칙입니다.
또한 Deployment는 롤링 업데이트, 롤백 등 다양한 배포 전략을 설정할 수 있어, 중단 없는 안정적인 배포를 지원합니다.
Deployment의 사양에는 실제로 배포될 파드의 정의를 담고 있는 PodTemplate이 포함되어 있으며, 이를 통해 어떤 컨테이너를 어떤 환경에서 실행할지를 선언합니다.
deploy.yaml 생성
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-v1
spec:
selector:
matchLabels: # PodTemplate 에 선언된 Label 을 지정하여 Deployment 적용
app: nginx
replicas: 2 # Pod 개수
template: # PodTemplate 시작
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
env: # 환경변수 설정 key-value
- name: APP_MODE
value: "v1"
ports:
- containerPort: 80 # PodTemplate 종료
Pod 배포
# pod 배포
kubectl apply -f deploy.yaml
# Pod, ReplicaSet, Deployment 조회
kubectl get deploy,rs,pods
아래처럼 Deployment → ReplicaSet → Pod 순으로 출력되어, 배포 구조 전체를 한눈에 파악할 수 있습니다.
Pod 업데이트
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-v1
spec:
selector:
matchLabels: # PodTemplate 에 선언된 Label 을 지정하여 Deployment 적용
app: nginx
replicas: 2 # Pod 개수
template: # PodTemplate 시작
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
env:
**- name: APP_MODE
value: "v2" # v1 -> v2 변경**
ports:
- containerPort: 80 # PodTemplate 종료
기본 롤링 업데이트 재배포 흐름
신규 pod 배포 → 배포 완료 → 기존 pod 1대 제거 → 제거 완료 → 신규 Pod 배포 → 배포 완료 → 기존 Pod 제거 → 제거 완료 → N번 반복
QoS(Quality of Service)는 노드의 리소스가 부족해질 때, 어떤 파드를 우선적으로 유지하고 어떤 파드를 먼저 제거할지를 결정하는 기준입니다. 이는 파드가 요청한 CPU/메모리 리소스의 설정 방식에 따라 자동으로 결정됩니다. (BestEffort → Bustable → Guaranteed)
QoS | 조건 | 우선 순위 |
---|---|---|
Guaranteed | requests와 limits이 동일한 경우 | 상 |
Burstable | requests와 limits이 다른 경우 | 중 |
BestEffort | requests와 limits이 설정되지 않은 경우 | 하 |
QoS 확인
quaranteed.yaml 작성
# Request, Limit 존재. 값 동일
apiVersion: apps/v1
kind: Deployment
metadata:
name: qos-guaranteed
spec:
replicas: 1
selector:
matchLabels:
app: qos-guaranteed
template:
metadata:
labels:
app: qos-guaranteed
spec:
containers:
- name: nginx
image: nginx:alpine
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "128Mi"
cpu: "100m"
pod 배포 및 QoS 확인
# 배포
kubectl apply -f guaranteed.yaml
kubectl get pods
GUARANTEED=$(kubectl get pods --no-headers -o custom-columns=":metadata.name" | grep qos-guaranteed)
# QoS 확인
kubectl get pod ${GUARANTEED} -o jsonpath='{.status.qosClass}'
kubectl describe pod ${GUARANTEED}
Role Base Access Control의 줄임말로 쿠버네티스 리소스에 대한 접근(인가 Authorization)을 관리합니다.
객체 | 설명 | 적용 범위 |
---|---|---|
Role | 특정 네임스페이스 내에서의 권한 규칙 모음 | 네임스페이스 |
ClusterRole | 클러스터 전역 또는 네임스페이스별로 재사용 가능한 권한 규칙 모음 | 클러스터 전체 |
RoleBinding | Role을 특정 Subject(User, Group SA)에 바인딩 | 네임스페이스 |
ClusterRoleBinding | ClusterRole을 특정 Subject(User, Group SA)에 바인딩 | 클러스터 전체 |
파드 내부에서 실행되는 프로세스는 자신에게 할당된 서비스 어카운트의 식별자를 사용해 클러스터 API 서버에 인증할 수 있습니다. 파드를 배포할 때 별도로 서비스 어카운트를 지정하지 않으면 기본적으로 default
서비스 어카운트가 사용됩니다. 이후 해당 파드는 Role 또는 ClusterRole과 연계된 권한을 네임스페이스 단위로 부여받아 동작하게 됩니다.
Service Account 혹은 User 에 부여하기 위한 권한입니다.
선언된 Role, ClusterRole 을 User, Service Account 등과 연결하는 리소스입니다.
참고
운영 수준의 컨테이너 오케스트레이션
[k8s] 쿠버네티스의 등장 배경과 쿠버네티스란?
쿠버네티스 시작하기 - Kubernetes란 무엇인가?
Kubernetes Components
Kubernetes Namespaces - Imperative using kubectl