본문 바로가기
컨테이너 오케스트레이션

Devops Day 54 (5.22) 컨테이너 오케스트레이션_쿠버네티스 구성 요소

by Jackykim 2023. 5. 22.

볼륨과 스테이트풀셋
파드는 Stateless합니다
앞서 언급했던 것처럼, 파드는 일시적이며, 언제나 삭제될 수 있음을 감안해야 합니다. 따라서, 파드 그 자체는 Stateless 합니다. 이러한 파드의 교체와 배치를 담당하는 것이 디플로이먼트입니다.

 

파드가 사라져도, 데이터를 남기고 싶다면
파드 그 자체에 상태(데이터)를 남겨야만 하는 Stateful 애플리케이션으로는 MySQL, mongoDB, redis와 같은 데이터베이스가 있을 수 있습니다. 그래서 쿠버네티스에도 영속적인(Persistence) 데이터(프로그램의 실행이 종료되어도 사라지지 않는 데이터)를 저장하기 위해 볼륨(Volume)을 연결할 수 있습니다.
Q. : 볼륨과 퍼시스턴스 볼륨(Persistence Volume)은 어떤 차이가 있나요? AWS EC2에도 비슷한 개념이 있습니다. EBS와 인스턴스 스토어 볼륨의 차이점과 연결해서 설명해 주세요.
A : 볼륨(Volume)은 데이터를 저장하는 가상 공간으로, 인스턴스에 연결되어 데이터를 보존하지만 인스턴스 종료 시 접근이 불가능합니다.

- 퍼시스턴스 볼륨(Persistence Volume)은 컨테이너 기반 애플리케이션에서 사용되며, 컨테이너 종료 및 재시작에도 데이터를 유지합니다.

- AWS EC2의 EBS(Elastic Block Store)는 인스턴스에 연결하여 사용되는 네트워크 스토리지 서비스로, EC2 인스턴스에 대한 퍼시스턴스 스토리지 솔루션입니다. EBS 볼륨은 EC2 인스턴스와 분리되어 독립적으로 관리됩니다.
파드에 볼륨을 연결하면, 데이터를 영속적으로 저장하는 것이 가능합니다.


Stateful한 애플리케이션을 관리하려면
파드 명세에 PV를 정의해서 직접 연결하는 것은 좋은 방법이 아닙니다.
이때 이러한 의존도를 줄이기 위해, 퍼시스턴스 볼륨 클레임(Persistence Volume Claim, 이하 PVC)을 이용하여 PV와 연결합니다. PVC는 파드가 볼륨의 세부 사항을 몰라도 볼륨을 사용할 수 있게 도와줍니다.
- PV는 실제로 데이터가 저장되는 공간입니다.

- PVC는 PV를 선택, 연결해 주는 요청 그 자체입니다.

Q. 파드와 PV 직접 연결하는 것이 좋지 않은가요?
A : 파드와 PV(Persistence Volume)를 직접 연결하는 것은 일반적으로 권장되지 않습니다. 이는 다음과 같은 이유로 인해 그렇습니다:

1. 유연성과 재사용성: 파드와 PV를 직접 연결하면 해당 PV는 특정 파드에 독점적으로 바인딩됩니다. 이는 파드가 삭제되면 해당 PV를 다른 파드에서 사용할 수 없게 됨을 의미합니다. 그러나 PV와 파드를 추상화하는 개념인 퍼시스턴스 볼륨 클레임(Persistent Volume Claim, PVC)을 사용하면 PV를 동적으로 요청하고 여러 파드 간에 재사용할 수 있습니다.

2. 관리의 용이성: 직접적인 PV-파드 연결은 관리의 어려움을 초래할 수 있습니다. PV의 속성이 변경되어야 할 때마다 모든 파드에 대해 수동으로 수정해야 합니다. 이는 확장성이나 유지보수 측면에서 비효율적이며 오류 가능성도 높아집니다. 반면, PV와 PVC의 중간 계층을 사용하면 PV의 속성을 쉽게 변경하고 파드는 PVC를 통해 해당 PV에 액세스할 수 있습니다.

3. 볼륨의 독립성: 직접적인 PV-파드 연결은 PV가 특정 스토리지 백엔드에 종속되도록 만듭니다. 이는 스토리지 백엔드를 변경하려는 경우 문제가 될 수 있습니다. PV와 PVC를 사용하면 PV가 스토리지 백엔드에 대해 독립적이며, 스토리지 백엔드를 쉽게 교체하거나 업그레이드할 수 있습니다.

따라서 PV와 파드를 직접 연결하는 대신 PVC를 사용하여 중간 계층을 구성하는 것이 일반적으로 더 유연하고 관리하기 쉬운 방법입니다. PVC는 파드가 요청하는 퍼시스턴스 스토리지를 추상화하고, PV는 PVC에 대한 실제 구현을 제공하는 방식으로 작동합니다. 이를 통해 PV와 파드 간의 결합도를 낮추고 퍼시스턴스 스토리지의 유연한 관리를 가능하게 합니다.

 

Q. : PVC는 어떻게 작동되나요?
A : PVC(Persistent Volume Claim)는 파드가 필요로 하는 퍼시스턴스 스토리지를 요청하는 추상화된 개체입니다. PVC는 PV(Persistent Volume)와 동적으로 연결되어 파드에 필요한 스토리지를 제공합니다. PVC는 PV를 요청하고, 컨트롤러가 해당 요청과 일치하는 PV를 할당하여 파드에 마운트될 수 있도록 합니다. 이를 통해 PVC는 퍼시스턴스 스토리지의 관리와 재사용을 용이하게 합니다.

 

Stateful한 애플리케이션이 수평 확장한다면
파드를 정의할 때 PVC를 통해 볼륨에 연결할 수가 있습니다. 그런데, 그냥 이러한 파드를 디플로이먼트로 배포해도, PVC를 통해 연결되는 볼륨은 하나이기 때문에, 결국 같은 스토리지를 사용하는 모양새가 됩니다.

파드마다 별도의 데이터를 저장할 수 있게 만들려면, 수평확장되는 파드에 서로 다른 PV가 연결되어야 합니다. 스토리지 클래스(StorageClass) 리소스는 사용자가 요청할 때, 자동으로 PV를 프로비저닝 할 수 있게 돕습니다.

스토리지 클래스 관련 :
동적 볼륨 프로비저닝 : 동적 볼륨 프로비저닝을 통해 온-디맨드 방식으로 스토리지 볼륨을 생성할 수 있다. 동적 프로비저닝이 없으면 클러스터 관리자는 클라우드 또는 스토리지 공급자에게 수동으로 요청해서 새 스토리지 볼륨을 생성한 다음, 쿠버네티스에 표시하기 위해 PersistentVolume 오브젝트를 생성해야 한다.

동적 프로비저닝 활성화하기

동적 프로비저닝을 활성화하려면 클러스터 관리자가 사용자를 위해 하나 이상의 스토리지클래스(StorageClass) 오브젝트를 사전 생성해야 한다. 스토리지클래스 오브젝트는 동적 프로비저닝이 호출될 때 사용할 프로비저너와 해당 프로비저너에게 전달할 파라미터를 정의한다.
다음 매니페스트는 표준 디스크와 같은 퍼시스턴트 디스크를 프로비전하는 스토리지 클래스 "slow"를 만든다.

기본 동작

스토리지 클래스가 지정되지 않은 경우 모든 클레임이 동적으로 프로비전이 되도록 클러스터에서 동적 프로비저닝을 활성화 할 수 있다. 클러스터 관리자는 이 방법으로 활성화 할 수 있다.

 

하나의 StorageClass 오브젝트를 default 로 표시한다.

API 서버에서 DefaultStorageClass 어드미션 컨트롤러를 사용하도록 설정한다.

관리자는 storageclass.kubernetes.io/is-default-class 어노테이션을 추가해서 특정 StorageClass 를 기본으로 표시할 수 있다.

 

참조 : https://kubernetes.io/ko/docs/concepts/storage/dynamic-provisioning/

 

스토리지 클래스
스토리지클래스는 관리자가 제공하는 스토리지의 "classes"를 설명할 수 있는 방법을 제공한다. 다른 클래스는 서비스의 품질 수준 또는 백업 정책, 클러스터 관리자가 정한 임의의 정책에 매핑될 수 있다.

 

스토리지클래스 리소스

각 스토리지클래스에는 해당 스토리지클래스에 속하는 퍼시스턴트볼륨을 동적으로 프로비저닝 할 때 사용되는 provisioner, parameters 와 reclaimPolicy 필드가 포함된다.

관리자는 특정 클래스에 바인딩을 요청하지 않는 PVC에 대해서만 기본 스토리지클래스를 지정할 수 있다.

스테이트풀셋

스테이트풀셋은 애플리케이션 구성(파드)을 복제하더라도, 스토리지 클래스를 이용해 파드가 필요로 하는 볼륨을 자동으로 프로비저닝하여 연결합니다. 따라서 첫 번째 파드를 primary(master), 두 번째 파드를 secondary 복제본처럼 구성하는 것도 가능합니다.

스테이트풀셋은 파드의 순서와 고유성을 보장합니다.

이는 앞서, 가축과 애완동물의 비유를 떠올리면 좋습니다. 스테이트풀셋이 생성한 파드는 상호 대체할 수 없는 파드입니다.

스테이트풀셋을 사용할 때의 주의사항

- 파드에 지정된 스토리지는 관리자에 의해 퍼시스턴트 볼륨 프로비저너를 기반으로 하는 storage class를 요청해서 프로비전하거나 사전에 프로비전이 되어야 합니다.

- 헤드리스 서비스가 필요합니다.

 

Q. 네트워크 트래픽에 따라 요청이 랜덤하게 분산되는 일반적인 서비스에 비해, 헤드리스 서비스는 특정 스테이트풀셋에게 트래픽을 보냅니다. 왜 그렇게 해야 하나요?
A : 헤드리스 서비스(Headless Service)는 네트워크 트래픽을 랜덤하게 분산하는 일반적인 서비스와는 달리, 특정 스테이트풀셋(StatefulSet)에 대해 트래픽을 보냅니다. 이는 다음과 같은 이유로 필요합니다:

 

식별성: 헤드리스 서비스는 각각의 스테이트풀셋 멤버에 대해 고유한 DNS(Domain Name System) 진입점을 제공합니다. 이를 통해 각 스테이트풀셋 멤버에 대해 개별적으로 접근할 수 있으며, 식별성을 갖습니다. 이는 특정 멤버에 직접적으로 접근해야 하는 경우에 유용합니다.

 

상태 유지: 스테이트풀셋은 각각의 멤버가 유일한 상태(State)를 가지는 애플리케이션을 구성합니다. 헤드리스 서비스를 사용하면 트래픽이 항상 동일한 스테이트풀셋 멤버로 전달되므로, 상태를 유지하고 유지되는 연결을 통해 데이터 일관성을 보장할 수 있습니다.

특정한 요구사항: 일부 애플리케이션은 특정 스테이트풀셋 멤버에 대한 직접적인 접근이 필요한 경우가 있습니다. 예를 들어, 데이터베이스 클러스터의 마스터 노드에 쓰기 작업을 진행하기 위해서는 해당 노드에 대한 접근이 필요합니다. 이런 경우에 헤드리스 서비스를 사용하여 특정한 스테이트풀셋 멤버에게 트래픽을 보내는 것이 유용합니다.

 

따라서, 헤드리스 서비스는 식별성, 상태 유지, 특정한 요구사항을 충족하기 위해 특정 스테이트풀셋 멤버에게 트래픽을 보내는 것이 필요합니다.

 

쿠버네티스 네트워크
인그레스
인그레스는 클러스터 내의 서비스에 대한 외부 접근을 관리하는 API 게이트웨이입니다. 일반적으로 HTTP를 관리하며 로드 밸런서, SSL Termination (클러스터 내에서는 HTTP로만 통신하게 하는 전환 과정), 가상 호스팅을 제공합니다.

예시 실습 :
1. 먼저 기존 서비스 타입을 LoadBalancer로 ClusterIP로 바꾸고 적용합니다. ClusterIP는 클러스터 내에서만 접근 가능합니다. 더 이상 EXTERNAL-IP는 사용할 수 없습니다.

2. 인그레스 리소스를 다음과 같이 만들고 적용합니다 -> kubectl apply -f ingress.yaml

3. 생성된 인그레스를 조회합니다. 인그레스는 kubectl get all로는 조회가 안되므로 다음과 같이 조회합니다.

 

4. 인그레스는 인그레스 리소스(정책 그 자체) 외에도 인그레스 컨트롤러(정책을 실행시키는 도구)가 반드시 필요합니다. minikube를 사용하는 경우, 인그레스 컨트롤러는 애드온으로 별도의 설치가 필요합니다. 공식 문서를 참고해서 nginx 인그레스 컨트롤러를 활성화하세요.

 

5. 터널을 열고, http://localhost에 접속해 봅시다.

 

인그레스의 필요성
외부 IP 주소를 할당해 주는 서비스와 로드 밸런서를 생성하고 컨테이너로 트래픽을 보내는 방법을 이용합니다. 이렇게 파드를 노출시킬 수 있는데, 왜 인그레스를 별도로 사용해야 할까요?

바로 인그레스 리소스는 로드 밸런싱과 더불어 호스트 기반 라우팅을 지원하기 때문입니다.
앞서 만든 서비스는 LoadBalancer에서 ClusterIP로 바꿨기 때문에 인그레스가 로드 밸런서의 역할을 수행해야 합니다.

아주 단순한 애플리케이션도 서비스는 두 개 이상의 HTTP 요청을 가지는 것이 보통입니다. 보통 각각 Web Server와 WAS로 대표됩니다.


YAML 파일에서 spec.rules.host에 별도의 호스트를 지정하여 Web Server는 www.mydomain.click, WAS는 api.mydomain.click으로 설정하는 것도 가능합니다.

인그레스 컨트롤러라고 해서 뭔가 특별한 프로그램은 아닙니다. 우리가 흔히 잘 알고 있는 nginx와 같은 애플리케이션이 바로 인그레스 컨트롤러입니다.

 

참고 : https://kubernetes.io/ko/docs/tasks/access-application-cluster/ingress-minikube/ 

 

발표 :
[C183] 애플리케이션에 HTTP 500과 같은 에러가 발생한 경우, 컨테이너를 다시 실행해야 할 것입니다. HTTP 에러가 발생했다는 것을 어떻게 알 수 있을까요? 어떻게 해야 쿠버네티스가 에러가 발생한 컨테이너를 자동으로 재시작하게 만들 수 있을까요? (힌트: liveness probe 키워드를 검색하세요)

 

HTTP 500과 같은 에러는 애플리케이션이 서버 오류를 경험했음을 나타냅니다. 쿠버네티스에서는 Liveness Probe를 사용하여 애플리케이션의 상태를 주기적으로 확인하고, 에러가 발생한 경우 해당 컨테이너를 자동으로 재시작할 수 있습니다.

 

Liveness Probe는 컨테이너의 상태를 확인하기 위해 정의된 작업 또는 검사 항목을 실행합니다. 이를 통해 컨테이너가 정상적으로 작동하는지 여부를 판단할 수 있습니다. Liveness Probe는 주로 HTTP 요청을 사용하여 애플리케이션의 상태를 확인합니다.

 

httpGet: HTTP GET 요청을 사용하여 애플리케이션의 상태를 확인합니다.

만약 unhealty 상태가 된다면 해당 파드는 죽고 다시 시작하게 된다.

 

참고 : https://velog.io/@dnflekf2748/k8s-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88%EC%97%90-%EB%AC%B8%EC%A0%9C%EA%B0%80-%EC%83%9D%EA%B2%BC%EC%9D%84-%EB%95%8C#:~:text=%EB%A7%8C%EC%95%BD%20%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98%EC%97%90%20HTTP%20500%EA%B3%BC%20%EA%B0%99%EC%9D%80%20%EC%97%90%EB%9F%AC%EA%B0%80%20%EB%B0%9C%EC%83%9D%ED%95%9C%20%EA%B2%BD%EC%9A%B0,-HTTP%20%EC%97%90%EB%9F%AC%EA%B0%80&text=%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88%EC%9D%98%20%EB%AC%B8%EC%A0%9C%EA%B0%80%20%EC%83%9D%EA%B8%B0%EB%A9%B4,%EB%A5%BC%20%ED%99%95%EC%9D%B8%20%ED%95%A0%20%EC%88%98%20%EC%9E%88%EB%8B%A4.

 

[C184] 왜 파드와 PV(퍼시스턴스볼륨)를 직접 연결하지 않는 걸까요?
파드와 PV(퍼시스턴스 볼륨)를 직접 연결하지 않는 이유는 다음과 같습니다:

 

유연성과 재사용성: PV는 클러스터 전체에서 독립적으로 생성되고 관리되는 개체입니다. PV와 파드를 직접 연결하면 해당 파드에 대한 유연성과 재사용성이 제한됩니다. PV를 사용하여 여러 파드에서 동시에 액세스하거나, 다른 파드로 이동하거나 재사용할 수 있습니다.

 

관리의 용이성: PV와 파드를 분리함으로써 스토리지의 관리가 용이해집니다. PV는 스토리지 백엔드와 연결되어 있으며, PV에 대한 변경 또는 관리 작업을 수행할 때 파드에 영향을 미치지 않습니다. PV를 중간 계층으로 사용하여 스토리지의 관리를 단순화하고, 필요에 따라 PV와 파드를 독립적으로 조작할 수 있습니다.

 

동적 프로비저닝: PV와 PVC(퍼시스턴스 볼륨 클레임)를 사용하면 필요한 스토리지 요구 사항을 정의하고, 클러스터에서 자동으로 PV를 동적으로 프로비저닝할 수 있습니다. 파드와 직접 연결하는 대신 PVC를 사용하여 필요한 스토리지를 요청하면, 시스템은 해당 요청과 일치하는 PV를 찾거나 새로 생성하여 할당합니다.

 

스토리지 백엔드의 변경: PV를 사용하여 스토리지 백엔드를 추상화하면, 스토리지 백엔드를 변경하거나 업그레이드할 때 파드에 영향을 주지 않고도 PV를 교체할 수 있습니다. 이는 애플리케이션의 가용성과 유지 보수를 향상시킵니다.

 

따라서, PV와 파드를 직접 연결하지 않고 중간 계층인 PVC를 사용하여 관리의 용이성과 유연성을 확보할 수 있습니다. 이를 통해 스토리지의 유연한 요청과 재사용, 관리의 편의성, 동적 프로비저닝 등의 이점을 얻을 수 있습니다.