Kubernetes 인 액션 3장 파드: 쿠버네티스에서 컨테이너 실행
Devops/Kubernetes

Kubernetes 인 액션 3장 파드: 쿠버네티스에서 컨테이너 실행

뉴비뉴 2023. 4. 9.

다루는 내용

  • 파드의 생성, 실행, 정지
  • 파드와 다른 리소스를 레이블로 조직화하기
  • 특정 레이블을 가진 모든 파드에서 작업 수행
  • 네임스페이스를 사용해 파드를 겹치지 않는 그룹으로 나누기
  • 특정한 형식을 가진 워커 노드에 파드 배치

3. 1 파드 소개

파드의 핵심 사항은 파드가 여러 컨테이너를 가지고 있을 경우에, 모든 컨테이너는 항상 하나의 워커 노드에서 실행되며 여러 워커 노드에 걸쳐 실행되지 않는다.

3.1.1 파드가 필요한 이유

여러 프로세스를 실행하는 단일 컨테이너보다 다중 컨테이너가 나은 이유

IPC 혹은 로컬 파일을 통해 통신하는 여러 프로세스로 구성돼, 같은 노드에서 실행해야 하는 애플리케이션을 상상해보자.쿠버네티스에서 프로세스를 항상 컨테이너에서 실행시키고, 이 각 컨테이너는 격리된 머신과 비슷하기 때문에 여러 프로세스가 단일 컨테이너 안에서 실행하는 것이 타당하다고 생각할 수 있지만 실제로는 그렇지 않다.

 

컨테이너는 단일 프로세스를 실행하는 것을 목적으로 설계했다.(프로세스가 자기 자신의 자식 프로세스를 생성하는 것을 제외하면)

 

단일 컨테이너에서 관련 없는 다른 프로세스를 실행하는 경우 모든 프로세스를 실행하고 로그를 관리하는 것은 모두 사용자 책임이다.

3.1.2 파드 이해하기

컨테이너가 제공하는 모든 기능을 활용하는 동시에 프로세스가 함께 실행되는 것처럼 보이게 할 수 있다.

같은 파드에서 컨테이너 간 부분 격리

그룹 안에 있는 컨테이너가 특정한 리소스를 공유하기 위해 각 컨테이너가 완벽하게 격리되지 않도록 한다. 쿠버네티스는 파드 안에 있는 모든 컨테이너가 자체 네임스페이스가 아닌 동일한 리눅스 네임스페이스를 공유하도록 도커를 설정한다.

모든 컨테이너는 같은 호스트 이름과 네트워크 인터페이스를 공유한다.

|노트| 파드 안에 있는 컨테이너가 별도 PID 네임스페이스를 사용할 경우에는 ps aux 명령을 실행하면 해당 컨테이너 안에서 실행되는 프로세스만을 볼 수 있다.

컨테이너가 동일한 IP와 포트 공간을 공유하는 방법

파드 안의 컨테이너가 동일한 네트워크 네임스페이스에서 실행되기 때문에, 동일한 IP 주소와 포트 공간을 공유한다는 것이다. 이는 동일한 파드 안 컨테이너에서 실행 중인 프로세스가 같은 포트 번호를 사용하지 않도록 주의해야 함을 의미한다. 그렇지 않으면 포트 충돌이 발생할 수 있다. 이는 동일한 파드일 때만 해당된다.

다른 파드에 있는 컨테이너는 서로 다른 포트 공간을 갖기 때문에 포트 충돌이 일어나지 않는다.

파드 간 플랫 네트워크 소개

쿠버네티스 클러스터의 모든 파드는 하나의 플랫한 공유 네트워크 주소 공간에 상주하므로 모든 파드는 다른 파드의 IP 주소를 사용해 접근하는 것이 가능하다. 둘 사이에는 어떠한 NAT 도 존재하지 않는다. 두 파드가 서로 네트워크 패킷을 보내면, 상대방의 실제 IP 주소를 패킷 안에 있는 출발지 IP 주소에서 찾을 수 있다.

3.1.3 파드에서 컨테이너의 적절한 구성

파드를 각각 별도의 머신으로 생각할 수 있지만, 파드는 특정한 애플리케이션만을 호스팅한다.

다계층 애플리케이션을 여러 파드로 분할

프론트엔드 서버와 데이터베이스 컨테이너 두 개로 구성된 단일 파드를 실행하지 못할 것은 없지만, 적절한 방법은 아니다.

 

프론트엔드와 백엔드가 같은 파드에 있다면, 둘은 항상 같은 노드에서 실행된다. 만약에 두 노드를 가진 쿠버네티스 클러스터가 있고 이 파드 하나만 있다면, 워커 노드 하나만 사용하고 두 번째 노드에서 이용할 수 있는 컴퓨팅 리소스(CPU와 메모리)를 활용하지 않고 그냥 버리게 된다.

 

파드를 두 개로 분리하면 쿠버네티스가 프론트엔드를 한 노드로 그리고 백엔드는 다른 노드에 스케줄링해 인프라스트럭처의 활용도를 향상시킬 수 있다.

파드에서 여러 컨테이너를 사용하는 경우

여러 컨테이너를 단일 파드에 넣는 주된 이유는 애플리케이션이 하나의 주요 프로세스와 하나 이상의 보안 프로세스로 구성된 경우이다.

예를 들어 파드 안에 주 컨테이너는 특정 디렉터리에서 파일을 제공하는 웹 서버일 수 있으며, 추가 컨테이너(사이드카 컨테이너)는 외부 소스에서 주기적으로 콘텐츠를 받아 웹 서버의 디렉터리에 저장한다.

 

사이드카 컨테이너의 다른 예제로는 로그 로테이터와 수집기, 데이터 프로세서, 통신 어댑터 등이 있다.

3.1 YAML 또는 JSON 디스크립터로 파드 생성

파드를 포함한 다른 쿠버네티스 리소스는 일반적으로 쿠버네티스 REST API 엔드포인트에 JSON 혹은 YAML 매니페스트를 전송해 생성한다.

파드를 정의하는 주요 부분 소개

  • Metadata: 이름, 네임스페이스, 레이블 및 파드에 관한 기타 정보를 포함한다.
  • Spec: 파드 컨테이너, 볼륨, 기타 데이터 등 파드 자체에 관한 실제 명세를 가진다.
  • Status: 파드 상태, 각 컨테이너 설명과 상태, 파드 내부 IP, 기타 기본 정보 등 현재 실행 중인 파드에 관한 현재 정보를 포함한다.

3.2.2 파드를 정의하는 간단한 YAML 정의 작성하기

3.2.3 kubectl create 명령으로 파드 만들기

$ kubectl create -f kubia-maunal.yaml

pod “kubia-manual” created

파드를 만들었으면 전체 정의를 보는 것은 $ kubectl get pod kubia-manual -o yaml or json

3.2.4 애플리케이션 로그 보기

$ docker logs <container id>

ssh로 파드가 실행 중인 노드에 접속해 docker logs 명령으로 로그를 가져올 수도 있지만, 쿠버네티스는 더 쉬운 방법을 제공한다.

$ kubectl logs kubia-manual
Kubia server starting…

컨테이너 이름을 지정해 다중 컨테이너 파드에서 로그 가져오기

$ kubectl logs kubia-manual -c kubia(컨테이너 이름)
LET ME) kubia 로 실행되어 있는 컨테이너 즉 파드가 3개 있다면 그 로그들을 가져온다.

3.2.5 파드에 요청 보내기

로컬 네트워크 포트를 파드의 포트로 포워딩

서비스를 거치지 않고 특정 파드와 대화하고 싶을 때 쿠버네티스는 해당 파드로 향하는 포트 포워딩을 구성해준다.

다음 명령은 머신의 로컬 포트 8888을 kubia-manual 파드의 8080 포트로 향하게 한다.

$ kubectl port-forward kubia-manual 8888:8080
… Forwarding from 127.0.0.1:8888 → 8080

3.3 레이블을 이용한 파드 구성

레이블(labels)을 통해 파드와 기타 다른 쿠버네티스 오브젝트의 조직화가 이뤄진다.

3.3.1 레이블 소개

레이블은 파드와 모든 다른 쿠버네티스 리소스를 조직화할 수 있는 단순하면서 강력한 쿠버네티스 기능이다. 레이블은 리소스에 첨부하는 키-값 쌍으로, 이 쌍은 레이블 셀렉터를 사용해 리소스를 선택할 때 활용된다. 레이블 키가 해당 리소스 내에서 고유하다면, 하나 이상 원하는 만큼 레이블을 가질 수 있다.

  • app: 파드가 속한 애플리케이션, 구성 요소 혹은 마이크로서비스를 지정한다.
  • rel: 파드에서 실행 중인 애플리케이션이 안정, 베타 혹은 카나리 릴리스 인지 보여준다.

LET ME) 수 많은 서비스가 있을 것이고, 그 레이블 안으로 연관 된 것들이 이동하여 조직화 하는 것을 말한다.

3.3.2 파드를 생성할 때 레이블 지정

$ kubectl create -f kubia-manual-with-labels.yaml
pod “kubia-manual-v2” created

$ kubectl get po --show-labels

LABELS createion_method=manual,env=prod

특정 레이블에만 관심 있는 경우 해당 레이블을 -L 스위치로 지정해 각 레이블을 자체 열에 표시할 수 있다.

$ kubectl get po -L creation_method,env

3.3.3 기존 파드 레이블 수정

추가 수정하는 경우

$ kubectl label po kubia-manual creation_method=manual
pod “kubia-manual” labeled

레이블을 변경하는 경우

$ kubectl label po kubia-menual-v2 env=debug --overwrite
pod “kubia-menual-v2” labeled

3.4.1 레이블 셀럭터를 사용해 파드 나열

creation_method=manual 인 것만
$ kubectl get po -l creation_method=manual

env가 아닌 것들만

$ kubectl get po -l ‘!env’

  • creation_method!=manual: creation_method 레이블을 가지고 있는 파드 중에 값이 manual이 아닌 것
  • env in (prod,devel): env 레이블 값이 prod 또는 devel로 설정되어 있는 파드
  • env notin (prod,devel): env 레이블 값이 prod, devel 이 아닌 파드

3.5 레이블과 셀렉터를 이용해 파드 스케줄링 제한

파드가 어느 노드에 스케줄링 됐느냐는 중요하지 않다. 각 파드는 요청한 만큼의 정확한 컴퓨팅 리소스(CPU, 메모리 등)를 할당 받는다. 그렇기 때문에 쿠버네티스에게 파드를 어디에 스케줄링할지 알려줄 필요는 없다.

 

하지만 파드를 스케줄링 할 위치를 결정할 때 약간이라도 영향을 미치고 싶은 상황이 있다. 예를 들어 하드웨어 인프라가 동일하지 않은 경우를 들 수 있다. 워커 노드 일부는 HDD를 가지고 있고 나머지에는 SSD를 가지고 있는 경우, 특정 파드를 한 그룹에 나머지 파드는 다른 그룹에 스케줄링되도록 할 수 있다. 또 다른 예는 GPU 가속을 제공하는 노드에만 GPU 계산이 필요한 파드를 스케줄링하는 것을 들 수 있다.

 

정확한 노드를 지정하는 대신 필요한 노드 요구 사항을 기술하고 쿠버네티스가 요구 사항을 만족하는 노드를 선택하도록 한다. 이는 노드 레이블과 레이블 셀럭터를 통해 할 수 있다.

3.5.1 워커 노드 분류에 레이블 사용

$ kubectl label node gke-kubia-xxxx-xxxx gpu=true

node “gke-kubia-xxxx-xxxx” labeled

$ kubectl get nodes -l gpu=true

3.5.2 특정 노드에 파드 스케줄링

스케줄러가 GPU를 제공하는 노드를 선택하도록 요청하려면, 파드의 YAML 파일에 노드 샐렉터를 추가해야한다.

3.6 파드에 어노테이션 달기

파드 및 다른 오브젝트는 레이블 외에 어노테이션(annotations) 을 가질 수 있다.

어노테이션은 키-값 쌍으로 레이블과 거의 비슷하지만 식별 정보를 갖지 않는다.

 

레이블은 오브젝트를 묶는 데 사용할 수 있지만, 어노테이션은 그렇게 할 수 없다.

반면 어노테이션은 훨씬 더 많은 정보를 보유할 수 있다. 이는 주로 도구들 tools에서 사용된다.

어노테이션은 쿠버네티스에 새로운 기능을 추가할 때 흔히 사용된다. 일반적으로 새로운 기능의 알파 혹은 베타 버전은 API 오브젝트에 새로운 필드를 바로 도입하지 않는다. 필요한 API 변경이 명확해지고 쿠버네티스 개발자가 이에 동의하면 새로운 필드가 도입된다. 그리고 관련된 어노테이션은 사용이 중단된다.

 

어노테이션이 유용하게 사용되는 경우는 파드나 다른 API 오브젝트에 설명을 추가해 두는 것이다. 이렇게 하면 클러스터를 사용하는 모든 사람이 개별 오브젝트에 관한 정보를 신속하게 찾아볼 수 있다. 예를 들어 오브젝트를 만든 사람 이름을 어노테이션으로 지정해두면, 클러스터에서 작업하는 사람들이 좀 더 쉽게 협업할 수 있다.

3.6.1 오브젝트의 어노테이션 조회

$ kubectl describe or -o yaml

3.6.2 어노테이션 추가 및 수정

레이블을 만들 때와 같은 방법으로 파드를 생성할 때 어노테이션을 추가할 수 있다.

$ kubectl annotate pod kubia-manual mycompany.com/someannotation=”foo bar”

pod “kubia-manual” annotated

$ kubectl describe pod kubia-manual

Annotations: mycompany.com/someannotation=foo bar

3.7 네임스페이스를 사용한 리소스 그룹화

각 오브젝트는 여러 레이블을 가질 수 있게 때문에, 오브젝트 그룹은 서로 겹쳐질 수 있다. 또한 클러스터에서 작업을 수행할 때 (예를 들어 kubectl 명령을 통해) 레이블 셀렉터를 명시적으로 지정하지 않으면 항상 모든 오브젝트를 보게 된다.

쿠버네티스는 오브젝트를 네임스페이스로 그룹화 한다. 여기서 네임스페이스는 프로세스를 격리하는데 사용하는 ‘리눅스 네임스페이스’가 아니다.

쿠버네티스 네임스페이스는 오브젝트 이름의 범위를 제공한다. 모든 리소스를 하나의 단일 네임스페이스에 두는 대신에 여러 네임스페이스로 분할할 수 있으며, 이렇게 분리된 네임스페이스는 같은 리소스 이름을 다른 네임스페이스에 걸쳐 여러 번 사용할 수 있게 한다.

3.7.1 네임스페이스의 필요성

여러 네임스페이스를 사용하면 많은 구성 요소를 가진 복잡한 시스템을 좀 더 작은 개별 그룹으로 분리할 수 있다.

또한 멀티테넌트 환경처럼 리소스를 분리하는 데 사용된다. 리소스를 프로덕션, 개발, QA 환경 혹은 원하는 다른 방법으로 나누어 사용할 수 있다.

 

리소스 이름은 네임스페이스 안에서만 고유하면 된다. 서로 다른 두 네임스페이스는 동일한 이름의 로스스를 가질 수 있다.

 

LET ME) 멀티테넌시란 여러 개의 프로젝트를 서비스하는 단일 클러스터를 의미합니다. 이 클러스터는 각 프로젝트를 서로 분리 실행하도록 설정되어 있습니다.

3.7.2 다른 네임스페이스와 파드 살펴보기

$ kubectl get ns

$ kubectl get po --namespace kube-system

네임스페이스 이름으로는 쿠버네티스 시스템 자체와 관련된 리소스임이 분명하다.

네임스페이스를 사용해 서로 관계없는 리소스를 겹치지 않는 그룹으로 분리할 수 있다.

$ kubectl create namespace custom-namespace

3.7.4 다른 네임스페이스의 오브젝트 관리

$ kubectl create -f kubia-manual.yaml -n custom-namespace

pod “kubia-manual” created

|TIP| 다른 네임스페이스로 빠르게 전환하려면 다음 별칭(alias)을 설정한다. alias kcd=’kubectl config set-context $(kubectl config current-context) —namespace ‘

3.8 파드 중지와 제거

3.8.1 이름으로 파드 삭제

$ kubectl delete po kubia-gpu pod “kubia-gpu” deleted

3.8.2 레이블 셀렉터를 이용한 파드 삭제

$ kubectl delete po -l creation=manual

pod “kubia-manual” deleted

pod “kubia-manual-v2” deleted

$ kubectl delete po -l rel=canary

3.8.3 네임스페이스를 삭제한 파드 제거

네임스페이스 안에 있는 파드나 네임스페이스 자체를 필요로 하지 않는다. 파드는 네임스페이스와 같이 삭제된다.

$ kubectl delete ns custom-namespace

3.8.4 네임스페이스를 유지하면서 네임스페이스 안에 있는 모든 파드 삭제

$ kubectl delete po --all

LET ME) 이 경우에 네임스페이스 Z에 있는 파드들을 삭제해야 되는데 네임스페이스가 A 에 위치할 수도 있다. 그런 경우는 kubectl delete po --all -n Z 하면 될 것 이다.

하지만 파드를 삭제해도 계속 생성 될 것이다. 왜냐하면 래플리케이션 컨트롤러가 있기 때문이다.

3.8.5 네임스페이스에서 (거의) 모든 리소스 삭제

$ kubectl delete all --all

|노트| all 키워드를 이용해 모든 것을 삭제하려 해도 모든 것이 완전히 삭제되는 것은 아니다. 특정 리소스는 보존돼 있으며, 명시적으로 삭제할 필요가 있다.

|노트| kubectl delete all --all 명령은 kubernetes 서비스도 삭제하지만 잠시 후에 자동으로 다시 생성된다.

3.9 요약

  • 특정 컨테이너를 파드로 묶어야 하는지 여부를 결정하는 방법
  • 파드는 여러 프로세스를 실행할 수 있으며 컨테이너가 아닌 세계의 물리적 호스트와 비슷하다.
  • YAML 또는 JSON 디스크립터를 작성해 파드를 작성하고 파드 정의와 상태를 확인할 수 있다.
  • 레이블과 레이블 셀렉터를 사용해 파드를 조직하고 한 번에 여러 파드에서 작업을 쉽게 수행할 수 있다.
  • 노드 레이블과 셀렉터를 사용해 특정 기능을 가진 노드에 파드를 스케줄링할 수 있다.
  • 어노테이션을 사용하면 사람 또는 도구, 라이브러리에서 더 큰 데이터를 파드에 부착할 수 있다.
  • 네임스페이스는 다른 팀들이 동일한 클러스터를 별도 클러스터를 사용하는 것처럼 이용할 수 있다.
  • kubectl explain 명령으로 쿠버네티스 리소스 정보를 빠르게 찾을 수 있다.

댓글

💲 추천 글