이 영역을 누르면 첫 페이지로 이동
천천히 꾸준히 조용히 블로그의 첫 페이지로 이동

천천히 꾸준히 조용히

페이지 맨 위로 올라가기

천천히 꾸준히 조용히

천천히 꾸준히 조용히.. i3months 블로그

[Kubernetes] kubectl 연습 - Deployment ReplicaSet

  • 2026.07.21 16:51
  • DevOps/Docker && Kubernetes
반응형

 

 

 

내가 쿠버네티스 클러스터를 다룰 때는 kubectl을 사용한다. (kube-control)

 

 

 

 

 

그냥 명령어임. 도커 데스크탑 말고 CLI로 쓸 때 열심히 치던 명령어와 비슷하다.

 

 

13months@13monthsBook ~ % kubectl create deployment my-web --image=nginx
deployment.apps/my-web created
13months@13monthsBook ~ %

 

 

Deployment로 간단한 웹서버를 하나 띄워보자.

Pod을 직접 만들지 않고 Deployment를 사용해서 띄운다. 

 

 

13months@13monthsBook ~ % kubectl get deployments
NAME     READY   UP-TO-DATE   AVAILABLE   AGE
my-web   1/1     1            1           2m4s
13months@13monthsBook ~ % kubectl get pods
NAME                      READY   STATUS    RESTARTS   AGE
my-web-684f49ddf4-bm4gh   1/1     Running   0          3m36s
13months@13monthsBook ~ %

 

 

READY: 1/1 은 원하는 개수 중 준비된 개수를 의미하고 AVAILABLE은 지금 서비스 가능한게 1개 있다는 것. 

만든건 deployment 인데 ReplicaSet이랑 Pod도 한개 같이 생겼다. 

 

684f머시기는 ReplicaSet가 붙인 식별자이고, bm4gh는 Pod의 식별자를 의미한다. (라벨아님 라벨은 my-web)

Pod는 언제든 죽고 새로 띄워지기에 매번 새로운 이름을 할당받는다. 

Pod 안에는 nginx 웹서버가 한개 떠서 동작하는 중. 

 

 

13months@13monthsBook ~ % kubectl delete pod my-web-684f49ddf4-bm4gh
pod "my-web-684f49ddf4-bm4gh" deleted from default namespace
13months@13monthsBook ~ % kubectl get pods
NAME                      READY   STATUS    RESTARTS   AGE
my-web-684f49ddf4-gj4bf   1/1     Running   0          4s
13months@13monthsBook ~ %

 

 

Pod을 지우니까 새로 생긴 Pod이 생성된다. 

ReplicaSet 아이디까지는 같지만 Pod 아이디는 달라짐. 

 

 

13months@13monthsBook ~ % kubectl get pods -o wide
NAME                      READY   STATUS    RESTARTS   AGE    IP           NODE       NOMINATED NODE   READINESS GATES
my-web-684f49ddf4-gj4bf   1/1     Running   0          104s   10.244.0.4   minikube   <none>           <none>
13months@13monthsBook ~ % kubectl delete pod my-web-684f49ddf4-gj4bf
pod "my-web-684f49ddf4-gj4bf" deleted from default namespace
13months@13monthsBook ~ % kubectl get pods -o wide
NAME                      READY   STATUS    RESTARTS   AGE   IP           NODE       NOMINATED NODE   READINESS GATES
my-web-684f49ddf4-ztrt6   1/1     Running   0          3s    10.244.0.5   minikube   <none>           <none>
13months@13monthsBook ~ %

 

 

kubectl get pods -o wide 명령어로 아이피도 같이 확인해보면 죽고 새로 뜰 때 마다 아이피가 변하는걸 확인할 수 있다. 

근데 지금은 Pods를 직접 삭제했는데 어차피 앞으로는 Pod를 직접 다루지 않고 Deployment를 다룬다. 

 

# 1. kubectl 자동완성 기능을 켜기 위한 설정을 셸 설정 파일에 추가
echo 'source <(kubectl completion zsh)' >> ~/.zshrc

# 2. k를 kubectl의 별칭으로 등록
echo 'alias k=kubectl' >> ~/.zshrc

# 3. k로도 자동완성이 되게 연결
echo 'complete -F __start_kubectl k' >> ~/.zshrc

# 4. 설정을 지금 터미널에 바로 반영
source ~/.zshrc

 

 

탭치면 자동완성 되긴 하고 kubectl 치는것도 귀찮으면 k로 쳐도 된다. 

 

 

13months@13monthsBook ~ % k get po
NAME                      READY   STATUS    RESTARTS   AGE
my-web-684f49ddf4-ztrt6   1/1     Running   0          3m55s
13months@13monthsBook ~ % kubectl expose deployment my-web --port=80
service/my-web exposed
13months@13monthsBook ~ % kubectl get service
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP   53m
my-web       ClusterIP   10.101.193.95   <none>        80/TCP    11s
13months@13monthsBook ~ % k delete pod my-web-684f49ddf4-ztrt6
pod "my-web-684f49ddf4-ztrt6" deleted from default namespace
13months@13monthsBook ~ % k get pods -o wide
NAME                      READY   STATUS    RESTARTS   AGE   IP           NODE       NOMINATED NODE   READINESS GATES
my-web-684f49ddf4-x9tlm   1/1     Running   0          7s    10.244.0.6   minikube   <none>           <none>
13months@13monthsBook ~ % k get service
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP   57m
my-web       ClusterIP   10.101.193.95   <none>        80/TCP    3m31s
13months@13monthsBook ~ %

 

 

kubectl expose 명령어로 서비스를 만들자. deployment 앞에 서비스를 배치할거임.

서비스를 만들면 그 서비스의 IP가 고정되니 Pod가 죽어도 서비스의 IP는 그대로 유지된다. 

 

 

 


 

 

 

지금까지는 kubectl 명령어를 직접 쳤는데 이건 쿠버의 철학인 declarative와 거리가 좀 있다.

yaml을 정의해보자. 

 

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-web
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-web
  template:
    metadata:
      labels:
        app: my-web
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80

 

 

스프링부트에서 항상 쓰던건데 이걸 처음부터 타이핑하지는 않음. AI로 yaml만들면 되긴 하는데 cka에서는 그게 안된다. 

--dry-run=client -o yaml 옵션을 붙이자. 실제로 만들지는 않고, 그 결과를 yaml 형식으로 보여달라는 명령어임.

 

13months@13monthsBook k8s % k apply -f my-web2.yaml
deployment.apps/my-web2 created
13months@13monthsBook k8s % k get pods
NAME                       READY   STATUS    RESTARTS   AGE
my-web-684f49ddf4-x9tlm    1/1     Running   0          19m
my-web2-6777b885f8-q6pnz   1/1     Running   0          95s
my-web2-6777b885f8-qd66d   1/1     Running   0          95s
my-web2-6777b885f8-rnjtk   1/1     Running   0          95s
13months@13monthsBook k8s % k get deploy
NAME      READY   UP-TO-DATE   AVAILABLE   AGE
my-web    1/1     1            1           37m
my-web2   3/3     3            3           3m2s
13months@13monthsBook k8s % vim my-web2.yaml 
13months@13monthsBook k8s % k apply -f my-web2.yaml 
deployment.apps/my-web2 configured
13months@13monthsBook k8s % k get pods
NAME                       READY   STATUS    RESTARTS   AGE
my-web-684f49ddf4-x9tlm    1/1     Running   0          21m
my-web2-6777b885f8-4h9gk   1/1     Running   0          6s
my-web2-6777b885f8-cr9z8   1/1     Running   0          6s
my-web2-6777b885f8-q6pnz   1/1     Running   0          3m44s
my-web2-6777b885f8-qd66d   1/1     Running   0          3m44s
my-web2-6777b885f8-rnjtk   1/1     Running   0          3m44s
13months@13monthsBook k8s %

 

 

replicas 개수를 1개 -> 3개 -> 5개로 바꿨음. 

3개에서 5개로 변할 때는 기존 3개는 그대로 두고 새로 2개만 추가해준다. 

 

yaml만 수정하면 알아서 deployment가 Pod를 만들어주니 내가 직접 Pod를 만들 필요가 없다.

 

 

13months@13monthsBook k8s % k delete deployment my-web my-web2
deployment.apps "my-web" deleted from default namespace
deployment.apps "my-web2" deleted from default namespace
13months@13monthsBook k8s % k delete service my-web
service "my-web" deleted from default namespace
13months@13monthsBook k8s % k get all
NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   80m
13months@13monthsBook k8s %

 

 

deployment를 삭제하면 그 아래 ReplicaSet과 Pods도 함께 정리된다. 

처음 apply 했을 때는 created로 나타나지만, 설정 파일 수정 후 다시 apply 하면 configured로 차이만 반영한다. 

아예 파일이 없으면 만들고, 있는데 수정됐다면 차이만 반영하고, 변화가 없다면 아무것도 안함.

 

 

13months@13monthsBook k8s % k create deployment broken --image=nginx:존재하지않는버전999
deployment.apps/broken created
13months@13monthsBook k8s % k get pods
NAME                    READY   STATUS             RESTARTS   AGE
broken-cbb5595d-5pwg5   0/1     InvalidImageName   0          6s
13months@13monthsBook k8s % k describe pod broken-cbb5595d-5pwg5 
Name:             broken-cbb5595d-5pwg5
Namespace:        default
Priority:         0
Service Account:  default
Node:             minikube/192.168.49.2
Start Time:       Tue, 21 Jul 2026 16:19:16 +0900
Labels:           app=broken
                  pod-template-hash=cbb5595d
Annotations:      <none>
Status:           Pending
IP:               10.244.0.12
IPs:
  IP:           10.244.0.12
Controlled By:  ReplicaSet/broken-cbb5595d
Containers:
  nginx:
    Container ID:   
    Image:          nginx:존재하지않는버전999
    Image ID:       
    Port:           <none>
    Host Port:      <none>
    State:          Waiting
      Reason:       InvalidImageName
    Ready:          False
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-mkq62 (ro)
Conditions:
  Type                        Status
  PodReadyToStartContainers   True 
  Initialized                 True 
  Ready                       False 
  ContainersReady             False 
  PodScheduled                True 
Volumes:
  kube-api-access-mkq62:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    Optional:                false
    DownwardAPI:             true
QoS Class:                   BestEffort
Node-Selectors:              <none>
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type     Reason         Age               From               Message
  ----     ------         ----              ----               -------
  Normal   Scheduled      16s               default-scheduler  Successfully assigned default/broken-cbb5595d-5pwg5 to minikube
  Warning  InspectFailed  1s (x3 over 15s)  kubelet            spec.containers{nginx}: Failed to apply default image tag "nginx:존재하지않는버전999": couldn't parse image name "nginx:존재하지않는버전999": invalid reference format
  Warning  Failed         1s (x3 over 15s)  kubelet            spec.containers{nginx}: Error: InvalidImageName
13months@13monthsBook k8s %

 

 

deployment를 만들 때 nginx 버전을 이상하게 치면 고장난다.

kubectl get pods 명령어와 kubectl describe pod이름 명령어로 에러 로그를 확인해보자. 

 

STATUS를 보면 InvalidImageName으로 이미지 자체가 규칙에 안맞음을 확인할 수 있음. 

이미지 태그에 한글이 들어가니 깨졌다. 

 

Events부분을 확인해보면 에러 원인을 확인할 수 있다.

couldn't parse image name invalid reference format 이라니까 저걸 보고 고쳐주면 됨. 

 

13months@13monthsBook k8s % k set image deployment/broken nginx=nginx:latest
deployment.apps/broken image updated
13months@13monthsBook k8s % k get pods
NAME                      READY   STATUS    RESTARTS   AGE
broken-74897b87bc-cb7vv   1/1     Running   0          7s

 

 

kubectl set images는 실행 중인 Deployment 컨테이너 이미지를 수정하는 명령어.

이미지가 깨졌으니까 이미지를 바꿔야 고칠 수 있다. 

 

set image를 하면 내부적으로는 무중단 업데이트가 진행된다. 

이걸 확인해보자. 

 

 

13months@13monthsBook k8s % kubectl scale deployment broken --replicas=3
deployment.apps/broken scaled
13months@13monthsBook k8s % k get pods
NAME                      READY   STATUS    RESTARTS   AGE
broken-74897b87bc-49kxs   1/1     Running   0          3s
broken-74897b87bc-79rd2   1/1     Running   0          3s
broken-74897b87bc-cb7vv   1/1     Running   0          4m5s
13months@13monthsBook k8s % k set image deployments/broken nginx=nginx:1.27
deployment.apps/broken image updated
13months@13monthsBook k8s % k get pods
NAME                      READY   STATUS              RESTARTS   AGE
broken-58cc58dd76-qmssq   0/1     ContainerCreating   0          3s
broken-74897b87bc-49kxs   1/1     Running             0          18s
broken-74897b87bc-79rd2   1/1     Running             0          18s
broken-74897b87bc-cb7vv   1/1     Running             0          4m20s
13months@13monthsBook k8s %

 

 

무중단 업데이트의 방법 중 하나인 롤링 업데이트가 실행되는 순간이다. 

예전의 Pod을 먼저 다 죽이지 않고 점진적으로 Pod를 띄운다. 

 

kubectl rollout status deployment/broken 명령어를 사용하면 deployment의 교체가 다 끝났는지 알 수 있다.

진행 중이라면 그 상황을 실시간으로 확인할 수 있음. 

 

13months@13monthsBook k8s % k get pods
NAME                      READY   STATUS    RESTARTS   AGE
broken-58cc58dd76-2qxf7   1/1     Running   0          2m52s
broken-58cc58dd76-dd7f6   1/1     Running   0          2m53s
broken-58cc58dd76-qmssq   1/1     Running   0          3m3s
13months@13monthsBook k8s % k rollout history deployment/broken 
deployment.apps/broken 
REVISION  CHANGE-CAUSE
1         <none>
2         <none>
3         <none>

13months@13monthsBook k8s %

 

 

rollout history의 REVISION을 통해 Deployment가 몇 번 바뀌었는지를 확인할 수 있다. 

이미지를 두 번 바꿨으니 REVISION 3까지 생겼다. 다만 왜 바꿨는지 이유를 적어놓지 않아서 나머지는 none으로 뜸. 

 

이렇게 rollout history에 리비전이 남아있다는건 바로 롤백도 가능하다는 것. 

 

13months@13monthsBook k8s % k rollout history deployment/broken 
deployment.apps/broken 
REVISION  CHANGE-CAUSE
1         <none>
2         <none>
3         <none>

13months@13monthsBook k8s % k rollout undo deployment/broken
deployment.apps/broken rolled back
13months@13monthsBook k8s % k get pods
NAME                      READY   STATUS    RESTARTS   AGE
broken-74897b87bc-9p9gq   1/1     Running   0          9s
broken-74897b87bc-mt2cr   1/1     Running   0          8s
broken-74897b87bc-nv5rn   1/1     Running   0          9s
13months@13monthsBook k8s % k rollout history deployment/broken 
deployment.apps/broken 
REVISION  CHANGE-CAUSE
1         <none>
3         <none>
4         <none>

13months@13monthsBook k8s % k describe deployment broken | grep Image
    Image:         nginx:latest
13months@13monthsBook k8s %

 

ReplicaSet 해시가 다시 돌아왔고 nginx 버전도 돌아왔다. 

 

rollout history를 보면 REVISION이 1 3 4 로 변했는데.. 

같은 내용의 리비전은 번호가 중복될 수 없고 항상 최신 번호를 받는다. 그러니 2번이 4번으로 식별자를 바꿨음. 

 

 


 

 

describe로 잡을 수 있는 문제는 쿠버네티스 수준에서 해결할 수 있는 문제.

Pod이 안 뜨거나, 이미지를 못 받거나, 자원이 부족하거나.. 이럴 때는 describe의 Events를 확인한다. 

 

컨테이너가 시작되긴 했지만 그 안에서 실행되는게 고장난 경우 앱이 출력하는 로그를 본다. 

logs 명령어로 확인할 수 있다. 

 

 

13months@13monthsBook k8s % k run crasher --image=busybox --command -- sh -c "echo '앱 시작...'; echo '에러: 설정 파일을 찾을 수 없음' >&2; exit 1"
pod/crasher created
13months@13monthsBook k8s % k get pods
NAME                      READY   STATUS             RESTARTS      AGE
broken-74897b87bc-9p9gq   1/1     Running            0             6m13s
broken-74897b87bc-mt2cr   1/1     Running            0             6m12s
broken-74897b87bc-nv5rn   1/1     Running            0             6m13s
crasher                   0/1     CrashLoopBackOff   1 (16s ago)   23s
13months@13monthsBook k8s % k logs crasher
앱 시작...
에러: 설정 파일을 찾을 수 없음
13months@13monthsBook k8s %

 

 

kubectl run 명령어로 pod를 바로 띄울 수 있다. 

arg로 exit 1; 호출하고 죽어버리니 컨테이너는 잘 뜨지만 앱이 오류를 뱉고 죽는다. 이 때 logs로 디버깅하면 됨.

 

이건 못고친다 그냥 logs로 읽을 수 있다만 확인하고 넘어가자. 

계속 죽는 애플리케이션은 현재 로그가 비어있을 수 있으니 kube ctl logs --previous로 죽기 직전까지의 로그를 봐야 함.

 

 

반응형
저작자표시 (새창열림)

'DevOps > Docker && Kubernetes' 카테고리의 다른 글

[Kubernetes] kubectl 연습 - RoleBinding  (0) 2026.07.26
[Kubernetes] Kubernetes Concept  (0) 2026.07.21
[k8s] 쿠버네티스 도입  (0) 2023.12.17
[Docker] 네트워킹과 Docker Compose  (1) 2023.12.10
[Docker] Dockerfile 프로젝트 배포하기  (3) 2023.12.06

댓글

이 글 공유하기

  • 구독하기

    구독하기

  • 카카오톡

    카카오톡

  • 라인

    라인

  • 트위터

    트위터

  • Facebook

    Facebook

  • 카카오스토리

    카카오스토리

  • 밴드

    밴드

  • 네이버 블로그

    네이버 블로그

  • Pocket

    Pocket

  • Evernote

    Evernote

다른 글

  • [Kubernetes] kubectl 연습 - RoleBinding

    [Kubernetes] kubectl 연습 - RoleBinding

    2026.07.26
  • [Kubernetes] Kubernetes Concept

    [Kubernetes] Kubernetes Concept

    2026.07.21
  • [k8s] 쿠버네티스 도입

    [k8s] 쿠버네티스 도입

    2023.12.17
  • [Docker] 네트워킹과 Docker Compose

    [Docker] 네트워킹과 Docker Compose

    2023.12.10
다른 글 더 둘러보기

정보

천천히 꾸준히 조용히 블로그의 첫 페이지로 이동

천천히 꾸준히 조용히

  • 천천히 꾸준히 조용히의 첫 페이지로 이동

검색

방문자

  • 전체 방문자
  • 오늘
  • 어제

카테고리

  • 분류 전체보기 (714)
    • Algorithm (205)
      • Data Structure (5)
      • Theory && Tip (33)
      • Baekjoon (166)
      • ALGOSPOT (1)
    • Spring (123)
      • Spring (28)
      • Spring Web MVC (20)
      • Spring Database (14)
      • Spring Boot (6)
      • Spring 3.1 (11)
      • Spring Batch (6)
      • Spring Security (16)
      • JPA (12)
      • Spring Data JPA (5)
      • QueryDSL (4)
      • eGovFramework (1)
    • Programming Language (74)
      • C (25)
      • C++ (12)
      • Java (19)
      • JavaScript (15)
      • Python (1)
      • PHP (2)
    • Computer Science (163)
      • Machine Learning (38)
      • Operating System (18)
      • Computer Network (28)
      • System Programming (22)
      • Universial Programming Lang.. (8)
      • Data Science (11)
      • Embedded Software (10)
      • Computer Architecture (4)
      • Compiler Design (11)
      • Computer Security (13)
    • Database (21)
      • Database (7)
      • MySQL (3)
      • Oracle (3)
      • Redis (5)
      • Elasticsearch (3)
    • DevOps (24)
      • Docker && Kubernetes (11)
      • Jenkins (4)
      • Cloud Service (9)
    • Mobile (28)
      • Android (21)
      • Flutter (7)
    • 💡 솔루션 (17)
    • 👥 모각코 (12)
    • 💬 기록 (15)
    • 📚 논문 (7)
    • -------------- (25)

최근 글

나의 외부 링크

메뉴

  • 홈
반응형

정보

i3months의 천천히 꾸준히 조용히

천천히 꾸준히 조용히

i3months

블로그 구독하기

  • 구독하기
  • RSS 피드

티스토리

  • 티스토리 홈
  • 이 블로그 관리하기
  • 글쓰기
Powered by Tistory / Daum. Copyright © i3months.

티스토리툴바