IL-0075 Civis Analytics · 2019-01-16 (게시일)kubernetesawsobservability
Civis Analytics 는 Civis Data Science Platform 에서 Python, R, 컨테이너 스크립트를 돌리는 기반을 자체 인프라 Bocce 에서 쿠버네티스로 옮기고, 이 이전을 Croquet 라고 불렀다. 2018년 9월 사내에 먼저 공개한 뒤 클러스터가 불안정해졌다. 스크립트가 대량으로 몰리자 클러스터는 EC2 인스턴스 약 290대까지 커졌고, 예전에는 80대를 넘은 적이 없었다. CPU 제한이 없던 API 서버 컨테이너 세 개가 마스터 노드의 CPU 와 메모리를 다 써 버려 컨트롤 플레인을 쓸 수 없게 됐다. 사내 사용자들을 예전 인프라로 되돌리자 클러스터가 안정됐다.
팀은 500 노드, 가능하면 1,000 노드를 목표로 정하고 스테이징 클러스터에서 오토스케일링 그룹 크기를 조금씩 늘리며 부하 테스트를 했다. API 요청 처리량, 5xx 오류율, 요청 지연 같은 지표가 없어서 Prometheus operator 로 Prometheus 를 배포했다. 마스터 노드를 m4.large 세 대에서 m4.4xlarge 세 대로 키웠지만 500 노드를 무리 없이 넘기지는 못했다. API 서버의 max-requests-inflight 를 400 에서 1200 으로 올리자 429 응답은 줄었지만 CPU 와 메모리 사용 양상은 크게 바뀌지 않았다.
다음으로 DaemonSet 을 의심했다. Sumologic 수집기와 Datadog DaemonSet 을 빼고 테스트하니 약 800 노드까지 버텼다. Sumologic 만 다시 넣어도 700 노드 넘게 무리 없이 커졌으므로 Datadog 이 원인이었다. Datadog 에이전트는 DD_KUBERNETES_COLLECT_METADATA_TAGS 설정 때문에 노드마다 일정 간격으로 쿠버네티스 API 에서 서비스 목록을 가져갔다. 이렇게 모은 태그는 팀의 모니터링에 쓸모도 없었다. Datadog 설정을 고친 뒤 클러스터는 EC2 인스턴스 700대 넘게 무리 없이 커졌다. 이 밖에 etcd 의 EBS 볼륨을 20 GB 에서 100 GB 로 늘려 IOPS 를 100 에서 300 으로 올렸지만 효과는 크지 않았다.
다시 사내에 공개하자 DNS 타임아웃으로 스크립트가 실패한다는 제보가 들어왔다. 팀은 문제를 안정적으로 재현하지 못했지만 클러스터 규모와 관련이 있다고 보고, 스크립트의 DNS 정책을 ClusterFirst 에서 Default 로 바꿨다. 그 뒤로 클러스터 문제는 없었고, 팀은 이 클러스터가 700 노드를 감당한다고 결론지었다.
스크립트 실행 기반을 쿠버네티스로 옮긴 Croquet 를 사내에 공개한 뒤, 개발자들은 kubectl 명령이 느리다고 했다. 사용자들은 노트북과 서비스가 가끔 시작되지 않는다고 알렸다.
스크립트가 대량으로 몰리자 클러스터는 EC2 인스턴스 약 290대까지 커졌다. 예전에는 80대를 넘은 적이 없었다. 이때 마스터 노드의 CPU 사용률이 높아졌고, 들여다보니 쿠버네티스 API 서버 컨테이너 세 개가 모두 CPU 를 꽉 채워 쓰고 있었다.
API 서버에는 CPU 제한이 없어서 노드 CPU 를 다 써 버렸다. 다른 컨트롤 플레인 구성 요소가 자원을 얻지 못해 클러스터를 쓸 수 없게 됐다. API 서버는 노드 메모리도 다 쓴 뒤에야 재시작됐다.
팀은 처음에 마스터 노드가 작다고 보고 m4.large 를 m4.4xlarge 로 키웠다. 감당할 수 있는 규모는 늘었지만 500 노드를 무리 없이 넘기지는 못했다. 부하 테스트 중에는 API 접근 로그에 429 응답이 여러 번 찍혔고, 부하가 정점에 가까워지면 응답 지연과 5xx 오류율이 치솟았다.
다시 사내에 공개한 뒤에는 사용자들이 DNS 타임아웃 오류로 스크립트가 실패한다고 알렸다.
원인 ? 용량 한계
개발자들이 kubectl 명령이 느리다고 했고, 사용자들은 노트북과 서비스가 가끔 시작되지 않는다고 알렸다. 마스터 노드의 CPU 사용률이 높았고, 조사해 보니 API 서버 컨테이너 세 개가 CPU 를 꽉 채워 쓰고 있었다. 당시 팀이 볼 수 있던 지표는 마스터 노드 CPU 의 CloudWatch 지표와 Datadog 의 컨테이너별 CPU, 메모리 지표였다. API 요청 처리량과 5xx 오류율과 요청 지연은 볼 수 없었다.
가장 큰 실수는 쿠버네티스가 모든 것을 알아서 해 준다고 가정한 것이었다. 쿠버네티스는 노드 5,000대와 파드 100,000개를 지원한다고 하지만, 그 규모에 이르려면 손봐야 할 설정이 많다. 클러스터에 넣는 서드파티 도구, 특히 DaemonSet 을 조심해야 한다. 많은 도구가 보통 규모에 맞춰 만들어졌고 큰 규모에서는 시험되지 않았다. 클러스터 상태를 watch 하는 서비스가 데이터를 지나치게 많이 가져가도록 설계되면 규모 문제가 생긴다. kube2iam 은 모든 파드의 메타데이터를 메모리에 들고 있다가 메모리가 바닥났고, Fluentd Kubernetes Metadata Filter 플러그인도 같은 문제가 있다. 대개 설정 하나로 고칠 수 있지만, 부하 테스트를 해 보기 전에는 잘 드러나지 않는다.
같은 원인 · 공통 텔레메트리 에이전트, 쿠버네티스 API 서버, etcd
같은 원인 · 공통 쿠버네티스 API 서버, etcd
같은 원인 · 공통 쿠버네티스 API 서버, etcd
같은 원인 · 공통 텔레메트리 에이전트
같은 원인 · 공통 텔레메트리 에이전트
같은 원인 · 공통 쿠버네티스 API 서버
같은 원인 · 공통 텔레메트리 에이전트
같은 원인 · 공통 쿠버네티스 API 서버
같은 원인 · 공통 쿠버네티스 API 서버
IL-0026같은 원인 · 공통 텔레메트리 에이전트
같은 원인 · 공통 쿠버네티스 API 서버
같은 원인 · 공통 쿠버네티스 API 서버