CLOUDWAVE

Kubernetes Basic : Cluster, Node, Pod, Label&Annotation, Namespace ( 25.01.09 )

갬짱 2025. 1. 15. 19:40

쿠버네티스란?

리눅스재단 소속의 CNCF에 인큐베이팅되어 첫번째로 졸업한 서비스 ( CNCF의 서비스 단계 : sandbox → incubating → graduated / archived )

서비스의 추상화, 서비스의 효과적 관리 → 효과적이고 손쉬운 도구 제공( 자가치유, 오토스케일링 등 )

 

global scale internet bussiness : 다양한 소비자의 요구사항이 존재 → 배포, 빌드가 잦아짐 → MSA(Microservices Architecture), container기술의 중요성이 커짐

upstream project( 오픈소스 )를 기반하여 다양한 서비스를 생성 → 기능을 정의한 interface를 공개( 상세구현없이 스펙만을 정의 ) + provider개념( 환경에 맞게 직접구현 )

xinfra : 환경에 맞게 생성하는 yaml파일이 종류별로 존재함 ( 약간의 내용만 다를뿐 기본적으로 유사함 )

 

쿠버네티스는 수많은 컨테이너를 관리하기위한 서비스

  • 선언이 유지되기 위해 노력함 ( self-healing )
  • 선언을 봄 ( ideal state )
  • 선언이 구현된 실질적인 환경을 봄( actual state ) = 선언대로 구현되었는지 반복적으로 체크

 

k8s의 기본구성단위( 클러스터 )

  • Control Plane : 쿠버네티스의 머리, 중심부 ⇒ kubectl를 통해 접근(CLI), 이에대한 모든 요청은 apiserver를 통해 이루어짐
    • etcd : 분산형 데이터베이스, 쿠버네티스에서 일어나는 모든 기록 → 장애처리
      ⇒ control plane 노드는 최소 3개이상으로 진행할 것 ( 1대를 upgrade할 때 2대가 처리, 그중 하나가 죽어도 안전함 ) ~ 최대 5개로 진행하는 경우도 존재함
    • controller manager : 제어 루프를 이용해 설정된 상태를 지속적으로 유지하도록 함
      선언과 실제 구현을 비교, 지속적으로 감시 점검
    • scheduler : 클러스터의 노드에 파드를 배포 하는 역할( feasibility 계산 하여 적절한 노드에 배포)
    • kube apiserver : 쿠버네티스 오브젝트에 대한 데이터를 설정하고 검증. REST 서비스 제공 ( docker daemon에 전달될때 API형태로 전달됨 ), 통신HUB의 역할

  • Worker Nodes
    • kubelet : 컨테이너화된 애플리케이션이 제대로 실행되도록 관리하고 모니터링 → 내부 pod를 관리, 보고, 헬스체크, 로그관리, 자원관리 ⇒ API서버에 통신
    • kube-proxy : 애플리케이션의 구성 요소간에 네트워크 트래픽을 분산
    • container runtime ⇒ containerd로 지정됨(고정) : 서비스를 올려서 구동하는 역할 기본적인 container-runtime(구동환경)은 Docker쿠버네티스의 container runtime : 1.12버전까지는 docker를 사용 → 이후 containerd를 사용( 컨테이너 표준 ) → 이를 구현한 것이 docker, podman, containerd, rtk 등…

 

control node와 worker node의 상호작용 

 

k8s에서 애플리케이션 실행

  • 앱 디스크립터( YAML ) : 다양한 종류의 컨테이너들을 선언
  • kubectl을 통해 Control plane에 전달 → API서버를 통해 스케줄러가 feasibility(남아있는 여유노드)를 검색하여 배치, 명령을 실행etcd에 저장
    • 어떤 노드에 어떤 컨테이너가 실행되는지는 don’t care ( 쿠버네티스를 사용하는 목적 )
    • 컨테이너의 이미지는 자동적으로 레지스트리에서 검색되어서 실행함
  • ( 도커파일을 작성하여 도커데몬에 전달하는 것과 유사함 )
  • 이후 controller가 지속적인 감시관리, 컨테이너의 작업이 끝나면 etcd에 기록된 컨테이너 상태의 active를 inactive로 변경됨

 

k8s의 POD

POD란

: 쿠버네티스의 애플리케이션의 기본실행단위 ( 만들고 배포할 수 있는 가장 작은 단위 )

  • pod는 컨테이너를 하나 이상 가질 수 있다. ( 한개 이상의 컨테이너가 소속 )
  • 관례적으로 pod는 하나의 컨테이너가 포함됨 ( 단일책임원칙으로 운영, 일대일 대응 )
    • 업무목적 컨테이너(app)는 1개 + 운영적인 목적의 컨테이너( 로그 저장 및 전달 등과 같은 부가적인 업무 )가 함께 저장되기도 함(sidecar container) ⇒ sidecar pattern
  • 파드내 컨테이너(들)은 오로지 하나의 노드 내에서만 존재 ( 하나의 파드가 노드를 거쳐있을 수는 없음 )

 

동일한 파트 내의 컨테이너는 네트워킹 및 볼륨을 공유하게된다

⇒ 업무 컨테이너가 작성한 내용을 운영 컨테이너가 접근가능함

⇒ 자동적으로 통신가능

 

POD 기본명령

쿠버네티스 기본 명령어 : 쿠버티스 클라이언트를 통해 모든 명령어를 전달함 ( 다양한 리소스들을 확인 접근 가능 ) ( kubectl + 동사 + 리소스 )

kubectl get po = kubectl get pods

kubectl get no = kubectl get nodes

kubectl get ns = kubectl get namespaces

 

[ POD 생성 ]

(1) VSCode extension YAML( by Redhat ), Kubernetes, Kubernetes support를 설치

(2) pod구조 및 생성을 정의하는 YAML의 작성( Template )

** YAML형식 : 관례상 2개이상 들여쓰기를 수행하고 tab을 사용하지 않음

서로 다른 YAML 정의를 하나의 파일에 사용 ( - - - ) ⇒ 별개의 YAML파일로 인지함

  • apiVersion = k8s api version
  • YAML파일에서 kind항목은 리소스의 유형을 지정함( k8s 리소스 타입 )
  • metadata : 이름, 레이블 등의 부가정보
  • spec : 리소스의 구체적인 구성 = 컨테이너 정보
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.14.2
    ports:
    - containerPort: 80
kubectl apply -f ./pod.yaml

지정한 yaml파일을 이용한 pod생성

  • create : 신규생성
  • apply : 신규생성 및 추후사용(기록보관)

 

[ POD 상태 확인 ]

kubectl get po

Kubernetes 클러스터 내의 pod들을 모두 출력함

 

kubectl get po -o wide

상세정더 많은 정보를 알려준다 → 컨테이너의 IP정보까지 알려줌

 

kubectl get po -w

pod의 상태가 변경될때까지 대기한다 ( watching mod = monitoring mode )

 

kubectl logs <pod_name> -n <namespace>

log : 컨테이너 내의 어플리케이션의 표준출력(stdout)및 표준오류(stderr)를 본다

 

kubectl describe pod <pod_name> -n <namespace>

describe : pod 컨테이너의 정보를 상세조회 → etcd에 저장된 내용을 그대로 복사하여 화면에 출력

  • Events 항목 = 동사 + 대상 + 이름
  • Node : Pod가 실행되고 있는 노드
  • Type : Noraml(정상)
  • From : kubelet

현재 pod의 정보를 yaml로 내보냄

kubectl get po goapp-pod2 -o yaml > data.yaml

 

하단에 구동과 관련된 status 상태정보가 추가됨

 

[ pod 삭제 ]

kubectl delete po 파드명

kubectl delete po all —all : 모든 파드를 삭제

  • 삭제해도 지워지지 않는 리소스가 존재함
  • service "kubernetes" deleted → 그러나 다시 살아남( kubectl get svc )

 

Kubernetes Network Basic

k8s에는 기본적으로 3개의 네트워크가 적용된다.

(1) 노드 네트워크, 호스트 네트워크 = flat Network = kind network(172.19.0.0/16) : 기본적인 네트워크, kind의 네트워크와 동일함

  • 클러스터를 구성하는 노드(Node) 간의 통신을 위한 네트워크

(2) 서비스 네트워크 = 클러스터 네트워크 : 내부의 다양한 서비스를 띄우기 위한 네트워크

  • Service : Pod에 안정적인 네트워크 접근을 제공하기 위한 Kubernetes 리소스( ClusterIP, NodePort, LB )

(3) 파드 네트워크 → 10.110.1.2 : 클러스터 내부에 다양한 파드를 띄우기 위한 별도의 네트워크

  • 별도의 ip주소를 overlay하여( 가상화 ) ip주소 고갈을 방지한다
  • CNI(Container Network Interface) 플러그인이 물리적인 노드 네트워크와 가상화된(overlay된) 네트워크를 연결 CNI가 노드 네트워크와 연결된 파드 네트워크를 만든다 = 파드 네트워크를 구성하고 가상화한다

 

Kubernetes Network 실습

현재 전반적인 네트워크 구조

  • 윈도우 (192.168.239.1) , underlay
  • kind network(172.19.0.0/16) → docker 소속 , overlay
    ( 이에 IDE container, 노드 3개를 포함한 k8s가 속해있음 )
    • pod network(10.110.0.0/16), overlay : nginx pod, goapp pod
    • service netowrk, overlay

 

[ 네트워크 가상화 ]
: underlay위에 overlay라는 가상망을 구축한다. underlay는 overlay의 내용을 정확하게 알지 못한다( 캡슐화 )

  • Underlay: 실제 물리적 네트워크, 물리적 노드와 연결된 네트워크.
  • Overlay: 물리적 네트워크(underlay) 위에 구축된 가상화된 네트워크. 이 네트워크는 가상화된 네트워크로, 실제 물리적 주소를 알지 못합니다.

 

원래 IDE컨테이너와 k8s는 kind네트워크로 연결된 상태 → 그러나 k8s안에 만든 IP를 조회해보면 10번대의 다른 영역으로 출력됨 ⇒ Kubernetes 내부 Pod들은 외부 네트워크(172..)와 분리된 Overlay 네트워크(10…)를 사용하기 때문에, 직접적인 통신이 불가능

 

[ 네트워크 주소변환(NAT) ]

  • 외부→POD = 캡슐화 : 각 네트워크 계층에서 헤더가 추가 = 패킷 헤더에는 외부 네트워크의 주소와 목적지 주소가 설정 = 외부의 IP 주소를 클러스터 노드 IP 주소로 변경하는 NAT 작업
  • POD→외부 = 역캡슐화 : overlay영역에서는 underlay의 데이터영역에 대한 정보를 다시 헤더와 데이터로 저장하게됨( ex. 10망의 내부 data영역에 172망의 위치정보가 존재 → 172망의 내부 data영역에 192망의 위치정보가 존재 ⇒ 데이터 영역을 까서 해석하고 쓰는 느낌으로 진행 )

[ 포트포워딩 ]

클라이언트의 특정 포트를 Kubernetes 내부 Pod의 포트와 연결해, 통신 문제를 우회 = Overlay 네트워크와 외부 네트워크 간의 연결을 일시적으로 설정

kubectl port-forward nginx 8081:80

 

파드 nginx에서의 포트 80을 로컬의 포트 8081과 묶어줌

kubectl port-forward 명령을 이용하여 pod nginx에서의 포트 80을 로컬의 포트 8081과 묶어줌 kind network에서 포트포워딩으로 pod network에 접속 → 윈도우 브라우저에서도 포트포워딩으로 kind network에 접속가능하게 해줌 ( open in browser를 실행시 한번더 로컬로 포트포워딩 = VScode의 자동적인 기능 ) ( 총 2회 )

 

API 그룹

쿠버네티스 API를 더욱 쉽게 확장하게 해준다.

YAML 파일 내의 apiVersion : 리소스마다 속해져있는 버전을 명시함 ( API그룹/버전 )

  • API그룹
    • core API 그룹은 이름을 생략할 수 있음
  • API버전
    • 알파는 제일 낮은 단계 ( 테스트용 ), 기본적으로 비활성화( 예: v1alpha1 )
    • 베타는 수정가능성 → 기능자체가 사라지지는 않음 ( 예: v2beta3 )
    • 안정화는 vX로 표기 ( 예: v1 )

⇒ 정의한 YAML내용에 따라 provider가 구현하는 방식이 API그룹별로 상이함

 

Label & Annotation

  • Label
    • 쿠버네티스의 모든 리소스에 부여가능한 임의의 key-value 쌍 리소스를 만들때 metadata영역에 부여
      동적변경 : kubectl label 명령어
    • label selector : 지정한 라벨을 기반으로 리소스를 선택, 분류가능 → ReplicaSet, ReplicationController, Deployment, DaemonSet, Service 등에서 사용
  • Annotation = 주석
    • 쿠버네티스의 모든 리소스에 부여가능한 임의의 key-value 쌍 리소스를 만들때 metadata영역에 부여
      동적변경 : kubectl annotate 명령
    • 라벨보다 다양하고 자세한 정보를 담음( 상세설명 ) : 시스템 정보, 디버깅 정보, 배포 관련 데이터 등
    • selector로 선택불가능

 

Label의 특징

  • 그룹화하고 싶은 pod들을 동시적으로 묶어서 처리가능 ( ex. 마이크로서비스의 지정 )
    • 생성(apply), 삭제(delete)의 다양한 작업때 라벨을 지정하여 그룹화된 파드를 제어가능함
  • 라벨은 다차원으로 여러개 부여가능 ( 예시 : app은 pod가 속한 애플리케이션, MS를 지정 + rel은 애플리케이션의 안정적 버전 지정 )
    • 통신사 연결 기능 ( labels = app : pay, tier : BE )캐시서비스 기능 ( label : app=pay, tier=cache )저장 기능 ( label : app=pay, tier=db )
    • 인증 기능 ( label : app=pay, tier=BE )
    • 결제 기능 ( labels = app : pay, tier : FE )

 

Lable의 실제활용( 실습 )

apiVersion: v1
kind: Pod
metadata:
  name: goapp-pod2
  labels:
    env: prod
	  app: myapp
	  tier: BE
spec:
  containers:
  - image: dangtong/goapp
    name: goapp-container
    ports:
    - containerPort: 8080
      protocol: TCP
kubectl create -f ./goapp-with-label.yaml

 

[ 라벨조회 ]

  • kubectl describe 로 특정 리소스의 라벨 조회가능
  • kubectl get 리소스명 -L 라벨명 으로 각 pod가 특정 라벨에 대해 가지는 값 조회 ( 라벨셀렉터 )
    kubectl get po -L env
    kubectl get po -L env,app
    kubectl get po -L env,app,tier 
    
  • 조건적용
    • and조건 : kubectl get po -l 'app in (application), tier in (frontEnd)’
    • or조건 : kubectl get po -l 'app in (application,backEnd)’

 

  • 파드(Pod) 리스트를 조회할 때 각 파드에 설정된 라벨(Label)을 함께 출력하는 명령
    kubectl get po --show-labels
    ​

 

[ 라벨추가 ]

kubectl label pod goapp-pod2 app="application" tier="frontEnd"
kubectl label nginx-pod rel=stable --overwrite

 

[ 라벨삭제 ]

kubectl label pod goapp-pod2 app- tier-

 

[ 스케줄링용 라벨 ]

쿠버네티스에서는 기본적으로 어떤 노드에 pod가 스케줄 될지 알 수 없음 노드에 라벨을 부여하여 특정되는 노드에 pod가 스케줄링되도록 제어가능

# 노드에 라벨 추가
kubectl label node [worker01.acorn.com](<http://worker01.acorn.com/>) ssd=true
apiVersion: v1
kind: Pod
	metadata:
		name: goapp-pod
	spec:
		**nodeSelector:
			ssd: “true”**
		containers:
		- image: dangtong/goapp
			name: goapp

 

Annotation의 실제활용(실습)

kubectl annotate pod goapp-pod2 make="rudals" team="olivenetworks”

 

관례적으로 reverse domain 형식으로 부여한다. 250kb 까지 작성 가능하지만, 되도록 짧고 간결하게 사용 할것

selector를 이용한 직접확인불가 → describe 명령을 이용한 개별확인

kubectl describe pod goapp-pod2

 

삭제

kubectl annotate pod app-pod2 maker- teams-

 

 

Namespace

[ 쿠버네티스의 두가지 운영방식 ]

 

(1) 클러스터수준의 운영 : 작은단위의 업무별로 클러스터를 나누어 운영

  • 하나의 클러스터 ⇒ kind를 통해 만들어지는 workder node, control node
  • 기술수준이 낮음 → 장애의 전파를 막기 어려움
  • 그러나 별도의 망으로 서비스를 진행해야하는 규제때문에 수행하기도 함( ex. 금융권 서비스 )
  • 업무별로 해당하는 pod들을 모두 모두 업그레이드 해야됨

(2) 네임스페이스 수준의 운영 : 하나의 큰 클러스트내부에 여러 노드가 구성됨 업무별로 노드를 횡단으로 나누어 운영

  • 메모리 관리역량이 좋음, 기술수준이 높음
  • 네임스페이스만 업그레이드 하면 됨

 

namespace 개요

쿠버네티스의 객체이름의 범위를 제공하는 것 → 멀티-테넌트 환경으로 분리하는 효과

node는 물리적으로 존재( worker, control ) ↔ pod는 물리적은 노드 위에 임의적으로 올라감 ( 어떤 worker node에 올라갈지 모름 )

 

namespace의 효과 = node위의 pod간 격리

  • node내에서 특정 pod가 오염되면 node전체가 오염될 위험이 있음
  • node단위로 내부를 제어하지 않고 node를 넘어서서 관리할 수 있는 수단으로 사용됨
  • pod하나의 단위로 cpu, 메모리, gpu 등의 사용량을 한정(지정)가능 ⇒ 나아가서 namespace단위로 지정가능
    • namespace는 같은 노드위에 파드들을 논리적으로 격리시킴
    • namespace를 삭제하면 어떤 노드에 있던지 모두 파드가 삭제됨
    • namespace단위로 통신제어 가능
    • namespace단위로 리소스를 제어가능( cpu, 메모리 사용량의 총합 )

 

namespace 사용법

[ 네임스페이스 조회 ]

kubens

현재 위치해있는 namespace에서 하이라이팅됨

kubectl apply로 리소스를 생성하면 기본적으로 현재위치의 namespace에 생성됨 → -n 옵션으로 소속될 네임스페이스 지정가능

 

[ 네임스페이스 조회 ]

kubectl get ns 

클러스터에 존재하는 네임스페이스들의 목록을 보여줌

kubectl get po -n 네임스페이스 

 

해당 네임스페이스에서 존재하는 파드들의 리스트를 보여줌

 

[ 네임스페이스 생성 ]

kubectl create ns olive-network

또는 YAML을 작성하여 구체적인 정의가능 ( kind : Namespace ) → kubectl apply -f

 

[ 네임스페이스 이동(전환) ]

kubens는 현재 네임스페이스를 가르키기도 하지만 네임스페이스간 이동기능을 지원하기도 함

 

[ 네임스페이스 삭제 ]

kubectl delete ns olive-network

 

goapp-pod가 정의된 goapp-pod.yaml ⇒ 생성시 특정 네임스페이스 지정가능

삭제시에도 kubectl delete po goapp-pod -n kube-system

혹은 해당 ns로 이동하여 삭제