본 포스팅은 MLOps를 위해 필요한 k8s 지식을 정리하는 것을 목적으로함

MLOps에서 k8s가 필요한 이유.

MLOps를 위해서는 크게 다음과 같은 작업이 필요하다.

  1. Reproducibility - 실행 환경의 일관성 & 독립성
  2. Job Scheduling - 스케줄 관리, 병렬 작업 관리, 유휴 자원 관리 
  3. Auto-healing & Auto-scaling - 장애 대응, 트래픽 대응 자동화

-> 이것들을 Docker(Containerization), k8s(Container Orchestration)를 통해 해결할 수 있다.


Kubernetes

Identity - Container Orchestration

  • 여러명이 함께 서버를 공유하며 각자 모델학습을 돌리고자 할때 스케줄을 미리짜거나 gpu자원을 매번 확인하거나 학습이 끝나면 사용했던 메모리를 정리를 하는 등의 번거로운 일을 매번 할 필요 없이 수많은 컨테이너와 인프라 환경을 정해진 룰에 따라서 알아서 관리해주는 기술

Concept - 선언형 인터페이스 & Desired State

  • 마치 우리가 길찾기를 할때 목적지만 적으면 현재위치에서 목적지로의 최적의 경로를 알려주는것을 선언형 인터페이스라고 볼 수 있고 여기서 '최적의 경로를 찾아줘'가 Desired State가 된다. 

1.  minikube, kubectl

minikube

  • 마스터 노드의 일부 기능과 개발 및 배포를 위한 단일 워커 노드를 제공해 주는 간단한 쿠버네티스 플랫폼 환경을 제공
  • https://minikube.sigs.k8s.io/docs/start/

kubectl


minikube start

minikube를 docker driver를 기반으로 하여 시작


minikube status

정상적으로 생성되었는지 minikube의 상태 확인


minikube delete

쿠버네티스 환경 삭제


2. Pod

  • Pod는 쿠버네티스에서 생성하고 관리할 수 있는 배포 가능한 가장 작은 컴퓨팅 단위
  • 쿠버네티스는 도커 컨테이너단위가 아닌 Pod단위로 스케줄링, 로드밸런싱, 스케일링 등의 관리 작업을 수행(쿠버네티스에 어떤 애플리케이션을 배포하고 싶다면 최소 Pod 단위로 구성해야 한다는 의미)
  • 하나의 Pod는 한 개의 Container 혹은 여러개의 Container 로 이루어짐(Pod 내부의 여러 Container는 자원을 공유)
  • Pod는 stateless 한 특징을 지니고 있으며, 언제든지 삭제될 수 있는 자원
  • 여러 노드에 1개 이상의 Pod를 분산 배포/실행 가능 (Pod Replicas)
  •  Pod를 생성할 때 노드에서 유일한 IP를 할당 (하나의 Pod는 하나의 서버로 볼 수 있으며 유일한 IP는 서버 분리 효과라고 생각할 수 있음) -> 이 IP는 클러스터 내부에서만 접근 가능하기 때문에 클러스터 외부 트래픽을 받기 위해서는 Service 혹은 Ingress 오브젝트가 필요!
  • Pod내의 여러 컨테이너 간의 통신은 localhost로 가능하며 이때 각 컨테이너는 각자 다른 포트를 가지고 있어야 함 (볼륨 공유 가능)

**Pod와 컨테이너 설계 시 고려할 점 (Pod: Container = 1:1 or 1:N 결정)**
  1. 컨테이너들의 라이프 사이클이 같은가
    • A라는 컨테이너는 application이고 B라는 컨테이너는 로그 수집기라고 가정하면 A컨테이너가 종료되었을때 B컨테이너는 실행의 의미가 없다. -> 컨테이너를 묶어두는 방법을 사용할 수 있음
  2. 스케일링 요구사항이 같은가
    • 어떤 application이냐에 따라 요구되는 트래픽이 다르기 때문에 스케일에 대한 고민이 필요하다.
  3. 인프라 활용도가 더 높아지는 방향으로
    • 쿠버네티스는 각 노드의 리소스 등 여러 상태를 고려해서 Pod가 어떤 노드에 배포되면 좋을지 결정하게 된다. Pod의 크기가 불필요하게 클 경우 자원이 낭비되기 때문에 여러개의 컨테이너를 여러개의 Pod로 분리시키는 등의 방법으로 인프라를 효율적으로 사용해야 한다.
    • Pod와 컨테이너를 1:1로 기본 설계하고 특별한 사유가 있는 경우 1:N 구조를 고민하는것이 일반적

**Pod의 한계점**
  1. Pod가 나도 모르는 사이에 종료되었다면?
    • Self-Healing 이 없음, Pod나 노드 이상으로 종료되면 끝
    • ReplicaSet 오브젝트를 도입하여 사용자가 선언한 수만큼 Pod를 유지
  2. Pod IP는 외부에서 접근할 수 없고 생성할 때 마다 Pod의 고유 IP가 변경된다. 
    • 클러스터 외부에서 접근할 수 있는 고정적인 단일 엔드포인트가 필요
    • Pod 집합을 클러스터 외부로 노출하기 위한 Service 오브젝트 도입

**Pod 생성**

간단한 Pod 예시

kubectl apply -f 를 수행하면, 에 해당하는 kubernetes resource를 생성 또는 변경 할 수 있다.

  • kubernetes resource 의 desired state를 기록해놓기 위해 항상 YAML 파일을 저장하고, 버전관리하는 것을 권장
  • kubectl run 명령어로 YAML 파일 생성 없이 pod를 생성할 수도 있지만, 이는 k8s에서 권장하는 방식이 아님

Pod 조회

current namespace의 의 Pod목록을 조회

namespace : k8s에서 리소스를 격리하는 가상의 단위

  • 하나의 namespace에 여러 pod가 포함될 수 있음
  • kubectl config view --minify 로 current namespace가 어떤 namespace인지 확인 할 수 있다.
  • 기본 namespace는 default namespace


특정 namespace 혹은 모든 namespace의 pod 조회


Pod 로그


Pod 내부 접속


Pod 삭제


Pod 환경변수

Pod에 환경변수를 선언해서 컨테이너 속에 정보를 전달시킬 수 있다.


Label과 Selector

Label

  • 쿠버네티스 오브젝트를 식별하기 위한 key/value 쌍의 메타정보
  • 쿠버네티스 리소스를 논리적인 그룹으로 나누기 위해 붙이는 이름표

Selector

  • Label을 이용해 쿠버네티스 리소스를 필터링하고 원하는 리소스 집합을 구하기 위한 label query

Label을 이용해서 리소스 집합을 구해야하는 경우가 많고 k8s에서는 Label을 이용해서 명령을 실행할때 pod 집합 단위로 수행하게 된다. 그렇기 때문에 Pod를 생성할때 Label을 잘 설계하여 명시하는 것이 권장된다.


kubectl 명령어


ReplicaSet

내결함성(fault tolerance)

-> 소프트웨어나 하드웨어 실패가 발생하더라도 소프트웨어가 정상적인 기능을 수행할 수 있어야 한다.

-> 사람의 개입없이 내결함성을 가진 소프트웨어를 구상해볼 수 있다.


ReplicaSet 개념

  • Pod 복제본을 생성하고 관리
  • ReplicaSet 오브젝트를 정의하고 원하는 Pod의 개수를 replicas 속성으로 선언
  • 클러스터 관리자 대신 Pod 수가 부족하거나 넘치지 않게 Pod 수를 조정(replicas 속성으로 선언한 개수만큼 유지)

ReplicaSet 역할

  • ReplicaSet을 이용해 Pod 복제 및 복구 작업을 자동화
  • 클러스터 관리자는 ReplicaSet을 만들어 필요한 Pod의 개수를 쿠버네티스에게 선언
  • 쿠버네티스가 ReplicaSet 요청서에 선언된 replicas를 읽고 그 수만큼 Pod 실행 보장

ReplicaSet에 Replicas, Pod Selector, Pod Template을 정의해주면 수동적으로 pod yaml을 작성해서 배포할 필요가 없음

-> 자동으로 pod 생성

ReplicaSet에 Port-Forward를 하게되면 첫번째 생성된 Pod로만 요청이 전달된다.

-> 로드밸런싱이 일어나지 않음


kubectl 명령어


기존에 생성한 Pod를 ReplicaSet으로 관리하는 방법

  • ReplicaSet은 자신이 관리하는 Pod의 수를 선언된 replicas를 넘지 않게 관리한다.
  • 이때 기존에 Pod가 따로 생성되어있고 같은 label로 Pod Selector를 사용해 replicas=3으로 ReplicaSet을 생성하면 2개의pod만 추가적으로 생성한다.
  • 즉 기 생성된 Pod의 label이 ReplicaSet의 Pod Selector와 같다면 관리 범주에 들어오므로 Pod Selector를 설계할 때 주의해야 함

ReplicaSet이 내결함성(fault-tolerance)을 어떻게 지키는지 확인하기

  • ReplicaSet이 관리하는 Pod를 삭제하면 새로운 Pod가 replicas 수만큼 자동생성됨

비슷해보이는 두가지 ReplicaSet 삭제방법


Pod가 ReplicaSet에 의해 관리되는지 아닌지 확인하는 방법


Gracefully하게 ReplicaSet과 Pod 삭제방법


ReplicaSet Pod Template 변경시 주의사항

  • 기존에 ReplicaSet에 의해 생성된 Pod가 있을때 ReplicaSet의 Pod Template을 변경하더라도 기존의 Pod를 삭제하고 새로운 Pod를 생성하지 않는다.
  • ReplicaSet의 변경된 Pod Template을 적용시키려면 replicas 값이 변경되고나 기존의 Pod가 삭제되어 새로 Pod가 만들어 져야 하는 경우에 적용된다.

Pod Template 이미지 변경을 통한 롤백 디버깅

위와 같이 처리하게 되면 개발자는 문제가 어디서 생겼는지 디버깅 할 수 있는 시간을 벌 수 있으면서 사용자는 요청에 대한 정상적인 응답을 받을 수 있게 됨


etc


3. Deployment

  • Deployment는 Pod와 Replicaset에 대한 관리를 제공하는 단위
  • 여기서 관리의 의미는 Self-Healing, Scaling, Rollout과 같은 기능을 포함하며 쉽게말해 Pod를 한번 감싼 개념
  • Pod를 Deployment로 배포함으로써 여러 개로 복제된 Pod, 여러 버전의 Pod를 안전하게 관리 가능

Deployment를 사용하는 이유

  • 만약 새로운 버전의 이미지를 적용해야 하는 상황이 왔을 때 ReplicaSet의 이미지를 업그레이드 하고 실행중인 Pod를 제거해야만 replicas에 의해 새 버전의 이미지가 적용된 Pod가 생성된다.
  • 이때 새 버전에서 에러가 발생하여 다시 이미지를 다운그레이드 해야하는 상황이 오게되면 위와 같은 동작을 수작업으로 반복해야 한다.
  • 여기서 우리는 Pod Template 이미지가 바뀔 때마다 쿠버네티스가 알아서 ReplicaSet을 생성하고 이전 Pod를 제거해주는 방법을 생각해볼 수 있다.
  • Deployment는 Pod 배포 자동화를 위한 오브젝트 (ReplicaSet + 배포전략)
  • Deployment 는 ReplicaSet을 여러개 가질 수 있으며 ReplicaSet의 replicas를 자동 조정하여 필요한 ReplicaSet을 쉽게 사용할 수 있다.

Deployment 생성

간단한 Deployment 예시


Deploymet 롤아웃

전략1 - Recreate 배포

  • 새로운 버전을 배포하기 전에 이전 버전이 즉시종료됨
  • 컨테이너가 정상적으로 시작되기 전까지 서비스하지 못함
  • replicas 수만큼의 컴퓨팅 리소스 필요
  • 서비스 운영단계에서는 부적합, 개발단계에서 유용

전략2 - RollingUpdate 배포 

  • 새로운 버전을 배포하면서 이전 버전을 종료
  • 서비스 다운 타임 최소화
  • 동시에 실행되는 Pod의 개수가 replicas를 넘게 되므로 컴퓨팅 리소스가 더 많이 필요

RollingUpdate 속도 제어 옵션

1. maxUnavailable

  • 롤링 업데이트를 수행하는 동안 유지하고자 하는 최소 Pod의 비율(수)을 지정할 수 있음
  • 최소 Pod 유지 비율 = 100 - maxUnavailable 값
  • ex) replicas: 10, maxUnavailable: 30% 이면 즉시 3개의 Pod를 Scale Down하게 되고 그 이후부터는 새로운 버전의 Pod생성과 이전 버전의 Pod종료가 반복됨 -> 즉 롤아웃을 수행할 때 replicas수의 70% 이상의 Pod를 항상 Running 상태로 유지하겠다는 의미

2. maxSurge

  • 롤링 업데이트를 수행하는 동안 허용할 수 있는 최대 Pod의 비율(수)을 지정할 수 있음
  • 최대 Pod 허용비율 = maxSurge 값
  • ex) replicas: 10, maxSurge: 30% 이면 새로운 버전의 Pod를 3개까지 즉시 생성할 수 있고 Pod 생성과 이전 버전의 Pod 종료를 진행하면서 총 Pod의 수가 replicas 수의 130%를 넘지 않도록 유지해야 함

3. maxUnavailable, maxSurge가 필요한 이유

  • 모든 Old Pod를 New Pod로 전환하는데 시간을 최소화 할 수 있다.
  • 새로운 Pod를 replicas 수만큼 미리 배포한다면 리소스가 부족할 수 있다.
  • maxUnavailable을 이용해서 최소 서비스 운영에 영향을 주지 않을 만큼 유지해야 하는 Pod수를 선언할 수 있다.
  • maxSurge로 어떤 시점에 동시에 존재할 수 있는 최대 Pod 수를 선언하여 배포 속도를 조절함과 동시에 리소스를 제어할 수 있다.
  • 즉 유지해야할 Pod 수의 상한선과 하한선을 쿠버네티스에 알리기 위한 옵션

Deployment Pod replicas 변경


Deployment Pod Template 이미지 변경

  • Pod Template이 변경되기 때문에 Deployment가 새로운 해시값을 가지는 ReplicaSet을 생성한다.
  • 이전 ReplicaSet은 자신이 관리하는 Pod를 모두 제거하고 새로운 ReplicaSet은 새로운 Pod를 replicas 수만큼 생성한다.
  • 이미지 변경이 아닌 레이블 변경이 이루어져도 해시값이 달라지기 때문에 위와 동일한 동작을 함

Deployment 롤백

Deployment는 롤아웃 히스토리를 Revision으로 관리


4. Service

  • Service는 쿠버네티스에 배포한 애플리케이션(pod)을 외부에서 접근하기 쉽게 추상화한 리소스이다.
  • pod는 항상 고유 IP를 할당받고 생성되지만 언제든지 죽었다가 살아날 수 있으며 그 과정에서 IP는 항상 재할당 받기에 클러스터 외부에서 고정된 IP로 원하는 Pod에 접근할 수 없다.
  • 따라서 클러스터 외부에서 Pod에 접근할 때는, Pod의 IP가 아닌 Service를 통해서 접근하는 방식을 거친다.
  • Service는 고정된 IP를 가지며, Service는 하나 혹은 여러개의 Pod와 매칭될 수 있다.
  • 따라서 클라이언트가 Service의 단일 endpoint 주소로 접근하면, 실제로 Service에 매칭된 Pod에 접속할 수 있게 된다.

Service의 Type

  • NodePort 라는 type을 사용했기 때문에, minikubefksms kubernetes cluster 내부에 배포된 서비스에 클러스터 외부에서 접속할 수 있었다.
    • 이때 IP는 노드의 IP주소, Port는 서비스에 할당받은 Port를 사용
  • LoadBalancer 라는 type을 사용해도 마찬가지로 클러스터 외부에서 접속할 수 있지만, LoadBalancer를 사용하기 위해서는 LoadBalancing 역할을 하는 모듈이 추가적으로 필요하다.
  • ClusterIP라는 type은 고정된 IP, Port를 제공하지만, 클러스터 내부에서만 접근할 수 있는 대역의 주소가 할당된다.
    • 개발단계에서 port-forward를 통해 localhost로 요청이 정상적으로 작동하는지 확인할 수 있음
  • 실무에서는 주로 kubernetes cluster에 MetalLB와 같은 LoadBalancing 역할을 하는 모듈을 설치한 후, LoadBalancer type으로 서비스를 expose하는 방식을 사용한다.
    • NodePort는 Pod가 어떤 Node에 스케줄링될 지 모르는 상황에서, Pod가 할당된 후 해당 Node의 IP를 알아야 한다는 단점이 존재한다.

기본 Service 관련 kubectl 명령어


ClusterIP 서비스로 Pod 노출하는 방법

1. 환경변수 이용

  • 서비스가 먼저 배포된 이후에 pod가 배포되기 때문에 쿠버네티스는 각 pod가 배포될때 이미 알고있는 정보인 SERVICE_HOST와 SERVICE_PORT를 각 컨테이너의 환경변수로 전달시킨다.
  • 그렇기 때문에 역으로 Pod의 환경변수로 Service를 추적할 수 있다.
  • 다른말로 pod가 생성된 이후 나중에 생성된 서비스에 대한 환경변수는 알 수 없다는 것을 유의

  • 위와같이 특정 pod의 컨테이너에 접속해보면 pod가 소속된 서비스 뿐만아니라 pod가 생성되기 전 배포된 현재 네임스페이스의 모든 서비스에 대한 환경변수를 컨테이너가 가지고 있기 때문에 컨테이너 내부에서 다른 pod로 요청을 보낼 수 있다.

2. 서비스 이름 이용 - 쿠버네티스 DNS 서버

  • hosts 파일에 정의되지 않은 다른 서비스의 도메인 이름으로 요청이 가능한 이유? -> kube-system 네임스페이스에서 실행중인 kube-dns pod를 통해 도메인 네임을 찾게 됨

  • nameserver: 컨테이너에서 사용할 DNS 서버 주소
  • search: 클러스터 내에서 사용할 도메인 접미사 정의
  • svc.cluster.local: 모든 클러스터 로컬 서비스 이름에 사용되는 도메인 접미사
  • FQDN(fully qualified domain name): <서비스이름>.<네임스페이스>.svc.cluster.local
  • FQDN을 이용해서 DNS 쿼리를 실행(DNS Server에서 Service IP를 조회)


3. 서비스 이름으로 다른 네임스페이스에 있는 서비스 호출


Service ClusterIP 특징

  • Service는 파드 집합에 대한 단일 엔드포인트를 생성한다.
  • Service를 생성하면 ClusterIP가 생성된다.
  • ClusterIP는 클러스터 내부에서만 접속할 수 있다.

ClusterIP를 이용해서 다른 Pod에게 요청을 보내는 방법

  • 특정 애플리케이션 파드를 위해 배포된 Service 이름을 알아낸다.
  • 애플리케이션 컨테이너에서 OOO_SERVICE_HOST 환경변수로 Service IP를 알아낼 수 있다.
  • 단, Pod보다 늦게 생성한 Service 환경변수는 사용할 수 없다. + 다른 네임스페이스의 Service는 환경변수로 설정되지 않는다.
  • 애플리케이션 컨테이너에서 Service IP대신 Service 이름을 도메인으로 요청을 보낼 수 있다.
  • 애플리케이션 컨테이너에서 Service Port는 OOO_SERVICE_PORT 환경변수를 이용한다.

Service NodePort 특징

  • 클러스터 내 모든 노드에 포트 할당은 Service를 NodePort 타입으로 생성 했을 때 일어난다.
  • 노드의 External IP와 서비스 NodePort를 이용해서 pod에 접근 할 수 있다.
  • 서비스 ClusterIP도 여전히 클러스터 내부에서 사용할 수 있다.

NodePort를 이용해서 다른 Pod에게 요청을 보내는 방법

  • GKE사용자라면 NodePort에 대한 인바운드 트래픽 허용 정책을 클라우드 서비스에 설정한다.
  • 노드 IP와 NodePort를 이용해서 원하는 파드 집합에 요청을 실행한다.

Service LoadBalancer 특징

  • LoadBalancer 타입의 서비스를 생성하면 클라우드 서비스의 로드밸런서가 실행한다.(on-premise는 별도 Load Balancer 설치 필요)
  • 로드밸런서의 IP가 Service의 External IP로 할당된다.
  • Service의 External IP이자 로드밸런서 IP로 외부에서 파드에 접근할 수 있다.
  • 서비스 ClusterIP, NodePort의 기능도 여전히 사용할 수 있다.

LoadBalancer를 이용해서 다른 Pod에게 요청을 보내는 방법

  • 서비스의 External IP를 이용해서 원하는 파드 집합에 요청을 실행한다.

Ingress & IngressController

Ingress가 왜 필요할까?

  • 서비스를 외부로 노출시키는 방법들은 external ip를 할당받고 그것을 통해 외부 트래픽을 받을 수 있다. 하지만 클러스터에 수많은 서비스가  존재하게 되면 클라이언트가 External IP를 관리하고 기억해야 하는 부담이 커지게 된다. 
  • 이에따라 많은 서비스를 어떻게하면 단일 엔드포인트로 제공할 수 있을까에 대한 고민이 있을 수 있다.

Ingress: Service 추상화, 의미있는 단일 엔드포인트 제공

  • 트래픽을 Service로 분산하기 위한 라우팅 규칙 모음
  • 클라이언트가 호출한 Host 헤더나 path를 통해 Service를 구분하고 트래픽을 포워딩(ex. order.snackbar.com)
  • 클라이언트가 하나의 ip로 접근할 수 있게 도와줌

Ingress Controller: Ingress 규칙에 따라 트래픽 분산을 실행하기 위한 리소스

  • 쿠버네티스 클러스터 제공자가 구현한 Ingress Controller마다 기능이 다르다.(AWS, GCP, nginx ingress controller)
  • 쿠버네티스 지원 Ingress Controller: https://bit.ly/3GkpoZq

Ingress 생성 방법

- multiple host

  • 여기서 host는 가짜 도메인이기 때문에 /etc/hosts 파일을 ingress의 IP주소와 매핑되도록 변경해주어야 한다.

- Single host


- Kubectl 명령어


Pod livenessProbe(직역: 생사확인)

  • 컨테이너의 health 상태를 확인하는 쿠버네티스 프로세스는 워커노드에서 실행되고 있는 kubelet 이다.
  • pod가 정상적으로 배포되더라도 내부의 애플리케이션 컨테이너가 요청을 처리할 수 없다면 아무런 의미 x
  • 쿠버네티스가 컨테이너 상태를 확인할 수 있도록 엔드포인트를 livenessProbe로 정의해서 쿠버네티스에 알려주게되고 kubelet은 livenessProbe 엔드포인트를 이용해서 컨테이너의 상태를 체크할 수 있게됨
  • libenessProbe 엔드포인트를 주기적으로 실행 -> 적절한 응답을 받지 못했을때 자체적으로 컨테이너를 재시작하는 매커니즘

Pod livenessProbe 선언방법

HttpGet livenessProbe 선언 - HTTP status code로 살아있는지 확인하는 방법


Pod readinessProbe(직역: 준비성확인)

  • 데이터 로드 등과 같은 이유로 아직 준비가 안된 파드를 제외하여 클라이언트에게 불편한 경험을 주지 않을 수 있음
  • 쿠버네티스가 컨테이너 준비 정도를 확인할 수 있도록 Pod readinessProbe를 선언
  • 일정 수준 이상 연속해서 실패하면 서비스 엔드포인트에서 파드를 제거

Pod readinessProbe 선언방법

Exec readinessProbe 선언 - process exit status code로 준비 상태를 확인하는 방법


ConfigMap

- 쿠버네티스는 Pod로부터 설정파일을 분리해서 관리할 수 있는 방법을 제공

- ConfigMap 오브젝트로 설정파일을 관리하고 Pod와 분리할 수 있다.


Pod로부터 어플리케이션 설정 정보 분리하기

  • Pod의 컨테이너 환경변수가 ConfigMap의 값을 참조 -> ConfigMap을 먼저 선언해야 함
  • Pod 볼륨으로 ConfigMap을 사용

ConfigMap을 사용하는 장점

  • Pod가 종료되고 다시 생성되더라도 동일한 Pod Manifest에는 동일한 ConfigMap이름으로 참조하기 때문에 설정 파일의 정보를 재사용 할 수 있다.
  • ConfigMap 이름으로 설정값들을 참조하기 때문에 설정값의 변경이 자유롭다. -> Pod와의 의존성이 적어지고 설정파일을 독립적으로 관리

ConfigMap 생성 방법

1. 리터럴 방식

key=value 를 직접 커맨드 라인에 작성하는 방법

kubectl create configmap --from-literal=key=value

Example

  • 모든 key/value 쌍을 선언해야 할때 위와같은 방식으로 작성하면 yaml 파일이 길어지기 때문에 greeting-map에 선언한 모든 key/value 쌍을 envFrom으로 컨테이너 환경변수로 설정할 수 있다.


2. 파일 및 폴더를 지정하는 방식

kubectl create configmap --from-file=파일이나 디렉토리 경로

- 파일 이름: key, 파일 내용: value

Example

  • 이후 Pod Manifest에서 envFrom으로 1번 리터럴 방식과 동일하게 작성

3. Pod 볼륭을 이용한 ConfigMap 사용

ConfigMap을 생성 -> ConfigMap 타입의 Volume을 Pod에서 선언 -> 컨테이너가 해당 볼륨을 마운트

Example


Secret

  • 애플리케이션 설정파일에는 서버 접속을 위한 비밀번호, 암호화를 위한 public/private key등 노출이 되면 안되는 민감 정보도 있음
  • 이러한 민감 정보를 관리하기 위한 쿠버네티스 오브젝트가 Secret
  • ConfigMap처럼 민감한 데이터를 key/value 쌍으로 저장
  • 쿠버네티스가 Secret 값을 Base64로 인코딩해서 관리(보안)
  • 컨테이너에서 Secret 값을 읽을 때는 디코딩되어 전달
  • Pod 선언 시 Secret 볼륨이나 환경변수를 통해서 Secret 값을 사용 가능

-> 쿠버네티스에서 보안관리가 가능하기 때문에 애플리케이션의 민감 데이터를 관리하기 위해 별도의 서버를 실행할 필요가 없음


Secret 사용 방법(ConfigMap과 유사하게 사용)

  1. 컨테이너 env.valueFrom.secretMapKeyRef 사용
  2. 컨테이너 envFrom.secretRef 사용
  3. Secret을 Pod 볼륨으로 연결하고 컨테이너에서 마운트

Example) TLS인증서를 Secret 볼륨으로 관리하기


5. PVC

  • PVC(Persistent Volume Claim)는 PV(Persistent Volume)이라는 리소스가 함께 다닌다. 이 리소스들은 stateless 한 Pod에 영구적으로 데이터를 보존하고 싶은 경우 사용하는 리소스이다. (도커의 docker run -v 옵션과 유사한 역할을 함)
  • PV는 관리자가 생성한 실제 저장 공간의 정보를 담고 있고, PVC는 사용자가 요청한 저장 공간의 스펙에 대한 정보를 담고 있는 리소스이다.
  • PVC를 사용하면 여러 pod간의 data 공유도 쉽게 가능하다.
  • Pod 내부에서 작성한 데이터는 기본적으로 언제든지 사라질 수 있기에, 보존하고 싶은 데이터가 있다면 Pod에 PVC를 mount해서 사용해야 한다는것을 기억하자
  • PVC는 Namespace Object이기 때문에 Namespace에 디펜던시가 걸리지만 PV는 Cluster Role과 비슷하게 클러스터에서 공용으로 사용할수 있는 객체라는것을 명심
  • PV, PVC, Storageclass에 대한 자세한 설명 여기 참고

PVC 생성

  • minikube를 생성하면 기보적으로 minikube와 함께 설치되는 storageclass가 존재한다.
  • kubectl get storageclass를 통해 확인 가능하며 storageclass는 PVC를 생성하면 PVC의 스펙에 맞는 PV를 그 즉시 자동생성해준뒤, PVC와 매칭시켜준다고 이해하면 된다.(dynamic provisioning을 지원)

  • pvc와 함께 pv가 생성된 것을 확인할 수 있다.(AGE 6s 확인)

Pod에서 PVC사용

  • volumeMounts, volumes 부분이 추가됨

pod에 접속하여 mount한 경로와 그 외의 경로에 파일을 생성

pod 삭제 후 pvc와 pv가 그대로 남아있는지 확인



 해당 pvc를 mount하는 pod를 다시 생성한 후 접속하여 아까 작성한 hello-world가 남아있는지 확인


6. Node 

Master Node

  • Cluster 관리를 위한 명령을 내리고 총괄하는 역할
  • Worker Node를 관리하고, Container 생성 요청에 따라 어떤 Worker Node에 Container를 띄울지 결정

Worker Node

  • 마스터 노드의 명령에 따라 Container를 생성하는 노드
  • 해당 노드 위에서 실행되고 있는 Container들의 상태를 주기적으로 마스터 노드에 보고

Reference

Doc(KOR) - https://kubernetes.io/ko/docs/tutorials/kubernetes-basics/