IL-0059 NRE Labs · 2018-12-04kubernetesgcp
NRE Labs는 Antidote 프로젝트 위에서 도는 네트워크 자동화 교육 사이트이고, 당시에는 SLA가 없는 테크 프리뷰 단계였다. 클러스터는 kubeadm으로 만든 단일 마스터 구성이었고, 마스터는 GCP의 가상 머신 한 대였다. kubeadm은 기본으로 etcd를 kubelet이 관리하는 단일 노드 정적 파드로 띄운다. 쿠버네티스의 모든 상태가 etcd에 있으므로 etcd가 멈추면 클러스터 전체가 멈춘다.
12월 4일 etcd 정적 파드의 liveness probe가 실패하기 시작했다. kubelet은 약 2분마다 etcd에 SIGTERM을 보내 재시작했고, 그때마다 API 서버도 함께 끊겼다. 운영자는 kubelet 재시작 뒤 잠깐 살아난 것을 복구로 착각했고, 재시작 횟수 183도 놓쳤다. terraform과 ansible로 클러스터를 지우고 다시 만들면서 증거까지 없앴다. 새 클러스터에서도 같은 일이 나자 운영자는 etcd 로그와 kubelet 로그를 차례로 봤다. 그리고 probe 설정의 failureThreshold 8과 timeoutSeconds 15를 곱한 2분이 실제로 관찰한 재시작 주기와 같다는 것을 알아냈다.
운영자가 같은 etcdctl 명령을 직접 실행하면 매번 종료 코드 0으로 끝나 실패를 재현하지 못했다. etcd 자체는 정상이고 kubelet만 비정상으로 판단한다고 보고, kubeadm이 만든 매니페스트에서 liveness probe를 통째로 지웠다. probe가 왜 무작위로 실패하기 시작했는지는 답을 찾지 못했다.
2018년 12월 4일 아침 8시 회의 중 운영자가 NRE Labs의 일일 통계를 보다가 레슨 사용량이 떨어진 것을 알아챘다.
kubectl get pods -n=prod 는 "The connection to the server 1.2.3.4:6443 was refused - did you specify the right host or port?" 로 실패했다. SSH로 마스터가 도는 GCE 인스턴스에 들어가 보니 docker ps 출력에 API 서버가 없었다. kubelet을 재시작하자 kubectl이 다시 붙었고, syringe 파드를 재시작한 뒤 레슨 몇 개가 열렸다. 운영자는 밤사이 GCP 유지보수 뒤 마스터가 제대로 올라오지 않았던 것으로 판단하고, 트위터에 복구됐다고 알렸다.
곧 레슨 사용량이 다시 떨어졌다. kubectl get nodes 를 보니 노드 하나만 v1.11.3이고 나머지는 v1.12.1이었다. 운영자는 그 주에 노드를 빼고 새로 넣으면서 플레이북에 버전을 잘못 적었을 것으로 봤다. kube-system 파드 목록에서 etcd와 kube-apiserver 파드의 RESTARTS가 183이었지만, 운영자는 모두 Running인 것만 보고 넘어갔다. 그 상태로 terraform destroy로 클러스터를 통째로 지우고 다시 만들었다. 재구축은 약 30분 뒤 끝났지만 새 클러스터에서도 곧 같은 문제가 나타났다.
API 서버에 붙을 수 없어 SSH로 docker ps -a 를 보니 etcd 컨테이너가 계속 떴다가 내려갔다. etcd와 API 서버는 1.5분에서 2분쯤 쓸 수 있다가 끊겼다. etcd 로그에는 "embed: serving client requests on 127.0.0.1:2379" 다음 약 2분 뒤 "pkg/osutil: received terminated signal, shutting down..." 이 찍혔다. kubelet 로그에는 "Container {Name:etcd...truncated....} is dead, but RestartPolicy says that we should restart it." 가 남았다.
운영자가 아침 회의 중 NRE Labs 일일 통계를 보다가 레슨 사용량이 떨어진 것을 보고 알았다. 클러스터 모니터링은 갖추지 않은 상태였고, 원문은 모니터링이 우선순위에서 밀려 있었다고 적었다.
모든 인프라를 코드로 관리한 덕에 클러스터를 금방 다시 만들 수 있었다. 하지만 원인을 모른 채 지우면 증거도 함께 사라진다. 단일 마스터로 운영한다면 모니터링이 더 중요하다. kubectl 출력에서 Running만 보지 말고 재시작 횟수까지 읽어야 한다. 복잡한 원인을 기대하기 전에 기본부터 의심하고, 장애의 급박함에 밀려 성급한 결정을 내리지 않는다. 사이트를 반쯤 망가진 채로 두지 말고 점검 페이지로 상황을 알려야 한다.
–