※주의
이 글은 제가 혼자 공부하면서 여기저기 찾아보고 정리하는 곳이라서
글의 퀄리티나 내용상 맞지 않는 부분들이 있습니다.
공식문서가 더욱 더 큰 도움이 될 수 있습니다!
궁금점
쿠버네티스에서 네트워킹은 어떤 식으로 진행되고, 어떻게 연결되며 포트 포워딩에 대해서 궁금했다.
행동
쿠버네티스 클러스터 네트워킹
쿠버네티스에는 4가지 대응해야 할 네트워킹 문제가 있는데
1. 고도로 결합된 컨테이너 간의 통신
2. 파드 간 통신
3. 파드와 서비스 간 통신
4. 외부와 서비스 간 통신
서비스에 대해서
3,4번에 대해서 알기 위해서는 우선 서비스를 알아야 한다.
쿠버네티스에서 서비스는 파드의 논리적 집합과 그것들에 접근할 수 있는 정책을 정의하는 추상적 개념이다.
서비스가 대상으로 하는 파드 집합은 일반적으로 셀렉터가 결정한다. 셀렉터가 없는 서비스도 있다.
셀렉터가 있을 경우에는 엔드포인트 오브젝트가 파드의 포트에 매핑이 되지만,
셀렉터가 없을 경우에는 엔드포인트 오브젝트를 yaml파일을 통해 수동으로 생성해 주어야 한다.
1.고도로 결합된 컨테이너 간의 통신
같은 파드(pod)안에 있는 컨테이너 간의 통신이라는 얘기이다.
파드는 같은 파드안에 있는 컨테이너들 끼리는 네트워크와 저장소를 공유하기 때문에
서로서로 localhost로 접근 할 수 있다.
2.파드 간 통신
기본적으로 kubernetes는 kubenet이라는 아주 기본적이고 간단한 네트워크 플러그인을 제공 해주지만,
너무 간단하기 때문에 kubernetes에서는 Pod 네트워킹 인터페이스로
CNI 스펙을 준수하는 다양한 네트워크 플러그인을 사용하는 것을 권장한다.
그리고 알아야 하는 것은 Pod는 고유한 IP를 가지는 특징을 가지고 있다.
그래서 각 파드는 kubenet 혹은 CNI 네트워크 인터페이스(네트워크 플러그인)를 통해서
(kubelet이 시작할 때 플러그인들을 검색하고 파드 라이프사이클에서 적절한 시간에 플러그인을 실행하도록 되어있음.)
고유한 파드의 IP 주소로 서로 통신할 수 있다.
3.파드와 서비스 간 통신
service는 app:MyApp 이라는 레이블을 가진 파드의
targetPort는 TCP jenkins라는 이름을 가진 port를 대상으로 한다.
pod 템플릿에서 app:MyApp 이라는 레이블을 가지고있고
이 파드 컨테이너의 포트는 8080번지를 대상으로하고, 이름을 jenkins라고 명시해주어서
service에서 targetPort로 이 이름을 보고 들어올 수 있다.
4.외부와 서비스 간 통신
3번에서 한 것은 서비스와 파드끼리는 통신을 할 수 있지만
그것은 클러스터 내부에서의 통신이고
만약 외부 사용자가 내부의 파드에 통신을 하고싶다면
우선 외부 사용자의 트래픽을 서비스에 연결을 해주고 서비스가 3번에 있었던 것 처럼
파드에 연결을 해주는 그런 방식이다.
서비스의 default type은 clusterIP 인데 이 방식은 클러스터 내부적으로만 통신할 수 있게 되어 있다.(서비스와 파드의 통신)
그래서 서비스에 외부 통신을 가능하게 해주는 기능을 제공하는데,
외부 통신을 가능하게 해주는 Service의 type에는 두 가지가 있다.
1. NodePort
2. Load Balancer
NodePort
NodePort 타입 서비스는 기본적으로 ClusterIP 타입과 비슷하지만
노드 네트워크 IP를 통해서 접근을 할 수 있을 뿐만 아니라 ClusterIP로도 접근이 가능하다.
NodePort 서비스는 서비스에 외부 트래픽을 직접 보낼 수 있는 가장 원시적인(primitive) 방법이다. 이름에서 암시하듯이, NodePort는 모든 Node(VM)에 특정 포트를 열어 두고, 이 포트로 보내지는 모든 트래픽을 서비스로 포워딩한다.
노드 포트는 30000 - 32767 사이의 포트만 사용이 가능하다.
Load Balancer
LoadBalancer 서비스는 서비스를 인터넷에 노출하는 일반적인 방식이다.
GKE에서는 Network Load Balancer를 작동시켜 모든 트래픽을 서비스로 포워딩하는 단 하나의 IP 주소를 제공한다.
Ingress
ingress는 서비스의 한 종류가 아니고, 트래픽이 들어왔을 때
ingress를 통해서 클러스터에 들어갈 수 있게하는 입구 같은 역할을 한다.
인그레스 리소스가 작동하려면, 클러스터는 실행 중인 인그레스 컨트롤러가 반드시 필요하다.
이 외에도 다양한 컨트롤러를 제공한다.
그 중에서 알맞은 인그레스 컨트롤러를 사용하면 된다.
인그레스 컨트롤러는 일반적으로 로드 밸런서를 사용해서 인그레스를 수행할 책임이 있다.
internet
|
[ Ingress ]
--|-----|--
[ Services ]
이런식으로
최소한의 인그레스 리소스 예제:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: test-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- http:
paths:
- path: /testpath
pathType: Prefix
backend:
serviceName: test
servicePort: 80
인그레스 사양 에는 로드 밸런서 또는 프록시 서버를 구성하는데 필요한 모든 정보가 있다.
가장 중요한 것은, 들어오는 요청과 일치하는 규칙 목록을 포함하는 것이다.
인그레스 리소스는 HTTP 트래픽을 지시하는 규칙만 지원한다.
이 예시에서는, 호스트가 지정되지 않기에 지정된 IP 주소를 통해 모든 인바운드 HTTP 트래픽에 규칙이 적용 된다.
만약 호스트가 제공되면(예, foo.bar.com), 규칙이 해당 호스트에 적용된다.
기본 백엔드는 종종 사양의 경로와 일치하지 않는 서비스에 대한 모든 요청을 처리하도록
인그레스 컨트롤러에 구성되는 경우가 많다.
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: name-virtual-host-ingress
spec:
rules:
- host: first.bar.com
http:
paths:
- backend:
serviceName: service1
servicePort: 80
- host: second.foo.com
http:
paths:
- backend:
serviceName: service2
servicePort: 80
- http:
paths:
- backend:
serviceName: service3
servicePort: 80
예를 들어, 다음 인그레스 리소스는 first.bar.com에 요청된 트래픽을 service1로,
second.foo.com는 service2로, 호스트 이름이 정의되지 않은(즉, 요청 헤더가 표시 되지 않는)
IP 주소로의 모든 트래픽은 service3로 라우팅 한다.
이렇게 쿠버네티스는 인그레스 - 서비스 오브젝트를 이용해 외부와 네트워크 통신을 한다.
요약
파드안에서 컨테이너끼리 통신 = localhost를 공유
파드 끼리 통신 =
Pod의 특징 중 하나로 각 Pod는 고유한 IP 주소를 가진다.
kubelet의 기본 네트워크 플러그인 CNI로 구성된 네트워크 인터페이스를 통하여 고유한 IP 주소로 서로 통신할 수 있다.
그렇지만 pod는 쉽게 대체 될 수 있는 오브젝트이다.
어떠한 말이냐면, Pod IP를 어떤 서비스의 엔드포인트로 설정하는 것은 가능하지만, 해당 Pod가 계속 존재하고 있을 것이라는 보장도 없고 새로운 Pod가 생성되었을 때 그 IP 주소가 엔드포인트와 동일할 것이라고 보장할 수 없다는 것이다.
그래서 서비스 앞단에 proxy 혹은 로드밸런서를 위치시킨다.
클라이언트에서 proxy로 연결을 하면 proxy의 역할은
서버들 목록을 관리하며 현재 살아있는 서버에게 트래픽을 전달하는 것이다.
그 역할을 하는 것이 서비스라는 리소스 타입이다.
클러스터 내부에서 네트워크 통신 = 서비스를 이용
서비스와 외부와의 통신 = 서비스 타입중 로드밸런서, 혹은 노드포트 사용
또는 인그레스, 인그레스 컨트롤러를 사용하여 내부 서비스를 노출시킴으로써
외부와 통신한다.
참고
https://kubernetes.io/ko/docs/concepts/cluster-administration/networking/#kube-router
https://blog.leocat.kr/notes/2019/08/22/translation-kubernetes-nodeport-vs-loadbalancer-vs-ingress
https://coffeewhale.com/k8s/network/2019/05/11/k8s-network-02/
'Kubernetes & Docker > 궁금한 것' 카테고리의 다른 글
쿠버네티스 podSpec의 호스트(host)에 대해서 (0) | 2020.07.17 |
---|---|
쿠버네티스 레플리카셋(replicaset)의 실패 복구(failover)와 proxy에 대해서 (0) | 2020.07.17 |
쿠버네티스 스케줄러 : 노드(node)에 파드(pod)의 배치 방법 (2) | 2020.07.17 |
쿠버네티스 "kubectl get all" 명령어에 나오는 모든 것들에 대해서 (0) | 2020.07.17 |
쿠버네티스 YAML 파일 작성 시 실행 순서에 대해서 (0) | 2020.07.17 |