서비스 네트워크 session 옵션 살펴보기
서비스 네트워크 session 옵션 살펴보기
💡 KANS 스터디
CloudNet에서 주관하는 KANS(Kubernetes Advanced Networking Study)으로 쿠버네티스 네트워킹 스터디입니다. 아래의 글은 스터디의 내용을 기반으로 작성했습니다.스터디에 관심이 있으신 분은 CloudNet Blog를 참고해주세요.
들어가며
여기서는 서비스의 세부 옵션에 대해 살펴봅니다.
리소스 YAML
- 테스트 파드
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
27
28
29
30
31
32
33
34
35
36
37
38
39
apiVersion: v1
kind: Pod
metadata:
name: webpod1
labels:
app: webpod
spec:
nodeName: myk8s-worker
containers:
- name: container
image: traefik/whoami
terminationGracePeriodSeconds: 0
---
apiVersion: v1
kind: Pod
metadata:
name: webpod2
labels:
app: webpod
spec:
nodeName: myk8s-worker2
containers:
- name: container
image: traefik/whoami
terminationGracePeriodSeconds: 0
---
apiVersion: v1
kind: Pod
metadata:
name: webpod3
labels:
app: webpod
spec:
nodeName: myk8s-worker3
containers:
- name: container
image: traefik/whoami
terminationGracePeriodSeconds: 0
- 클라이언트 파드
1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: v1
kind: Pod
metadata:
name: net-pod
spec:
nodeName: myk8s-control-plane
containers:
- name: netshoot-pod
image: nicolaka/netshoot
command: ["tail"]
args: ["-f", "/dev/null"]
terminationGracePeriodSeconds: 0
- 서비스
1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: v1
kind: Service
metadata:
name: svc-clusterip
spec:
ports:
- name: svc-webport
port: 9000 # 서비스 IP 에 접속 시 사용하는 포트 port 를 의미
targetPort: 80 # 타킷 targetPort 는 서비스를 통해서 목적지 파드로 접속 시 해당 파드로 접속하는 포트를 의미
selector:
app: webpod # 셀렉터 아래 app:webpod 레이블이 설정되어 있는 파드들은 해당 서비스에 연동됨
type: ClusterIP # 서비스 타입
배포상태를 확인한다.
sessionAffinity: ClientIP
클라이언트와 통신할 때, 통신이 끊기면 재접속하면 서비스는 다시 랜덤하게 라우팅한다. 이럴 경우 기존의 정보가 날라가기에 세션을 유지하는 것은 중요하다. 개발할 때는 Redis와 같은 캐시서버를 세션으로 저장하는데, 서비스에서도 세션을 유지하는 옵션이 있다.
아래 명령어를 통해 현재 세션 설정을 확인하면, None을 볼 수 있다.
1
2
kubectl get svc svc-clusterip -o yaml | grep sessionAffinity
sessionAffinity: None
아래 명령어로 sessionAffinity를 활성화한다.
1
kubectl get svc svc-clusterip -o yaml | sed -e "s/sessionAffinity: None/sessionAffinity: ClientIP/" | kubectl apply -f -
활성화하고, KUBE-SVC 체인을 확인해본다. 서비스 ClusterIP를 통해 체인을 찾는다.
1
2
3
iptables -t nat -S | grep 10.200.1.201
-A KUBE-SERVICES -d 10.200.1.201/32 -p tcp -m comment --comment "default/svc-clusterip:svc-webport cluster IP" -m tcp --dport 9000 -j KUBE-SVC-KBDEBIL6IU6WL7RF
-A KUBE-SVC-KBDEBIL6IU6WL7RF ! -s 10.10.0.0/16 -d 10.200.1.201/32 -p tcp -m comment --comment "default/svc-clusterip:svc-webport cluster IP" -m tcp --dport 9000 -j KUBE-MARK-MASQ
찾은 KUBE-SVC 체인으로 필터링하면, 아래와 같이 recent —rcheck
체인이 추가된 것을 확인할 수 있다.
-A KUBE-SVC-KBDEBIL6IU6WL7RF -m comment --comment "default/svc-clusterip:svc-webport -> 10.10.1.2:80" -m recent --rcheck --seconds 10800 --reap --name KUBE-SEP-TBW2IYJKUCAC7GB3 --mask 255.255.255.255 --rsource -j KUBE-SEP-TBW2IYJKUCAC7GB3
1
2
3
4
5
6
7
8
9
10
iptables -t nat -S | grep KUBE-SVC-KBDEBIL6IU6WL7RF
-N KUBE-SVC-KBDEBIL6IU6WL7RF
-A KUBE-SERVICES -d 10.200.1.201/32 -p tcp -m comment --comment "default/svc-clusterip:svc-webport cluster IP" -m tcp --dport 9000 -j KUBE-SVC-KBDEBIL6IU6WL7RF
-A KUBE-SVC-KBDEBIL6IU6WL7RF ! -s 10.10.0.0/16 -d 10.200.1.201/32 -p tcp -m comment --comment "default/svc-clusterip:svc-webport cluster IP" -m tcp --dport 9000 -j KUBE-MARK-MASQ
-A KUBE-SVC-KBDEBIL6IU6WL7RF -m comment --comment "default/svc-clusterip:svc-webport -> 10.10.1.2:80" -m recent --rcheck --seconds 10800 --reap --name KUBE-SEP-TBW2IYJKUCAC7GB3 --mask 255.255.255.255 --rsource -j KUBE-SEP-TBW2IYJKUCAC7GB3
-A KUBE-SVC-KBDEBIL6IU6WL7RF -m comment --comment "default/svc-clusterip:svc-webport -> 10.10.2.2:80" -m recent --rcheck --seconds 10800 --reap --name KUBE-SEP-DOIEFYKPESCDTYCH --mask 255.255.255.255 --rsource -j KUBE-SEP-DOIEFYKPESCDTYCH
-A KUBE-SVC-KBDEBIL6IU6WL7RF -m comment --comment "default/svc-clusterip:svc-webport -> 10.10.3.3:80" -m recent --rcheck --seconds 10800 --reap --name KUBE-SEP-K7ALM6KJRBAYOHKX --mask 255.255.255.255 --rsource -j KUBE-SEP-K7ALM6KJRBAYOHKX
-A KUBE-SVC-KBDEBIL6IU6WL7RF -m comment --comment "default/svc-clusterip:svc-webport -> 10.10.1.2:80" -m statistic --mode random --probability 0.33333333349 -j KUBE-SEP-TBW2IYJKUCAC7GB3
-A KUBE-SVC-KBDEBIL6IU6WL7RF -m comment --comment "default/svc-clusterip:svc-webport -> 10.10.2.2:80" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-DOIEFYKPESCDTYCH
-A KUBE-SVC-KBDEBIL6IU6WL7RF -m comment --comment "default/svc-clusterip:svc-webport -> 10.10.3.3:80" -j KUBE-SEP-K7ALM6KJRBAYOHKX
해당 체인이 무엇인지 살펴보자.
https://ipset.netfilter.org/iptables-extensions.man.html 에서 recent 모듈에 대한 설명은
‘Allows you to dynamically create a list of IP addresses and then match against that list in a few different ways.’ 라고 나와있다. IP 목록을 생성하여 비교하는 모듈이다.
--rcheck
옵션은 IP 목록과 현재 패킷의 SRC 주소가 같은지 확인하는 옵션이다
즉, 특정 클라이언트가 서비스를 통해 파드1로 접속하면, iptables에 클라이언트 IP를 10800
s 동안 보관한다. 같은 클라이언트에서 재접속하면 IP List 목록과 일치하여, 같은 파드로 라우팅한다.
control-plane(클라이언트 파드가 위치하는 노드)에 접속하여, conntrack을 확인하여 클라이언트 IP에 대한 라우팅이 있는 것을 확인할 수 있다.
1
2
3
conntrack -L --dst-nat | grep 10.10.0.6
conntrack v1.4.7 (conntrack-tools): 5 flow entries have been shown.
tcp 6 62 TIME_WAIT src=10.10.0.6 dst=10.200.1.201 sport=35002 dport=9000 src=10.10.2.2 dst=10.10.0.6 sport=80 dport=35002 [ASSURED] mark=0 use=1
또, /proc/net/xt_recent/KUBE-SEP-{알맞은 파드 체인}
를 확인하면, IP List 목록에도 클라이언트 IP가 저장된 것을 확인할 수 있다.
테스트 진행
아래의 명령어를 통해 테스트를 진행하면, 세션이 유지되는 것을 확인할 수 있다.
1
2
kubectl exec -it net-pod -- zsh -c "for i in {1..100}; do curl -s $SVC1:9000 | grep Hostname; done | sort | uniq -c | sort -nr"
100 Hostname: webpod2
timeout 변경
timeout 설정을 진행할 수 있다. 기본값은 10800(3시간)이지만, 여기선 테스트를 위해 30초로 설정해본다.
1
kubectl patch svc svc-clusterip -p '{"spec":{"sessionAffinityConfig":{"clientIP":{"timeoutSeconds":30}}}}'
iptables를 확인해보면 30초로 second가 바뀐 것을 확인할 수 있다.
1
2
3
4
5
6
7
8
9
10
ptables -t nat -S | grep KUBE-SVC-KBDEBIL6IU6WL7RF
-N KUBE-SVC-KBDEBIL6IU6WL7RF
-A KUBE-SERVICES -d 10.200.1.201/32 -p tcp -m comment --comment "default/svc-clusterip:svc-webport cluster IP" -m tcp --dport 9000 -j KUBE-SVC-KBDEBIL6IU6WL7RF
-A KUBE-SVC-KBDEBIL6IU6WL7RF ! -s 10.10.0.0/16 -d 10.200.1.201/32 -p tcp -m comment --comment "default/svc-clusterip:svc-webport cluster IP" -m tcp --dport 9000 -j KUBE-MARK-MASQ
-A KUBE-SVC-KBDEBIL6IU6WL7RF -m comment --comment "default/svc-clusterip:svc-webport -> 10.10.1.2:80" -m recent --rcheck --seconds 30 --reap --name KUBE-SEP-TBW2IYJKUCAC7GB3 --mask 255.255.255.255 --rsource -j KUBE-SEP-TBW2IYJKUCAC7GB3
-A KUBE-SVC-KBDEBIL6IU6WL7RF -m comment --comment "default/svc-clusterip:svc-webport -> 10.10.2.2:80" -m recent --rcheck --seconds 30 --reap --name KUBE-SEP-DOIEFYKPESCDTYCH --mask 255.255.255.255 --rsource -j KUBE-SEP-DOIEFYKPESCDTYCH
-A KUBE-SVC-KBDEBIL6IU6WL7RF -m comment --comment "default/svc-clusterip:svc-webport -> 10.10.3.3:80" -m recent --rcheck --seconds 30 --reap --name KUBE-SEP-K7ALM6KJRBAYOHKX --mask 255.255.255.255 --rsource -j KUBE-SEP-K7ALM6KJRBAYOHKX
-A KUBE-SVC-KBDEBIL6IU6WL7RF -m comment --comment "default/svc-clusterip:svc-webport -> 10.10.1.2:80" -m statistic --mode random --probability 0.33333333349 -j KUBE-SEP-TBW2IYJKUCAC7GB3
-A KUBE-SVC-KBDEBIL6IU6WL7RF -m comment --comment "default/svc-clusterip:svc-webport -> 10.10.2.2:80" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-DOIEFYKPESCDTYCH
-A KUBE-SVC-KBDEBIL6IU6WL7RF -m comment --comment "default/svc-clusterip:svc-webport -> 10.10.3.3:80" -j KUBE-SEP-K7ALM6KJRBAYOHKX
이제 변경된 설정을 확인해보기 위해, 클라이언트 파드에 접속하여 다시 서비스로 접속을 시도한다. 한번 접속하고, 30초뒤에 접속하면 다른 파드로 라우팅된다. (30초이내라면 같은 파드로 라우팅된다.)