NCQ와 Flash Drive

NCQ (Native Command Queuing)

수신된 I/O의 실행 순서를 정해 불필요한 헤드 움직임을 줄여 성능을 개선하려는 목적으로 사용되는 기술.

  • 탐색 시간 최적화 알고리즘: 헤드 움직임을 최적화 하는 방향으로 명령 실행
  • 액세스 시간 최적화 알고리즘: 탐색 시간과 회전 지연 시간으로 성능을 최적화

Flash Drive

플래시 드라이브의 일종인 SSD(solid state drive)는 반도체 기반 solid state memory를 사용해 데이터를 저장하고 추출한다.

기업용 플래시 드라이브(EFD, Enterprise Flash Drive)는 기존 디스크 드라이브와 비교해 30배 높은 데이터 처리량과 10분의 1정도의 응답속도를 제공하며, 전력 소모량도 적다.

flash drive component & architecture

기존 디스크 드라이브와 호환을 위해 같은 커넥터를 사용한다.

구성요소

  • 컨트롤러 - 드라이브 동작 관리.
  • I/O 인터페이스 - 전력, 데이터 액세스 제공.
  • Mass Storage - 비휘발성 NAND 메모리 칩 배열. 데이터 저장.
  • Cache - data transaction의 임시 공간 혹은 버퍼.

채널

플래시 드라이브는 컨트롤러와 플래시 메모리 칩 사이에 다중 병렬 I/O 채널을 사용한다. 메모리 칩과 채널을 많이 사용할 수록 드라이브 내부 대역폭이 증가하여 성능이 좋아진다. 보통 8~24 채널을 사용한다.

메모리 칩

논리적 블록과 페이지 단위로 구성된다.

  • page

플래시 드라이브에서 읽거나 쓰는 가장 작은 object이다. 표준 크기는 없지만 일반적으로 4KB, 8KB, 16KB를 사용한다. LBA(logical block address)를 사용하는 디스크 드라이브와 같은 방식을 제공하기 위해 여러 데이터 블록 위에 연속적으로 걸쳐 있게 된다. 8 x 512B = 4KB 이므로, 4KB page는 연속된 주소의 8개의 데이터 블록을 가진다.

  • block

전통적인 하드 디스크 드라이브의 섹터에 있는 블록과 다른 개념이다. 여러 page를 그룹으로 묶어 block을 만든다. 한 block 당 32, 64, 혹은 128개의 page를 갖는다.

주요 특징

NAND Flash Memory

랜덤 데이터 액세스에 유리하다. 잘못된 블록이 탐지되면 ECC(Error Correcting Code)를 사용해서 데이터 무결성을 유지한다.

SLC(Single Level Cell)

MLC(multi-level cell)은 셀당 여러 비트를 저장할 수 있고, single-level cell은 한 비트만 저장할 수 있다. 하지만 SLC가 성능과 지속성 면에서 우수하다. 읽기 속도는 SLC가 MLC보다 두배 정도 빠르고, 쓰기 속도는 4배 정도 빠르다.

쓰기 레벨링

플래시 드라이브의 수명을 최대화 하기 위해 각 메모리 셀을 균일하게 사용하는 것이 좋다. 자주 업데이트 되는 데이터를 각각 다른 위치해 기록해 같은 셀을 계속 사용하는 것을 방지하는 것이 좋다.

728x90
반응형

'OS & Container > Storage' 카테고리의 다른 글

RAID 레벨  (0) 2022.03.15
RAID Array 구성요소, 기술  (0) 2022.03.08
데이터 액세스와 DAS  (0) 2022.02.27
디스크 드라이브 성능  (0) 2022.02.27
논리적 볼륨 매니저(LVM, Logical Volume Manager)  (0) 2022.02.26

호스트에서 데이터 액세스

스토리지 디바이스는 호스트 내부에 있거나 외부에 있을 수 있지만, 어떠한 경우든 호스트 컨트롤라 카드가 IDE/ATA나 SCSI, 파이버 채널같은 정의된 프로토콜을 이용해 스토리지에 접근한다. 파이버 채널과 iSCSI는 외부 스토리지 디바이스의 데이터에 접근하는데 사용된다. 외부 스토리지 디바이스는 호스트에 직접 연결하거나 스토리지 네트워크를 사용해 연결할 수 있다. 호스트에 직접 연결한 스토리지를 DAS(Direct Attached Storage)라고 한다.

일반적으로 애플리케이션이 파일 시스템의 데이터를 요청하면, 파일 시스템은 파일 속성을 논리적 블록 주소(LBA)로 변환해 스토리지 디바이스에 요청한다. 스토리지 디바이스는 LBA를 실린더-헤드-섹터(CHS) 주소로 변환해 데이터를 가져온다.

블록 레벨 액세스에서는 호스트에 파일 시스템을 생성하고 네트워크를 통해 블록 레벨로 데이터에 접근한다. 이 경우 raw 디스크나 논리적 볼륨이 파일 시스템을 만들기 위해 호스트에 할당된다.

파일 레벨 액세스에서 파일 시스템은 별도의 파일 서버나 스토리지 사이드에 생성되고, 파일 레벨 요청이 네트워크를 통해 전달된다. 파일 레벨에서 데이터를 접근하므로 블록 레벨 접근보다 오버헤드가 크다.

객체 레벨 액세스에서는 고유 식별자를 가진 객체 단위로 데이터에 접근한다.

직접 연결 스토리지(DAS)

DAS는 스토리지가 직접 호스트에 연결된 구성이다. 호스트 관점에서의 스토리지 위치에 따라 내부와 외부로 나뉜다.

내부 DAS

스토리지 디바이스가 직렬 또는 병렬 버스로 호스트에 연결된다. 물리적 버스는 길이에 제한이 있으며, 길이가 짧을수록 높은 연결 속도가 나온다. 대부분의 내부 버스는 제한된 개수의 디바이스만을 지원하고, 공간을 차지한다는 단점이 있다.

외부 DAS

호스트를 외부 스토리지 디바이스에 직접 연결하고, 데이터는 블록 레벨로 접근한다. 통신 프로토콜은 주로 SCSI나 FC를 사용한다. 호스트 외부에서 디바이스를 중앙 집중형식으로 관리할 수 있는 장점이 있다.

DAS의 장점과 한계

DAS는 네트워킹 구성보다 초기 투자 비용이 낮고, 쉽고 빠르다는 장점이 있다. 하지만 확장성이 좋지 않다는 단점이 있으며, 프론트엔드 포트를 공유하기 때문에 리소스를 최적으로 사용하기 어렵다. 사용하지 않는 리소스를 쉽게 재할당 할 수 없으므로 스토리지 풀마다 사용량에 차이가 발생한다.

728x90
반응형

'OS & Container > Storage' 카테고리의 다른 글

RAID 레벨  (0) 2022.03.15
RAID Array 구성요소, 기술  (0) 2022.03.08
NCQ와 Flash Drive  (0) 2022.03.02
디스크 드라이브 성능  (0) 2022.02.27
논리적 볼륨 매니저(LVM, Logical Volume Manager)  (0) 2022.02.26

디스크 드라이브 성능

디스크 서비스 시간

디스크 서비스 시간(disk service time): I/O 요청을 완료하는 데 걸리는 시간. 탐색 시간(seek time)과 회전 지연 시간(rotational latency), 데이터 전송 속도(data transfer rate)에 영향을 받는다.

탐색 시간

탐색 시간(seek time)은 엑세스 시간(access time)이라고도 하며, R/W 헤드를 지름 방향(접선과 수직인 방향)으로 움직여 위치시키는 것을 말한다.

탐색 시간 스펙으로 다음과 같이 있다.

  • 풀 스트로크(full stroke): R/W head를 0번에서 마지막으로 움직이는데 걸리는 시간
  • 평균: 랜덤 트랙으로 R/W head를 움직이는데 걸리는 시간. 보통 풀 스트로크의 1/3이다.
  • 트랙에서 트랙: 인접한 트랙으로 R/W 헤드를 이동하는데 걸리는 시간

각 스펙은 밀리초 단위로 측정하며, 제작사에서 명시한다. 최신 디스크의 경우 평균은 3~15 밀리초이다.

short-stroking

적은 실린더를 사용하여 용량을 줄이고 탐색 시간을 줄이는 방법.

회전 지연 시간

플래터가 회전하여 R/W헤드 아래에 요청한 데이터가 위치하기까지의 시간. 스핀들의 회전 속도에 영향을 받으며 밀리초 단위로 측정된다. 평균 지연 시간은 한 바퀴를 회전하는 시간의 1/2이다.

15,000 rpm(250rps) 드라이브의 평균 회전 시간은 1 / 250 / 2 = 2 밀리초이다.

데이터 전송 속도

단위 시간동안 드라이브가 HBA(Host Bus Adapter)로 전송할 수 있는 데이터의 양

읽기 연산에서는 플래터 -> R/W헤드 -> 드라이브 내부 버퍼 -> 드라이브 인터페이스 -> HBA로 이동한다. 쓰기 연산에서는 HBA -> 드라이브 인터페이스 -> 드라이브 내부 버퍼 -> R/W헤드 -> 플래터로 이동한다.

R/W연산에서 데이터 전송 속도는 드라이브 내부와 외부 전송 속도로 측정된다. 내부 전송 속도는 플래터에서 R/W헤드를 거처 디스크 내부 버퍼(캐시)로 이동하는 속도다. 내부 전송 속도는 탐색 시간과 회전 지연 시간의 영향을 받는다. 외부 전송 속도는 인터페이스에서 HBA로 이동하는 속도다. 보통 ATA의 133MB/s로 볼 수 있다.

디스크 I/O 컨트롤러 사용률

디스크 I/O 컨트롤러의 사용률은 I/O 반응 속도에 영향을 준다.

컨트롤러 평균 응답 시간 = 서비스 시간 / (1 - 컨트롤러 사용률)

컨트롤러 사용률이 100%가 되면, 컨트롤러의 응답 시간은 무한대에 가까워진다. 컨트롤러의 부하가 증가하여 70%가 넘으면 급격히 응답시간이 늘어난다.

728x90
반응형

'OS & Container > Storage' 카테고리의 다른 글

RAID 레벨  (0) 2022.03.15
RAID Array 구성요소, 기술  (0) 2022.03.08
NCQ와 Flash Drive  (0) 2022.03.02
데이터 액세스와 DAS  (0) 2022.02.27
논리적 볼륨 매니저(LVM, Logical Volume Manager)  (0) 2022.02.26

논리적 볼륨 매니저(LVM, Logical VOlume Manager)

파일 시스템 용량을 동적으로 확장하고, 스토리지를 효율적으로 관리하는 LVM은 시스템에서 동작하는 소프트웨어로, 논리적, 물리적 스토리지를 관리한다.

LVM은 파일 시스템과 물리 디스크 사이의 레이어(Layer)다. 디스크를 좀 더 작은 가상 볼륨으로 파티셔닝(partitioning) 하거나 작은 디스크를 합쳐 큰 가상 볼륨을 컨캐터네이션(concatenation) 할 수 있다.

파티셔닝 partitioning

큰 디스크 드라이브를 여러개의 논리적 볼륨(LV, Logical Volume)으로 나눌 수 있다. 디스크 드라이브를 호스트에 처음 설치 할 때, 여러 실린더를 그룹화해 파티션을 만든다. 호스트 파일 시스템은 파티셔닝과 디스크의 구조를 모르는 상태에서 논리적 볼륨에 접근한다.

컨캐터네이션 concatenation

여러 물리 드라이브를 그룹화해 하나의 논리 볼륨으로 만드는 것이다. LVM이 최적화된 스토리지 액세스를 제공하며 리소스 관리를 한다. 사용자는 물리적 디스크 개수나 데이터의 위치를 몰라도 된다.

LVM 구성

물리적 볼륨 PV, physical volume

LVM에서 호스트 시스템에 연결된 각 물리 디스크를 물리적 볼륨이라고 한다. LVM은 물리적 볼륨이 제공하는 물리적 스토리지를 OS나 애플리케이션이 사용하는 논리적 뷰로 변환한다.

볼륨 그룹 volume group

1개 이상의 물리 볼륨을 그룹화해 볼륨 그룹을 만든다. 각 볼륨을 초기화 할 때, LVM이 사용할 고유 물리적 볼륨 아이디(PVID, physical volume identifier)를 할당한다.

볼륨 그룹에 동적으로 물리적 볼륨을 추가하거나 삭제할 수 있지만, 하나의 물리적 볼륨을 여러 볼륨 그룹간에 공유할 수는 없다. 하나의 물리적 볼륨을 나눠 여러 볼륨 그룹이 사용할 수도 없다.

각 볼륨 그룹을 만들 때는 물리적 익스텐트(physical extent) 라고 하는 같은 크기의 데이터 블록 집합으로 파티셔닝한다.

논리적 볼륨 LV, logical volume

볼륨 그룹에서 만들어진다. 논리적 볼륨은 디스크 파티션으로 생각할 수 있으며 볼륨 그룹 자체는 디스크로 볼 수 있다.

728x90
반응형

'OS & Container > Storage' 카테고리의 다른 글

RAID 레벨  (0) 2022.03.15
RAID Array 구성요소, 기술  (0) 2022.03.08
NCQ와 Flash Drive  (0) 2022.03.02
데이터 액세스와 DAS  (0) 2022.02.27
디스크 드라이브 성능  (0) 2022.02.27

스테이트풀셋

필요성

파드별로 각자 다른 persistant volume을 할당하고 싶으면 어떻게 해야 할까. 디플로이먼트의 파드 템플릿은 모두 동일한 pvc를 가지기 때문에 곤란하다.

특정 애플리케이션이 안정적인 네트워크 아이덴티티를 요구(ACL 구성 등)하면 어떻게 해야 할까. 파드 한개당 서비스 한개를 맵핑해야 할까.

스테이트풀셋 이해

이런 유형의 파드를 실행하기 위해 레플리카셋 대신 사용하는것이 스테이트 풀셋 리소스다.

스테이트풀셋은 애플리케이션 인스턴스가 각각 안정적인 이름과 상태를 가지며 개별적으로 취급해야 하는 애플리케이션에 알맞게 만들어졌다.

스테이트풀셋과 레플리카셋

애플리케이션을 애완동물과 가축으로 빗대어

스테이트리스 애플리케이션은 가축이다. 인스턴스가 교체되어도 사용자는 이를 알아차리지 못하고 이용하는데 문제도 없다.

스테이트풀 애플리케이션은 애완동물이다. 애완동물이 죽으면 사용자는 이를 바로 알아차리고 이용하는데 문제가 생긴다. 대체하려는 애완동물을 구할때도 이름과 생김새가 완전히 같은 애완동물을 찾아야 한다. 이에 스테이트풀셋은 초기에 PetSets라고 불렸다.

스테이트풀셋으로 관리되는 파드가 종료되면 새로 교체되는 파드 인스턴스는 이름, 네트워크 아이덴티티, 상태가 동일한 상태로 되살아난다. 각 파드는 다른 피어와 구별되는 자체의 볼륨 세트를 가지며, 예측 가능한 아이덴티티를 가진다.

안정적인 네트워크 아이덴티티

스테이트풀셋 A의 파드는 0부터 시작되는 인덱스가 할당되어 A-0, A-1 과 같이 지어진다.(파드 이름이 컨테이너의 host로 쓰인다.)

거버닝 서비스

스테이트풀 파드는 각각 다르므로 한개를 선택할 때 특정 파드를 선택 할 필요가 있다.

이런 이유로 거버닝 헤드리스 서비스를 생성해서 각 파드에게 실제 네트워크 아이덴티티를 제공해야 한다.

​ ex) default 네임스페이스의 foo라는 거버닝 서비스가 있고 파드의 이름이 A-0이라면,

​ FQDN은 a-0.foo.default.svc.cluster.local로 접근할 수 있다.

이는 레플리카셋으로 관리되는 파드에서는 불가능하다.

또한, foo.default.svc.cluster.local 도메인의 SRV레코드를 조회해서 모든 스테이트풀셋의 파드 이름을 찾는 목적으로도 DNS를 사용 할 수 있다.

스테이트풀셋 스케일링

스테이트풀셋을 스케일업하면 새로운 인스턴스는 다음 서수 인덱스를 갖는다.

​ ex) A-0, A-1 -> A-2

스테이트풀셋을 스케일다운하면 항상 높은 서수의 인덱스를 먼저 제거한다.

​ ex) A-0, A-1 -> A-2

안정적인 스토리지 제공

퍼시스턴트 볼륨과 퍼시스턴트볼륨클레임은 일대일로 맵핑되어 각 파드는 별도의 퍼시스턴트 볼륨을 갖는 각각의 퍼시스턴트볼륨클레임을 참조해야 한다.

볼륨 클레임 템플릿

스테이트풀셋은 파드 템플릿을 구성할 때 각 파드와 함께하는 볼륨 클레임 템플릿을 가질 수 있다.

퍼시스턴트볼륨클레임의 생성과 삭제

스테이트풀셋을 스케일 업하면 두개 이상의 API오브젝트(파드와 파드에서 참조하는 하나 이상의 PVC)가 생성된다. 하지만 스케일 다운을 할때는 파드만 삭제하고 PVC는 남겨둔다.

PVC가 삭제된 후 PV가 재활용되거나 삭제될수 있기 때문이다.

동일 파드의 새 인스턴스에 PVC 다시 붙이기

스케일 다운 이후 스케일 업을 하면 PV에 바인딩된 동일한 PVC를 연결 할 수 있다.

스테이트풀셋이 보장하는 것

스테이트풀셋은 두개의 스테이트풀파드 인스턴스가 절대 동일한 아이덴티티로 실행되지 않고, 동일한 PVC에 바인딩 되지 않도록 보장한다.

만약 파드 교체가 일어나는 경우 새로운 파드를 생성하기 전에 파드가 실행중이 아니라는 것을 확인해야 한다.

728x90
반응형

디플로이먼트(Deployment)

디플로이먼트는 레플리카 셋 대신 애플리케이션을 배포하고 선언적으로 업데이트 하는 리소스다.

디플로이먼트를 생성하면 레플리카셋 리소스가 생성되고, 레플리카셋 리소스가 파드를 관리한다.

  • 디플로이먼트를 만드는 이유

애플리케이션을 업데이트 할 때 추가 레프리카 셋을 만들고 배포를 하는 방식을 통제하여야 하는데, 이를 디플로이먼트가 관리한다.

ex) 낮은 수준의 배포(kubectl을 통한 배포)를 진행하는 중 작업중인 노드가 내려간다면, 배포 중간 상태로 배포가 마무리된다.

디플로이먼트가 레플리카셋을 생성, 레플리카셋이 파드를 생성

디플로이먼트를 작성하며 레플리카셋이 생성한 파드의 이름을 조회하면 <디플로이먼트 이름> + <레플리카셋 해시값> + <파드 해시값> 으로 구성된다.

레플리카셋의 이름은 <디플로이먼트 이름> + <레플리카셋 해시값> 으로 생성되며 이는 레플리카셋이 해당 파드를 관리함을 의미한다.

디플로이먼트가 파드의 템플릿 버전별로 레플리카셋을 생성하기 때문에, 파드 템플릿의 해시값을 사용하면 디플로이먼트에서 지정된 버전의 파드 템플릿에 대하여 항상 동일한 레플리카셋을 사용 할 수 있다.

디플로이먼트 전략

  • Rolling Update

    기본 전략. 하나씩 기존 파드를 제거하고 신규 파드로 교체한다.

  • Recreate

    모든 기존 파드를 삭제한 뒤 새로운 파드를 만들어 낸다. 서비스 다운타임이 발생한다.

신규 파드 업데이트 이후 레플리카셋이 남아있는 이유

$kubectl get rs 와 같은 명령으로 레플리카셋을 조회해보면 기존에 사용되었던 레플리카셋이 지워지지 않고 남아있다. 디플로이먼트에 의해 관리되는데, 업데이트가 끝난 이후에 왜 계속 남아있을까?

디플로이먼트 롤백

새로 배포된 파드 템플릿에서 오류가 발생한 경우 롤아웃을 되돌려야 한다. 이 때, 디플로이먼트를 사용하여 마지막 혹은 정해진 버전으로 쉽게 롤백할 수 있다. 삭제되지 않은 레플리카셋은 이 때 사용된다.

모든 개정 내역의 수는 디폴로이먼트 리소스의 editionHistoryLimit 속성에 의해 제한된다.(쿠버네티스 버전이 올라가면서 revisionHistoryLimit로 변경)

maxSurge와 maxUnavailable

  • maxSurge

    디플로이먼트가 의도하는 레플리카 수보다 얼마나 많은 파드 인스턴스 수를 허용할 것인지. 백분율 혹은 절대값으로 지정. 기본값 25%

  • maxUnavailable

    업데이트 중 의도하는 레플리카 수(Desired State) 기준으로 사용할 수 없는 파드 인스턴스 수. 백분율 혹은 절대값으로 지정. 기본값 25%

minReadySeconds

일정시간동안 준비상태를 검사하여 rollout하는 디플로이먼트 spec의 리소스 속성이다.

오작동 버전의 배포를 방지할 수 있다.

사용 가능한 파드가 되려면 minReadySeconds 기간동안 readiness probe가 성공해야 한다.

롤아웃 데드라인

기본적으로 10분동안 롤아웃이 진행되지 않으면 실패한것으로 간주된다.

디플로이먼트의 ProgressDeadlineExceeded 으로 확인 할 수 있다.

디플로이먼트 스펙의 progressDeadlineSeconds 속성으로 정의 할 수 있다.

728x90
반응형

서비스

세션 어피니티

동일한 명령을 실행하더라도 서비스 프록시가 각 연결을 임의의 파드로 전달하기 때문에 연결 할 때 마다 임의의 파드가 선택된다.

반면 특정 클라이언트의 모든 요청을 매번 같은 파드로 전달하려면 서비스의 세션 어피니티 속성을 기본값 None 대신 ClientIP로 설정해야 한다.

apiVersion: v1
kind: Service
spec:
    sessionAffinity: ClientIP
...

DNS를 통한 서비스 검색

  • 클러스터에서 실행중인 다른 모든 팟이 사용하는 kube-dns 라는 시스템 리소스가 있다.
  • kube-dns는 모든 서비스를 알고있는 쿠버네티스의 자체 DNS 서버.
  • 파드가 내부 DNS 서버를 사용할 지 여부는 각 파드 스펙의 dnsPolicy 속성으로 구성 할 수 있다.
  • 서비스 이름을 알고 있는 파드는 FQDN(Fully Quallified Domain Name)으로 통신 할 수 있다.위 curl은 클러스터 내부의 pod을 kubectl exec 명령을 통해 실행한 상태에서 수행한다. (클러스터 내부 통신이기 때문)
    • svc.cluster.local 은 모든 클러스터의 로컬 서비스 이름에 사용되는 클러스터의 도메인 접미사. 생략 가능하다.
    • 파드가 같은 네임스페이스에 있는 경우 네임스페이스도 생략할 수 있다. 단순히 서비스의 이름만 써도 된다.
    • 파드 컨테이너 내부의 DNS resolver 구성 /etc/resolv.conf 를 보면 이해 할 수 있다.
  • Ex) curl http://svc-orra-dev.ns-ordev.svc.cluster.local:8082
  • 서비스에 IP 핑은 할 수 없다.

외부 클라이언트에 서비스 노출

  • 노드포트로 서비스 유형(Type) 설정
  • 서비스 유형을 노드포트 유형의 확장인 '로드밸런서'로 설정
  • 단일 IP 주소로 여러 서비스를 노출하는 인그레스 리소스 만들기

노드포트

노드포트 타입 서비스를 만들면, k8s는 모든 노드에 특정 포트를 할당하고 서비스를 구성하는 파드로 들어오는 요청을 전달한다.

로드밸런서

로드밸런서 타입 서비스를 만들면, 일번적으로 클라우드 인프라에서 로드밸런서를 자동으로 프로비저닝하는 기능을 제공한다. 쿠버네티스가 로드밸런서 서비스를 지원하지 않는 환경에서 실행중인 경우 노드포트 서비스처럼 작동한다.

서비스를 생성하고 클라우드 인프라가 로드밸런서를 생성하고 IP주소를 서비스 오브젝트에 쓰면, 로드밸런서 IP주소가 서비스의 external IP 주소로 표시돤다.

외부 연결 특성의 이해

불필요한 홉

외부에서 노드포트로 서비스에 접속하는 경우, 서비스가 임의로 선택한 파드가 동일 노드일 수도 있고, 아닐수도 있다. 파드에 도달하려면 추가 네트워크 홉이 필요한 경우가 생길 수 있다.

외부 연결을 수신한 노드에서 실행중인 파드로만 외부 트래픽을 전달하도록 서비스를 구성할 수 있다. 서비의 스펙에 externalTrafficPolicy 필드를 설정하면 된다.

spec:
    externalTrafficPolicy: Local

하지만 로컬에 파드가 없으면 연결이 중단되어버린다. (Kubernetes 1.15 이상: 패킷이 다른 노드에 있는 구성원 pod로 전달)

클라이언트 IP가 보존되지 않음

클러스터 내 클라이언트가 서비스로 연결 할 때, 서비스의 파드는 클라이언트의 IP주소를 얻을 수 있다.

하지만 노드포트로 연결을 수신하면 패킷에서 소스 네트워크 주소 변환(source network address translation)이 수행되어 소스 IP가 변경된다.

예를들어 엑세스 로그에 브라우저 IP를 남길 수 없는 문제가 생길 수 있다.

하지만 externalTrafficPolicy를 설정 한 경우, 노드 사이에 추가 홉이 없기 때문에 SNAT이 수행되지 않는다.

인그레스

필요성

로드밸런서 서비스는 공용 IP주소를 가진 로드밸런서가 필요하지만, 인그레스는 한 IP주소로 수십개의 서비스에 접근이 가능하도록 지원해준다.

클라이언트가 http 요청을 인그레스에 보낼 때, 요청한 호스트와 경로에 따라 요청을 전달할 서비스를 결정한다.

인그레스는 L7에서 동작하며, 쿠키 기반 세션 어피니티 등과 같은 기능을 제공 할 수 있다.

레디니스 프로브(Readiness Probe)

주기적으로 호출되며 특정 파드가 클라이언트의 요청을 수신 할 수 있는 상태인지 결정한다.

Exec Probe

프로세스를 실행시켜 종료 상태 코드로 결정한다.

Http Get Probe

http get 요청을 보내 http 응답 상태 코드를 보고 준비 여부를 결정한다.

TCP Socket Probe

지정된 포트로 TCP 연결을 수행하여 소켓이 연결되면 준비된것으로 간주한다.

레디니스 프로브 동작

컨테이너가 시작 될 때 첫번째 점검을 수행하기 전 기다리는 시간을 구성할 수 있다.(initialDelaySeconds)

그 다음 주기적으로 레디니스 프로브를 수행한다. 파드가 준비 상태가 되지 않으면 서비스의 엔드포인트에서 제거된다. 준비되면 다시 서비스에 추가된다.

Liveness Probe와 다르게 준비 상태가 아니더라도 컨테이너가 재시작 되지 않는다.

레디니스 프로브 중요성

만약 프론트엔드 파드중 하나에 연결 문제가 발생해 더 이상 DB에 연결 할 수 없는 경우, 레디니스 프로브를 통해 쿠버네티스에 알려야 한다.

레디니스 프로브를 항상 정의해야 하는 이유

파드에 레디니스 프로브를 추가하지 않으면, 파드가 시작하는 즉시 서비스의 엔드포인트가 된다.

애플리케이션을 시작하는데 오래 걸리는 경우, 준비가 되지 않은 파드로 요청이 전달되어 "Connection refused"와 같은 에러를 보게 된다.

레디니스 프로브에 파드의 종료 코드를 포함하지 말아야 한다

쿠버네티스는 파드를 삭제하자마자 모든 서비스에서 파드를 제거하기 때문에, 레디니스 프로브에 파드의 종료 코드를 포함할 필요가 없다.

헤드리스 서비스

쿠버네티스가 서비스에 대한 DNS 조회를 수행하면 DNS 서버는 서비스의 클러스터 IP를 반환한다.

하지만 서비스 스펙에서 clusterIP 필드를 None으로 설정하면 서비스 IP 대신 파드 IP들을 반환한다.

이를 이용해 클라이언트는 하나 이상의 파드에 연결 할 수 있다.

이는 READY 상태가 된 파드만 보여주며 준비되지 않은 파드도 포함하려는 경우 서비스에 다음과같이 어노테이션을 추가해야 한다.

kind: Service
metadata:
    annotations:
        publishNotReadyAddresses: "true"

서비스 트러블슈팅

  • 외부가 아닌 클러스터 내에서 서비스 클러스터 IP에 연결되는지 확인한다.
  • 서비스에 액세스 할 수 있는지 확인할 때, 클러스터 IP에 핑을 때리는건 의미없다.(서비스의 클러스터 IP는 가상 IP임으로 핑에 응답하지 않음.)
  • Readiness Probe를 정의했다면 확인한다. publishNotReadyAddresses 어노테이션이 없다면 준비되지 않은 파드는 서비스에 포함되지 않는다.
  • 파드가 서비스에 포함되어있는지 확인하려면 'kubectl get endpoints'를 조회해 확인한다.
  • FQDN이나 그 일부로 서비스에 접근하는 경우, FQDN 대신 클러스터 IP로 접근해본다.
  • 대상 포트(target port)가 아닌 서비스의 포트로 연결되는지 확인한다.
  • 파드 IP에 직접 연결해 파드가 올바른 포트에 연결되어 있는지 확인한다.
  • 파드 IP로 접근할 수 없는 경우, 애플리케이션이 localhost에만 바인딩하는지 확인한다.
728x90
반응형

POD을 안정적으로 유지하기

컨테이너에 주 프로세스에 크래시가 발생하면 kubelet이 컨테이너를 재시작한다.

하지만 크래시 없이 애플리케이션이 중단되는 경우(ex. 자바 애플리케이션의 메모리누수로 OutofMemorysErrors가 발생해도 JVM 프로세스는 중단되지 않는다.)에, 쿠버네티스에 신호를 보내 애플리케이션을 재시작하도록 하는 방법이 있어야 한다.

Liveness Probe

각 컨테이너가 정상인지 확인한다. 프로브가 실패하는 경우, 컨테이너를 재시작한다.

spec에 지정 할 수 있다.

  • HTTP Get

    지정한 IP주소, 포트, 경로에 HTTP Get 요청을 수행한다.

    응답 코드가 4xx, 5xx와 같은 오류가 아니라 2xx, 3xx인 경우 성공.

    http 오류 코드 혹은 응답이 없는경우 실패.

  • Socket

    지정된 포트에 TCP 연결을 시도한다. 연결의 성공여부가 프로브의 성공여부.

  • Exec

    컨테이너 내의 임의의 명령을 실행하고 종료 코드를 확인한다.

    상태코드가 0이면 성공, 다른 모든 코드는 실패.

*크래시된 컨테이너의 로그 얻기

컨테이너가 재시작되면 kubectl logs 명령은 현재 컨테이너의 로그를 표시한다.

이전 컨테이너의 로그를 얻고 싶다면 --previous 옵션을 사용한다.

$ kubectl logs [POD] --previous

Liveness Probe 추가설정

delay

컨테이너가 시작된 후 일정시간 뒤에 liveness probe 실행 (ex. delay=0s)

timeout

컨테이너가 응답해야 하는 제한시간. 제한시간 내 응답 못할시 실패. (ex. timeout=1s)

period

liveness probe 실행주기. (ex. period=10s)

failure

몇 번 연속 실패하면 컨테이너가 다시 시작되는지에 대한 값. (ex. failure=3)

728x90
반응형

+ Recent posts