월루를 꿈꾸는 대학생
KNAS Service (ClusterIP & NodePort) 본문
실습 환경
- 클러스터와 다른 네트워크인 pc가 rtr을 통해서 접속
- 테스트 단말 용도
서비스
- 파드가 증가하면 ip도 변경되는데 그걸 aws의 eip처럼 고정 ip주는 서비스를 제공하기도함
- 동일한 애플리케이션의 다수의 파드의 접속을 용이하게 하기 위한 서비스에 접속
- 노드포트 : 보통 파드가 랜덤으로 포트가 열리는데 노드포트로 포트포워딩 느낌으로 파드와 외부를 연결해준다
- 종류 : cluster ip , node port , lb
Cluster IP = L4
- 클라이언트(TestPod)가 'CLUSTER-IP' 접속 시 해당 노드의 iptables 룰(랜덤 분산)에 의해서 DNAT 처리가 되어 목적지(backend) 파드와 통신
- 부하 분산을 시켜준다 . 하나의 cluster ip로 여러 명이 접속시 하나는 pod1 , 하나는 pod3 이런 느낌
cat <<EOT> svc-clusterip.yaml
apiVersion: v1
kind: Service
metadata:
name: svc-clusterip
spec:
ports:
- name: svc-webport
port: 9000
targetPort: 80
selector:
app: webpod
type: ClusterIP
EOT
# 서비스는 10~ 대역은 서브넷팅해서 서비스인 cluster ip에 할당
# 그래서 clusterip 서비스는 10.96.76.231 할당 받음
# pod ip인 cluster 172~ 대역은 calico의 ipam의해 설정
#port
#targetport
#endpoint는 각 파드의 ip를 나타냄 - webpod쪽 endpoint가 서비스에 매칭된 레이블 app에 해당하는 파드를 모니터링 // 파드의ip와 포트가 있음
# 서비스의 clusterip에 직접적으로 연결 시 아무것도 안 나옴
# cluster ip의 상세정보에 있는 port 9000번으로 접근시 응답
# host: 서비스 클러스터 ip
# remote address = 목적지 파드에 접근한 놈ip : net-pod 의 ip
# 서비스의 ip에 접근할 때 가상포트인 9000번을 이용하면 백엔드 쪽 endpoint가 모니터링 중인 파드의 ip와 타겟포트 쪽으로 부하분산을 해준다
# 타겟포트가 대상포트
# l4처럼 부하분산이 되는 걸 확인 3개의 포트에 나눠서 접근
# 마스터노드에 있는 testpod가 클러스터ip로 접근하니 iptables의 룰에 의해서 pod1 pod2 pod3 나눠서 랜덤으로 부하분산되어 접근됨
# 동작을 이해하자! = 매운맛
IPTABLES 정책 확인
# rule 갯수 확인
# 규칙 패킷 바이트 카운트 초기화
iptables -t filter --zero; iptables -t nat --zero; iptables -t mangle --zero
# prerouting 체인 내용
# PREROUTING 안에 서브체인으로 cali-PREROUTING이 있음
# 체인을 계속해서 따라간다!!
# PREROUTING 안에 KUBE-SERVICES 체인으로 이동
# KUBE-SERVICES 안에 있는 IP대역 중 CLUSTER IP의 대역 체인으로 또 이동
# 목적지IP의 9000번 포트 매칭이 되면 해당 서브체인 따라감
# 3개 중 하나로 보내는데 그 중 하나를 따라가 보면 파드의 IP를 DNAT한다고 나옴
# 첫번째 들어갈 확률 33퍼
# 두번째 세번째 중 하나 들어갈 확률 50퍼
# 세번째만 남으니 100퍼 이런식으로 부하분산
# 정리
# 10.96.76.231 서비스의 IP와 9000번 포트로 들어오면 SEP로 부하분산이 되고 SEP 정보를 따라가면 DNAT 처리가 되고 해당 파드 IP로 DNAT이 됨
1) 트래픽이 가장 처음 거쳐가는 훅 PREROUTING
2) KUBE-SERVICES에서 모든게 매칭중
3) CLUSTER IP와 포트에 매칭되는 것들은 해당 체인으로 이동
4) 확률에 따라 해당되는 곳으로 이동
5) 파드 IP와 포트가 나오고 최종 동작은 DNAT
# 출발지 ip 처리
# POSTROUTING 마지막 처리되는 훅 빠져나갈 때 처리됨
# KUBEPOSTROUTING에서 NODEPORT와 CLUSTER IP의 처리가 다름
# CLUSTER IP는 RETURN에 해당되어 밑으로 내려가서 MARK , MASQUERADE 되는 게 아니라 상위로 올라가버림 IP가 변환되지 않고 POD IP가 유지되어서 상대방 POD로 간다 = 출발지 IP가 안 바뀐다
# NODE PORT는 출발지 IP가 변경될 예정
REMOTE ADDRESS가 변경되지 않고 그대로 찍혔음
#장애 발생시 상태확인
- 고정적인 IP를 제공해준다
- 서비스에 묶인 ENDPOINT 중 POD 1개를 장애를 일으키면 통신이 끊기는지 아닌지 확인
- label selector에 묶여 있는 endpoint의 pod들만
# 파드 1개 삭제
- endpoint가 모니터링하는 pod3번 ip가 사라짐
- 부하분산 중 pod3이 사라지고 1과2만 반복
- 고가용성 확인
- endpoint가 모니터링을 아주 잘함
# 파드의 레이블 변경
# 똑같이 ENDPOINT 모니터링에서 벗어남
# 서비스라는 오브젝트가 관심가지는 것은 레이블에 해당하는 파드뿐
###쿠버네티스의 Endpoint Controller 는 지속적으로 엔드포인트를 Watch 하고 List 에 추가, 삭제를 함###
sessionAffinity: ClientIP
- 부하분산 말고 로그에 있는 쿠키를 사용해서 처음 접근했던 파드만 계속 접근하고 싶을 때
- 클라이언트가 접속한 파드에 랜덤이 아니라 고정적인 접속을 지원 -> sessionAffinity
# sessionAffinity 설정 확인 -> none
# sessionAffinity 설정시 처음 접근했던 파드만 접근
# kubectl get svc svc-clusterip -o yaml | sed -e "s/sessionAffinity: None/sessionAffinity: ClientIP/" | kubectl apply -f -
Cluster ip 단점
- 클러스터 외부에서 서비스로 접근 불가 -> NodePort 사용
- iptables에 파드에 대한 헬스체크 기능이 없어서 문제가 생긴 파드에 연결이 가능하다 ->파드에 readiness probe 설정을 통해 문제 생기면 엔드포인트에서 삭제되도록!
NodePort
- 클러스터ip의 외부 접근이 안 되지만 nodeport는 외부접근이 가능한 서비스
-외부 클라이언트가 '노드IP:NodePort' 접속 시 해당 노드의 iptables 룰에 의해서 SNAT/DNAT 되어 목적지 파드와 통신 후 리턴 트래픽은 최초 인입 노드를 경유해서 외부로 되돌아감
- 노드포트 할당 범위는 30000-32767
노드의 ip에 노드포트 오브젝트를 달고 노드포트의 랜덤포트에 연결하면 dnat걸어서 pod로 연결해줌
cat <<EOT> svc-nodeport.yaml
apiVersion: v1
kind: Service
metadata:
name: svc-nodeport
spec:
ports:
- name: svc-webport
port: 9000
targetPort: 8080
selector:
app: deploy-websrv
type: NodePort
EOT
파드 3개 배포
#노드포트는 클러스터ip 개념 포함한다
# 포트는 노드포트 / 타겟포트는 파드
nodeport 접속 확인
# 외부에서 노드에 접근할 시 부하분산되어 접근됨
# nodeport 선언시 k8s의 모든 노드포트들이 기본적으로 오픈이 된다
# endpoint에 마스터 노드가 없지만 노드포트가 선언 될 때 모든 노드에서 해당 포트가 열린 상태가 됨
# 노드포트는 소스ip를 바꾼다
iptables 정책 확인
#tcp 트래픽으로 이 노드로 들어오는 포트 32422 모든 ip에 대해서 해당 서브체인을 따라라 그렇게 따라가다보면 cluster ip처럼 나옴
#마스터 노드 빠져나갈때 소스 ip가 nat 걸림
#masquerade 출발지 ip를 노드 ip로 변경해서 나가는 거였는데 외부에서 이 마스터로 오고 마스터에서 실제 파드가 있는 노드로 보낼 때 masquerade보내서 출발지 ip가 바뀜snat
# 소스ip가 변경이 되니까 민감한 서비스의 경우 로그를 뜰 수가 없음
# 클라이언트 ip를 수집하기 위해 externalTrafficPolicy가 필요
externalTrafficPolicy 설정
- NodePort 로 접속 시 해당 노드에 배치된 파드로만 접속됨, 이때 SNAT 되지 않아서 외부 클라이언트 IP가 보존됨!
- 소스ip를 nat 안 시킴
# 파드가 없으면 접속이 불가
# 기본 정보 확인
#local로 변경
kubectl scale deployment deploy-echo --replicas=2
- 파드 3이 사라짐
#실시간 로그 기록
kubetail -l app=deploy-websrv -f
# 파드3으로 접근이 안 되고
# client ip가 20. 대역으로 snat 안 됨 확인
# 로그 또한 ip가 그대로 찍혀서 수집 가능
노드포트 부족한 점
-외부에서 노드의 IP와 포트로 직접 접속이 필요함 → 내부망이 외부에 공개(라우팅 가능)되어 보안에 취약함 ⇒ LoadBalancer 서비스 타입으로 외부 공개 최소화 가능
-클라이언트 IP 보존을 위해서, externalTrafficPolicy: local 사용 시 파드가 없는 노드 IP로 NodePort 접속 시 실패 ⇒ LoadBalancer 서비스에서 헬스체크(Probe) 로 대응 가능
- 즉 LB로 보완이 가능하다
테트리스 게임 배포
환경
클라이언트 ip 보존
#외부pc에서 node1에 해당 nodeport 접근 시 클라이언트 ip가 변경되지 않음
## 다시 클러스터로 변경했을 때
## snat 됨
'Server&Network > Kubernets_Dokcer' 카테고리의 다른 글
쿠버네티스 API 개념 및 보안 내용 정리 (0) | 2022.03.14 |
---|---|
CoreDNS & Service (MetalLB) (0) | 2022.02.20 |
쿠버네티스 대시보드 삽질기 (0) | 2022.02.06 |
KNAS 3주차 _ 2 (0) | 2022.02.03 |
KNAS 3주차_1 (0) | 2022.02.02 |