[k8s] Service 리소스 Overview (1) 공부/CLOUD

Date 2021. 8. 14. 19:26

클러스터 내부에서든 외부에서든 실제 Workload를 받는 부분인 Pod에 접근하기 위해서는 Pod의 IP정보+ port를 알아야 한다.

 

Replication Controller가 조정할 수도 있고 Node가 죽어서 다른 Node 로 파드를 옮기는 등 쿠버네티스에서 Pod라는 리소스는 항상 죽을 수 있다. 즉 Pod를 식별하는 IP는 계속 변경된다.

 

이런 문제를 해결하기 위해서 Pod에 접근하는 고정된 IP가 필요한데, 이를 담당하는 오브젝트가 바로 Service 이다.

 

서비스는 리소스가 살아있는 한 고정된 IP를 가지고 있으며, TCP/UDP 패킷을 Pod로 Redirect 해준다.

Service의 작동방식

우선 어떤 Pod로 트래픽을 분산할지 Pod를 찾아야 한다. Pod를 찾는 방법은 labelSelector가 있다. (다른 방법이 있을 수 있음~?)

 

우선 해당 Selector를 만족하는 Pod들을 찾는다. 또한 그 Pod의 IP를 이용해 Endpoint 리소스(IP:ContainerPort)를 생성한다.

 

EndPoint 리소스들은 서비스에 붙게되며, 클러스터 내부의 클라이언트가 해당 서비스에 요청을 보내면 서비스는 해당하는 Endpoint 중 하나로 트래픽을 redirect 하게 된다.

 

  • 만약 Pod가 요청에 대한 세션을 가지고 있어야 한다면 sessionAffinity 를 사용할 수 있다. 이를 통해 요청은 계속해서 동일한 Pod로 전달된다.
  • Service는 TCP/UDP 트래픽을 분산하므로 HTTP 메시지를 볼 수 없다. ( 따라서 Cookie 값을 보고 로드밸런싱 한다던지의 기능을 수행할 수 없다. )
  • 여러개의 Port를 서비스에 연결할 수 있다.
  • targetPort로 숫자 이외의 http,https 등 alias 등을 사용할 수 있다. 이렇게 사용하면 Pod의 포트가 변경되어도 서비스를 수정할 필요가 없다.

Discovering Service

클러스터 내부에서 Service로 요청을 보내려면 해당 Service의 IP를 알아야 한다. 어떻게 알아야 할까?

  1. ENV
    1. 파드가 실행되면 환경변수 값들로 서비스의 IP와 포트가 들어간다. 가장 처음 존재하는 쿠버네티스 서비스의 경우
KUBERNETES_SERVICE_HOST= ... 
KUBERNETES_SERVICE_PORT= ...

로 파드 컨테이너의 환경변수로 들어간다.

 

  1. DNS
    1. 내부 DNS 서버인 kube-dns를 이용한다. 해당 DNS 서버에 서비스의 FQDN을 쿼리함으로써 서비스의 IP를 찾을 수 있다.

Service outside the cluster

Pod가 클러스터 외부 리소스에 접근할 때도 Service 리소스를 사용할 수 있다. externalName 타입의 서비스로 클러스터 외부의 도메인을 등록함으로써 서비스의 FQDN을 통해 클러스터 외부의 서비스에 접근할 수 있다.

 

Service를 클러스터 외부에 노출하기

 

클러스터 외부의 클라이언트가 Service에 요청을 보내기 위해서는 다양한 방식이 존재한다.

 

  1. NodePort
    1. 말 그대로 (워커)Node의 Port를 오픈한다. 해당 NodeIP:Port로 요청을 보내면 NodePort서비스는 Pod로 트래픽을 redirect 한다.
    2. 서비스에 dedicated한 Node의 Port를 할당한다. 해당 서비스로 트래픽을 보내려면 두가지 방법이 존재한다. 
    3. SERVICE_IP:PORT, nth NODE IP:NODEPORT
    4. SERVICE_IP의 경우 클러스터 내부 IP이고, 클러스터 외부에서는 NODE의 IP를 통해 접근할 수 있다.(물론 인바운드 NODEPORT에 대한 트래픽을 받아야 한다.)
    5. 이 방법의 경우 특정 노드가 죽어버리면 그 IP를 통해서는 더이상 트래픽을 받지 못한다는 단점이 있다.
  1. LoadBalancer
    1. Kubernetes Cloud Provider들이 제공해주는 LoadBalancer 리소스를 통해 dedicated IP로 트래픽을 받아 NodePort로 트래픽을 redirect한다.
    2. public하게 접근가능한 IP를 할당한다. 내부적으로는 NodePort서비스로 구현된다.
    3. LB의 IP:PORT로 접근 시 특정 NodePort로 연결한다. 해당 NodePort는 또 Pod로 트래픽을 분산한다.(implicitly assigned Nodeport)
  1. Ingress
  • 주로 HTTP 패킷을 받아 여러 서비스로 패킷을 전달한다. (다음 글에서 설명)

 

Peculiarities of External Connection

  1. 불필요한 Network hops
    1. 외부에서 Pod로 트래픽을 보내려면 LB -> NodePort -> Pod를 거친다. 여기서 Node에 Pod가 존재할 수도 있고 없으면 다른 Node로 보낼 수도 있는데, 이는 불필요한 hop수를 증가시킨다.
    2. Service 오브젝트의 스펙에 externalTrafficPolicy: local 을 명시하면 해당 Node에 존재하는 파드로만 트래픽을 분산한다. ( 이 경우 해당 Node에 실행중인 Pod가 없다면 hanging된다. 또한 트래픽을 불균등하게 받을 수 있다.. 특정 Node에 실행중인 Pod가 많으면)

 

  1. Client IP를 잃어버린다.
    1. Nodeport 서비스의 경우 SNAT해서 원래의 IP를 잃어버리고 Pod에 트래픽이 도달한다.

 

References

Service, Kubernetes up & running

[Network] DNS(Domain Name System) 란 무엇일까 Computer Science/Network

Date 2021. 5. 29. 20:21

1. Domain ? 

 

웹브라우저를 통해 네이버를 접속하기 위해서 우리는 naver.com 이란 도메인을 이용한다. 하지만 웹 브라우저가 서버와 통신하기 위해서는 naver.com 가 아닌 서버의 IP 주소를 알아야 하는데 이 때 도메인을 IP 주소로 변환하는데 도움을 주는 것이 DNS 이다. 이렇게 도메인을 IP로 변환한 이후에 웹브라우저는 본격적으로 서버에 요청을 보내게 된다.

 

2. DNS 질의

 

DNS 정보를 알기 위해 클라이언트는 DNS 질의(DNS Query)를 서버에 보내게 된다. 

이 때 매번 DNS 서버에 질의를 할 수 없으므로 브라우저와 운영체제는 DNS 레코드 정보를 캐싱하게 된다. 만약 도메인 정보가 캐싱되어 있으면 그대로 변환하고, 없으면 이제 IP를 얻기 위한 DNS Query가 시작된다.

 

먼저 가장 먼저 로컬에 등록된 DNS Resolver로 쿼리를 보낸다. DNS Resolver는 클라이언트에게 적절한 응답을 할 책임이 있다. 

먼저 DNS Resolver는 클라이언트의 쿼리를 받고 자신의 캐시를 확인한다. 이 때 캐싱되어 있으면 응답하고,

아니면 루트 네임 서버에 쿼리한다. 루트 네임 서버는 전 세계에 13대 밖에 없다고 한다.

 

루트 네임 서버는 쿼리를 받고 여기서 TLD(Top-Level-Domain) 서버의 주소를 응답한다.  naver.com 의 경우 TLD는 com 으로, 루트 네임 서버는 .com DNS 서버의 주소를 응답해 준다.

 

이제 DNS Resolver는 TLD DNS 서버에 Query를 보내고, TLD DNS 서버도 마찬가지로 캐싱되어 있으면 응답하고, 그렇지 않다면 해당 도메인의 네임서버의 주소를 응답해주게 된다. 

 

마지막으로 해당 도메인의 네임서버는 DNS 레코드를 갖고 있으며, DNS Resolver -> Client 순으로 응답하게 된다.

 

DNS Query를 빨리 해결하기 위해서 서버들은 다양한 정보를 캐싱해둔다. 이 때 DNS 레코드의 TTL(Time-To-Live)란 캐싱된 정보가 유효한 시간으로 이 시간 동안은 캐싱을 유지한다.

 

 

References

 

https://www.cloudflare.com/ko-kr/learning/dns/what-is-dns/

 

'Computer Science > Network' 카테고리의 다른 글

[Network] HTTPS와 TLS  (0) 2021.06.23

[Docker] 도커의 네트워크 네임스페이스 공부/OTHERS

Date 2021. 5. 26. 21:25

1. 도커의 네트워크 디바이스

도커의 네트워크는 기본적으로 docker0라는 가상 Bridge를 중심으로 구성된다.
이외에도 호스트 네트워크를 사용하는 host, 그리고 null 즉 네트워크 없이 구성할 수도 있다.

 

2. 컨테이너 생성 시 네트워크

먼저 생성된 컨테이너는 veth 쌍을 할당받는다. 하나는 eth0 (컨테이너용), 또하나는 vethXXX로 이름이 붙여지고 docker0 브릿지에 붙는 peer이다.

이렇게 구성함으로써 컨테이너(eth0) - 호스트(vethXXX) - 브릿지(docker0) 형태로 구성되어 패킷이 오갈 수 있는 통로를 만들어준다.

컨테이너 두개를 생성하여 veth pair가 두개 생성되어 호스트에 붙은 상태다.

 


보다시피 master가 docker0으로 되어있다.

또한 여기서 컨테이너 내부에서는 route 경로로 172.0.0.1(docker0) 가 설정된 것을 볼 수 있는데 이는 컨테이너에서 나가는 패킷들은 모두 docker0으로 향하게 한다.

마지막으로 호스트에서는, docker0 브릿지로 FORWARD 되는 패킷들을 모두 ACCEPT 하여 컨테이너와 외부 간 통신이 가능하게 해준다.

 

이를 통해 컨테이너간, 또 컨테이너와 외부 간 네트워크 통신을 가능하게 해준다.

'공부 > OTHERS' 카테고리의 다른 글

[Container] Container와 VM  (0) 2021.05.27
[Linux] 네트워크 네임스페이스, veth  (0) 2021.05.25

[Linux] 네트워크 네임스페이스, veth 공부/OTHERS

Date 2021. 5. 25. 22:40

이 글은 도커 없이 컨테이너 만들기 3편 을 읽고 정리한 글입니다.

1. 네트워크 네임스페이스

리눅스 네임스페이스 중 하나인 네트워크 네임스페이스는 독립적인 네트워크 환경을 구성해 프로세스 간 격리할 수 있는 기술이다.

독립된 네트워크 네임스페이스에서 호스트 디폴트 네임스페이스로 접근할 수 없다. 반대도 마찬가지다. 이를 통해 컨테이너간 네트워크 자원을 분리할 수 있다.
RED 라는 네임스페이스와 BLUE라는 네임스페이스를 생성했다.

네임스페이스들은 모두 /var/run/netns 하위에 생성된다.

 

ip netns add RED
ip netns add BLUE

 

 

2. veth

리눅스의 버추얼 이더넷 인터페이스다. 즉 가상 NIC를 제공해준다. 쌍으로 생성되며 이를 이용해 네트워크 네임스페이스들 간 연결해줄 수 있다.
기본적으로 ip 명령어를 이용해 생성하며 down 상태로 디폴트 네트워크 네임스페이스에 존재하게 된다.

veth0veth1 두개의 쌍을 생성한다.

 

ip link add veth0 type veth peer name veth1

3. 패킷 전송하기

생성된 두 NIC를 각각 RED, BLUE 네임스페이스에 붙인다.

ip link set veth0 netns RED
ip link set veth1 netns BLUE

 

두 디바이스를 활성화 해주고 IP 주소를 할당해준다.

ip netns exec RED ip link set veth0 up ; ip netns exec RED ip addr 11.11.11.2/24 dev veth0
ip netns exec BLUE ip link set veth1 up ; ip netns exec BLUE ip addr 11.11.11.3/24 dev veth1

 

nsenter 커맨드를 이용해 네임스페이스에 진입할 수 있다. RED 네임스페이스에 진입해 아이피 주소 할당을 확인할 수 있다.

nsenter --net=/var/run/netns/RED
ip addr show

 

루프백 과 veth0에 할당된 아이피를 확인할 수 있다.

 

두 네임스페이스 모두 초기 상태이기 때문에 ARP Table, Routing Table 모두 비어있음을 알 수 있다.

ip neighbour show
// ARP table 

ip route show
// route table

 

여기서 RED -> BLUE로 패킷을 보내면 ARP Request 해서 BLUE의 MAC address 찾고 패킷을 전송할 것이다. 확인해 보자.

BLUE Terminal

tcpdump -i veth1

RED Terminal

ping 11.11.11.3

ARP Request -> Response, 그리고 ICMP 로 echo가 왔다갔다 하는것을 볼 수 있다.

 

4. Bridge

 

브릿지는 L2 계층 장비로써 Collision Domain을 쪼개줌으로써 충돌을 줄여준다.
리눅스에서는 가상 브릿지를 만드는 것도 제공해준다.

RED(reth0) - HOST(reth1) - HOST(bridge0) - HOST(beth1) - BLUE(beth0) 형식으로 네트워크를 구성해 RED->BLUE로 패킷을 전송해보겠다.

네임스페이스를 생성하고 디바이스 및 브릿지를 생성해준다.

ip netns add RED
ip link add reth0 type veth peer name reth1
ip link set reth0 netns RED

ip netns add BLUE
ip link add beth0 type veth peer name beth1
ip link set beth0 netns BLUE

ip link add bridge0 type bridge
ip link set reth1 master bridge0
ip link set beth1 master bridge0

 

디바이스들을 모두 turn on 하고 reth0과 beth0에 각각 IP address를 할당해 준다.

ip netns exec RED ip addr add 11.11.11.2/24 dev reth0
ip netns exec BLUE ip addr add 11.11.11.3/24 dev beth0

ip netns exec RED ip link set reth0 up; ip link set reth1 up
ip netns exec BLUE ip link set beth0 up; ip link set beth1 up 
ip link set br0 up

 

위와 마찬가지로 ICMP ping 을 전송한다.

 

HOST Terminal

tcpdump -l -i bridge0

 

BLUE Terminal

tcpdump -l -i beth0

RED Terminal

ping -c 1 11.11.11.3

 

ARP는 수행하지만 패킷이 전송되지 않는다. why ?

이거는 리눅스의 방화벽인 iptables 설정 때문이다.

호스트에 들어오는 모든 패킷들은 netfilter를 보고 룰에 따라 처리한다.

이때 우리가 시도하는것은 reth0 -> beth0 으로 FORWARD ( 외부끼리의 통신, 호스트를 거쳐갈 뿐이고 src dest 모두 외부다. ) 인데

디폴트로 DROP 이다. 따라서 룰 추가를 해줘야 한다.

iptables -t filter -A FORWARD -s 11.11.11.0/24 -j ACCEPT

 

src 가 11.11.11.0/24 인 FORWARD 패킷들은 ACCEPT 한다는 뜻이다.

다시 tcpdump하고 packet 전송 시 성공적으로 ping이 보내지는 것을 알 수 있다.

'공부 > OTHERS' 카테고리의 다른 글

[Container] Container와 VM  (0) 2021.05.27
[Docker] 도커의 네트워크 네임스페이스  (0) 2021.05.26

Recent Posts

Popular posts

Recent Comments

Tag List

도커 AWS 클라우드 테라폼 컨테이너 DB 네트워크 운영체제 ORM GCP 인증 리눅스 네임스페이스 백준 k8s 인가 파이썬 알고리즘 JWT TypeScript API DNS IAC JavaScript
Total : Today : Yesterday :
Blog powered by Tistory, Designed by hanarotg