강의 정보

강의 필기록 원본이라 글이 좀 어수선할 수 있습니다.

CNI

  • pod ip 할당, pod - pod 통신 관장
  • 로그 등의 작업물들은 모두 /var/lib/cni 에 저장함

CoreDNS

  • ExternalName: ns 별로 dns 레코드 설정하기는 기능이 있는 것 같다.
  • CoreDNS 가 장난질 ExternalName 을 설정해서 coredns 가 cname 처리하게하는 것도 가능한 것 같다.

Kube-proxy

역사

1. Userspace mode

  • 처음에는 그냥 프록시서버로 시작했다
  • 처음에는 pod -> iptables 가 보고 clusterip 면 kube-proxy로 보내서 그놈이 처리하게 했음
    • kube-proxy 는 nginx 나 haproxy 와 거의 유사하게 동작
    • userspace 모드라고 부르고, 현재는 비활성화되어있다
    • pod process 와 kube-proxy process 간의 CPU context switching 때문에 패킷 전송에 딜레이가 걸려 퍼포먼스가 안나왔기 때문
    • 이게 그 이슈다: Github/kubernetes: Issue 12682

2. iptables mode

  • 이거는 이제 userprocess 를 사용하지 않기 위해 kube-proxy는 iptables 룰만 설정하고, 모든 proxy 작업을 iptables 에게 맡겨버림
  • 하지만 이것도 문제가 많다: 노드가 많아지면 많아질수록 iptables rule 이 너무 많아져서 kernelspace 가 너무 커진다

3. IPVS mode

  • 이놈이 애초에 lb 용으로 개발된 커널모듈이기 때문에 rule 이 많아도 처리속도가 빠르다
  • iptables 에는 svc 로 가는 패킷이면 SNAT 을 해서 iptables 로 보내는 룰만 추가
  • kube-proxy 는 iptables 의 위의 룰 하나랑 ipvs 룰들을 추가한다

4. Cilium: kube-proxy-less mode

  • Kube-proxy 가 하는일이 너무 많기에 cilium의 간판인 bpf 로 이것을 대체하는 것

잡담

  • kube-proxy 가 가지는 node-proxier role (rbac)
    • endpoint 와 svc 에 대한 list, watch 권한이 있음
  • svc 에 labelselector 를 기입하지 않고 ep 를 수동으로 생성해서 원하는 곳으로 lb 되게 할 수도 있다
  • clusterip 를 none 으로 주면 headless 가 되고, 이것은 kube-proxy 의 iptables, ipvs 룰들을 bypass 해서 단순히 “통신” 만 되게 한다

NodePort

  • onprem 과 aws elb 에서 모두 유용하게 쓰일 수 있기에 개발됨
  • 어찌보면 당연: nodeport 가 있기에 외부 LB 가 그곳으로 패킷을 찌를 수 있음
  • iptables rule: kube-service, kube-postrouting
    1. (kube-service) 트래픽 들어왔을 때 nodeport / hostport 이면 마킹
    2. LOCAL_IN : k8s 쪽에서 장난치지 않음 (디폴트)
    3. externalTrafficPolicy: Local: LOCAL_IN -> local process
  • externalIP:
    • linux 가 하나의 router 니까
    • ip 에 맞게 routing 을 하는데
    • externalip 가 달려있으면 라우팅을 하지 않고 자기가 직접 처리한다 (L4 로 올려보낸다 인듯)

CNI

VXLAN, IPIP: Overlay Network

  • VXLAN: UDP 사용
  • 원래 패킷에 VXLAN 패킷을 달고 그 앞에다가 ip, mac 을 새로 다시 설정해서 실제 node 차원에서의 서브넷 네트워크를 사용할 수 있게 (VXLAN Tunneling)
  • 하지만 이것은 물리적인 라우터를 조작할 수가 없을 때 사용 (거의 대부분 그렇제 근데)
  • 장점은
    • 거의 모든 네트워크 환경에서 사용 가능
  • 단점은
    • daemonset 을 띄워야 한다는 것
    • 그리고 encap / decap 비용 + 노드간의 정보 동기화
    • daemonset 에 버그가 생기면 tcpdump 하는 것 말고는 답이 없다

Routing table 건들기

  • 물리적인 라우터의 RT 를 조작할 수 있으면 이런 것 없이 테이블만 건드려준다
  • AWS 가 이짓을 한다
    • 어차피 Overlay network 위에 ec2 를 띄우고 거기에 k8s 를 띄우는데 거기에까지 overlay 를 하나 더 깔 이유가 없다
    • 그래서 VPC 로 router 들을 직접 조작하되 k8s 에는 overlay 를 깔지 않음

잡담

  • 요즘은 kube-proxy 를 다른것으로 대체하는 것이 인기
    • Cilium 때문인듯
    • 이놈이 nodeport 를 처리하는 기능도 있다고 한다.
  • 대역폭?
    • CPU 와 MEM 이 합쳐서 25.6Gb/s 대역폭을 제공하는데
    • 만약에 10Gb/s 의 대역폭을먹는 작업을 하면
      • 예를들어 ssd 에서 뭔가를 가져온다 한다면
      • ssd 에서 읽어서 mem에서 cpu로 보내는데 10Gb/s
      • cpu -> mem 10Gb/s
      • mem -> NIC 10Gb/s
      • NIC -> mem 10Gb
      • 이렇게 40 을 먹는다고 한다.
    • CPU <- 25.6Gb/s -> MEM <-> NIC <-> 인터넷
  • ndot:
    • 가령 aaa 로 nslookup 을 때리면
      • aaa
      • aaa.{NAMESPACE}
      • aaa.{NAMESPACE}.svc
      • aaa.{NAMESPACE}.svc.{CLUSTER}
      • aaa.{NAMESPACE}.svc.{CLUSTER}.local
    • 이렇게 계층적으로 질의를 하게 되는 시스템
  • 하지만 계층적으로 질의하기 때문에 불필요한 네트워크를 먹게 된다
    • 따라서 FQDN 으로 마지막에 . 을 찍어줌으로써 계층적 질의를 막을 수 있고
    • 이를 위해 처음부터 FQDN 으로 url 을 지정해주면 효율을 높일 수 있다

Network 관련 트러블슈팅

ingress-nginx

  • annotation 잘못 설정해주면 디버깅하기 힘들다: ic pod 도 정상이고 로그도 별거 없는데 갑자기 welcome to ingress 가 뜨던가 아니면 변경한 설정이 반영이 안되는 등
  • 이놈의 rbac: endpoint 를 추적하여 be 로 보낸다
  • kube-proxy 가 망가져도 ingress-nginx 는 작동한다

Container network

  • Linux 에서 network namespace 를 나눠서 container 의 namespace 를 나누면
  • namespace 안에서 가상의 랜카드인 eth0 가 생성되고
  • namespace 밖에서는 저 eth0 와 통신할 veth 가 생성된다
  • 따라서 eth0 와 veth 가 쌍으로 생성되어 트래픽이 namespaced network 밖으로 나온다
  • 그래서 tcpdump 를 뜨고 싶을 때 호스트딴에서 veth 에 dump 를 뜨거나
  • pod 에서 tcpdump ephermeral container 를 띄워서 (pod 의 container 들은 network namespace 를 공유하고 있으니까) tcpdump 프로세스를 돌릴 수 있다.
    • 이건 경장한 꿀팁이다: 뭐라하면 tcpdump 떠서 network 문제가 아님을 확인한 후 network 문제가 아니라 application 문제면 니탓이오를 시전할 수 있다