지금까지 저는 모든 작업을 단일 노드 클러스터 위에서 진행했었습니다. 왜냐하면 여러 노드가 필요할 경우 그냥 갖다붙이면 되지 않겠나, 하고 생각했기 때문입니다. 그런데 그 단순한 작업을 생각보다 많이 헤맸습니다. 그래서 이번 글에서는 기존의 마스터 노드에 새로운 노드를 join하면서 발생했던 문제점과 그 해결책을 정리해보려고 합니다.
노드가 Join이 안 됨
가장 첫 번째로 마주했던 문제는 그냥 join이 안 된다는 거였습니다. 저는 K3S를 사용하고 있는데 설치 스크립트를 사용해도 아무런 에러 메시지조차 뜨지 않았습니다. systemctl
명령어를 사용하여 에러 로그를 확인하기는 했는데, 그냥 평범한 Connection refused 계열 에러 로그밖에 뜨지 않아서 특별한 정보를 얻을 수 없었습니다. 깃허브를 한-참 돌아다닌 결과, 아래 issue에서 마스터 노드에 --node-external-ip=<<public-ip>>
라는 플래그를 따로 설정해줘야 한다는 것을 알았습니다.
이 문제가 발생한 이유는 쿠버네티스가 node의 external ip로 설정된 네트워크에서만 join 요청을 받기 때문으로 생각됩니다. 저는 virtualbox 가상 머신을 이용하여 노드를 띄우는 중이어서 첫 번째 인터페이스가 10.0.x.y
주소를 가지는 각 가상 머신 내부에서만 접근할 수 있는 네트워크에 연결되어있었습니다. 그래서 아마도 이 네트워크 대역으로 external IP가 설정돼버렸고, 그래서 다른 네트워크에서 오는 모든 요청이 무시되었던 것이 아닌가 생각됩니다.저는 마스터와 워커를 모두 가상 머신으로 띄웠고, 호스트 머신에 브릿지 모드로 연결하였으므로 가상 머신들은 모두 호스트가 연결된 공유기 네트워크에 직접 연결됩니다. 그래서 마스터의 external IP를 공유기 내부 네트워크에 속하는 IP로 바꿔 주었고, 문제를 해결했습니다.
여기에서 저를 더 헤매게 만들었던, 어이없었던 점은 연결이 또 아주 안 되는 것은 아니라는 거였습니다. 가상 머신을 삭제했다가 다시 만든 후 에러 로그를 봤더니 호스트 이름이 unique하지 않다는 로그를 발견했습니다. 그런데 당연하게도 저는 host 이름을 unique하게 설정했습니다. 그래서 클러스터 내부의 secret을 찾아 보았더니 워커 노드에 해당하는 node-password secret을 발견했습니다. (node-password 시크릿은 클러스터의 각 노드당 하나씩 발급되는 시크릿입니다.)
이는 곧 가상머신을 삭제하기 전, 이전 시도에서 워커 노드가 마스터 노드에 접속해서 node-password를 발급받는 데에 성공했음을 의미합니다. 이로부터 생각해보건대 node-password를 발급받는 과정은 apiserver를 통해 이루어지고(왜냐하면 api서버는 외부 네트워크에서도 접속이 잘 되므로) 그 이후에 어떤 과정이 kube-proxy를 통해 이루어지는데 (왜냐하면 마스터와 워커가 통신하는 통로는 api서버 아니면 kube-proxy이므로) kube-proxy가 external IP에 어떤 영향을 받은 게 아닌가...생각되기도 합니다.
Pod간에 통신이 안 됨
결국 위와 같은 과정을 통해서 정상적으로 노드를 join했습니다. 그런데 새로운 서비스를 띄워 보니 이상하게도 새로운 서비스에는 접속이 안 되는 문제가 발생했습니다. Gateway timeout 에러가 계속 발생했던 것입니다. 그래서 다음과 같은 과정을 통해서 문제 상황을 발견했습니다.
- (Gateway timeout은 이미지와 관계없기는 하지만) 혹시 이미지가 문제인가...? → 바꿔 봐도 안 됨
- 새로운 서비스가 워커노드에 떠 있는 것을 발견
- 기존의 서비스들 중 잘 동작하는 서비스 중 하나를 워커노드로 옮김 → 옮겼더니 동작 안 함
- Node 사이에 통신은 잘 되는가? → Join이 성공했으니 잘 될 수밖에
- Pod 사이에 통신은 잘 되는가? → ping 해본 결과 pod 내부에서 같은 노드 pod끼리는 잘 됨, 다른 노드의 pod끼리는 안 됨
- Node들 사이에 CNI 인터페이스를 통해 통신이 가능한가? → ping 안 감
- 결론 : CNI 문제가 분명함
저는 Hubble을 사용하기 위하여 기본으로 설치되는 Flannel 대신에 Cilium CNI를 설치했습니다. 이게 문제인 게 분명해 보였습니다. 이때 어디선가 Cilium은 Cilium이 배포되기 전에 배포된 팟들은 건드리지 않는다는 글을 읽었습니다. 아마 아래 troubleshooting 도큐먼트인 것 같은데, 확실하지 않습니다.
그래서 그냥 Cilium operator와 Treafik service를 포함해서 문제될 만한 pod들을 전부 지웠습니다. (어차피 다시 생성될 것이므로) 그랬더니 위 모든 문제가 해결되는 기적같은 일이 벌어졌습니다(...) 저도 왜 이런지는 모르겠습니다. 분명히 전에 문제가 있었을 때에도 워커 노드에서 ip route
및 ip addr
명령어로 Cilium 인터페이스가 확인이 됐었고, 마스터 노드와 워커노드에 Cilium 팟이 각각 떠 있는 것을 확인했었습니다.
결론
프로그램이 오류가 나거나 말을 안 들을 때에는 껐다 키면 좋아집니다. 쿠버네티스 클러스터도 예외가 아님을 확인했습니다.