2018년 4월 4일 수요일

traefik, the kubernetes ingress controller

https://docs.traefik.io/user-guide/kubernetes/

kubernetes 클러스터도 하나 생겼으니 기념삼아 이것저것 생각나는 걸 깔아봤다.

안내문에 적힌 치즈 웹서비스를 다음과 같이 테스트해봤고, 까먹었을 때 보기 위해 적어둔다.

export ADDR=kube-node-3 PORT=32479; for h in cheeses.minikube cheddar.minikube stilton.minikube wensleydale.minikube; do curl $ADDR:$PORT -H "Host: $h" -v; done

kube-node-3은 ds가 아니라 deployment (=그 노드에서만 동작하는) 방식으로 설치한 traefik이 테스트 시점에 구동중인 노드였다.

원래 하고 싶었던 건 kubernetes 클러스터에 external loadbalancer를 붙이고 (그게 traefik이 되면 좋고) 거기서 다시 hostname 기반으로 분산을 하는 거였다. 외부에서 접근했을 때 traefik이 실행중인 노드로 접근하게 만드는 걸 아직 몰라서, 일단 hostname 방식으로 동작한다는 걸 확인하기 위해 Host 헤더를 강제로 집어넣었다. 원했던 대로 각 호스트의 웹서버가 각각 반응해줘서 기뻤다.

http://alesnosek.com/blog/2017/02/14/accessing-kubernetes-pods-from-outside-of-the-cluster/ 여기서 설명하는 내용을 보면 traefik이 제공하는 ingress controller를 잘 쓰면 애초에 원하던 걸 처리할 수 있는 것 같다.

여전히 남는 의문은, 그럼 ingress controller가 동작중인 node를 어떻게 다시 공인IP의 세계로 노출시키는가 하는 점인데.

https://stackoverflow.com/a/37796383 를 보면 externalIPs라는 설정을 언급하고 있지만, 이건 hostname에 반응하는 것처럼 특정IP를 목표로 지정된 트래픽이 (미리 설정된 외부의 route에 따라) k8s 안쪽까지 들어가면, 그 IP에 반응하도록 서비스를 설정하는 것인데, 임의의 hostname을 지정할 수도 있는 것과 달리 숫자IP를 고정적으로 지정해야 해서 그다지 좋은 방식은 아닌 것 같다. 내가 찾던 방향도 아닌 것 같고.

https://medium.com/@maniankara/kubernetes-tcp-load-balancer-service-on-premise-non-cloud-f85c9fd8f43c 내용을 보면 yaml에서부터 externalIPs 설정을 적어주지 않고 kubectl expose 명령으로도 정할 수 있나보다. expose 명령의 옵션을 자세히 보지 않았던 게 잘못이다.
(이어서 tcp-echo-server라는 예제를 통해 NodePort 대신 hostNetwork:true 속성을 켜는 방법을 보여주는 것도 재밌는 방법처럼 보이지만, 권장되는 방법도 아니고, traefik을 쓸 거니까 관심사는 아니다)

expose 명령의 --external-ip 옵션에 traefik이 떠 있는 node의 IP를 지정하고 (kubernetes dashboard에 EXTERNAL-IP 항목으로 나온다) 80 포트를 80 포트로 연결하라고 한 다음에, (/etc/hosts에 kube-node-3와 같은 IP로 지정된) curl cheddar.minikube 명령을 실행하면 Cheddar라는 페이지가 출력된다. 앞서 curl에 Host 헤더를 강제로 먹였던 것과 같은 결과다.

AWS 같은 클라우드 서비스에서야 LoadBalancer 타입으로만 지정해도 expose에 사용될 공용IP를 받아서 지정하면 끝이니 복잡할 게 없이 클라우드 API 호출로 IP만 받으면 바로 끝날 동작이다.

공유기 안쪽에서 192.168.x.x 범위로 구성할 때를 기준으로 바꿔서 생각해보면 이렇게 되겠다.
  1. 공유기 밖에서 공유기 안으로 넘어오는 단계 - 포트포워딩, DMZ 등
  2. 넘어온 트래픽을 받을 내부IP를 어떻게 고정적으로 유지할지 - DNS에서 IP 고정
  3. 그 내부IP가 받은 신호가 traefik 같은 ingress controller로 넘어가는 과정을 어떻게 유지할지 - expose 명령을 쓰고, 고정된 내부IP를 external-ip로 지정