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

천천히 꾸준히 조용히

페이지 맨 위로 올라가기

천천히 꾸준히 조용히

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

[Kubernetes] kubectl 연습 - namespace와 Secret

  • 2026.08.20 13:48
  • DevOps/Docker && Kubernetes
반응형

 

 

 

namespace는 클러스터 내부의 구역을 의미한다. 

클러스터 안의 리소스(Pod, Deployment, Service)를 논리적으로 묶는 라벨으로 생각하면 됨.

클러스터는 하나고, 그 안의 리소스를 그룹으로 구분한다. 노드를 구분하는 것도 아님. 노드와 namespace는 완전히 다른 축이다. 

 

 

 

 

클러스터 안에 두 개의 노드가 있고 (Control Plane, Worker Node)

그 노드 안에는 Pod가 있다. 

namespace는 저렇게 물리적으로 구분하는게 아니고 같은 클러스터 안을 논리적으로 구분한다. 

 

저걸 쓰는 이유는 C++의 namespace를 사용하는 이유와 똑같음. 

my-web 이라는 deployment를 여러 군데에서 사용할 때 namespace만 다르게 지정해주면 된다. 

 

개발 / 운영 리소스를 따로 설정할 때도 유용한다. 

 

 

13months@13monthsBook k8s % kubectl get namespaces
NAME              STATUS   AGE
default           Active   131m
kube-node-lease   Active   131m
kube-public       Active   131m
kube-system       Active   131m
13months@13monthsBook k8s %

 

 

namespace를 따로 설정하지 않으면 default로 들어간다.

kube-system은 쿠버의 핵심 부품이 들어가는 방이고, kube-public과 kube-node-lease는 잘 안쓴다. 

 

13months@13monthsBook k8s % k get pods -n kube-system
NAME                               READY   STATUS    RESTARTS   AGE
coredns-7d764666f9-kd4kp           1/1     Running   0          132m
etcd-minikube                      1/1     Running   0          132m
kube-apiserver-minikube            1/1     Running   0          132m
kube-controller-manager-minikube   1/1     Running   0          132m
kube-proxy-7vtvh                   1/1     Running   0          132m
kube-scheduler-minikube            1/1     Running   0          132m
storage-provisioner                1/1     Running   0          132m
13months@13monthsBook k8s %

 

 

-n 옵션을 주면 kube-system namespace가 가진 리소스를 확인할 수 있다. (-A 옵션을 주면 모든 namespace를 다 볼 수 있음)

그냥 kubectl get pods만 하면 default가 가진 것만 확인할 수 있었음. 

 

 

 

 

kube-system이 어떤 역할을 하는지 살펴보자. 

 

1. api-server 

클러스터의 유일한 출입구로 kubectl로 명령어를 보내면 무조건 api-server를 거친다. 

스프링의 디스패처 서블릿 같은것.. 보안 인증 검증을 api-server에서 통합 관리할 수 있어 편함. 

얘가 죽으면 kubectl 자체가 안 먹힌다. kubectl이 반응이 없다면 api-server를 의심

 

2. etcd

클러스터의 모든 상태를 저장하는 데이터베이스로 어느 노드에 뭐가 있는지, Service 설정은 어떻게 되어있는지, Pod가 몇 개 있어야 하는지 등 모든 정보가 etcd에 저장된다. 

declarative로 원하는 상태를 적어두는데 여기서 적은 내용이 etcd에 저장된다. 

얘가 죽으면 클러스터가 제대로 동작하지 않으니 etcd를 백업하고 복원하는게 정말 정말 중요하다. 

 

3. scheduler 

새로운 Pod를 어떤 노드에 배치할지를 결정한다. 

서버컴 n개 중 어디가 여유로운지를 판단해서 최적의 배치를 결정하는 역할을 수행함. 

결정만 하고 실제로 배치하지는 않는다. api-server에게 알려주고 띄우는건 api-server가.. 

얘가 죽으면 배치할 노드를 정하는 애가 없으니 새로운 Pod이 Pending 상태로 멈춰있는다. 

 

4. controller-manager

현재 상태가 정의된 상태인지 계속 확인한다.

계속 etcd를 감시하고 Pod 개수가 일치하지 않으면 etcd에게 개수 맞추라고 알려준다. 

얘가 죽으면 자동 복구가 안 되니 Pod가 죽어도 새로 뜨지 않고 Replica를 바꿔도 반영되지 않는다. 

 

5. kubelet

노드에서 실제로 컨테이너를 띄우는 역할을 수행한다. 

위에 1번 ~ 4번 까지는 Control Plane이지만 kubelet은 모든 노드에 하나씩 있음.

api-server가 Pod를 띄우라고 지시하면 kubelet이 containerd에게 컨테이너를 실행하라고 시킨다. 

얘가 죽으면 해당 노드가 NotReady 상태가 된다. 

 

kubectl create deployment my-web 명령어를 실행하면 

 

1. kubectl이 명령을 api-server에게 보냄

2. api-server가 검증 후 Deployment 실행을 etcd에 저장

3. controller-manager가 Pod 생성을 지시

4. scheduler가 새 Pod를 minikube 노드에 넣자고 결정하고

5. kubelet이 containerd로 실제로 실행한다 

 

 

일단 Worker Node 안에는 Pod가 배치된다 (물리적으로) 

Deployment와 ReplicaSet은 노드 안에 없음. 그냥 실체가 없는 기록일 뿐이다. 

저 두 개는 실제로 수행되는 프로그램이 아니고 etcd에 저장된 설정 정보일 뿐임.

 

즉, kube-system은 노드가 아니라 namespace. Control Plane 노드가 아니다.

위에서 본 etcd / api-server / scheduler 등은 Control Plane의 부품이 Pod로 실행되고 있는 것. 

쿠버네티스가 자기 자신을 돌리기 위해 필요한 시스템리소스를 모아둔 namespace 라고 생각하자. 

 

(개념 헷갈리면 힘드니까 제대로 읽고 정리하기)

 

Control Plane 노드에는 etcd / kube-apiserver / kube-scheduler / kube-controller-manager

Worker Node를 포함한 모든 노드에는 kubelet / kube-proxy 를 가진다. 

Control Plane 노드에서도 api-server 같은 Pod를 띄워야 하고 Pod를 띄우는 건 kubelet이 수행하니까.. 

 

namespace와 노드는 서로 Orthogonal 관계라서 Pod는 특정 namespace에 속할 수도 있고 특정 노드에도 속할 수 있다. 

 

 

13months@13monthsBook k8s % kubectl get pods -n kube-system -o wide
NAME                               READY   STATUS    RESTARTS   AGE   IP             NODE       NOMINATED NODE   READINESS GATES
coredns-7d764666f9-kd4kp           1/1     Running   0          20h   10.244.0.2     minikube   <none>           <none>
etcd-minikube                      1/1     Running   0          20h   192.168.49.2   minikube   <none>           <none>
kube-apiserver-minikube            1/1     Running   0          20h   192.168.49.2   minikube   <none>           <none>
kube-controller-manager-minikube   1/1     Running   0          20h   192.168.49.2   minikube   <none>           <none>
kube-proxy-7vtvh                   1/1     Running   0          20h   192.168.49.2   minikube   <none>           <none>
kube-scheduler-minikube            1/1     Running   0          20h   192.168.49.2   minikube   <none>           <none>
storage-provisioner                1/1     Running   0          20h   192.168.49.2   minikube   <none>           <none>
13months@13monthsBook k8s %

 

 

-o는 출력 형식을 지정하고 wide는 더 많은 정보를 보여달라는걸 의미한다. 

-o wide 옵션으로 IP와 NODE 컬럼을 추가로 확인할 수 있다. (-o yaml -o json -o name 옵션도 있음)

 

아이피 종류가 2개인데, 192.168.49.2 아이피는 minikube 자체의 아이피이다.

 

일반 Pod은 Pod 전용 대역에서 IP를 받아서 사용한다. (10.244.x)

etcd /  apiserver / controller 등 호스트 네트워크를 쓰는 Pod는 노드의 아이피를 그대로 받아서 사용한다. 

핵심 구성요소들은 쿠버 네트워크에 의존하지 않고 노드 네트워크를 직접 사용한다.

 

minikube는 실습용 미니 쿠버네티스로 클러스터를 작게 축소해서 컴퓨터에 실습 환경을 구축할 떄 사용한다.

minikube start --driver=docker 로 실행했기에 노드 1개짜리 쿠버네티스 클러스터가 계속 돌고 있음. 

 

etcd /  kubelet / kube-apiserver 등 쿠버 구성요소들은 리눅스에서 돌아가는 소프트웨어이다.

애초에 컨테이너 기술 자체가 리눅스 커널 기능이기도 함. 이 격리 기술은 맥이나 윈도우에는 없음. 

 

맥에서 도커를 쓸 때도 맥 안에 리눅스 VM을 하나 띄워두고 그 안에서 컨테이너를 돌린다. (Docker Desktop이 해줌)

 

일단 지금은 minikube를 사용하는데. 그러기에 Controle Plane 노드 한개만 돌아가고 있음. Control Plane과 Worker Node 겸용..

실제 클러스터에서는 Control Plane 노드에는 일반 Pod를 올리지 않는다.

실제로 노드 여러개 띄우고 실습 할 때는 minikube sstart --nodes=3 으로 설정해주면 된다. 

 

 

 

 


 

 

 

 

쿠버에서 앱에 설정값을 넘겨줄 때는 ConfigMap과 Secret을 사용한다. (DB 접속 정보 등.. application.yml을 생각하기)

 

13months@13monthsBook k8s % k create configmap my-config --from-literal=APP_COLOR=blue --from-literal=APP_MODE=production
configmap/my-config created
13months@13monthsBook k8s % kubectl get configmap
NAME               DATA   AGE
kube-root-ca.crt   1      21h
my-config          2      14s
13months@13monthsBook k8s % kubectl describe configmap my-config
Name:         my-config
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
APP_COLOR:
----
blue

APP_MODE:
----
production


BinaryData
====

Events:  <none>
13months@13monthsBook k8s % vim config-test.yaml
13months@13monthsBook k8s % vim config-test.yaml
13months@13monthsBook k8s %
apiVersion: v1
kind: Pod
metadata:
  name: config-test
spec:
  containers:
  - name: test
    image: busybox
    command: ["sh", "-c", "echo COLOR=$APP_COLOR MODE=$APP_MODE; sleep 3600"]
    envFrom:
    - configMapRef:
        name: my-config
~
13months@13monthsBook k8s % kubectl apply -f config-test.yaml
pod/config-test created
13months@13monthsBook k8s % kubectl logs config-test 
COLOR=blue MODE=production
13months@13monthsBook k8s % kubectl exec -it config-test -- sh
/ # echo $APP_COLOR
blue
/ # env | grep APP
APP_MODE=production
APP_COLOR=blue
/ #

 

 

이미지는 환경변수를 모르지만 쿠버가 실행 시점에 밖에서 값을 주입해준다. 

웹개발에서 똑같은거 계속 하는데 그냥 쿠버에서는 어떻게 하는지? 를 보여주는거임 

 

스프링부트에서 yml 작성할 때 데이터베이스 접속정보를 평문으로 그대로 입력하지 않는 것 처럼 민감정보는 secret으로 따로 다룬다.

 

13months@13monthsBook k8s % kubectl create secret generic my-secret --from-literal=DB_PASSWORD=mypassword123
secret/my-secret created
13months@13monthsBook k8s % kubectl describe secret my-secret
Name:         my-secret
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  Opaque

Data
====
DB_PASSWORD:  13 bytes
13months@13monthsBook k8s % kubectl get secret my-secret -o yaml
apiVersion: v1
data:
  DB_PASSWORD: bXlwYXNzd29yZDEyMw==
kind: Secret
metadata:
  creationTimestamp: "2026-07-22T04:20:59Z"
  name: my-secret
  namespace: default
  resourceVersion: "30742"
  uid: ac1972e2-72d9-4406-a537-bd116753db8c
type: Opaque
13months@13monthsBook k8s % echo 'bXlwYXNzd29yZDEyMw==' | base64 -d
mypassword123%

 

 

secret이라서 암호화 돼서 못보는게 아닌가 싶긴 한데;; 사실 암호화가 아니다. 그냥 인코딩일 뿐임. 

그래도 평문으로 보이는 것 보다는 나으니까..? 

 

사실 secret을 base64로 다루는 본질적인 이유는 바이너리 데이터를 다루기 위해서이다.

secret을 secret처럼 다루려면 RBAC로 아무나 kubectl get secret을 수행하지 못하도록 권한을 통제하면 된다. 

 

apiVersion: v1
kind: Pod
metadata:
  name: secret-test
spec:
  containers:
  - name: test
    image: busybox
    command: ["sh", "-c", "echo PW=$DB_PASSWORD; sleep 3600"]
    env:
    - name: DB_PASSWORD
      valueFrom:
        secretKeyRef:
          name: my-secret
          key: DB_PASSWORD
          

13months@13monthsBook k8s % kubectl apply -f secret-test.yaml 
pod/secret-test created
13months@13monthsBook k8s % kubectl logs secret-test 
PW=mypassword123
13months@13monthsBook k8s %

 

envFrom 대신 valueFrom을 사용하면 특정 키를 골라서 넣을 수 있다. 

 

 

apiVersion: v1
kind: Pod
metadata:
  name: volume-test
spec:
  containers:
  - name: test
    image: busybox
    command: ["sh", "-c", "ls /etc/config; cat /etc/config/APP_COLOR; sleep 3600"]
    volumeMounts:
    - name: config-volume
      mountPath: /etc/config
  volumes:
  - name: config-volume
    configMap:
      name: my-config
      
13months@13monthsBook k8s % vim volume-test.yaml
13months@13monthsBook k8s % k apply -f volume-test.yaml 
pod/volume-test created
13months@13monthsBook k8s % k logs volume-test 
Error from server (BadRequest): container "test" in pod "volume-test" is waiting to start: ContainerCreating
13months@13monthsBook k8s % k logs volume-test
APP_COLOR
APP_MODE
13months@13monthsBook k8s % k get pod volume-test -o yaml | grep -A 5 command
      {"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"name":"volume-test","namespace":"default"},"spec":{"containers":[{"command":["sh","-c","ls /etc/config; cat /etc/config/APP_COLOR; sleep 3600"],"image":"busybox","name":"test","volumeMounts":[{"mountPath":"/etc/config","name":"config-volume"}]}],"volumes":[{"configMap":{"name":"my-config"},"name":"config-volume"}]}}
  creationTimestamp: "2026-07-22T04:34:10Z"
  generation: 1
  name: volume-test
  namespace: default
  resourceVersion: "31394"
--
  - command:
    - sh
    - -c
    - ls /etc/config; cat /etc/config/APP_COLOR; sleep 3600
    image: busybox
    imagePullPolicy: Always
13months@13monthsBook k8s % k exec -it volume-test -- sh
/ # ls -la /etc/config/
total 12
drwxrwxrwx    3 root     root          4096 Jul 22 04:34 .
drwxr-xr-x    1 root     root          4096 Jul 22 04:34 ..
drwxr-xr-x    2 root     root          4096 Jul 22 04:34 ..2026_07_22_04_34_10.2502450523
lrwxrwxrwx    1 root     root            32 Jul 22 04:34 ..data -> ..2026_07_22_04_34_10.2502450523
lrwxrwxrwx    1 root     root            16 Jul 22 04:34 APP_COLOR -> ..data/APP_COLOR
lrwxrwxrwx    1 root     root            15 Jul 22 04:34 APP_MODE -> ..data/APP_MODE
/ # cat /etc//config/APP_COLOR 
blue/ # exit
13months@13monthsBook k8s %

 

 

kubectl logs volume-test 결과로 blue가 안 나왔다. 

그리고 컨테이너가 만들어지는 중에 로그를 찍어보니 에러가 발생함. 자주 발생하는 에러임. 

 

command: ["sh", "-c", "ls /etc/config; cat /etc/config/APP_COLOR; sleep 3600"]

 

커맨드를 보면 ls만 출력됐고 cat 결과가 안 나왔으니 이 부분을 확인해보자. 

exec으로 컨테이너 안에 들어가서 cat 해보니 blue가 출력되긴 했음. 

그러니 마지막 줄이 개행 없이 끝나서 화면에 안 보였던 것.

 

ConfigMap을 파일로 마운트하면 값이 바뀔 때 컨테이너 내부 파일도 자동으로 갱신된다. 

ls 찍어봤을때 심볼릭 링크로 타고 타고 들어가고 있음을 확인할 수 있음. 

링크 없이 진짜 파일을 참조하고 있었다면 Atomicity가 보장되지 않을 수 있으니 심볼릭 링크를 사용한다. 

 

환경변수는 컨테이너 시작할 때 한 번 주입되고 끝난다. ConfigMap 바꿔도 Pod에는 반영되지 않음.

파일 마운트로 처리하면 ConfigMap이 바뀌면 파일도 자동으로 바뀐다. 

 

사실 당연한 소리긴 함. 마운트 했다고 하더라도 그 안의 스프링부트가 다시 떠야지 마운트 된거를 새로 읽을거고.. 

 

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

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

[Kubernetes] Certified Kubernetes Administrator 연습 (4)  (0) 2026.08.17
[Kubernetes] Certified Kubernetes Administrator 연습 (3)  (0) 2026.08.06
[Kubernetes] kubectl 연습 - RoleBinding  (0) 2026.07.26
[Kubernetes] kubectl 연습 - Deployment ReplicaSet  (0) 2026.07.21
[Kubernetes] Kubernetes Concept  (0) 2026.07.21

댓글

이 글 공유하기

  • 구독하기

    구독하기

  • 카카오톡

    카카오톡

  • 라인

    라인

  • 트위터

    트위터

  • Facebook

    Facebook

  • 카카오스토리

    카카오스토리

  • 밴드

    밴드

  • 네이버 블로그

    네이버 블로그

  • Pocket

    Pocket

  • Evernote

    Evernote

다른 글

  • [Kubernetes] Certified Kubernetes Administrator 연습 (4)

    [Kubernetes] Certified Kubernetes Administrator 연습 (4)

    2026.08.17
  • [Kubernetes] Certified Kubernetes Administrator 연습 (3)

    [Kubernetes] Certified Kubernetes Administrator 연습 (3)

    2026.08.06
  • [Kubernetes] kubectl 연습 - RoleBinding

    [Kubernetes] kubectl 연습 - RoleBinding

    2026.07.26
  • [Kubernetes] kubectl 연습 - Deployment ReplicaSet

    [Kubernetes] kubectl 연습 - Deployment ReplicaSet

    2026.07.21
다른 글 더 둘러보기

정보

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

천천히 꾸준히 조용히

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

검색

방문자

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

카테고리

  • 분류 전체보기 (717) N
    • 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 (27) N
      • Docker && Kubernetes (14) N
      • 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.

티스토리툴바