kube-proxy
"쿠버네티스 서비스/파드 IP들을 iptables로 관리해주는 친구"
https://kubernetes.io/docs/reference/networking/virtual-ips/#proxy-modes
- 서비스의 IP를 Pod IP로 변환해주는 역할
- 모든 worker node에 하나씩 위치한다. (daemonset 형태)
- kube-proxy는 클러스터의 각 노드에서 실행되는 네트워크 프록시로, 쿠버네티스 서비스 개념의 일부를 구현한다.
- kube-proxy의 주요 작업은 패킷을 라우팅하지 않고 서비스를 호출할 때 패킷이 목적지에 도달할 수 있도록 구성하는 것이다.
- kube-proxy는 생성된 서비스에 대한 iptables 규칙을 생성한다.
- kube-proxy는 각 노드에서 실행되며 APIServer와 통신하여 존재하는 서비스 및 엔드포인트에 대한 세부 정보를 가져온다.
- kube-proxy는 쿠버네티스 클러스터 내부에서 서비스와 관련된 모든 것을 처리하는 동작을 한다. 서비스의 IP로 전달되는 패킷들이 파드로 전달되게 해준다.
iptables
https://ojt90902.tistory.com/1523
- 이 모드에서 kube-proxy는 커널 netfilter 하위 시스템의 iptables API를 사용하여 패킷 전달 규칙을 구성한다
- 각 엔드포인트에 대해 기본적으로 백엔드 파드를 무작위로 선택하는 iptables 규칙을 설치한다
패킷이 들어오면 IP Table의 체이닝은 PREROUTING --> FORWARD --> POSTROUTING 형태로 진행된다.
- iptables에는 여러 규칙이 정의되어있다.
- 패킷은 정의된 규칙을 만족하는지 확인한다. 규칙을 만족하면, 해당 규칙이 적용된다.
- 패킷은 종료 규칙을 만날 때 까지 순회한다. 종료 규칙을 만나면 다음 페인으로 패킷이 전달된다.
- 종료 규칙의 종류는 다음과 같다.
- ACCEPT
- REJECT
- DROP
- SNAT
- DNAT
- MASQUERADE
[PREROUTING 단계]
파드에서 서비스로 요청을 보내면, 파드의 요청은 가장 먼저 노드의 iptables로 전달된다.
iptables에 전달된 패킷은 가장 먼저 PREROUTING 테이블 규칙이 적용된다.
[root@c100 pod-manifests]# iptables -t nat -S PREROUTING
# Warning: iptables-legacy tables present, use iptables-legacy to see them
-P PREROUTING ACCEPT
-A PREROUTING -m comment --comment "cali:6gwbT8clXdHdC1b1" -j cali-PREROUTING
-A PREROUTING -m comment --comment "kubernetes service portals" -j KUBE-SERVICES
-A PREROUTING -m addrtype --dst-type LOCAL -j CNI-HOSTPORT-DNAT
[root@c100 pod-manifests]# iptables -t nat -S cali-PREROUTING
# Warning: iptables-legacy tables present, use iptables-legacy to see them
-N cali-PREROUTING
-A cali-PREROUTING -m comment --comment "cali:r6XmIziWUJsdOK6Z" -j cali-fip-dnat
[root@c100 pod-manifests]# iptables -t nat -S cali-fip-dnat
# Warning: iptables-legacy tables present, use iptables-legacy to see them
-N cali-fip-dnat
[root@c100 pod-manifests]# iptables -t nat -S KUBE-SERVICES
# Warning: iptables-legacy tables present, use iptables-legacy to see them
-N KUBE-SERVICES
-A KUBE-SERVICES -d 10.43.234.219/32 -p tcp -m comment --comment "exporter/prometheus-mysql-exporter:mysql-exporter cluster IP" -j KUBE-SVC-ZCHHRZ7KY6N2F6MX
...
[root@c100 pod-manifests]# iptables -t nat -S KUBE-SVC-ZCHHRZ7KY6N2F6MX
# Warning: iptables-legacy tables present, use iptables-legacy to see them
-N KUBE-SVC-ZCHHRZ7KY6N2F6MX
-A KUBE-SVC-ZCHHRZ7KY6N2F6MX ! -s 10.42.0.0/16 -d 10.43.234.219/32 -p tcp -m comment --comment "exporter/prometheus-mysql-exporter:mysql-exporter cluster IP" -j KUBE-MARK-MASQ
-A KUBE-SVC-ZCHHRZ7KY6N2F6MX -m comment --comment "exporter/prometheus-mysql-exporter:mysql-exporter -> 10.42.190.68:9104" -j KUBE-SEP-PCZLSTZXRKCFT7DK
[root@c100 pod-manifests]# iptables -t nat -S KUBE-MARK-MASQ
# Warning: iptables-legacy tables present, use iptables-legacy to see them
-N KUBE-MARK-MASQ
-A KUBE-MARK-MASQ -j MARK --set-xmark 0x4000/0x4000
[root@c100 pod-manifests]# iptables -t nat -S KUBE-SEP-PCZLSTZXRKCFT7DK
# Warning: iptables-legacy tables present, use iptables-legacy to see them
-N KUBE-SEP-PCZLSTZXRKCFT7DK
-A KUBE-SEP-PCZLSTZXRKCFT7DK -s 10.42.190.68/32 -m comment --comment "exporter/prometheus-mysql-exporter:mysql-exporter" -j KUBE-MARK-MASQ
-A KUBE-SEP-PCZLSTZXRKCFT7DK -p tcp -m comment --comment "exporter/prometheus-mysql-exporter:mysql-exporter" -m tcp -j DNAT --to-destination 10.42.190.68:9104
Before: 10.42.190.68 -> 10.43.234.219:9104
After: 10.42.190.68 -> 10.42.190.68:9104
iptables를 통해서 서비스 IP로 전달되던 패킷이 파드 IP로 변경됐다. DNAT는 종료 규칙이므로 패킷은 PREROUTING 체인에서 더이상 동작하지 않고 FORWARD 체인으로 넘어간다.
[FORWARD 단계]
[root@c100 pod-manifests]# iptables -t filter -S FORWARD
# Warning: iptables-legacy tables present, use iptables-legacy to see them
-P FORWARD ACCEPT
-A FORWARD -m comment --comment "cali:wUHhoiAYhphO9Mso" -j cali-FORWARD
-A FORWARD -m conntrack --ctstate NEW -m comment --comment "kubernetes load balancer firewall" -j KUBE-PROXY-FIREWALL
-A FORWARD -m comment --comment "kubernetes forwarding rules" -j KUBE-FORWARD
-A FORWARD -m conntrack --ctstate NEW -m comment --comment "kubernetes service portals" -j KUBE-SERVICES
-A FORWARD -m conntrack --ctstate NEW -m comment --comment "kubernetes externally-visible service portals" -j KUBE-EXTERNAL-SERVICES
-A FORWARD -m comment --comment "cali:S93hcgKJrXEqnTfs" -m comment --comment "Policy explicitly accepted packet." -m mark --mark 0x10000/0x10000 -j ACCEPT
-A FORWARD -m comment --comment "cali:mp77cMpurHhyjLrM" -j MARK --set-xmark 0x10000/0x10000
[POSTROUTING 단계]
[root@c100 pod-manifests]# iptables -t nat -S POSTROUTING
# Warning: iptables-legacy tables present, use iptables-legacy to see them
-P POSTROUTING ACCEPT
-A POSTROUTING -m comment --comment "cali:O3lYWMrLQYEMJtB5" -j cali-POSTROUTING
-A POSTROUTING -m comment --comment "CNI portfwd requiring masquerade" -j CNI-HOSTPORT-MASQ
-A POSTROUTING -m comment --comment "kubernetes postrouting rules" -j KUBE-POSTROUTING
[정리]
- 서비스로 가는 패킷은 PREROUTING 체인에 정의된 규칙에서 파드의 주소로 변경된다. 이 때, 몇 퍼센트 확률로 분배가 되는지 정의되어있다. 이후 FORWARD 체인으로 넘겨진다.
- FORWARD에서는 CNI를 타는지 결정된다. 이후 POSTROUTING 체인으로 넘겨진다.
- POSTROUTING에서는 패킷의 출발 주소가 MASQUARDE로 정의된다. 이 때, 출발 주소가 출력 네트워크 인터페이스 주소로 변경된다.
- 서비스가 파드의 주소로 바뀌는 과정은 아래와 같다
- 서비스 주소 + 서비스 포트를 만족하는 경우, 특정 NAT 테이블로 점프한다
- 특정 NAT 테이블은 서비스의 엔드포인트와 관련된 파드의 주소들로 Jump 하도록 규칙이 작성돼있다. 이 때, 어떤 파드를 선택하는지는 Possibility로 정의돼있다.
ipvs
- IPVS 모드는 iptables 모드와 유사한 netfilter 후크 기능을 기반으로 하지만 해시 테이블을 기본 데이터 구조로 사용하고 커널 공간에서 작동한다
- 이는 IPVS 모드의 kube-proxy가 iptables 모드의 kube-proxy 보다 지연 시간이 짧은 트래픽을 리다이렉트하고 프록시 규칙을 동기화할 때 성능이 훨씬 향상된다는 의미이다
- iptalbes 모드와 비교하여 IPVS 모드는 더 높은 네트워크 트래픽 처리량을 지원한다
- IPVS 모드에서 kube-proxy를 실행하려면 kube-proxy를 시작하기 전에 노드에서 IPVS를 사용할 수 있도록 설정해야 한다
- kube-proxy가 IPVS 프록시 모드에서 시작되면 IPVS 커널 모듈을 사용할 수 있는 지 확인한다
- IPVS 커널 모듈이 감지되지 않으면 kube-proxy가 오류와 함께 종료된
nftables (kubernetes version 1.29 alpha 기능)
- nftables API는 iptables API의 후속 API 이며 iptables보다 더 나은 성능과 확장성을 제공하도록 설계되었다
- nftables 모드는 1.30을 기준으로 여전히 개발이 진행 중이며 현재로서는 다른 Linux 모드보다 성능이 반드시 뛰어날 것으로 예상되는 것은 아니다
CNI
"파드간 네트워크 연결 및 IP 할당"
- 파드 간 통신을 가능하게 해주는 역할을 한다.
- 파드에 네트워크 인터페이스를 설정하고 IP 주소를 할당하는 역할을 한다.
- 모든 워커노드에 중복되지 않는 subnet을 부여하고 워커노드에서 실행되는 파드는 해당 subnet에 포함된 IP를 부여받는다.
calico
Felix | - 각 노드에 할당된 파드의 IP 대역이 BGP로 전파되면 해당 대역과 정상적으로 통신이 이루어질 수 있도록 iptables와 라우팅테이블 등을 조정한다. - 네트워크 정책을 수신하고 이를 iptabels, ebpf 등을 통해 적용한다. |
BIRD | - BGP를 사용하여 네트워크 라우팅을 설정한다. - BGP 피어링을 통해 네트워크 경로를 교환한다. - 외부 네트워크와의 피어링을 통해 클러스터 외부와의 통신을 설정할 수 있다. |
confd | - |
CoreDNS
"쿠버네티스 DNS 관리"
https://malwareanalysis.tistory.com/267
- 쿠버네티스 클러스터 DNS 서버 역할을 한다
- 쿠버네티스 애드온으로 쿠버네티스 클러스터 실행 시 pod로 실행된다
- 파드는 DNS 질의를 사용할 때 kube-dns 서비스부터 찾는다
- 파드로 들어가 /etc/resolv.conf 파일을 확인하면 kube-dns ClusterIP가 설정돼있다
- CoreDNS는 파드와 서비스에 대한 도메인을 관리하며 해당하는 DNS 요청이 오면 DNS 응답을 전달한다
- 파드 도메인: <파드-IP>.<namespace>.pod.cluster.local
- 서비스 도메인: <서비스이름>.<namespace>.svc.cluster.local
- 쿠버네티스 클러스터 외부로 나가는 DNS 쿼리도 coredns가 담당한다
- ping google.com ->
apiVersion: v1
kind: ConfigMap
metadata:
name: coredns
namespace: kube-system
data:
Corefile: |
.:53 {
errors
health
ready
# pod, service domain 응답 설정
kubernetes CLUSTER_DOMAIN in-addr.arpa ip6.arpa {
pods insecure
upstream
fallthrough in-addr.arpa ip6.arpa
}
prometheus :9153
# 그 이외의 domain은 외부로 forward
forward . /etc/resolv.conf {
max_concurrent 1000
}
cache 30
loop
reload
loadbalance
}
apiVersion: v1
data:
Corefile: |
.:53 {
errors
health {
lameduck 5s
}
ready
kubernetes cluster.local cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 30
}
prometheus 0.0.0.0:9153
forward . /etc/resolv.conf
cache 30
loop
reload
loadbalance
}
kind: ConfigMap
metadata:
annotations:
meta.helm.sh/release-name: rke2-coredns
meta.helm.sh/release-namespace: kube-system
creationTimestamp: "2024-03-07T09:21:30Z"
labels:
app.kubernetes.io/instance: rke2-coredns
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: rke2-coredns
helm.sh/chart: rke2-coredns-1.29.001
k8s-app: kube-dns
kubernetes.io/cluster-service: "true"
kubernetes.io/name: CoreDNS
name: rke2-coredns-rke2-coredns
namespace: kube-system
resourceVersion: "843"
uid: a2171d0c-a5d9-4fda-b01d-45bfef4ef94a
$ kubectl exec -it sample-app-XXX -- bash
cat /etc/resolve.conf
search sample-app.svc.cluster.local svc.cluster.local cluster.local
nameserver 10.43.0.10
options ndots:5
$ kubectl get svc -n kube-system | grep core
coredns ClusterIP 10.43.0.10 <none> 53/UDP,53/TCP
'클라우드 > Kubernetes(쿠버네티스)' 카테고리의 다른 글
[kubernetes] Service (Headless Service, ExternalName), Endpoint (0) | 2024.08.13 |
---|---|
[Kubernetes] ArgoCD (0) | 2024.07.30 |
[쿠버네티스] 클러스터 구축 (0) | 2024.06.08 |
[kubernetes] kubernetes의 update 종류와 동작 방법 (apply, edit, patch, replace) (0) | 2023.08.18 |
[kubernetes] pod lifecycle (0) | 2023.08.10 |