이번 플로우는 외부에서 HTTP 호출을 하는 플로우입니다.
외부에서 HTTP 호출할 때 각 오브젝트가 어떻게 상호작용하는가
(Image Source : https://medium.com/google-cloud/kubernetes-nodeport-vs-loadbalancer-vs-ingress-when-should-i-use-what-922f010849e0)
Ingress 컨트롤러가 외부 요청을 수신하고, Ingress 리소스에 특정 호스트명 또는 URL 경로에 따라 요청을 특정 서비스로 라우팅한다.
서비스는 실제 트래픽을 받지 않고 Kube-Proxy를 통해 받는다. kube-proxy는 서비스의 라우팅 규칙을 읽고 트래픽이 적절한 Pod으로 전달시키는 주체이다. Kube-Proxy는 iptables을 이용해 트래픽을 전달시킨다.
주인공들
- Ingress 컨트롤러
- Service 오브젝트
- Kube-Proxy
Ingress 컨트롤러
(Image source : https://phoenixnap.com/kb/kubernetes-ingress)
역할 및 동작:
- 역할: Ingress 컨트롤러는 외부 트래픽을 클러스터 내의 서비스로 라우팅하는 역할을 합니다.
- 동작:
- Ingress 컨트롤러는 클러스터 내에서 Pod 형태로 실행되며, Ingress 리소스를 모니터링합니다.
- Ingress 리소스는 호스트 기반 또는 경로 기반의 라우팅 규칙을 정의하며, Ingress 컨트롤러는 이러한 규칙에 따라 트래픽을 적절한 서비스로 라우팅합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: multi-service-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /ping
spec:
rules:
- host: example.com
http:
paths:
- path: /a/pings
pathType: Prefix
backend:
service:
name: a-service
port:
number: 80
- path: /b/pings
pathType: Prefix
backend:
service:
name: b-service
port:
number: 80
Service 오브젝트
(Image Source : https://medium.com/devops-mojo/kubernetes-service-types-overview-introduction-to-k8s-service-types-what-are-types-of-kubernetes-services-ea6db72c3f8c)
역할 및 동작:
- 역할: 서비스는 변동이 심한 파드 IP 대신 고정된 IP 주소를 제공하여 클라이언트가 파드에 안정적으로 접근할 수 있게 합니다. 실제로 프로세스로 떠 있지 않고 etcd에 저장된다.
- 동작:
- 서비스는 특정 레이블 셀렉터를 사용하여 대상 Pod을 선택합니다.
- ClusterIP, NodePort, LoadBalancer 등의 서비스 타입이 있으며, 각 타입은 다른 방식으로 트래픽을 라우팅합니다.
- 서비스는 실제로는 Kube-Proxy를 이용해 트래픽을 올바른 Pod으로 전달합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
nginx-service.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
type: NodePort
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 30007
Kube-Proxy kube-proxy 공식문서
(Image source : https://www.mdpi.com/1424-8220/22/8/2869)
실제로 네트워크 트래픽을 받는 주체이다. 실제로 노드별로 하나씩 실행 중이다. 노드가 3개라면 3개가 실행 중이다.
역할 및 동작:
- 역할: Kube-Proxy는 Kubernetes 클러스터 내에서 네트워크 프록시 역할을 하며, 서비스와 Pod 간의 트래픽을 관리합니다. iptables 사용하여 네트워크 규칙을 설정합니다. 네트워크 계층을 추상화한 서비스 객체의 실제 구현체의 역할이다. 관련 문서
- 동작:
- 서비스와 엔드포인트 정보 조회:
- kube-proxy는 API 서버와의 watch 통신을 통해 클러스터 내의 서비스 정보를 주기적으로 조회합니다.
- 네트워크 규칙 설정:
- kube-proxy는 iptables, IPVS, 또는 userspace 모드 중 하나를 사용하여 클러스터 내에서 트래픽이 올바른 Pod으로 라우팅되도록 네트워크 규칙을 설정합니다.
잠깐, iptables에 대해서)
iptables 개요
iptables
는 리눅스 시스템에서 네트워크 트래픽을 제어하고 필터링하는 도구입니다. 네트워크 패킷을 필터링하고, 라우팅 결정을 내리고, NAT(네트워크 주소 변환)를 수행할 수 있습니다.
iptables를 포함해서 HTTP 요청이 서비스에서 파드로 전달되는 과정
- 클라이언트 요청:
- 클라이언트는 서비스 IP(Cluster IP)와 포트를 통해 HTTP 요청을 보냅니다.
- DNAT(Destination Network Address Translation) 설정:
kube-proxy
는 클라이언트 요청을 적절한 파드로 라우팅하기 위해 DNAT 규칙을 설정합니다. 이 규칙은 서비스의 Cluster IP와 포트로 들어오는 모든 요청을 해당 파드의 IP와 포트로 변환합니다.
예시:
1
iptables -t nat -A PREROUTING -d <service_cluster_ip> -p tcp --dport <service_port> -j DNAT --to-destination <pod_ip>:<pod_port>
- 예를 들어, 서비스 Cluster IP가 10.96.0.1이고 포트가 80이며, 파드 IP가 192.168.1.2이고 포트가 8080인 경우:
1
iptables -t nat -A PREROUTING -d 10.96.0.1 -p tcp --dport 80 -j DNAT --to-destination 192.168.1.2:8080
파드 응답이 클러스터 밖으로 나가는 과정
- SNAT(Source Network Address Translation) 설정:
- 파드의 응답 패킷이 클라이언트로 반환될 때 올바른 출발지 IP 주소를 가지도록 SNAT 규칙을 설정합니다. 이 규칙은 파드의 IP 주소를 노드의 IP 주소로 변경하여 클라이언트가 올바르게 응답을 받을 수 있도록 합니다.
예시:
1
iptables -t nat -A POSTROUTING -s 192.168.1.2 -p tcp --sport 8080 -j SNAT --to-source 10.0.0.1