카테고리 없음

[k8s] Docker&K8s -2

ride-dev 2025. 4. 27. 13:58

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. 아키텍처

https://kubernetes.io/docs/concepts/overview/components/

쿠버네티스 클러스터는 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

제거가 잘 진행되었음을 확인할 수 있습니다.

728x90
반응형