가용성 설계
가용성 설계
고가용성을 위한 아키텍처 고려 사항
고가용성 아키텍처를 구현하기 위해서는 클라우드 서비스를 활용한 인프라 수준의 고가용성 설계 및 구축뿐만 아니라, Application 자체도 고가용성을 지원할 수 있도록 구성되어야 합니다.
서버, 네트워크 등 하부 인프라를 고가용성으로 구성하더라도, 단일 장비에 장애가 발생했을 때 서비스 중단을 방지하려면, Application 수준에서도 장애를 감지하고 대응할 수 있는 구조를 갖추고 있어야 합니다.
이는 수요 급증 시 Auto-Scaling을 통해 처리량을 늘리려는 경우에도 마찬가지입니다.
Application이 확장에 유연하게 대응할 수 있도록 설계되어야 안정적인 서비스 확장을 기대할 수 있습니다.
단순한 Application 구성
단순한 Application은 예측하지 못한 장애를 줄이고 안정적인 운영을 가능하게 합니다.
반면, Application에 많은 기능이 모여 복잡도가 높아지면, 구성상의 오류나 예측하지 못한 상호작용이 발생할 가능성이 커지고, 그에 따른 비효율성도 증가합니다.
단순한 구조는 제어해야 할 영역을 줄여 운영상의 오버헤드를 최소화 합니다.
이는 복원력(resilience), 재사용성(reusability), 확장성(scalability), 관리 용이성(manageability) 등을 갖춘 워크로드 아키텍처를 구축하는 데 도움이 됩니다.
이러한 이유로, 워크로드마다 가용성, 확장성, 데이터 일관성, 재해 복구 등 다양한 비즈니스 요구사항이 존재하며, 이는 아키텍처 설계의 핵심 기준이 됩니다.
예를 들어, Application에 수만 명의 사용자가 동시에 접속하는지, 트래픽이 일정한지 혹은 특정 시점에 급증하는지, 서비스 중단이 허용 가능한지와 그 허용 수준은 아키텍처 설계 시 중요한 고려 요소입니다.
워크로드를 처리하기 위해 Application을 복잡하게 구성하면, 더 많은 기능과 유연성을 제공할 수 있습니다.
그러나 그만큼 구성 요소 간의 조정과 통신 관리에 더 많은 투자가 필요하며, 이는 오히려 가용성에 부정적인 영향을 줄 수 있습니다.
따라서, 고가용성이 워크로드의 필수 요건이라면, 가능한 한 복잡성을 줄이고 관리 지점을 최소화하는 것이 바람직합니다.
- 비즈니스 요구 사항에 필수적인 최소한의 구성 요소를 아키텍처에 추가합니다.
- PaaS(Platform as a Service)를 활용하여 클라우드 환경에 최적화된 Application을 구성합니다.
- Serverless Computing을 이용하여 최소한의 코드로 단순 반복 연산을 처리합니다.
고가용성을 확보하기 위해서는 최소한의 필수 구성 요소만으로 Application을 구현하여 관리 지점을 줄이고, 확장성과 반복 가능성을 강화하는 것이 중요합니다.
또한, IaaS 기반의 코드보다는 PaaS를 활용하는 것이 바람직한데, 이는 인프라 관리 부담과 고가용성 구성에 대한 복잡성을 줄일 수 있기 때문입니다.
아래 그림의 아키텍처는 API Gateway와 Cloud Functions를 활용하여 모바일 사진 관리 서비스를 Serverless Computing으로 구현한 사례입니다.
Authentication, Search, Register, Thumbnail, Delete 기능을 각각 Cloud Functions의 독립된 함수로 분리하여 구현하였습니다.
사용자가 모바일 앱에서 작업을 수행하면, API Gateway를 통해 해당 요청이 함수로 전달되어 처리됩니다.
이 아키텍처에서는 모든 기능이 독립적으로 작동하기 때문에, 하나의 기능을 수정하더라도 다른 기능에 영향을 주지 않습니다.
이처럼 기능을 분리하여 단순성을 확보한 후에는, 서비스 모니터링을 통해 서비스 가시성(Service Observability)을 확보하는 것이 중요합니다.
Cloud Functions에서는 이를 위해 호출 수, 실행 시간, 현재 작업 수, 성공/실패 호출 수, 메모리 사용량 등에 대한 모니터링 기능을 제공하며, 함수 실행 로그도 확인할 수 있습니다.
Application 결합 해제 및 종속성 관리
고가용성 Application을 구현하기 위해서는 구성 요소의 종속성(Dependency)을 잘 관리해야 합니다.
구성 요소의 종속성을 관리한다는 것은, 각 구성 요소가 독립적으로 작동하는지, 혹은 다른 요소와 종속 관계를 맺고 있는지를 파악하고, 종속된 요소의 가용성을 면밀히 검토하는 것을 의미합니다.
궁극적으로 고가용성 구현의 핵심은 단일 구성 요소의 장애가 전체 서비스의 중단으로 이어지지 않도록 설계하고 관리하는 데 있습니다.
따라서, 종속적으로 연결된 구성 요소 중 가용성이 가장 낮은 요소에 대한 관리 방안이 고가용성 설계 및 운영에서 최우선적으로 고려되어야 합니다.
결과적으로, 한 서비스의 가용성은 종속된 구성 요소 중 가장 가용성이 낮은 요소의 수준을 초과할 수 없습니다.
- 전체 종속성의 목록을 유지 관리합니다.
- 중요한 종속성 항목을 최소화하여 한 구성 요소의 장애가 전체 시스템에 영향을 미치는 가능성을 줄입니다.
- 중요한 종속성은 중복하여 구성합니다.
- Load Balancer나 비동기 메시징을 사용하여 요청과 응답을 결합 해제(decoupling)합니다.
아래 그림은 Load Balancer를 이용하여 웹과 Application 계층의 종속성을 해제한 아키텍처의 예시입니다.
웹 서버와 Application 서버를 직접 연결할 경우, 구성 요소 간의 종속성이 높아져 Auto-Scaling과 같은 확장성 구현이 어려워질 수 있습니다.
이에 따라 중간에 Load Balancer를 배치함으로써 웹과 Application 간의 종속성을 줄이고, 전체 시스템의 확장성을 향상시켰습니다.
웹 계층과 Application 계층 사이에 Load Balancer가 존재하지 않는 경우, 웹 계층은 Application 계층의 서버 IP 주소를 직접 지정하여 요청을 전달해야 합니다.
이러한 방식은 서버 간의 강한 결합을 초래하며, Application 계층의 서버 중 하나가 중단될 경우 해당 서버로 향하는 요청은 처리되지 못하고 유실될 수밖에 없습니다.
이는 일부 사용자에게 서비스 장애로 인식될 수 있으며, 전체 시스템의 안정성을 저하시킵니다.
반면, Load Balancer를 웹 계층과 Application 계층 사이에 배치하면, 클라이언트 요청을 처리할 단일 진입점을 제공함으로써 서버 IP를 하드코딩하지 않고도 요청을 유연하게 전달할 수 있습니다.
특히 Application 계층에 Auto-Scaling 기능을 적용한 경우, 동적으로 생성되거나 삭제되는 서버 인스턴스에도 자동으로 요청을 분산시킬 수 있어, 시스템의 확장성과 탄력성을 확보할 수 있습니다.
이처럼 Load Balancer는 동기(Synchronous) 통신 기반의 실시간 요청 처리에 적합하며, 동일한 기능을 수행하는 여러 서버 간의 트래픽을 분산하여 고가용성을 확보하는 데 기여합니다.
예를 들어, Web 서버 그룹과 App 서버 그룹의 앞에 Load Balancer를 배치해서 그룹 내 서버에 트래픽을 분산하는 데 효과적으로 활용할 수 있습니다.
하지만 서비스 간의 결합 해제(Decoupling)를 보다 강력하게 구현하고자 할 경우, Message Queue Service를 사용하는 방식이 더욱 적합합니다.
아래 그림은 Message Queue를 활용하여 두 Application 간의 강한 결합을 느슨한 결합 구조로 전환한 아키텍처를 보여줍니다.
Message Queue Service는 서로 다른 기능을 수행하는 여러 서버 간의 비동기(Asynchronous) 통신을 가능하게 합니다.
이때, 생산자(Producer)와 소비자(Consumer)의 처리 속도나 용량은 반드시 일치할 필요가 없습니다.
이로 인해 각 서비스는 독립적으로 동작할 수 있으며, 일시적인 장애나 지연이 발생하더라도 전체 시스템에 영향을 주지 않습니다.
또한 메시지는 큐에 안전하게 저장되므로, 소비자가 준비되었을 때 이를 처리할 수 있으며, 결과적으로 복원력 있는 시스템 구조를 구현할 수 있습니다.
상태 비저장(Stateless) Application 개발
상태(State)란 클라이언트의 요청에 대한 응답을 처리하는 데 영향을 미치는 서비스 내부 정보를 의미합니다.
좀 더 정확히 말하면, 상태를 구성하는 변수나 자료 구조의 값들은 해당 서비스가 처리한 요청의 이력에 의존합니다.
상태 저장(Stateful) Application은 작업 수행을 위해 로컬에 캐시된 데이터와 같은 다양한 종속 항목을 사용합니다.
그 결과, 이러한 캐시 데이터와 종속 항목은 모두 메모리에 적재되며, 서버 자원의 사용률을 증가시킵니다.
그런데, 요청의 증가 속도가 서버의 처리 속도보다 높아지면 서버는 점차 느려지고, 결국 작동을 멈출 수도 있습니다.
이를 해결하기 위해 Auto-Scaling으로 새로운 서버를 추가할 수 있습니다.
하지만 기존 서버에 이미 요청 작업이 누적되어 있다면, 신규 서버를 추가했더라도 기대한 만큼의 성능 향상을 가져오지 않을 수 있습니다.
- Application을 상태 비저장(Stateless)으로 구현합니다.
- 서비스 외부에 상태 관리 데이터베이스(State Management Database)를 구현합니다.
상태 비저장(Stateless) Application은 로컬에 정보를 저장하지 않고 외부의 상태 관리 데이터베이스(State Management Database)에 저장하여 작업을 처리합니다.
사용자 요청이 들어오면 먼저 상태 관리 데이터베이스에 해당 요청을 저장하고, CPU에서 요청을 처리할 때는 상태 관리 데이터베이스에서 요청을 읽어와서 처리합니다.
이러한 구조에서 서버는 상태를 저장하지 않고, 요청을 처리하는 데에만 가동됩니다.
새로운 서버가 서버 풀에 추가되면 바로 상태 관리 데이터베이스에서 요청을 읽어 처리할 수 있습니다.
이 방식은 작업 부하를 전체 서버에 빠르게 분산시켜, 고가용성과 확장성을 효과적으로 구현할 수 있게 합니다.
상태 관리 데이터베이스로는 주로 빠른 읽기/쓰기가 가능한 NoSQL을 사용합니다. 특히 높은 성능이 요구되는 Application의 경우에는 CacheStore(DBaaS) 사용을 권장합니다.
고가용성을 위한 클라우드 아키텍처 설계
확장 및 가용성을 위한 네트워크 설계
- 장애 발생을 고려한 네트워크 설계
사용자가 서비스에 안정적으로 접속하려면, 서버가 안정적으로 작동하는 것뿐만 아니라, 서버까지 연결되는 네트워크 또한 안정적으로 운영되어야 합니다.
서비스 경로 중 일부 네트워크 구간에 장애가 발생하더라도 서비스가 중단되지 않도록 내재적으로 이중화를 지원하는 서비스를 선택하거나 직접 네트워크 연결을 이중화하여 장애에 대비해야 합니다.
- 수요 증가를 고려한 네트워크 설계
모든 클라우드의 서비스에는 사용자가 구성할 수 있는 자원에 일정한 제한이 존재합니다.
예를 들어, Samsung Cloud Platform에서는 하나의 Account당 최대 5개의 VPC를 생성할 수 있으며, 각 VPC에는 최대 3개의 서브넷을 구성할 수 있습니다.
이러한 제한 사항을 충분히 검토하여 향후 수요 증가에 따른 자원 확장 시 용량 제한이 장애 요소가 되지 않도록 해야 합니다.
따라서, 초기 네트워크 설계 단계에서 시스템을 어떤 범위(Account, VPC, 서브넷 등)로 배치할지 신중히 검토해야 합니다.
서비스의 지리적 범위가 넓다면 Global CDN을 고려해야 합니다.
서비스의 사용자가 넓은 지리적 위치에 분포해 있을 경우, 향상된 사용자 경험을 제공하기 위해 Global CDN을 구성하여 콘텐츠 전송의 지연 시간을 단축할 필요가 있습니다.
- 다른 정보시스템 및 네트워크와의 연결을 고려한 네트워크 설계
다른 네트워크의 정보시스템과 연결할 때는 퍼블릭 네트워크를 경유할지 프라이빗 네트워크를 통해 보호된 연결을 구성할지 신중히 검토해야 합니다.
프라이빗 네트워크로 연결하여 전송을 보호하려는 경우, 양쪽 네트워크에서 사용하는 프라이빗 IP 주소 범위가 중첩되지 않도록 주의해야 합니다.
새로 구성하는 시스템의 프라이빗 IP 주소를 설정할 때는 기존 네트워크의 IP 범위를 확인한 후 중첩되지 않도록 주소 범위를 설계해야 합니다.
또한 프라이빗 연결을 구성할 지점의 수에 따라 네트워크 토폴로지를 고려해야 합니다.
프라이빗 연결은 연결 지점이 늘어날수록 비용이 증가하며, 네트워크 제어 정책과 라우팅의 복잡성도 함께 증가합니다.
따라서 이러한 복잡성을 줄이기 위해서는 허브 앤 스포크(Hub-and-Spoke) 방식의 중앙 집중형 연결 구조를 구성하는 것이 바람직합니다.
- 장애 발생에 대비하여 이중화된 네트워크 연결을 구성하거나 고가용성을 지원하는 네트워크를 선택합니다.
- 클라우드 서비스의 제한 용량을 고려하여 현재와 향후 정보시스템에 적합한 네트워크를 설계합니다.
- 다른 정보시스템과 연결할 경우 IP 주소 범위가 중첩되지 않도록 설계하고, 가급적 허브 앤 스포크 토폴로지를 구성합니다.
다중 VPC를 구성하고 있는 조직의 경우 전체 네트워크 아키텍처를 설계하기 위해서 VPC 수준에서 IP 주소 계획을 수립해야 합니다.
위 그림은 여러 VPC로 구성된 Samsung Cloud Platform 상의 네트워크를 나타내고 있습니다.
왼쪽과 오른쪽 모두 VPC 3개가 Samsung Cloud Platform 상에 구성되어 있고, 두 경우 모두 VPC 간에 프라이빗 통신할 수 있도록 연결 구성되어 있습니다.
왼쪽은 VPC Peering을 이용하여 VPC 연결을 구성하였습니다.
VPC Peering은 1:1 연결을 지원하므로, 모든 VPC를 연결하기 위해서는 3개의 연결 수립이 필요합니다.
반면, Transit Gateway는 여러 VPC를 단일 구성으로 관리할 수 있게 합니다.
3개의 VPC를 하나의 Transit Gateway로 연결하고, 3개 VPC 간의 라우팅을 설정합니다.
오른쪽의 Transit Gateway는 네트워크 연결을 중앙화함으로써 연결을 단순화하고 손쉽게 연결을 관리할 수 있게 합니다.
관리형 서비스 사용
관리형 서비스(Managed Service)는 클라우드 사업자가 운영을 관리하는 인프라의 기반 위에서 제공되는 서비스입니다.
클라우드 사업자가 관리하는 영역은 기반 서버 운영체제 및 보안, 스토리지, 네트워크 등입니다.
사용자는 기반 인프라의 설치 및 운영에 대한 부담없이 서비스가 제공하는 Application 기능에만 집중할 수 있습니다.
클라우드 사업자가 관리하기 때문에 안정적으로 서비스를 제공할 수 있으며, 고가용성을 위한 설계와 운영이 구현되어 있습니다.
따라서 관리형 서비스를 사용하면 사용자는 해당 구성 요소에 대한 고가용성 설계 및 운영 부담을 줄일 수 있게 됩니다.
Serverless Computing인 Cloud Functions는 관리형 서비스의 대표적인 예로, 단순 반복적인 업무를 처리할 때 Virtual Server 대신 활용하면, 고가용성을 효과적으로 구현할 수 있습니다.
이를 통해 사용자는 별도의 설계, 관리 부담 없이 장애 발생 가능성을 최소화하고 수요 증가에 탄력적으로 대응할 수 있습니다.
데이터베이스의 경우에는 MySQL의 고가용성을 위해서 두 대 이상의 서버를 생성하고 운영체제의 기본 패치를 수행하고 있다고 가정합니다.
각 서버에 MySQL을 설치한 후 InnoDB Cluster로 HA(High Availability) 또는 Replica를 구성합니다.
이 과정에서는 서버 간 네트워크 구성, 데이터 보호를 위한 보안 설정, 백업 구성 등 다양한 작업을 별도로 수행해야 하며, 이는 모두 구현 단계에 해당합니다.
이후에도 운영 단계에서는 지속적인 관리 작업이 필요합니다.
만약 관리형 서비스인 MySQL(DBaaS)를 사용할 경우, 이러한 과정을 상당히 단순화할 수 있습니다.
데이터베이스를 구성할 때 옵션 설정만으로 고가용성 구성을 자동화으로 수행할 수 있으며, 운영 측면에서도 높은 유연성과 효율성을 확보할 수 있습니다.
- 단순 반복적인 작업은 Cloud Functions를 활용하여 Serverless Computing을 구현합니다.
- Database 서비스를 사용하여 고가용성을 구현합니다.
Microservice 아키텍처 구현
Monolithic Architecture와 Microservice Architecture
모놀리식 Application은 여러 모듈이 단일 프로그램으로 결합된 단일 계층 소프트웨어 Application을 말합니다.
아래의 그림은 전자 상거래 Application의 아키텍처 예시입니다.
위 그림에서 Application에는 고객, 상품, 주문 등 다양한 모듈이 하나로 통합되어 있으며, 데이터베이스 역시 회원DB, 상품DB, 주문DB 등이 단일 DB 서버에 구성되어 있는 것을 확인할 수 있습니다.
이처럼 모놀리식 Application으로 개발하면 패키징된 Application을 서버에 복사하는 것만으로도 쉽게 Application을 배포할 수 있습니다.
모든 모듈이 CPU, 메모리, 디스크 등의 자원을 공유하므로, 로깅, 캐싱, 보안 등의 기능을 단일 솔루션으로 통합 관리할 수 있는 장점이 있습니다.
또한 같은 서버 내에서 모듈 간 호출이 이루어지므로 성능 측면에서도 유리합니다.
하지만 시간이 지남에 따라 Application이 점점 커지고 복잡해지면, 변경 사항을 관리하기 어려워지고, 배포 또한 초기보다 복잡해지며 운영 부담이 증가하게 됩니다.
특히 하나의 모듈에서 발생한 오류나 변경이 전체 시스템 장애로 이어질 가능성이 높습니다.
이로 인해 관리 및 테스트에 많은 시간과 비용이 소요될 수밖에 없습니다.
반면, Microservice 아키텍처는 자체 아키텍처와 비즈니스 로직을 갖춘 작은 단위의 Application으로 구성되며, 각각 단일 기능 또는 기능 집합을 독립적으로 구현합니다.
모놀리식 아키텍처에서는 각 비즈니스 로직 모듈이 하나의 Application 서버에 모여 있고, 여러 DB가 하나의 데이터베이스 서버에 통합되어 있는 것을 확인할 수 있습니다.
그리고 웹, Application, 데이터베이스는 소켓 통신으로 연결되어 있습니다.
반면 위의 Microservice 아키텍처에서는 비즈니스 로직과 데이터베이스가 각 비즈니스 로직별로 독립적으로 구성되어 있으며, 프론트엔드와는 API를 통해 연결됩니다.
Application을 관리 가능한 여러 단위로 분리하여 개발하면 각 기능의 개발 속도가 빨라지고 전체 구조를 보다 쉽게 관리할 수 있습니다.
기능이 독립적으로 구성되어 있기 때문에, 모든 기능을 동일한 언어로 개발할 필요가 없으며, 다른 기능의 프레임워크(변경)에도 영향을 받지 않습니다.
따라서 각 기능의 코드와 로직을 개별적으로 개선하기 용이합니다.
또한 기능들을 서로 격리하여 운영할 수 있으므로, 다른 기능에서 발생한 장애나 과부하로부터의 영향을 배제 또는 최소화할 수 있습니다.
하지만 각 기능 간에 API를 통해 통신을 해야 하므로, 서비스 간 통신 메커니즘을 별도로 구현해야 합니다.
또한 서비스 흐름이 여러 기능에 걸쳐 수행되고 각 기능에서 데이터베이스 트랜잭션이 발생하기 때문에, 호출 실패나 지연이 발생할 경우 상태 추적이 어려울 수 있습니다.
무엇보다 독립적인 구성요소가 많아질수록, 각 요소를 개별적으로 관리해야 하므로 운영 부담이 증가할 수밖에 없습니다.
Microservice Architecture 적합성 검토
구축하고자 하는 Application에 Microservice 아키텍처 적용 적합성 여부를 판단하려면 다음 사항을 고려해야 합니다.
- 비즈니스 도메인이 여러 개의 독립된 하위 도메인(Sub Domain)으로 나뉠 수 있는가? (도메인 주도 설계(Domain-driven design, DDD)의 핵심원칙 기반)
- 개발/운영 조직이 여러 팀으로 나누어지고 각 팀이 “서비스 단위"를 책임지도록 할 수 있는가? (DevOps) 및 마이크로서비스 아키텍처(MSA) 전략의 핵심 원칙의 일환)
- 부분적인 트래픽 핫스팟(partial traffic hotspots)을 예측하고, 고가용성(high availability, HA)의 전략이 요구되는 안정적인 도메인이 분명히 존재하는가?
- 조직 내 각 서비스(또는 마이크로서비스)는 고유한 변화 속도, 릴리즈 사이클, 요구사항을 가지는가?
- 운영 자동화 체계(CI/CD, 모니터링, 로깅, 트레이싱 등)를 운영 성숙도 향상 및 장애대응 강화 측면에서 적용할 수 있는가?
- 조직과 제품이 장기적으로 성장하고, 도메인 별 독립적인 발전을 추구하는 전략적 목표를 고려하고 있는가?
Microservice Architecture 구현 예시
클라이언트 요청은 Load Balancer를 통해 VM/Container 워크로드 및 API Gateway 서비스로 전달됩니다.
API 요청을 제외한 클라이언트 요청은 Kubernetes Engine에서 제공되는 ingress로 전달되며, Kubernetes Engine은 ingress를 통해 들어온 요청을 매핑된 서비스 Pod로 라우팅합니다.
클라이언트의 API 요청을 처리하기 위해 API Gateway는 최전방에 위치하여 외부로부터 들어오는 모든 API 호출에 대해 인증 및 서비스 라우팅을 수행합니다.
Microservice Architecture는 구조화된 서비스 단위로 분리된 데이터베이스를 구성하고 있습니다.
Microservice 구성 요소 간의 네트워크를 제어하기 위해 Service Mesh 기술을 사용할 수 있으며, 이를 통해 분할된 Application 간의 다양한 네트워크 구성과 데이터 흐름에 대한 관리 및 추적이 가능합니다.
각 서비스에 대해 별도의 데이터 저장소를 구성하게 되면, 해당 서비스의 특성에 가장 적합한 데이터베이스를 선택할 수 있는 유연성이 확보됩니다.
예를 들어, 확장성이 요구되는 웹사이트 트래픽 관리 서비스에는 확장성이 뛰어난 NoSQL을 활용할 수 있으며, 주문 처리 서비스의 경우에는 관계형 데이터베이스(RDBMS)를 사용하여 데이터의 무결성과 트랜잭션의 일관성을 보장할 수 있습니다.
또한, 각 서비스에 대해 별도의 빌드 체계를 구성하면 서비스별로 변경 사항을 보다 쉽게 적용할 수 있으며, 새로운 기능을 신속하게 배포할 수 있는 환경을 마련할 수 있습니다.
이러한 방식은 필요한 코드만 개선함으로써 다른 서비스에 영향을 주지 않고, 개별 서비스의 품질을 빠르게 향상시킬 수 있다는 장점이 있습니다.
서비스 간 통신에는 API를 활용하여 도메인별로 서비스를 관리하고, 요청을 적절하게 라우팅할 수 있습니다.
특히 API Gateway를 도입하면 서비스 규약을 중앙에서 통합적으로 관리하고 배포할 수 있으며, 과도한 요청이 발생할 경우에는 요청을 일정 수준에서 제한(Throttling)하는 기능도 제공받을 수 있습니다.
Kubernetes Engine의 컨테이너 환경에 Application을 구성하면, 더욱 빠른 배포와 유연한 확장이 가능해집니다.
각 컨테이너에는 CPU 및 메모리 사용량에 대한 제한을 설정할 수 있어, 특정 서비스가 과도하게 자원을 사용하는 것을 방지할 수 있습니다.
또한 Kubernetes에서는 Probe 기능을 통해 컨테이너의 정상 작동 여부를 지속적으로 확인하고, 문제가 발생했을 경우 자동으로 재시작하여 오류에 대비할 수 있습니다.
Serverless Computing 환경에서는 Cloud Functions를 활용하여 단순하고 반복적인 작업을 이벤트 기반으로 처리하는 아키텍처를 구성할 수 있습니다.
아울러 Object Storage에 웹 콘텐츠를 저장함으로써, 웹 콘텐츠 요청에 따른 부하를 서버에서 분산시켜 효율적인 자원 관리를 도모할 수 있습니다.
수요에 따라 조정
서비스의 가용성 문제는 단지 구성 요소의 고장으로 인해 서비스가 정지되는 경우에만 발생하는 것이 아닙니다. 예상하지 못한 외부적 요인으로 인해 요청 부하가 증가하면서, 작동하던 서버의 용량이 한계에 달해 서비스가 정지되는 경우 역시 사용성에 영향을 미치는 중요한 요소 중 하나입니다.
온프레미스에서는 이러한 과부하 상황에 대응하기 위해 많은 사전 준비와 철저한 관리가 필요하지만, 클라우드 환경에서는 수요 증감에 민첩하고 유연하게 대응할 수 있는 인프라를 제공하고 있습니다.
- Virtual Server의 Image 관리를 통해 서버 확장/축소를 구현합니다.
- 인프라 자원 용량 관리 부담이 없는/낮은 관리형 서비스를 사용합니다.
Virtual Server는 수요에 따라 서버 타입의 사양을 높여서 수직 확장(Scale-up)할 수 있으며, Image로 생성한 서버를 Load Balancer에 등록해 수평 확장(Scale-out)하거나, 서버를 삭제해 수평 축소(Scale-in)할 수 있습니다.
Auto-Scaling을 사용할 경우 수작업 없이 설정된 정책에 따라 서버의 수를 자동으로 수평 확장하거나 축소할 수 있습니다.
관리형 서비스를 사용하면 클라우드 사업자가 인프라의 확장과 축소를 직접 관리하므로 유연한 아키텍처 설계가 가능합니다.
Cloud Functions와 같은 Serverless Computing은 하부 인프라의 제한 없이 이벤트 기반 컴퓨팅을 구성할 수 있고, Object Storage와 같은 서비스를 활용하면 용량 제한 없이 데이터 저장소를 구축할 수 있습니다.
Database 서비스는 수요에 따라 서버 수를 확장할 수는 없지만, 데이터베이스 서버의 사양을 손쉽게 수직 확장할 수 있으며, Replica를 통해 읽기 성능도 향상시킬 수 있습니다.
자원 조정 자동화
클라우드는 수요 변화에 유연하게 대비하기 위한 유용한 도구를 제공하는데, Auto-Scaling은 수요 변화에 따라 자원 자동 조정을 지원하는 대표적인 서비스입니다.
클라우드의 가장 중요한 특징인 탄력성(Elasticity)은 서비스에 대한 수요가 증가할 때 물리적 자원을 추가적으로 제공하고, 자원에 여유가 있을 때는 자원을 회수하여 수요에 따라 자원을 유연하게 조정할 수 있는 기능입니다.
탄력성은 특정한 지표를 기반으로 자동화 작동을 통해 가동됩니다.
Samsung Cloud Platform에서는 Virtual Server와 Container에서 Auto-Scaling이 작동합니다.
- 지표 기반의 Auto-Scaling을 구현하여 Virtual Server의 수평 확장/축소를 구현합니다.
- Kubernetes Engine Node Pool의 자동 확장을 활성화하여 자원 자동 확장을 구현합니다.
- Auto-Scaling
Auto-Scaling은 자원 사용량을 기반으로 사전에 정의한 조건이나 일정에 따라 VM을 자동으로 추가 생성 또는 삭제하는 컴퓨팅 서비스입니다.
이를 통해 사용자는 안정적인 서비스를 유지하고 효율적으로 서버를 운용할 수 있습니다.
Load Balancer에 서버 그룹으로 VM을 등록하여, 요청 부하를 각 VM에 전달합니다.
미리 지정한 정책에 따라 VM을 신규 생성하여 추가하거나, 기존 VM을 삭제하기도 합니다.
정책으로 설정할 수 있는 지표는 CPU, 메모리, 디스크 사용률, 네트워크 트래픽 등입니다.
- Container
컨테이너는 VM에 호스팅 된 런타임 엔진 위에서 실행되기 때문에 컨테이너를 자동으로 확장하려면 두 가지 결정이 필요합니다.
첫째, 추가 컨테이너가 현재 작업 부하에 필요한지 판단해야 합니다.
둘째, 신규 컨테이너가 기존 노드풀의 노드 위에 할당될 수 있는지, 아니면 새로운 노드에 할당돼야 하는지 결정해야 합니다.
신규 노드가 자동으로 할당되도록 하려면, Kubernetes Engine의 노드풀을 생성할 때 노드풀 자동 확장/축소(Auto-Scaling) 옵션을 사용해야 합니다.
확장성을 제한하는 병목 지점 관리
서비스 아키텍처 중 수요 증가 자동 대응을 위해 Auto-Scaling을 적용하려면, 서비스의 용량 제한으로 인해 병목이 될 가능성이 있는 자원을 사전에 식별해야 합니다.
- 서비스 흐름 중 확장이 불가능한 지점을 확인합니다.
- 확장 시 늘어난 수요를 처리할 수 있는 대안을 고려합니다.
부하 증가를 처리하기 위해 단일 VM 인스턴스에 CPU 코어, 메모리 또는 네트워크 대역폭을 추가하여 수직 확장되는 Application도 있습니다.
이러한 Application은 확장성이 엄격하게 제한되어 있어, 부하 증가를 처리하도록 수동으로 구성해야 하는 경우가 많습니다.
예를 들어, 관계형 데이터베이스는 수평 확장이 불가능합니다.
데이터베이스 서비스는 이중화를 구현하더라도 Active–Standby를 지원하기 때문에 수평 확장을 구현할 수 없습니다.
이 경우 사전에 최대 용량을 고려하여 CPU 및 메모리의 사양을 높이는 수직 확장을 고려할 수 있고, Replica나 캐싱을 통해 읽기 부하를 오프로드하는 방법도 고려할 수 있습니다.
부하 급증 시 단계적 수준 저하 및 부하 완화 설계
부하가 급증하여 서버에 과부하가 발생하더라도, 서비스가 중단되지 않도록 설계해야 합니다.
트래픽을 조절하여, 사용자에게 낮은 품질의 응답을 반환하더라도 서비스가 완전히 정지하지 않도록 해야 합니다.
또한, 과부하 상황에서도 서비스가 동작할 수 있도록 설계해야 합니다.
서비스에서 과부하를 감지하여 사용자에게 낮은 품질의 응답을 반환하거나, 과부하로 인해 전체 서비스가 완전히 정지하지 않도록 트래픽을 부분적으로 대기시키거나 삭제해야 합니다.
- 대량 접속 제어 솔루션을 사용하여 접속 대기열을 구성합니다.
- 정적 웹 페이지를 구성해 사용자 요청에 임시 응답할 수 있도록 합니다.
대량 접속 제어 솔루션(Virtual Waiting Room) 등의 3rd Party 솔루션으로 사용자 대기열을 구성해서 대량으로 접속하는 부하를 단계적으로 처리할 수 있도록 합니다.
또한 Object Storage에 정적 웹 자산을 저장해서 웹서버의 부하를 경감할 수 있습니다.
장애 대응을 위한 구성 요소 설계
자원 이중화 및 Multi-AZ 구성
안정성이 높은 시스템은 단일 지점 장애가 없어야 합니다. 이를 위해 자원을 중복으로 구성하여 이러한 장애를 사전에 방지해야 합니다.
서비스에 내재적으로 제공되는 장애 회피 옵션을 활용하여 물리 기반의 장애로 인한 서비스 중단을 막고, 자원 중복 배치를 통해 하나의 자원에 장애가 발생했을 때 다른 자원이 작업을 처리할 수 있도록 합니다.
워크로드 데이터와 자원을 Multi-AZ에 배포하여, 특정 가용영역에 장애가 발생하더라도 서비스가 중단되지 않도록 합니다.
또한, 물리적 인프라 수준에서 단일 장애 지점(Single Point of Failure)을 피하기 위해, Multi-AZ에 자원을 중복 배포합니다.
- Virtual Server는 Load Balancer와 함께 중복 배치합니다.
요구 사항이 허용하는 경우 Auto-Scaling을 구성하여 자동화된 중복 구성을 구현합니다. - 서버 그룹의 Anti-Affinity를 적용하여, Virtual Server가 호스트 장애로 인해 서비스가 중단되는 것을 방지합니다.
- Multi-AZ에 자원을 배포하여 Single-AZ의 장애에 대응합니다.
- Database 서비스의 고가용성(HA) 및 복제(Replica)를 통해 통해 데이터베이스를 중복 구성합니다.
Multi-AZ의 AZ는 독립된 물리적 인프라로 구성되어, 다른 가용 영역의 장애에 영향을 받지 않도록 설계되어 있습니다.
따라서 장애가 발생하더라도 해당 AZ에만 영향이 있을 뿐 다른 AZ에는 영향을 주지 않습니다.
Multi-AZ를 선택하여 자원을 배포할 경우 다양한 재해에 대비할 수 있게 됩니다.
File Storage를 Multi-AZ로 구성하면 원본과 복제본이 각각의 AZ에 생성되고 원본과 복제본 간 데이터가 실시간 동기화 됩니다.
Kubernetes Engine을 구성하고 각각의 AZ에 별도의 노드풀을 생성합니다.
평상시에는 전체 노드 및 Pod에서 AZa의 Active Storage를 사용합니다.
AZa에 재해가 발생하면 AZa에서 구동되어 있는 Pod가 AZb 노드로 이동(Eviction) 되고, 스토리지 액세스 경로도 AZb Standby Storage로 전환됩니다.
만약 단일 서버로 배포해야 하는 경우가 있더라도, 해당 서버에 장애가 발생할 경우 전체 서비스의 장애로 이어지지 않도록 설계해야 합니다.
고가용성 서비스 구현을 위해 서비스의 주요 흐름을 구성하는 요소들은 이중화 또는 다중화 방식으로 구현하는게 필수적입니다.
특정한 제약으로 인해 단일 서버로 구성하는 Application의 경우에는, 해당 서버에 장애가 발생하더라도 서비스의 주요 흐름에 영향을 주지 않도록 배치해야 합니다.
아래 그림은 3계층 Application의 예시입니다.
이 Application은 Web - Legacy App – App – DB로 서비스의 흐름이 구성되어 있습니다.
Web, App, DB는 고가용성 이중화 구성이 되어 있지만, Legacy App은 특정 제약(이중화를 위한 소스코드 변경 불가, 소프트웨어 라이선스 제약 등)으로 인해 단일 서버에 구성할 수밖에 없습니다.
이러한 경우, Legacy App 서버에 장애가 발생하면 전체 서비스가 정지됩니다.
결과적으로 해당 서버가 단일 장애 지점이 되어 전체 서비스의 가용성을 저하시킵니다.
위의 아키텍처는 Legacy App을 주요 흐름에서 분리하여 App에서 참조하는 방식으로 구성되어 있습니다.
이렇게 구성할 경우에는 Legacy App 서버에 장애가 발생하더라도 일부 기능만 제한되고, 전체 서비스에는 최소한의 영향만 미치게 됩니다.
장애 대응을 위한 정상 자원 생성
클라우드 자원의 내재적인 기능 또는 자동 복구 구성을 통해 자원에 장애가 발생했을 때 복구할 수 있는 장치를 구성합니다.
- Auto-Scaling을 활용하여 비정상 자원을 복구합니다.
- Kubernetes Engine 노드 자동 복구 기능을 활성화해 장애에 대응합니다.
Auto-Scaling의 최소 인스턴스 수를 2로 구성한 경우, 한 VM이 장애로 인해 서비스에서 제외되면, Load Balancer가 이를 감지하고, Auto-Scaling 그룹이 최소 수량을 유지하기 위해 새로운 VM 인스턴스를 자동으로 추가 생성합니다.
이러한 방식을 통해 Virtual Server의 장애 자동 대응을 구성할 수 있습니다.
Container의 경우, Kubernetes Engine의 Node Pool에서 노드 자동 복구 기능을 활성화하면, 노드에서 장애 발생 시 자동으로 복구가 수행됩니다.
노드가 일정 시간(임계값 약 10분) 동안 지속적으로 NotReady 상태를 보고하거나, 아예 상태를 보고하지 못하는 경우에 복구가 개시됩니다.
하지만, 최초 노드 생성 시 정상 동작(Running) 상태로 되지 못하고 생성(Creating) 상태에 머물러 있거나, 같은 노드풀에서 비정상 노드가 4대 이상 발생한 경우에는 자동 복구가 제한될 수 있습니다.
악의적 공격으로부터 서비스 보호
보안 침해로 의해 서비스가 중단되는 것을 막기 위해 다양한 조치를 수행할 수 있습니다.
- 관리형 보안 서비스를 통해 보안 공격에 자동 대응합니다.
- Auto-Scaling을 통해 불능화 공격에 자동 대응합니다.
- 보안 이벤트 알림을 통해 신속한 대응 체계를 수립합니다.
DDoS Protection, WAF 등은 보안 공격을 완화하는 역할을 수행하며, 사용자가 직접 관리하지 않고 Samsung Cloud Platform에서 관리하는 보안 서비스입니다.
이를 통해 악의적 공격에 신속하게 대응할 수 있습니다.
DDoS 공격과 같은 서비스 불능화 공격의 경우, Auto-Scaling을 구성하여 서비스가 지속될 수 있도록 합니다.
또한, 관리자 알림을 구성하여 비정상 트래픽을 방화벽에서 차단할 수 있게 구성할 수 있습니다.














