파드
파드는 쿠버네티스에서 컨테이너를 실행하는 역할
쿠버네티스의 여러 오브젝트 중 가장 중요한게 파드이다(파드가 주인공)
나머지는 파드를 사용하거나 관리하거나 노출시키는 역할 수행할 뿐
파드 소개
파드란..
- 쿠버네티스의 기본 빌딩 블록 (기본 배포, 관리 단위)
- 함께 배치된 컨테이너 그룹
쿠버네티스는 컨테이너를 직접 배포하지 않음. 파드를 배포하고 파드를 운영함
컨테이너가 노드에 배포되는게 아니라 파드가 노드에 배포되는 것
파드는 하나 이상의 컨테이너를 포함 (주로 파드 하나에 컨테이너 하나만 포함하긴 함..)
- 항상 함께 배포되어야하는 컨테이너 모음이 있다? 한 파드에 넣어야함
파드가 필요한 이유
의문)
파드 같은거 없이 컨테이너를 직접 배포하고 실행하면 안되나?
왜 여러 컨테이너를 같이 실행할 필요가 있지?
모든 프로세스를 단일 컨테이너에 넣을 수 없나?
답)
함께 실행되고 관리되어야하는 프로세스들이 있음
컨테이너는 단일 프로세스를 실행하는 것을 목적으로 설계됨
-> 같이 실행되어야 하는 프로세스들이 있다면, 각자 컨테이너로 싼 다음 이 컨테이너들이 함께 실행되도록 해야함 -> 그래서 파드 두둥장!
즉, 파드는 여러 컨테이너를 하나의 단위로 묶어 관리하기 위한 상위 개념
파드 이해하기
한 그룹 안에 있는 컨테이너가 특정 리소스를 공유하게 하기 위해 각 컨테이너가 완벽히 격리되지 않도록 해야함
-> 이를 위해 쿠버네티스는 한 파드안의 컨테이너들은 자신만의 리눅스 네임스페이스가 아닌 파드의 리눅스 네임스페이스를 공유하도록 도커를 설정한다
-> 컨테이너 당 네임스페이스? NO! 파드 당 네임스페이스!
한 파드 안의 컨테이너들은 동일한 '네트워크 네임스페이스'와 'UTS 네임스페이스' 안에서 실행됨 (호스트 네임, 네트워크 인터페이스 공유한다는 뜻)
또한 동일 IPC 네임스페이스 아래에서 실행되기 때문에 컨테이너 간 IPC 로 통신 가능
- 파일 시스템은 다르다 -> 컨테이너 파일 시스템은 이미지에서 나옴. 다른 컨테이너와 완전히 분리. 쿠버네티스의 볼륨개념 사용 -> 파일 디렉토리 공유
파드안의 컨테이너 들은 '네트워크 네임스페이스' 공유하기 때문에 동일한 IP, PORT 공간 공유
- 한 파드 안의 컨테이너 간 로컬호스트 통신 가능
- 포트 안겹치게 조심
파드 간 플랫 네트워크
쿠버네티스 클러스터의 모든 파드는 하나의 플랫한 공유 네트워크 주소 공간에 상주
- 서로 다른 POD 의 IP로 접근 가능
- POD 간 NAT 존재 X
- POD 간 네트워크 통신은 단순. 어느 노드에 있는지 상관없이 LAN 상의 통신처럼 단순하게 통신함
파드는 논리적인 호스트
컨테이너가 아닌 환경에서의 VM 과 매우 유사하게 동작
파드에 컨테이너 구성을 어떻게 해야하나?
하나의 파드에는 하나의 어플리케이션만을 호스팅한다
한 어플리케이션을 여러 파드에 호스팅한다
밀접하게 연관된 구성요소나 프로세스만 하나의 파드에 넣어야 한다
판단 기준은?
한가지 예시를 들어 파드 안에 어떤 컨테이너들을 함께 넣거나 따로 넣어야하는지 판단 기준을 생각해보자.
만약 프론트엔드 어플리케이션 서버, 백엔드 DB서버가 있다고 할 때 이 두 컨테이너를 하나의 파드에 넣는게 맞는가?
답은 따로 파드를 구성하는게 더 좋다
-
리소스 활용 측면
만약 2개의 워커 노드를 가진 클러스터가 있다고 할 때, 2개의 컨테이너를 한 파드에 배치했다면 노드 한 개는 빈 상태로 두어야한다.
2개의 각각 파드를 구성했다면 2개의 노드를 FULL 로 사용할 수 있다 -
스케일링 측면
파드 단위로 스케일링 하기 때문에, 2개의 컨테이너를 따로 파드로 구성하여야 각자 유연한 스케일링이 가능하다.
스케일링 요구사항이 항상 같지 않다면 따로 스케일링이 가능한 구성이 맞는 구성이다
그렇다면 언제 한 파드에 여러 컨테이너를 넣어야하나?
어플리케이션이 하나의 주요 프로세스와 하나 이상의 보완 프로세스로 구성된 경우
- 주 컨테이너 : 특정 디텍토리에서 파일을 제공하는 웹서버
- 지원 컨테이너 : 외부 소스에서 주기적으로 콘텐츠를 받아 웹서버의 디렉토리에 저장
지원 컨테이너는 다른 말로는 사이드카 컨테이너로 불리며 로그 로테이터, 수집기, 데이터 프로세서, 통신 어댑터 등이 있다.
종합적으로 판단했을 때 판단 기준은 아래의 질문에 답을 구하며 정해볼 수 있다
1. 컨테이너를 꼭 같은 논리적 호스트에서 함께 실행해야하나?
2. 여러 컨테이너가 모여 하나의 구성요소를 나타내는가? 아니면 개별적인 구성요소인가?
3. 컨테이너가 함께 스케일링되어야 하는가?
기본적으로는 각각의 파드를 구성하되 꼭 같이 구성해야하는 경우에만 단일 파드 구성을 고려해 본다
디스크립터로 파드 생성
쿠버네티스 리소스(오브젝트)들은 아래 방법으로 생성할 수 있다
- REST API 엔드포인트에 JSON or YAML 매니페스트를 전송
- kubectl run 명령
메니페스트 전송 방식은 여러 종합적인 오브젝트들에 대한 정보를 담아 작성하고 이를 git에서 관리할 수 있기 때문에 더 효율적인 방법이다
각 유형별 리소스 구성은 쿠버네티스 API 오브젝트 정의를 알고 이해하고 써야한다
파드를 정의하는 주요 부분 소개
- apiVersion : 쿠버네티스 API 버전
- kind : 이 YAML 이 설명하는 리소스 유형
- Metadata : 이름, 네임스페이스, 레이블, 파드에 관한 기타 정보
- Spec : 파드 컨테이너, 볼륨, 기타 데이터에 대한 명세
- Status : 파드 상태, 컨테이너 상태, 파드 내부 IP 등 현재 실행중인 파드의 현재 정보
apiVersion: v1 # 이 디스크립터는 쿠버네티스 API 버전 v1 을 준수함
kind: Pod
metadata:
name: kubia-manual # 파드 이름
spec:
containers:
- image: luksa/kubia
name: kubia # 컨테이너 이름. 이 포트를 통해 파드에 연결할 수 있는지 여부는 상관없음 (단지 정보를 명시할 뿐)
ports:
- containerPort: 8080 # Application 이 수신하는 port
protocol: TCP
kubectl create 명령으로 파드 만들기
파드 생성, 생성 메니페스트 확인, 현재 파드들 보기
$ kubectl create -f kubia-manual.yaml
$ kubectl get po kubia-manual -o yaml
$ kubectl get pods
어플리케이션 로그 보기
컨테이너화된 어플리케이션은 로그를 파일에 쓰기보다 표준 출력과 표준 에러에 로그를 남기는 게 일반적이다
사용자는 서로 다른 어플리케이션들의 로그를 간단하고 동일한 방식으로 볼 수 있다
컨테이너 런타임은 이러한 스트림을 파일로 전달하고 다음 명령을 이용해 컨테이너 로그를 가져온다
$ docker logs <container id>
ssh로 파드가 실행중인 노드에 접속해 위 명령을 사용하여 로그를 가져올 수 있지만, 쿠버네티스는 좀 더 쉬운 방법을 제공한다
pod 로그 (좀 더 정확히 컨테이너 로그) 를 보기 위해 로컬 머신에서 다음 명령 실행
$kubectl logs kubia-manual
$kubectl logs kubia-manual -c kubia # 컨테이너 이름 지정
- 컨테이너 로그는 하루 단위로 로그 파일이 10MB 크기에 도달할 때 마다 순환됨
- 위 명령은 마지막으로 순환된 로그 항목만 보여줌
- 파드 삭제 후에도 파드의 로그를 보기 위해서는 모든 로그를 중앙 저장소에 저장하는 클러스터 전체의 중앙집중식 로깅을 설정해야함
파드에 요청 보내기
원래 kubectl expose 명령으로 외부에서 파드에 접속할 수 있게 해주는 서비스를 만들어야 한다
하지만 디버깅 목적으로 파드에 서비스 없이 연결할 수 있는 방법이 있다
$kubectl port-forward kubia-manual 8888:8080
$curl localhost:8888
로컬 포트 8888 로 파드의 포트 8080 으로 연결할 수 있다
파드 그룹화 필요성
마이크로 서비스 아키텍처 하에서 여러 파드들이 필요하고 각각의 파드들은 레플리케이션을 가지며 또한 여러 릴리즈(안정, 베타, 카나리)가 동시에 수행된다
즉 클러스터에 파드들 수백 수천개가 새겨 난장판이 될 수 있다.
어떤 파드가 어떤 것인지 쉽게 알 수 있도록 기준에 따라 그룹화 하는 방법이 필요
각 파드 개별에 대해 작업하기 보단 특정 그룹에 속한 모든 파드에 한 번에 작업하길 원한다
이를 가능하게 해주는 개념이 '레이블' 이다
레이블을 통해 파드와 기타 다른 쿠버네티스 오브젝트의 조직화가 이뤄진다
레이블
- 레이블은 파드와 모든 다른 오브젝트들을 조직화할 수 있는 단순하고 강력한 기능
- 리소스에 첨부하는 키-값 쌍
- 레이블 셀렉터를 통해 리소스를 선택할 때 사용됨
- 레이블 키가 해당 리소스 내에서 고유하다면 하나 이상의 레이블을 가질 수 있음
일반적으로 리소스 생성시 레이블을 부여하지만, 나중에 추가, 삭제, 수정이 가능함
레이블을 보고 이게 어떤 파드인지를 파악할 수 있다
ex) 아 이 pod는 account service를 위한 것이고 stable 환경을 위한 pod구나!
레이블 셀렉터
특정 레이블로 태그된 파드의 부분 집합을 선택해 원하는 작업 수행
특정 값과 레이블을 갖는지 여부에 따라 리소스를 필터링하는 기준이 됨
$ kubectl get po -l creation_method=manual
$ kubectl get po -l env
$ kubectl get po -l '!env'
$ kubectl get po -l creation_method!=manual
$ kubectl get po -l env in (prod, devel)
$ kubectl get po -l env notin (prod, devel)
레이블 셀렉터는 만족하는 파드 목록을 나열하는 것 뿐 아니라 파드 부분집합에 작업을 한번에 수행할 때도 유용 (ex, 특정 파드 그룹 삭제)
레이블과 셀렉터를 이용한 파드 스케줄링 제한
기본적으로 파드를 생성하면 워커노드 전체에 걸쳐 무작위로 스케줄링된다
기본적으로 파드는 요청한 만큼의 리소스를 할당받기만 하면 어느 노드에 스케줄링 되는지는 전혀 중요하지 않다
하지만 예외상황은 늘 있다
워커노드들의 하드웨어 인프라가 동일하지 않은 경우
1. 워커노드 일부는 HDD를, 일부는 SSD를 가지고 있는 경우
2. 워커노드 일부는 GPU를 사용, 나머지는 아닌 경우
쿠버네티스의 아이디어 자체가 '실행되는 어플리케이션이 실제 인프라에 대한 정보를 모르게 하는 것' 이기 때문에 어떤 노드에 스케줄링 되어야 한다 라고 구체적으로 지정하지 않는다.
정확한 노드를 지정하는 대신 노드 요구사항을 기술하고 쿠버네티스가 요구사항을 충족하는 노드를 선택하게 만들어야 한다. 이를 위해 노드 레이블과 레이블 셀렉터를 사용한다
운영팀은 새 노드를 클러스터에 추가할 때 노드에 대한 정보를 레이블로 지정해 분류할 수 있다.
$ kubectl label node gke-ubia-85f6-node-0rrx gpu=true
$ kubectl get nodes -l gpu=true
새로 만드는 파드가 gpu 사용이 가능한 노드에만 스케줄링 되도록 명시
apiVersion: v1 # 이 디스크립터는 쿠버네티스 API 버전 v1 을 준수함
kind: Pod
metadata:
name: kubia-gpu # 파드 이름
spec:
nodeSelector: # 이 레이블을 포함한 노드에 이 파드를 배포(스케줄링)하도록 지시한다.
gpu: "true"
containers:
- image: luksa/kubia
name: kubia # 컨테이너 이름. 이 포트를 통해 파드에 연결할 수 있는지 여부는 상관없음 (단지 정보를 명시할 뿐)
ports:
- containerPort: 8080 # Application 이 수신하는 port
protocol: TCP
cf) 모든 노드들은 kubernetes.io/hostname 키와 호스트 이름을 값으로 가진 레이블을 가진다. 이를 이용해 nodeSelector 에 실제 노드의 호스트이름을 지정할 수도 있지만 이는 올바른 방법은 아니다.
레이블 셀렉터로 지정한 특정 기준을 만족하는 노드의 논리적인 그룹을 생각하고 사용해야 한다. (쿠버네티스는 선언적 방식)
파드에 어노테이션 달기
어노테이션은 레이블과 비슷하면서도 다른 개념이다
어노테이션은 파드 뿐만 아니라 다른 쿠버네티스 오브젝트에도 사용할 수 있다
자동으로 추가될 수도 있고 사용자가 수동으로 추가할 수도 있다
레이블과 공통점
키-값 쌍
레이블과 다른점
식별정보를 갖지 않음
오브젝트를 묶는데 (그룹화) 사용하지 않음 -> 어노테이션 셀렉터? 란거 없음
훨씬 더 많은 정보를 보유할 수 있음 (상대적으로 긴 데이터 저장)
주로 도구들(tools)에서 사용됨
사용 예
-
오브젝트를 만든 사람 이름을 어노테이션으로 지정 -> 클러스터에서 작업하는 사람들이 좀 더 쉽게 협업할 수 있음
-
kubernetes.io/created-by 라는 어노테이션은 자동으로 생성되며, 이 오브젝트를 생성하는데 사용된 JSON 데이터를 보여준다 (1.8 버전까지만 쓰임)
어노테이션 추가 및 수정
처음 파드 생성시 추가 하거나 이미 생성된 파드에 어노테이션 추가/수정이 가능하다
키 값 충돌방지를 위해 고유 접두사를 사용한다
$ kubectl annotate pod kubia-manual mycompany.com/someanno="foo bar"
네임스페이스를 통한 리소스 그룹화
네임 스페이스란?
오브젝트를 겹치지 않는 그룹으로 분할하고자 할때 사용
한번에 하나의 그룹 안에 속한 리소스에만 작업하고 싶다는 요구사항 충족시켜줌
리눅스 네임스페이스와는 다름
오브젝트 이름의 범위를 제공
같은 리소스 이름을 다른 네임 스페이스에 걸쳐 여러번 사용할 수 있게 해줌
필요성
많은 구성요소를 가진 복잡한 시스템을 작은 개별 그룹으로 분리할 수 있음
- dev,stg,prd 를 네임스페이스로 나눌 수 있음
대부분의 리소스 유형은 네임스페이스 안에 속하지만 일부는 그렇지 않음
- 노드 리소스는 전역 이며 어떤 단일 네임스페이스에 얽매이지 않음
$ kubectl get ns # 클러스터에 있는 namespace 나열
# 기본적으로 default, kube-public, kube-system 이 생성되어 있음
$ kubectl get po --namespace kube-system # 특정 ns에 있는 pods 나열
# ns 명시하지 않으면 'default' ns 가 사용됨
kube-system는 쿠버네티스 시스템 자체와 관련된 리소스들
네임스페이스를 통해 리소스를 깔끔하게 분리하여 관리
- default ns에 사용자 생성 리소스들이 있고 / kube-system ns에 시스템 관련 리소스들이 있다. 둘은 깔끔하게 분리된다
네임스페이스는 리소스 격리이외에도 특정 사용자가 지정된 리소스에 접근할 수 있도록 허용하고 개별 사용자의 사용가능 컴퓨팅 리소스를 제한하는 데에 사용된다
네임스페이스 생성
-
YAML 파일 작성 후 제출
-
kubectl 이용
$ kubectl create namespace custom-namespace
다른 네임스페이스의 오브젝트 관리
생성한 ns안에 리소스를 만들고 싶으면?
- yaml 파일의 metadata 섹션에 'namespace: custom-namespace' 넣는다
- 아래와 같이 kubectl 로 생성
$ kubectl create -f kubia-manual.yaml -n custom-namespace
네임스페이스를 지정하지 않으면 kubectl은 현재 kubectl 컨텍스트에 구성된 기본 네임스페이스에서 작업을 수행함
현재 컨텍스트와 현재 컨텍스트의 ns는 'kubectl config' 명령으로 변경할 수 있음
네임스페이스는 실행중인 오브젝트에 대한 격리는 제공하지 않음
즉, 서로 다른 ns에 있는 pod들이 통신을 할 수도 있다. 네트워크가 꼭 격리되는 것은 아니다.ns에서 네트워크 격리를 제공하는지는 '쿠버네티스와 함께 배포하는 네트워킹 솔루션'에 따라 다르다. 해당 솔루션이 ns간 격리를 제공하지 않으면 둘은 통신이 가능하다
파드의 중지와 제거
default ns에 4개의 pod, custom-namespace에 1개의 pod를 삭제해 보자
pod 삭제시, 안에 있는 모든 컨테이너 종료됨
- SIGTERM 신호를 프로세스에 보내고 지정된 시간을 기다림 -> 종료 안되면 SIGKILL
- 프로세스가 정상적으로 종료되길 원하면 SIGTERM 신호를 올바르게 처리해야함
$ kubectl delete po kubia-gpu # 이름으로 삭제
$ kubectl delete po -l rel=canary # 레이블 셀렉터로 삭제
네임스페이스를 삭제하면 그 안에 있는 모든 파드는 자동으로 삭제된다
$ kubectl delete ns custom-namespace
$ kubectl delete po -all # 현재 네임스페이스의 모든 파드 삭제
# 현재 네임스페이스의 모든 오브젝트 삭제
# all 키워드로 모든 것을 삭제하려 해도 삭제안되는 것들도 있다 (시크릿 등)
# 이것들은 명시적으로 삭제가 필요함
$ kubectl delete all -all
Author And Source
이 문제에 관하여(파드), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@monami/파드저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)