[k8s] Docker&K8s -2
0. 들어가면서
docker & k8s 스터디 두 번째 파트입니다.
이번에는 실습한 내용을 따라가면서 더 익숙해질 수 있도록
내용을 실습 위주로 작성할 예정입니다.
(앞으로도 내용을 보완할 예정입니다)
1. 쿠버네티스 주요 개념
1.1 등장 배경
컨테이너를 단독으로 사용할 때 컨테이너가 다운될 수 있습니다.그렇게에 로드밸런싱 등 설정을 추가로 진행할 필요가 있습니다.
쿠버네티스는 로드밸런싱, 자동화된 롤아웃 롤백, 일괄 실행 등을 제공하여
컨테이너를 쉽게 관리할 수 있게 합니다.
1.2. 선언형 명령과 명령형 명령
쿠버네티스는 선언형 명령을 사용하여 컨테이너를 관리합니다.
명령형은 run, create, delete 등으로 직접 생성하고 수정하는 방식이고,
선언형은 yaml 등 파일 기반으로 관리하는 방식입니다.
파일을 기반으로 관리하기 때문에 구성관리가 편해집니다.
(추적과 변경이 쉬워집니다)
아래는 yaml 파일의 예시입니다.
# Nginx Deployment 형식
apiVersion: apps/v1
kind: Deployment # 리소스 선언
metadata:
name: nginx-deployment # 해당 리소스의 이름
labels: # 해당 리소스의 Label - Label 은 Kubernetes 의 Metadata
app: nginx
spec:
replicas: 3 # 파드 개수
selector:
matchLabels: # Deployment 를 적용할 Pod 를 선택
app: nginx
template: # Pod 템플릿 선언
metadata:
labels:
app: nginx # Pod 의 Label
spec:
containers: # 컨테이너 정의
- name: nginx # Pod Container 이름
image: nginx:1.14.2 # Pod Container Image 정의
ports:
- containerPort: 80 # Pod Container Port
1.3. 아키텍처
쿠버네티스 클러스터는 Control Plane(제어영역, 마스터), 하나 이상의 Node(노드, 작업자)로 구성됩니다.
1.3.1. Control Plane 구성 요소
Control Plane 은 클러스터의 전반적인 상태를 관리합니다.
kube-apiserver 는 쿠버네티스 HTTP API를 노출하는 핵심 구성 요소 서버로,
마스터로 전달되는 모든 요청을 받아들입니다.
etcd 는 모든 API 서버 데이터에 대한 일관되고 가용성이 높은 키 값 저장소로,
클러스터 내 모든 메타 정보를 저장하는 분산 데이터 저장소입니다.
API Server로만 통신하여, 다른 모듈이 etcd에 접근하려면 API server를 통해야 합니다.
kube-scheduler 는 사용자의 요청에 따라 컨테이너를 적절한 워커노드에 배치하는 스케쥴러로,
아직 노드에 바인딩되지 않은 Pod를 찾아 각 Pod를 적합한 노드에 할당합니다.
Kube-Controller-Manager는 대부분의 쿠버네스트 오브젝트 상태를 관리하며,
쿠버네티스 API 동작을 구현하기 위해 컨트롤러를 실행합니다.
Cloud-Controller-Manager는 클라우드 플랫폼에 특화된 리소스를 제어하며,
Ingress 를 통한 ELB 생성, Storage Class 를 통한 EBS 생성,
EC2 Node 추가/삭제, 로드밸런서 연결, Volume 장착 등을 제어합니다.
1.3.2. Node 구성 요소
노드 구성요소는 모든 노드(Worker Node)에서 실행되고, 실행중인 Pod를 유지 관리하며,
쿠버네티스 런타임 환경을 제공합니다.
Worker Node는 Control Plane과 통신하며, 실제 컨테이너가 동작하는 서버입니다.
더 많은 컨테이너 배포를 위해서는 워커 노드를 확장합니다.
Kubelet은 컨테이너를 포함, 노드에 할당된 Pod 의 생명 주기(Life-Cycle)를 관리합니다.
kube-proxy는 컨테이너의 네트워킹을 책임지는 프록시로, 네트워크 규칙을 유지 관리합니다.
Container Runtime은 실제 컨테이너를 실행하는 컨테이너 실행환경입니다.
1.3.3. Addons
애드온은 쿠버네티스의 기능을 확장합니다.
여러 가지가 있으며, 대표적인 애드온은 다음과 같습니다.
DNS, 클러스트 전체 DNS 확인
Web UI, 웹 인터페이스를 통한 클러스터 관리
CNI, k8s 네트워크 환경 구성
...
2. 쿠버네티스 실습
윈도우 WSL 우분투 환경에서 진행하도록 합니다.
kubectl은 쿠버네티스를 제어하는 명령어입니다.
# WSL2 Ubuntu
sudo snap install docker
sudo groupadd docker
sudo usermod -aG docker $USER
docker --version
# Kind 설치
[ $(uname -m) = x86_64 ] && curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.27.0/kind-linux-amd64
sudo chmod +x ./kind
sudo mv ./kind /usr/local/bin/kind
# Kind Cluster 생성
kind create cluster
# kubectl 설치
sudo snap install kubectl --classic
kubectl get pods -A
# Krew 설치
wget https://github.com/kubernetes-sigs/krew/releases/download/v0.4.5/krew-linux_amd64.tar.gz
tar zxvf krew-linux_amd64
./krew-linux_amd64 install krew
~/.bashrc >> export PATH="${KREW_ROOT:-$HOME/.krew}/bin:$PATH"
source ~/.bashrc
kubectl krew
# k9s 설치
wget https://github.com/derailed/k9s/releases/download/v0.50.4/k9s_linux_amd64.deb
sudo dpkg -i k9s_linux_amd64.deb
sudo apt-get install -f
k9s
# Helm 설치
sudo snap install helm --classic
helm ls
쿠버네티스 설치, 환경 설정이 완료되면,
kubectl api-resources 를 입력하여 확인합니다.
(kind create cluster로 환경을 생성해줘야 합니다)
아래는 쿠버네티스 정보를 확인할 수 있는 주요 명령어 입니다.
kubectl api-resources
# 대표적인 쿠버네티스 리소스 약어
# pods - po
kubectl api-resources | grep pods
# deployments - deploy
kubectl api-resources | grep deployments
# namespaces - ns
kubectl api-resources | grep namespaces
# configmaps - cm
kubectl api-resources | grep configmaps
# 노드 조회
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 pod -n kube-system coredns-6f6b679f8f-krwfh
# 디플로이먼트 조회
kubectl describe deployment -n kube-system coredns
# 네임스페이스 조회
kubectl describe namespace kube-system
Context
컨텍스트는 kubectl 명령어를 수행할 때,
동작 대상을 지정하는 설정입니다.
(클러스터, 사용자, 네임스페이스)
context는 연결할 쿠버네티스 클러스터(Cluster), 클러스터 인증에 사용할 사용자 정보 (토큰, 인증서) User,
기본으로 사용할 네임스페이스 Namespace로 구성되어 있습니다.
쿠버네티스 컨텍스트를 확인하는 주요 명령어는 아래와 같습니다.
# 현재 설정된 컨텍스트 확인
kubectl config current-context
# 모든 컨텍스트 확인
kubectl config get-contexts
# 다른 컨텍스트 전환
kubectl config use-context <Context Name>
# 컨텍스트 삭제
kubectl config delete-context <Context Name>
컨텍스트 정보는 ~/.kube/config 에서 확인할 수 있습니다.
Namespace
Namespace는 쿠버네티스 클러스터 내에서 리소스를 격리하는 논리적 단위로,
아래 명령어를 통해 Namespace에 속하는 리소스를 확인할 수 있습니다.
(kube- 는 예약어이기에 Namespace 생성 접두사에 사용할 수 없다는 것을 주의합니다)
# Namespace 에 속하는 리소스
kubectl api-resources --namespaced=true
# Namespace 에 속하지 않는 리소스
kubectl api-resources --namespaced=false
일단, 선언형이 아닌, 명령형 명령어를 통해 실습을 진행합니다.
# 네임스페이스 조회
kubectl get ns
# 네임스페이스 생성
kubectl create namespace ride
kubectl get ns
# 파트 생성
kubectl run nginx --image=nginx:alpine
#
kubectl get pods
kubectl describe pod nginx
kubectl describe pod nginx | grep Namespace
# knou 네임스페이스에 파드 생성
kubectl run nginx --image=nginx:alpine -n ride
#
kubectl get pods -n ride
kubectl get pods -A
# knou 네임스페이스에 다시 한 번 파드 배포
kubectl run nginx --image=nginx:alpine -n ride
Error from server (AlreadyExists): pods "nginx" already exists
# 논리적으로 격리되어 있기 때문에 다른 네임스페이스에는 동일한 이름의 파드를 배포할 수 있지만, 같은 네임스페이스에는 동일한 파드를 배포할 수 없다!
# -> 쿠버네티스 사용 시 가장 많이 하는 실수 중 하나. 다른 네임스페이스에 배포하는 것
# 테스트 파드 삭제
kubectl delete pods nginx
kubectl delete pods nginx -n ride
# 기본 네임스페이스 변경
## 현재 네임스페이스 정보 조회 (빈값: default)
kubectl config get-contexts
kubectl config view --minify
kubectl config view --minify --output 'jsonpath={..namespace}'
## 네임스페이스 변경
kubectl config set-context --current --namespace=knou
kubectl config get-contexts
kubectl config view --minify
kubectl config view --minify --output 'jsonpath={..namespace}'
# 네임스페이스 지정 없이 파드 배포
kubectl run nginx2 --image=nginx:alpine
kubectl get pods -n ride
# 테스트 파드 삭제
kubectl delete pods nginx2
Pod
k8s에서 배포 가능한 가장 작은 단위의 환경으로, 애플리케이션을 생성/관리할 수 있습니다.
1개 이상의 컨테이너로 구성되어 있으며, 동일한 파드 내의 컨테이너는 Storage, Network 를 공유합니다.
yaml 파일을 생성하여 Pod 배포를 선언형 명령으로 진행하겠습니다.
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
touch pod.yaml
# 위 yaml 파일 복사 붙여넣기
vim pod.yaml
cat pod.yaml
# 현재 pod 상태 확인
kubectl get pods -A
# pod 배포
kubectl apply -f pod.yaml
#
kubectl get pods
kubectl describe pods nginx
# 삭제
kubectl delete -f pod.yaml
아래와 같이 구성하여 로그를 확인할 수 있습니다.
apiVersion: v1
kind: Pod
metadata:
name: min
namespace: min
spec:
containers:
- name: min
image: busybox
env: # Pod 내부 변수 선언
- name: NAME # 변수 Key
value: "sj min" # 변수 Value
command: ["/bin/sh"]
args: ["-c", "while true; do echo \"Hello My Name is $(NAME)\"; date; sleep 2; done"]
touch pod2.yaml
# 위 yaml 파일 복사 붙여넣기
vim pod2.yaml
cat pod2.yaml
# 현재 pod 상태 확인
kubectl get pods -A
# pod 배포
kubectl apply -f pod2.yaml
#
kubectl get pods
kubectl describe pods knou
# 로그 조회
kubectl logs min
kubectl logs min -f
# 삭제
kubectl delete -f pod2.yaml --force
컨테이너가 여럿인 pod를 배포합니다.
apiVersion: v1
kind: Pod
metadata:
name: min-multi
spec:
containers:
- name: nginx
image: nginx
- name: redis
image: redis
touch multi.yaml
# 위 yaml 파일 복사 붙여넣기
vim multi.yaml
cat multi.yaml
# 현재 pod 상태 확인
kubectl get pods -A
# pod 배포
kubectl apply -f multi.yaml
#
kubectl get pods
kubectl describe pods min-multi
#
kubectl delete -f multi.yaml
사이드카 패턴을 사용한 pods 배포를 진행합니다.
apiVersion: v1
kind: Pod
metadata:
name: min-mart
spec:
volumes:
- emptyDir: {}
name: varlog
containers:
- name: min-mart
image: busybox
command:
- /bin/sh
- -c
- 'i=1; while :;do echo -e "$i: Price: $((RANDOM % 10000 + 1))" >> /var/log/min-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/min-mart.log']
volumeMounts:
- mountPath: /var/log
name: varlog
touch sidecar.yaml
# 위 yaml 파일 복사 붙여넣기
vim sidecar.yaml
cat sidecar.yaml
# 현재 pod 상태 확인
kubectl get pods -A
# pod 배포
kubectl apply -f sidecar.yaml
#
kubectl get pods
kubectl describe pods min-mart
# price 컨테이너 로그 조회
kubectl logs min-mart -c price -f
#
kubectl delete -f sidecar.yaml
# 사이드카 패턴을 사용하는 대표적인 서비스가 Istio
## Envoy Proxy 가 Side Car 로 동작하여 Container 의 모든 네트워크 패킷을 감시하고 제어
Pods를 단독으로 사용, 직접 배포할 수도 있지만,
가용성이 낮고, 자가 치유가 불가하기에
단독으로 사용하지 않도록 합니다.
Deployment
Deployment를 통해 pods과 레플리카셋에 대한 선언적 업데이트를 제공합니다.
다양한 배포 전략을 설정할 수 있습니다(롤아웃 등)
사용 커맨드는 아래와 같습니다.
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: "v1"
ports:
- containerPort: 80 # PodTemplate 종료
touch deploy.yaml
# 위 yaml 파일 복사 붙여넣기
vim deploy.yaml
cat deploy.yaml
# 현재 pod 상태 확인
kubectl get pods -A
# pod 배포
kubectl apply -f deploy.yaml
# Pod, ReplicaSet, Deployment 조회
kubectl get deploy,rs,pods
#
kubectl delete -f 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:
- name: APP_MODE
value: "v2" # v1 -> v2 변경
ports:
- containerPort: 80 # PodTemplate 종료
# 터미널 2
while true; do kubectl get pods -o wide; sleep 1; done
# 터미널 1
kubectl apply -f deploy.yaml
# 동작 방식 (기본 Rolling Update)
# 신규 pod 배포 -> 배포 완료 -> 기존 pod 1대 제거 -> 제거 완료 -> 신규 Pod 배포 -> 배포 완료 -> 기존 Pod 제거 -> 제거 완료 -> N번 반복
Guaranteed QoS
노드의 자원이 부족해질 때,
어떤 파드를 우선시할 지 설정합니다.
제거되는 순서는 다음과 같습니다.
BestEffort → Bustable → Guaranteed
각각에 해당하는 pods를 선언하겠습니다.
# Request, Limit 없는 Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: qos-besteffort
spec:
replicas: 1
selector:
matchLabels:
app: qos-besteffort
template:
metadata:
labels:
app: qos-besteffort
spec:
containers:
- name: nginx
image: nginx:alpine
touch besteffort.yaml
vim besteffort.yaml
# 배포
kubectl apply -f besteffort.yaml
kubectl get pods
BEST_EFFORT=$(kubectl get pods --no-headers -o custom-columns=":metadata.name" | grep qos-besteffort)
# QoS 확인
kubectl get pod ${BEST_EFFORT} -o jsonpath='{.status.qosClass}'
kubectl describe pod ${BEST_EFFORT}
BestEffort
# Request, Limit 존재하지만 값이 다름
apiVersion: apps/v1
kind: Deployment
metadata:
name: qos-burstable
spec:
replicas: 1
selector:
matchLabels:
app: qos-burstable
template:
metadata:
labels:
app: qos-burstable
spec:
containers:
- name: nginx
image: nginx:alpine
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "200m"
touch burstable.yaml
vim burstable.yaml
# 배포
kubectl apply -f burstable.yaml
kubectl get pods
BURSTARBLE=$(kubectl get pods --no-headers -o custom-columns=":metadata.name" | grep qos-burstable)
# QoS 확인
kubectl get pod ${BURSTARBLE} -o jsonpath='{.status.qosClass}'
kubectl describe pod ${BURSTARBLE}
Burstable
# 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"
touch guaranteed.yaml
vim guaranteed.yaml
# 배포
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}
Guaranteed
+. 그 외 편리성
쿠버네티스는 CLI 기반으로 이루어지기에 여러 플러그인이 있기도 하고,
다양한 커스터마이징을 하기도 합니다.
alias
공통적으로 적용할 수 있는 것은 alias입니다.
# Linux Bash
# 자동 완성 및 alias 축약 설정
source <(kubectl completion bash)
echo 'source <(kubectl completion bash)' >> ~/.bashrc
echo 'alias k=kubectl' >> ~/.bashrc
echo 'complete -F __start_kubectl k' >> ~/.bashrc
source ~/.bashrc
plug-in
플러그인을 사용할 때, krew를 통해 플러그인 설치를 간단히 진행할 수 있습니다.
curl -fsSLO "https://github.com/kubernetes-sigs/krew/releases/download/${KREW_VERSION}/krew-linux_amd64.tar.gz"
280 tar zxvf krew-linux_amd64.tar.gz
281 chmod +x krew-linux_amd64
282 ./krew-linux_amd64 install krew
283 rm krew-linux_amd64.tar.gz krew-linux_amd64
284 echo 'export PATH="${KREW_ROOT:-$HOME/.krew}/bin:$PATH"' >> ~/.bashrc
285 source ~/.bashrc
286 kubectl krew
https://krew.sigs.k8s.io/docs/user-guide/setup/install/
Installing · Krew
© 2025 The Kubernetes Authors. Krew is a Kubernetes SIG CLI project. Edit Page ·
krew.sigs.k8s.io
kube-ctx : 쿠버네티스 컨텍스트 사용
# 설치
kubectl krew install ctx
# 컨텍스트 확인
kubectl ctx
# 컨텍스트 사용
kubectl ctx <각자 자신의 컨텍스트 이름>
kube-ns : 네임스페이스(단일 클러스터 내에서 가상 클러스터) 사용
# 설치
kubectl krew install ns
# 네임스페이스 확인
kubectl ns
# kube-system 네임스페이스 선택 사용
kubectl ns kube-system
# default 네임스페이스 선택 사용
kubectl ns -
혹은
kubectl ns default
get-all : kubectl get all 로도 안보이는 쿠버네티스의 모든 리소스 조회
# 설치
kubectl krew install get-all
# 네임스페이스 확인
kubectl get-all -n kube-system
neat : kubectl yaml 파일 형태로 리소스 출력
# 설치
kubectl krew install neat
# 배포
k run nginx --image nginx
# 파드 정보 확인
k get pods nginx -o yaml | k neat
아래 명령어를 통해 실습 환경을 제거할 수 있습니다.
kind get clusters
kind delete cluster
제거가 잘 진행되었음을 확인할 수 있습니다.