기록

[MSA] 10. OS, 회복성 패턴, Kubernates 설정 본문

Bootcamp/MSA

[MSA] 10. OS, 회복성 패턴, Kubernates 설정

서기A 2023. 10. 23. 10:37

엔코아 플레이데이터(Encore Playdata) Backend 2기 백엔드 개발 부트캠프 (playdata.io)

 

백엔드 개발 부트캠프

백엔드 기초부터 배포까지! 매력있는 백엔드 개발자 포트폴리오를 완성하여 취업하세요.

playdata.io


1. Eureka Server 기동

# docker/docker-compose.yml
DB 연동을 위해 맨위에 \c ostock_dev 추가

DB 연동을 위해 설정 변경

# mvn & mvnw 복사해오기
cp -R ./configserver/.mvn/ ./.mvn
cp -R ./configserver/mvnw ./mvnw

.mvn 및 mvnw 복사해오기

# 복사해온 mvn & mvnw를 통해 한번에 패키지 빌드
./mvnw package dockerfile:build

jar build + docker image build

# build 한 image들을 docker-compose를 통해 실행
docker-compose up -d

docker-compose를 백그라운드로 실행

# Eureka 서버를 띄운 후 접속여부 확인

Eureka Server

# api 호출 test
http://localhost:8081/v1/organization/e839ee96-28de-4f67-bb79-870ca89743a0

api 호출 결과


2.  프로세스 제어 블록 (PCB)

운영체제는 모든 프로그램을 동시에 실행하지 못하고 순서대로 돌아가며 cpu를 사용한다.

이때, 프로세스는 자신의 차례가 되면 정해진 시간만큼만 cpu를 사용 후 시간이 끝났음을 알리는 인터럽트를 사용하여 프로세스의 종료를 알린다.

 

즉, 운영체제는 빠르게 번갈아 수행되는 프로세스의 실행순서를 관리하고 프로세스에 cpu를 비롯한 자원을 배분하기 위해 PCB를 이용한다.

# PCB 구성요소

1. 프로세스 ID (PID)
프로세스를 식별하기 위한 고유번호

2. 레지스터 값
이전에 했던 레지스터의 중간값들을 모두 복원

3. 프로세스 상태
현재 프로세스가 어떤 상태인지 pcb에 기록

4. cpu 스케줄링 정보
프로세스가 언제, 어떤 순서로 cpu를 할당받을지에 대한 정보도 pcb에 저장

5. 메모리 관리 정보
프로세스마다 메모리에 저장 된 위치가 다르기때문에, 프로세스가 어느 주소에 저장되어있는지에 대한 정보가 들어있다.

6. 사용한 파일과 입출력장치 목록
실행과정에서 특정 입출력장치나 파일을 사용하면 pcb에 해당 내용이 명시된다.

3. 문맥 교환 (Context Switch)

프로그램을 실행하면 PCB가 만들어지고, CPU는 PCB를 바탕으로 프로세스를 차례차례 수행한다.

이때, 하나의 프로세스 수행을 재개하기 위해 기억해야할 정보를 context라고 하는데, 이 context는 해당 프로세스의 PCB에 표현되어있다.

 

문맥교환이란, 기존 프로세스의 context를 PCB에 백업, 새로운 프로세스를 실행하기 위한 context를 PCB로 부터 복구하여 프로세스를 실행하는 것을 의미한다.

이 작업은 굉장히 빠르게 일어나기 때문에 사람은 감지하기 힘들다. ex) 유튜브 보면서 카톡


4. 프로세스의 메모리 영역

메모리의 영역은 대표적으로 4가지로 나뉘어있다.

 

1. 코드영역

실행할 수 있는 코드, 즉 기계어로 이루어진 명령어가 저장된다.

코드영역에는 데이터가 아닌 cpu가 실행할 명령어가 담겨있기 때문에 쓰기 금지이다. (변경 불가)

 

2. 데이터 영역

프로그램이 실행되는 동안 유지할 데이터가 저장 될 공간이다.

전역변수라고도 하고, 때문에 정적 할당 영역이라 부른다.

 

3. 힙 영역

Heap Segment는 프로그램을 만드는 사용자, 즉 개발자가 직접 할당할 수 있는 저장 공간이다.

이때 사용 완료한 메모리 공간을 반환하지 않으면 할당한 공간은 계속 남아 메모리 낭비를 초래하는데, 이러한 문제를 memory leak 이라고 한다.

 

4. 스택영역

데이터를 일시적으로 저장하는 공간으로, 데이터 영역에 담기는 값과는 달리 잠깐 쓰다가 없앨 값들을 저장한다.

메서드의 실행이 끝나면 사라지는 매개변수나 지역변수 등이 저장되고, 스택영역은 동적 할당영역이다.


5. 클라이언트 회복성 패턴

대부분 분산 시스템은 실패를 겪는다. 이러한 실패에 대응하는 어플리케이션을 구축하는 방법은 모든 개발자의 업무에서 가장 중요한 부분이다.

회복성 (resilience)을 갖춘 시스템을 구축할 때 소프트웨어 엔지니어 대부분은 infra structure나 중요 서비스의 한 부분이 완전히 실패한 부분만 고려한다.

 

1. 클라이언트 측 로드밸런싱

클라이언트 측 로드 밸런싱은 클라이언트가 서비스 디스커버리 에이전트(유레카같은)에서 서비스의 모든 인스턴스를 검색한 후, 해당 서비스 인스턴스의 물리적 위치를 캐싱하는 작업을 포함한다.

 

즉, 클라이언트 측 로드 밸런서는 서비스 클라이언트와 사용자 사이에 위치하기 때문에 서비스 인스턴스가 에러를 발생하거나 정상적으로 동작하지 않는지 탐지할 수 있다.

이때 클라이언트 측 로드 밸런서가 문제를 탐지하면, 가용 서비스 풀에서 문제된 서비스 인스턴스를 제거하여 해당 서비스 인스턴스로 더 이상 호출되지 않게 한다.

 

2. Circuit Breaker

서킷 브레이커는 API가 호출 될 때 응답이 너무 오래걸리거나 장애가 발생했을 때, 호출을 종료시킨다.

 

3. Fallback Pattern

fallback pattern을 사용하면 원격 서비스 호출이 실패할 때 예외를 생성하지 않고, 대체 코드를 실행한다.

이 때 다른 수단을 통해 작업을 수행할 수 있으면, 향후 처리를 위해 사용자 요청을 Queue에 입력하는 작업이 포함된다.
이를 통해, 사용자 호출에 문제가 있다고 예외를 표시하지는 않지만 나중에 요청을 재시도해야 한다고 알려 줄 수 있다.

 

4. Bulkhead 

스레드 풀은 서비스의 벌크헤드 역할을 한다. 각 원격 자원을 분리해 스레드 풀에 각각 할당하여,

한 서비스에 장애가 생긴다고 해도  해당 서비스의 호출 그룹에 대한 스레드 풀만 포화되어 (느려져) 요청 처리를 중단하고, 다른 서비스는 정상적으로 동작한다.

즉, 스레드 풀별로 서비스를 할당하면 다른 서비스는 포화되지 않기 때문에 병목 현상을 우회하는데 유용하다.

# Thread Pool
작업 처리에 사용되는 스레드를 제한된 개수만큼 지정한 후
Queue에 들어오는 작업들을 하나씩 thread 가 맡아 처리하는 것을 의미한다.

즉, 작업 처리 요청이 급증하더라도 스레드의 전체 개수는 늘어나지 않기 때문에 
시스템 성능이 급격히 저하되지 않는다.

# Thread Pool 단점
pool에 thread를 할당해놓는 것이기 때문에 thread를 사용하지 않더라도 자원을 할당해놓는다.
즉, 내 컴퓨터의 자원이 낭비될 수 있다.

 

5. 회복성 패턴이 중요한 이유

Api 요청을 날렸을 때 요청을 받은 곳에서 thread를 할당해놓는데, 만약 응답 처리가 이루어지지 않고 계속 요청만 날아갈 경우 이전 thread 요청을 다 해결하지 못한 상태에서 실행 대기 상태의 thread만 쌓이게 된다.

때문에 이를 해결하기 위해 Circuit Breaker가 동작해 서비스 자체를 끊어 자원을 가지지 못하게 한다.

1. 정상 시나리오
Circuit breaker가 타이머를 설정하고, 타이머가 만료되기 전에 원격 호출이 완료된다면
실행중인 서비스는 정상적으로 모든 작업을 수행할 수 있다.

2. 부분적 서비스 저하 시나리오
1번 서비스에서 circuit breaker를 통해 2번 서비스를 호출할 때,
2번 서비스가 느리게 실행되어 circuit breaker가 관리하는 thread 타이머가 만료되기 전에 호출이 완료되지 않으면
circuit breacker는 원격 서비스에 대한 연결을 종료하고 1번 서비스에 오류를 반환한다.

즉, 1번 서비스는 2번서비스 호출이 완료되길 기다리기 위해 자원을 점유하지 않는다.
(자원 : 자체 스레드 및 커넥션 풀)
2번 서비스에 대한 호출 시간이 만료되면 circuit breaker는 실패 회수를 추적하기 시작하는데,
특정 시간동안 해당 서비스에서 오류가 필요 이상으로 발생하면 circuit breaker는 회로를 차단하고
2번 서비스에 대한 모든 호출은 요청한 api 결과 없이 실패가 된다.

3. 즉시 문제 인식
1번 서비스는 circuit breaker의 타임아웃을 기다릴 필요 없이 문제가 생긴 것을 즉시 알 수 있다.
이 후 완전히 실패 처리를 하거나 대체 코드를 사용해 조치하는 것 중 선택할 수있다.
circuit breaker가 차단 되면 1번 서비스가 2번 서비스를 호출하지 않았기 때문에
2번 서비스는 자신을 회복할 수 있는 기회가 생긴다.

즉, 2번 서비스 관점에서 보면 여유 시간이 생기므로 서비스 저하가 발생했을 때 연쇄 장애를 방지할 수 있다.

6. 쿠버네티스 설정

# worker가 master node를 바라보게 설정
ssh w1-k8s

w1-k8s 접근

# ssh w1-k8s
# ssh w2-k8s
# worker node로 접근해 network 연결
sudo kubeadm join --token 123456.1234567890123456  --discovery-token-unsafe-skip-ca-verification 192.168.56.10:6443

네트워크 연결
w2-k8s 접근 후 네트워크 연결

# master에서 노드 확인
kubectl get nodes

연결 된 노드들 확인

# nginx 이미지를 통해 파드 생성
kubectl run nginx-pod --image=nginx

파드 생성

# 파드 확인
kubectl get pods -o wide

파드가 Ready 상태인 것 확인

# curl을 통해 ip로 접속
curl 172.16.103.129

파드가 준비되었다면, 접속해서 확인


7. 57일차 후기

OS에 대한 간략한 설명과, MSA의 구성에 반드시 필요한 회복성 패턴 및 쿠버네티스 추가 설정을 진행하였다.

운영체제에 관한 내용을 알고 있다면, 우리가 사용하는 컴퓨터의 내부에서 어떻게 돌아가는지 이해하는데 많은 도움이 될 수 있다. 또한, 면접과 같은데서도 종종 나오는 질문이기 때문에 틈틈히 공부해두면 좋을 것 같다는 생각이 들었다.

 

회복성 패턴의 경우, MSA는 기본적으로 API 호출로 구성이 되는데, 때문에 외부 API 요청 시 장애가 발생하는 경우를 대비해 반드시 필요하다. 기존 모놀리식 구성일 때는 한 프로젝트 내에서 모든 호출이 이루어졌기 때문에 해당 부분에 대처하기 비교적 용이했지만, MSA의 경우 외부와 연동해야하기 때문에 해당 부분이 조금 더 복잡하다 볼 수있다.

'Bootcamp > MSA' 카테고리의 다른 글

[MSA] 12. Kubernates 구조, AWS EC2  (0) 2023.10.25
[MSA] 11. Kubernates Pod  (0) 2023.10.24
[MSA] 9. centOS, Kubernates 설치  (0) 2023.10.20
[MSA] 8. Config Server, Eureka Server  (0) 2023.10.19
[MSA] 7. Docker 활용, ConfigServer  (0) 2023.10.13