데브시스터즈의 Cookie Run: OvenBreak 에 적용된 Kubernetes 기반 다중 개발 서버 환경 구축 시스템에 대한 발표입니다.
Container orchestration 기반 개발 환경 구축 시스템의 필요성과, 왜 Kubernetes를 선택했는지, Kubernetes의 개념과 유용한 기능들을 다룹니다. 아울러 구축한 시스템에 대한 데모와, 작업했던 항목들에 대해 리뷰합니다.
*NDC17 발표에서는 데모 동영상을 사용했으나, 슬라이드 캡쳐로 대신합니다.
2. 내용 (Kopub M)
발표자 소개
오 승 용
• 현 DEVSISTERS 서버개발자
• Publishing Infra
• Cookie Run: OvenBreak
• Cookie Run for Kakao, LINE Cookie Run
• NEXON – Erlang 기반의 인 게임 보이스 챗 서버 개발
• 스타트업 (WeClay)
• GIST(광주과학기술원) 학사과정 1기
2
3. 데브시스터즈 서버팀
• 모두가 DevOps Engineer
• 서버 구조를 설계하고, 어떤 언어, 어떤 스택을 쓸지, 프로토콜 구조를 잡고,
• 게임 기획에 참여하고, 게임 로직에 맞는 서버 코드를 짜고,
• 개발부터 프로덕션까지 서버 배포, 모니터링하고, 장애를 대응하고,
• 뭔가 아쉬우면 새로 만들고 (libquic, LogQuery 시스템, …)
할 일이 많고 다양하다
3
7. 새 서버가 유저를 만날 때까지
1. 문제 제기
DEV STAGE PROD
(Live, Real, ..)
QA
7
개발 서버 환경
서버와 클라의
첫 만남
검수
QA엔지니어
테스트
스테이징
운영 환경과 유사
배포 전 마지막
테스트
프로덕션
실제 유저들이
접속하는 서버
오늘 발표가 다룰 것
개발자가 로컬에서 구현을 마치면,
8. Dev 서버 하나를 모두가 같이 쓸 수 있을까?
1. 문제 제기
개발 초기에는
‘dev’ 서버 하나를 띄움
8
9. Dev 서버 하나를 모두가 같이 쓸 수 있을까?
1. 문제 제기
로그인
연동 팀
UX
개선
팀
로그인 인증
방식 변경
Dev
API 호환 X
왜 앱이
크래시나지??
9
10. Dev 서버 하나를 모두가 같이 쓸 수 있을까?
1. 문제 제기
“밸런스 데이터를 바꿔야 하는데, 다른 분들에게 영향을 주기 싫어요”
개발 환경 서버가 하나만 있으면 매우 불편
10
“이벤트 QA 하려면 서버 시간을 미래로 바꿔야 하는데 괜찮을까요?”
“번역 작업을 하고 싶은데, 테스트용 클라이언트를 매일 받기 싫어요”
11. 1. 문제 제기
개발 서버를 두 대 띄워서
돌려 쓰자!
Dev
Dev2
그렇다면,
11
12. 1. 문제 제기
한달 정도는 버텼으나, 환경 두 개로는 부족.
Dev
Dev2
그렇다면,
개발 서버를 세 대 띄워서…!?
Dev3
12
13. • 시점에 따라 필요한 개발 서버 환경 수가 유동적
• 각각의 개발 서버가 어떤 “역할”을 하는지 모름
• “이 서버는 누가 어떤 용도로 쓰고 있는 서버일까?”
• “내가 이 서버 써도 되나?”
• “이제 안 쓰는 서버인가?”
1. 문제 제기
13
23. 2. 구현
• 띄울 서버가 많고, 서버 간에 통신도 필요
• 추가 서버 환경이 필요할 때마다 새 서버 인스턴스를?
• 가능은 하지만 복잡. 서버 개발자 이외는 사용하기 어려움
• 모든 서버 앱들은 Dockerized (또는 Dockerize 가능)
Container Orchestration Tool 을 써 보자!
23
28. 2. 구현
Amazon ECS Docker
(Swarm mode)
Kubernetes
Container Orchestration Tool 고르기
28
X AWS 의존성
복잡. 기능 부실
X 심플
기능 부족 O
29. 2. 구현
• Google 내부에서 사용하던 Borg의 open source 버젼
• 활발하게 개발되고 있는 프로젝트
• 시스템 구축에 적합한 각종 기능들
• 자체 DNS를 통한 내부 서비스 discovery
• Namespace – 각 서버 환경별 클러스터 구분 용이
• GCP(GKE), Azure에서 managed service 제공
• 하지만 AWS 에서도 각종 방법으로 구축 가능
Kubernetes
29
Container Orchestration Tool 고르기
30. 빠르게 살펴보는 Kubernetes
30
• Pod - 최소 단위 (≈ docker container)
apiVersion: v1
kind: Pod
metadata:
name: nginx-app
label:
name: nginx-app
spec:
containers:
- name: nginx-app
image: nginx:1.7.9
ports:
- containerPort: 80
name: http
protocol: TCP
Host 1
172.x.x.1
nginx
Host 2
172.x.x.2
10.x.x.100:80
34. 빠르게 살펴보는 Kubernetes
34
• 2. 구현
• Service
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
spec:
type: ClusterIP
selector:
app: nginx-app
ports:
- port: 80
name: web-port
protocol: TCP
Service nginx-svc
10.x.x.130:80
Service Discovery
클러스터 내에서 (또는 클러스터의 DNS address를
바라본다면)
nginx-svc:web-port -> 10.x.x.130:80 으로 resolve
ex. curl http://nginx-svc:web-port
= curl http://10.x.x.130:80
35. 빠르게 살펴보는 Kubernetes
35
• 2. 구현
• Namespace
• Kubernetes 내 리소스의 논리적 분리 단위 (C++ 등의 그것과 비슷)
nginx-svc 서비스의 namespace가 ’ns1’,
요청을 보내는 도커의 namespace가 ns1이 아니라면
(ex. ns2)
nginx-svc.ns1:web-port
37. Namespace ‘dev2’
2. 구현
Kubernetes를 적용한 서버 구조
Amazon
ElastiCache
(Redis)
Amazon RDS
(MySQL)
Game
Server
League
Server
Scheduler
Server
Backoffice
(운영툴)
Namespace ‘dev1’
37
Logging Infra
38. 2. 구현
Kubernetes 적용하기
• 각 서버 어플리케이션들은 모두
Kubernetes 로
• 서버 환경 (dev1, dev2, ..)별 namespace
생성
• http://gameserver:80 으로 요청
➞ 같은 서버 환경의 game server로
요청됨
Game
Server
League
Server
Scheduler
Server
Backoffice
(운영툴)
38
39. 2. 구현
Kubernetes 적용하기
• Redis, MySQL ➞ AWS에서 제공하는 서비스 사용
• 각각 서버 환경별 space를 분리할 방법 존재
• MySQL – Database
• Redis – DB number
• Couchbase ➞ Kubernetes
• 별도 인스턴스 구성 시 서버 환경별 space 분리 불편
➞ Kubernetes 각 서버 환경 namespace에 container로
띄움
DB
39
40. 2. 구현
Kubernetes 적용하기
• Logging Infra ➞ Kubernetes
• Component와 띄울 노드가 많은데, 각각은 리소스를
별로 안 씀
(Zookeeper, Kafka, ElasticSearch, Logstash, ..)
• Ex. Zookeeper: 3대, Mem 500M, CPU < 5% (1 core)
Logging Infra
공통
40
41. Kubernetes 클러스터 띄우기
• Managed Cluster Service
• Google Cloud – GKE (Google Container Engine)
• Azure – Azure Container Service
• AWS는 직접 구축 또는 별도의 tool 이용
• kube-aws, kops, kargo, Tectonic, …
https://kubernetes.io/docs/getting-started-guides/#table-of-solutions
2. 구현
41
43. Kubernetes 클러스터에 서비스 띄우기
• 유형 1. 웹 서비스
• Game Server, …
• Non-stateful
• ReplicaSet 과 Service 사용
2. 구현
ReplicaSet
game-server
replicas: 2
Pod
game-server-x29fb
Pod
game-server-a1234
Service
game-server
43
45. 잠깐! 클라이언트가 Kubernetes 서비스에 접속하려면
2. 구현
• 그럼 동적으로 생성된 포트 번호를 외워야 되나요?
(직접 지정이 가능하나, 대략 3만번 ~ 6만번대 포트만 사용 가능)
• Kubernetes worker 하나가 죽으면 DNS record는 어떻게..
• 그럼 회사 망에서 Ingress ACL 모든 포트 오픈을 해야 하나요?
• HTTPS 쓰고 싶은데 인증서는 또 어떻게..
45
46. Ingress Controller
2. 구현
ReplicaSet
game-server
replicas: 2
Pod
game-server-x29fb
Pod
game-server-a1234
Service
game-server
AWS
Elastic Load
Balancer
proxy Service
Backoffice
backoffice.login-dev.??.com
game.login-dev.??.com
46
login-dev 서버환경
NodePort
47. Kubernetes 클러스터에 서비스 띄우기
• 유형 2. Stateful Service
• Zookeeper, Kafka, ..
• 보통 각 개별 pod 별로 직접 접근 필요
• Pod 하나를 가지는 ReplicaSet 및 Service 구성 + NodePort
• Kubernetes의 Persistent Volume + AWS EBS 이용
2. 구현
47
Host 1
kafka-1
Amazon EBS
Host 2 Host 2
kafka-1
Amazon EBS
ReplicaSet
zookeeper-1
replicas: 1
Pod
zookeeper-1-a1234
Service
zookeeper-1
172.x.x.100:42181
48. 서버를 띄우는 웹 페이지 만들기
• 이제 CLI 로 서버를 띄울 수 있게 되었다!
• 하지만 여전히 불편 – 어떤 서버가 있는지, 누가 띄웠는지 등등
• 서버를 띄우고, 내리고, 상태를 확인하는 웹 페이지를 만들자
2. 구현
48
49. Stove
• 개발 서버를 띄우는 웹
• Python / Django
• Pykube
2. 구현
49
50. Stove
• 떠 있는 서버의 정보를
쉽게 파악 가능
(띄운 사람, 버젼, 띄운 날 등)
• 서버별로 들어갈 웹 페이지 링크
2. 구현
50
51. Stove
• 커밋&푸시 ➔ Automated Docker Build
• Github API 통한 버젼별 commit log
• 서버 이름과 설명을 적어 목적을 알 수 있게
• 런치 / 업데이트 / 삭제 시 Slack Webhook
• 사내 방송 시스템과 연계하여 개발팀 알림
“xx 서버 업데이트 시작합니다”
2. 구현
51
52. 개발 서버가 많아지니.. 어디로 붙어야 하나?!
2. 구현
• 기존에는 서버 환경이 고정적이었으므로 하드 코딩
(ex. 디버그 클라이언트 런치 시 ‘dev’, ‘dev2’, ‘dev3’ 중 고르기)
• 서버가 많아지고, 때에 따라 다른 서버에 접속해야 하는데,
손으로 일일히 주소를 쓰기 힘들다
52
53. 개발 서버가 많아지니.. 어디로 붙어야 하나?!
• Preset API
• 접속할 서버 주소
• 접속 시 사용할 리소스 버젼
/ 게임데이터 버젼
2. 구현
53
55. 그래서, 목표는 달성했나요?
1. 개발팀 누구나 필요할 때 서버를 띄울 수 있게 ➞ 달성
• 클라이언트 개발자나 QA 엔지니어도 필요에 따라 서버 On/Off/Update
• 각 서버의 정체성이 명확해져 개발 시 API, 데이터 충돌 등 이슈 감소
• 마침 독립 테스트 서버가 필요했던 타 팀들
• 알파런 (Machine Learning), 테스트 자동화, …
3. 리뷰
55
56. 그래서, 목표는 달성했나요?
2. 개발 서버 환경 운영 비용의 감소
• AWS Reserved Instance
• 따로 띄우기 애매한 각종 서비스들 (ex. 다국어 CS 번역 봇)
3. 리뷰
56
57. Kubernetes는 옳은 선택이었나?
• Yes. 구현에 필요한 기능들을 비교적 편하게 쓸 수 있었음
• 아쉬웠던 점
• 복잡한 셋업 과정 (GCP를 쓰지 않는다면)
• 복잡한 문서
• API version 이 자주 변경됨 (ex. extensions/v1beta1 ➔ v1)
3. 리뷰
57
58. Kubernetes on Production Environment?
• 최근 Production 사용 사례 많음 (Pokemon Go, NCSOFT 등)
• 쿠키런 오븐브레이크: X
• 동기부여와 안정성 이슈
• IDC / On-Premise 물리 서버 환경에서 유용할 듯
3. 리뷰
58