클라우드 스킬업을 위해 기존 AWS에 올라간 솔루션을 GCP에 이전 설치할 기회가 생겼다.
다양한 GCP Resource를 활용해서 개발자/운영자의 입장을 고려하여 기존 구성을 변경해보며 Public cloud 를 익히는데도 도움이 될 수 있겠다싶었다.
1. 기존 구성안 검토
- 우선 기존에 AWS에 어떻게 구성되었는지 살펴봤다. 서버, DB, Storage 등 간단한 웹서버 구성이었다.
초기 요구사항은 기존의 트래픽 사용량 대비 비용절감을 원하셨지만 개인적인 바람은 서비스가 잘되서 트래픽을 감당할 수 없는 상황에도 안정적인 인프라 환경을 지원하는 것이었다.
현재 상황을 만족한 설계라면 기존 구성을 copy and paste하는 방식으로 그대로 migration할 수 있지만 나중을 위해선 유동적인 트래픽 상황에 대응하여 autoscaling, 장애상황에 대한 failover를 위한 HA를 고려하지않을 수 없었다.
기존 구성의 문제점
- 개발자분들의 얘기를 들으니 현재 local환경에서 개발을 하시고 클라우드 서버에 원격접속하신다고 했다.
보통 개발환경은 local, dev, integration, qa, staging, production 단계로 나뉜다. 프로젝트 환경에 따라 단계가 다르지만 간단히 각 단계를 살펴보면,
* local(로컬 개발 환경) : 개발자 PC에 각자 개발 및 테스트 환경이 셋업된 상태이다. 모든 개발자가 같은 개발 환경을 사용해야한다는 것이 문제다. 다른 버전의 JVM 등을 사용해서 코드를 합칠 때 local에서 작동한 코드가 작동하지 않을 수 있다. 개발 환경을 표준화하는 방법이 있지만 전체 개발 환경을 zip 파일 형태로 묶어서 사용하는 방법이 일반적이다. maven 등을 사용하면 개발에 사용되는 JDK, 라이브러리 버전 등을 지정할 수 있어 개발 환경 차이에서 오는 문제점의 상당 부분을 해소할 수 있다.
* dev(서버 개발 환경) : 각 개별 개발자들이 만든 코드를 합쳐서 서버 환경에서 테스트해볼 수 있는 환경이다. 소스코드를 git과 같은 형상관리 시스템에서 commit하면 코드는 dev 개발 환경에 자동으로 배포되고 이 환경에서 테스트가 된다. 기능 개발을 위주로 하여 production 환경보다 훨씬 작게 dev 개발 환경은 한 두개의 서버로 기능 구현이 가능한 정도로 구축하는 것이 일반적이다.
* integration(통합 개발 환경) : 여러 개의 컴포넌트를 동시 개발하는 프로젝트가 있고 각 컴포넌트가 다른 컴포넌트에 대해 dependency를 가지고 있을 때 컴포넌트를 통합 및 테스트하는 환경으로 사용한다.(단말과 서버를 같이 개발하는 경우 integration 환경에서 통합한다) dev 환경과 마찬가지로 최소한의 set으로 구성하고 dev 환경에서 release 되면 주기적으로 deploy한다
* qa(테스팅 환경) : QA 엔지니어에 의해 사용되는 환경으로 short release 주기에 따라 개발환경에서 QA 환경으로 배포되고 여기서 기능 및 비기능(load test) 등을 QA 엔지니어가 수행한다. 비기능 테스트를 수행할 때는 production과 거의 유사한 환경을 만들어 놓고 테스트를 수행한다.
* staging(스테이징 환경) : 운영 환경과 거의 동일한 환경을 만들어 놓고 운영환경으로 이전하기 전에 여러 비 기능적인 부분(security, 성능, 장애 등)을 검증하는 환경이다.
* production(운영 환경) : 실제 서비스를 위한 운영 환경
위와 같은 단계에서 현재 local, production 단계만 구성되어있어 서비스가 오픈되기 전 성능 테스트는 문제없지만 운영중인 서비스의 성능 테스트를 위해 staging 단계 등이 추가적으로 필요해보였다.
회사마다 개발 환경은 다르지만 어느 정도 규모가 있는 경우 local/dev/staging/prod 로 나뉘고 규모가 작다면 local/staging/prod 로 나뉜다
GCP resource hierarchy
GCP 리소스는 계층적으로 구성된다. 이 계층 구조를 사용하면 기업의 운영 구조를 GCP에 매핑하고 관련 리소스 그룹에 대한 액세스 제어 및 권한을 관리할 수 있다.
GCP 계층 구조의 최상위 노드는 조직(예: 회사)을 나타내는 조직 리소스다. 조직 리소스는 계층 구조 아래에 있는 모든 리소스에 대한 중앙 가시성과 제어를 제공한다.
계층 구조의 다음은 폴더다. 폴더를 사용하여 상위 조직의 여러 부서 및 팀에 대한 요구 사항을 분리할 수 있다. 유사하게 폴더를 사용하여 개발 리소스에서 프로덕션 리소스를 분리할 수 있다.
계층 구조의 맨 아래에는 프로젝트 가 있다 . 프로젝트에는 앱을 구성하는 컴퓨팅, 스토리지 및 네트워킹 리소스가 포함된다.
Creating and managing Folders
폴더 구조를 세부적으로 보면 위와 같이 "Company"라는 조직에는 "Department X" 및 "Department Y"를 나타내는 폴더와 두 부서에 공통적일 수 있는 항목에 대한 "Shared Infrastructure" 폴더가 있다. "Department Y" 아래에는 두 개의 팀으로 구성되어 있으며 팀 폴더 내에서는 제품별로 추가로 구성된다. "Product 1" 폴더에는 각각 프로젝트에 필요한 리소스가 있는 세 개의 프로젝트가 포함되어 있다. 이를 통해 IAM 정책 및 조직 정책을 적절한 수준의 세분화로 유연하게 할당할 수 있다.(참고:GCP docs: 폴더 생성 및 관리)
GCP 실무 경험이 많으신 엔지니어분께 실제 '폴더'를 구성하여 운영하는 조직은 거의 못보셨다고 듣긴했다. research를 했을 때도 GCP의 폴더를 활용하거나 Public cloud의 리소스를 활용하기보단 개발팀에서 자체적으로,
-> Local(각 개발자들이 예)github 상에서 master/branch 개발 진행)
-> Dev(project master가 branch merge 하면서 코드 리뷰 진행)
-> Integration( 예)Jenkins,testing & building 진행)
-> Test/QA(performance tesing, quality 테스트 진행)
-> Staging(클라우드 staging server 활용하여 성능 테스트 진행)
-> Production/live(클라우드 live server)
보통 위와 같은 수순을 거쳐 서비스를 운영한다. 과연 개발팀의 협조가 어느정도 이뤄질지 몰라도 현재의 개발 환경이 지속된다면 서비스가 오픈된 상태에서 추가적인 성능테스트나 업데이트가 발생할 때마다 downtime이 발생할 것은 너무나 예상된 결과였다. 기존 인프라 구성보다도 개발 환경에 대한 수정이 시급해보였다.
2. 개발자/엔지니어 간 Migration 미팅
- 앞으로 어떻게 진행되는 것이 좋을지 솔루션 개발자와 클라우드 엔지니어 간 미팅을 진행했다.
개발자분들은 기존 AWS 구성에 대해 어떤 입장이시고 얼마나 추가 개발 resource를 투입할 수 있는지 의견을 듣고 그에 맞는 migration을 단계적으로 진행해야겠다싶었다. 우선 현재 개발된 코드 수정이나 추가 서버 증설, 개발 환경 변경에 대한 계획에 대한 얘기는 없으셨다. 현재 AWS 상에 구축된 다양한 리소스들을 어떻게 활용하고 계신지, 어떤 부분은 개선이 필요한지 정도에 대한 간단한 코멘트를 해주셨다.
회의를 통해 지금 당장 초기 인프라 구성을 바꾸는 것보다는 기존의 구성을 그대로 가져가는 lift and shift 방식으로 방향을 잡고 기존 AWS 리소스에 대응되는 GCP 리소스를 살펴보며 구성을 해야겠다는 가닥이 잡혔다. 부서 간의 이해관계가 얽혀있어 조심스러운 자리였고 시간이 걸리겠지만 추후 Cloud Native에 맞게 애플리케이션 재설계를 검토해주시면 좋겠단 바람이었다.(MSA를 위한 참고 글)
3. GCP 구성 시 변경 사항
1) VPC
- 기존에 개발자용으로 Bastion host를 사용하여 접근했지만 굳이 Bastion host를 사용하지 않고도 secure하게 연결할 수 있다. Bastion host로 둘 경우 유지보수가 필요하기 때문에 VPN(GCP CloudVPN)을 두거나 IAP Proxy(TCP forwarding)로 대체 가능하다. 각각의 방법은 아래와 같다.
(1) Connecting to VMs without external IP addresses
Bastion hosts
- 사설 네트워크 인스턴스를 포함하는 네트워크에 대한 외부 진입 지점을 제공한다. Bastion host 인스턴스를 사용하여 GCP 네트워크의 다른 VM에 연결하는 방법을 알아보려면 Connecting through a bastion host을 참조.
(2) Connecting over a VPN connection
- GCP Cloud VPN을 통해 VM 인스턴스에 연결
(3) Cloud IAP enables context-aware access to VMs via SSH and RDP without bastion hosts
- Cloud IAP를 사용하면 TCP forwarding 기능을 구성하기만 하면 인터넷에 직접 서비스를 노출하지 않고 액세스할 수 있다.
2) Application
(1) App Modernization : PaaS (App Engine) or Container based (GKE)
- App Engine : 소스만 올리면 자동 구성(리소스를 .yaml로 정의해서 쉽게 배포),
-> LB - Backend Service 로 App Engine 을 지정할 수 있음 (Serverless NEG)
-> DB - App Engine 에서 Cloud SQL 연결하면 됨 (참고). 단, App Engine 은 그 자체로 public ip 가 서비스되므로 보안 관점에서 검토 필요
- GKE
- LB - 역시 Backend Service 로 GKE 를 지정할 수 있음 (Zonal NEG), 다만 GKE를 쓰는 경우라면 GKE의 Ingress를 생성해서 사용하는 것이 더 일반적임 (참고1, 참고2)
-> DB - GKE 에서 Cloud SQL연결(참고)
(2) Lift & Shift : 이중화 + Autoscaling 할 수 있는 방안 (실습해보기)
- Managed Instance Group + External HTTP Load Balancer (L7) : Instance Group에서 backend에 instance group 설정. Instance template 활용(machine type)
3) Database
(1) Migration from MySQL
- 기존의 logic을 크게 변경할 필요는 없다. 연결 부분에 대해서만 수정하면 된다.
(2) DB HA
- HA cloud SQL
4) Storage
개발 환경(dev,stage,qa,production)
Best practices for enterprise organizations
Connecting to VMs without external IP addresses
Connecting over a VPN connection
Cloud IAP enables context-aware access to VMs via SSH and RDP without bastion hosts
- From Object Storage to File Storage : 초기에 웹페이지 게시판에서 그림, 파일, 로그 등을 올리기 위한 목적으로 AWS Object Storage인 S3를 구축했으나 NAS의 File Storage 정도로 대체해도 무방
[Reference]