K8s Network
Pod 집합에서 실행중인 애플리케이션을 네트워크 서비스로 노출하는 추상화 기법입니다. Service를 활용하면, Pod에게 고유한 IP 주소, Pod 집합에 대한 단일 DNS 부여가 가능하며, 이들을 로드밸런싱을 통해서 부하분산이 가능하도록 합니다.
K8s에서는 Pod가 죽었다 살아나는 상황이 빈번합니다. 이때, Pod가 다시 살아나면 CNI로 인하여 IP가 변경됩니다.
만약 Frontend와 Backend Pod가 상호 통신중인 상태일 때, Backend Pod가 재실행되었다면?
K8s는 위와 같은 문제점을 해결하기 위해서 네트워크 단을 추상화한 Service 오브젝트를 구현했습니다.
Service는 Pod 앞단에 존재하는 Proxy와 같은 개념으로, 특정 Pod로 요청되는 트래픽을 Service가 판단하여 Pod로 전달합니다.
이렇게 되면, Pod가 재실행되건, 말건 애플리케이션은 Service로 트래픽을 전달하기에, Pod IP에 구애받지 않게 됩니다.
1. Service 타입(Service Publishing)
Service 타입은 Service에 접근하는 트래픽의 범위를 제어합니다.
애플리케이션 중 프론트앤드 단과 같은 서비스는 외부 IP 주소에 노출하고자 하는 경우 등 여러 고민 요소가 있는데, 적절한 Service 타입으로 이를 설정 가능합니다.
2. Endpoints
Service가 Packet을 전달하고자 하는 Pod 집합을 Endpoints라 합니다.
K8s에서는 Endpoints에 대한 모니터링이 실행되며, Pod가 종료/오류가 발생하면 Endpoints 항목에서 해당 Pod를 제거합니다.
Service의 Endpoints에 Pod를 포함시키려면, Selector 혹은 Label을 통해 가능합니다.
3. Ports / TargetPorts
Ports
TargetPorts
아래는 Ports 및 Target Ports를 활용한 예시입니다.
80 Port를 통해 http 트래픽이 들어올 수 있으며, 9376 Port를 통해 Service -> Pod로 트래픽이 전달합니다.
apiVersion: v1
kind: Service
metadata:
name: example-service
spec:
selector: # Service가 적용될 Pod 정보를 지정(옵션)
app: MyApp
ports:
- name: http
protocol: TCP
port: 80 # Service를 노출하는 포트
targetPort: 9376 # 애플리케이션(Pod)를 노출하는 포트
- name: https
protocol: TCP
port: 443
targetPort: 9377
Kube-proxy는 Service를 위한 가상 IP 매커니즘의 구현을 담당합니다.
Kube-proxy에는 3가지 종류의 모드가 존재하며, iptables 모드에 대해서 자세히 알아볼 예정입니다.
kube-proxy는 클러스터의 모든 노드에서 daemonset으로 실행됩니다. 그렇기에, 어떤 노드에서 Pod가 실행되어도 모든 노드에서는 Service를 통해 Pod로 접근이 가능합니다.
iptables
Kube-proxy가 iptables 모드인 경우 Linux의 iptables를 이용하며, 이를 통해 Service로 접근하는 패킷을 처리합니다.
해당 모드에서 kube-proxy는 Control Plane의 Service, Endpoint 오브젝트의 추가/제거를 감시합니다.
아래 다이어그램에서 "IP address for Service"는 Service의 iptables를 의미합니다.
iptables의 loadbalancing
kube-proxy iptables 모드 사용 시, 리눅스 넷필터(netfilter)를 통해 트래픽을 분산 처리합니다.
해당 모드에서 kube-proxy는 백엔드를 임의로 선택하며, 트래픽을 처리하기 위해 iptables를 사용하여 시스템 오버헤드를 줄입니다.
어떻게 오버헤드를 줄이는가?
Pod Readiness Probe를 통해 백엔드 Pod가 제대로 작동하는지 확인하기에, iptables 모드인 kube-proxy는 정상적인 백엔드만 볼 수 있습니다.
해당 과정을 통해 kube-proxy가 비정상 pod로 전송되는 트래픽을 막을 수 있습니다.
iptables 네트워킹 동작 순서
Service에는 Cluster IP, Nodeport, Loadbalancer 와 같이 3가지의 타입이 존재한다고 했었습니다.
iptables는 각 Service 타입마다 네트워킹 동작 순서의 차이가 존재합니다.
아래 이미지를 참고한 후 예를 들면, NodePort 타입인 경우, 클라이언트가 K8s/Service/Pod에 대해서 어떠한 정보가 없더라도 Service의 IP:Port로 향하도록만 한다면 트래픽은 적절한 백엔드로 향하고, 분산되도록 설계되어 있습니다.
iptable을 통한 분산 네트워킹 동작을 사용하고 싶지 않을 때가 존재합니다.
이때 사용하는 옵션이 SessionAffinity로, 활성화 시, 처음 접근/접속한 백엔드(Pod)에 계속 접속되도록 합니다.
무제한 고정하는 것이 아니라, 타임아웃을 주고 싶다면 Service에서.spec.sessionAffinityConfig.clientIP.timeoutSeconds 를 설정하면 됩니다.