Kubernetes Service Option - 1
- 이 글은 CNI를 Calico를 사용하는 가정하에 작성되었습니다.
클라우드 전환을 하다보면 문제가 되는 부분 중 하나가 바로 네트워크이다. 레거시 코드들은 개발자들의 생각보다 종속성을 많이 가지고 있는데 자주 나를 힘들게 하는건 IP이다. 파드가 기동될 때 마다 변경되는 파드 아이피, SRC/DST의 관리 등... 머리아프게 하는 것들이 많다. 자주 사용하는 옵션들을 천천히 정리해보려고 한다.
ExtrnalTrafficPolicy (Local/Cluster)
서비스 타입 중 NodePort와 LoadBalancer는 ExternalTrafficPolicy 옵션에서 Local/Cluster를 선택할 수 있다(기본값은 Cluster). 해당 타입은 src가 클러스터 IP로 찍히는데 access log를 관리해야하거나 IP 기반으로 제한 접근을 하고 싶은 경우가 생기면 사용하기 애매하다. 내부 아이피를 아무리 수집하고 정렬해봤자 의미가 없기 때문이다. 이러한 일이 발생하는 이유는 kubernetes docs에 상세하게 기술되어 있다.
이런 일을 막기 위해 ExternalTrafficPolicy라는 옵션이 존재한다. Cluster에서 Local로 바꾸게 되면 src를 클라이언트 IP로 보존한다. 노드포트는 이렇게 쓰면 endpoint가 없는 노드로 갈 경우에 패킷이 버려지기 때문에 해당 노드로만 접근해야한다. ingress의 x-forward-for과 같은 옵션을 사용해서 소스 IP를 보존하는 방법도 존재하지만 서비스 단의 이야기만 작성하겠다.
칼리코에도 아름답게 그림이 그려져있다. 아래 그림은 NodePort로 접근했을 떄 src가 어떻게 변화되는지 보여준다. kube-proxy로 인해 node1에서 실제 엔드포인트가 존재하는 node2로 넘어갈 때 node1의 src로 변경되고 있다. 로드밸런서도 과정이 하나 더 있는거 말고는 유사하다.
Local로 설정된 경우는 아래와 같다. 다른 노드를 거치지 않고 바로 엔드포인트가 존재하는 노드로 패킷을 전달한다. 네트워크 정책을 설정할 수 있게되고, 과정이 줄어 성능 향상도 기대해볼 수 있다.
엄청난 해결법처럼 보이지만 단점을 안고 있다. 트래픽이 불균형하게 들어갈 수 있다는 점인데, 이는 스케줄링을 통해 해결이 가능하나 대형 클러스터에서는 그러기도 힘들것으로 보인다. 한 개의 파드로 서비스하는 어플리케이션이라면 문제가 없지만 10개의 파드를 가진 어플리케이션이라면 각각에 균등하게 배분될 수 있도록 조절해주는 절차가 필요하다. 이는 운영 이후의 관점으로 느껴진다.