Google Cloud Summit 2023 Seoul - Cloud Run으로 Fast, Scalable, Durable 앱 구축하기
Google Cloud Customer Engineer 권신중님.
CloudRun: 완전관리형, 컨테이너 기반 애플리케이션 배포 / 운영 / 확장을 위한 서비스.
- 인프라 고민 필요없음.
CloudRun 소개
크게 두 가지 형태로 쓰임. Service / Job.
- Service: public / private한 웹사이트 또는 Endpoint
- url endpoint 제공
- autoscale 기준은 크게 두 가지 (or 조건으로 동작함)
- cpu 기준. default 60%
- request 개수 (concurrency) - default 80.
- canary deployment (traffic split) based on revision
- HTTP, WebSocket, gRPC, Event 등 다양한 조건으로 트리거
- Job: kubernetes Job과 동일. batch를 병렬로 수행할 수 있는 Container의 묶음
- 하나의 cloudrun instance (max 8Core, 32GB Mem)로 큰 작업 돌리는 것보다 여러 개 병렬처리하는 게 좋다
지원하는 Integration
- Google Cloud Redis
- custom Domain / Load balancer
- Load balancer를 붙일 수 있다? -> CDN도 붙일 수 있다는 뜻.
- Firebase hosting
Pricing
Pay-as-you-go (on-demand) 방식의 비용 설계. 비용 옵션은 크게 두 가지
- 요청 들어왔을 경우에만 cpu 할당 (option 1) - default
- 단, 서울리전 기준 option 2의 단가가 option 1보다 50% 정도 낮다.
- request pattern이 spiky / unpredictable 한 경우에 유용함.
- cpu 반드시 할당 (option 2)
- 꾸준히 traffic이 들어오는 경우에 유용함.
즉, option 1에서 option 2로 넘어갈 때 cost saving될 가능성이 있다.
최근에 cpu recommend 기능이 추가되었음.
- 일정 기간 (1개월 등) 앱이 어느 정도의 cpu 사용량을 기록했으니 recommended amount는 어느 정도인지를 추천해준다.
billable time
인스턴스는 하나 떠 있고 요청을 2개 처리하는 상황.
- cloudRun의 default concurrency 80. 즉 하나의 인스턴스가 이론적으로는 80개의 request를 처리할 수 있다. max는 1000
- overlay 구간은 비용의 double check가 되지 않는다. 즉 concurrency 수치 높일수록 비용 절감 효과.
- 단, 이 경우 사용자가 만든 앱 자체의 handling concurrency보다 높아져 버리면, 500에러 발생하고 있어도 autoscale이 동작하지 않는다
- i.e. 사용자가 springboot 앱을 만들었고, 앱 특성상 최대 50개의 요청을 동시처리할 수 있는 구조인데 concurrency를 100으로 주면 500에러 나고 있어도 autoscale을 지원하지 못한다.
- Concurrency는 사용자의 tuning point
New Features
사용자가 hello world 찍는 용도로는 더 이상 안 쓴다. 요구사항이 많아졌다.
- Sidecar Container 지원
- 더 큰 리소스 선택 가능 (8 vCPU / 32GiB RAM) - Service, Job 둘 다.
- 등등등...
여기서 소개할 내용은 크게 두 가지 - Sidecar Container, Direct VPC egress
지금까지 Cloud Run은 Single Container만 지원하고 있었음
- sidecar를 붙인다는 건, container workload 간 localhost로 통신 가능하다는 뜻.
- in-memory shared volume 활용 가능.
생각해볼 수 있는 usecase는 세 가지
- App Monitoring, Logging, Tracing
- cloudRun은 GCP의 logging / monitoring 기능을 지원하지만, 사용자는 prometheus를 원함.
- openTelemetry에서 제공하는 agent를 sidecar로 띄우는 것.
- Proxy 붙이기
- incoming request에 sidecar (i.e. nginx) - reverse proxy를 붙인다거나 / 인증, caching이 필요하다거나
- outgoing request에 sidecar (i.e. cloud sql proxy) - GCP에서 제공하는 managed DB인데, 통신 암호화라던가 ACL 지원해주는 Daemon 같은 느낌으로 proxy 사용을 권장하고 있음.
- Advanced Networking, Security, Service Mesh까지.
nginx를 sidecar로 붙이는 예시
- apiVersion을 보면 knative 스펙임.
- nginx conf 보면 loopback interface. (location 필드의 proxy_pass http://127.0.0.1:8888)
- main 컨테이너와 nginx 컨테이너의 bootup 서순 명시 - annotation의 'run.googleapis.com/container-dependencies' 필드
CloudRun으로 앱을 띄우고 외부 인터넷으로 접근 가능한 endpoint를 받았음.
- 대부분의 사용자는 GCP의 VPC 내부에 만들어둔, private IP로 접근가능한 리소스와 통신하고 싶어함
- 또는 on-prem 서버와 연동하고 싶음
지금까지는 Serverless VPC Access Connector라는 일종의 VM 머신을 발급받아서 통신해야 했음.
- egress 트래픽이 많으면 10개까지 늘어나는 VM.
중간에 있던 Access Connector (VM) 을 없앴다. VPC와 이제 직접 통신할 수 있음.
- 중간 hop에 해당하는 VM을 없앴을 때의 장점을 누릴 수 있다
- Latency 감소
- VM에 의존하던 Throughput에서 독립됨
- idle일 때도 인스턴스 발급 자체에서 발생하던 비용 없어짐
Web Console에서 활성화할 수 있다.
- subnet을 설정해야 하는데, /24 권장. (private interface를 위한 ip)
- service나 job 개수가 100을 넘어갈 것 같으면, 사용가능한 총 인스턴스 수의 4배 가량의 ip가 필요함.
Best Practices
개발자가 할 수 있는 선에서 Cold Start 줄여야 한다.
- 이미지 크기 줄이기, dependency 최소화, lazy loading...
- 그래도 안 되면 인프라의 도움을 받는다. Startup CPU boost. 문서상으로는 50% 정도 절감된다고 하는데, case by case.
- Min instance를 1로 설정하는 것도 방법.
특히 Java / .Net의 경우 cold start의 부담이 큰 편.
비용 최적화
- Concurrency 설정 잘해야 한다. App이 감당할 수 있는 concurrency를 테스트해봐야 함.
- request 늘려갈 때 500에러 뱉기 시작하는 지점이 한계치임. 그것보다 살짝 낮은 값으로 안전하게 잡으면 된다.
- cpu recommender 활용하기.
Operation/Security
- 민감한 환경변수는 Secret manager에 key-value로 넣고, IAM 활용해서 control하는 것을 권장함.