티스토리 뷰
Linux Network Basics
쿠버네티스의 Network를 살펴보기 전에 이해하는데 도움이 되는 전제 조건들을 미리 학습한 후, 쿠버네티스의 network를 살펴보도록 한다. 구체적으로는 Switching and Routing, DNS, Netwrok Namespace, Docker Network의 주제에 대해 살펴 볼 것이다.
Switching and Routing
두개의 컴퓨터 A, B가 있다고 가정하자. 이 컴퓨터는 컴퓨터, 가상머신, 노트북 등을 포함한다. A에서 B로 어떻게 통신할 수 있을까? 바로 switch
다.
우리는 두대의 컴퓨터를 스위치를 통해서 연결하고, 스위치는 컴퓨터들을 연결하기 위해 두개의 시스템을 포함하는 네트워크를 생성한다. 호스트에 대한 인터페이스를 확인하려면 호스트에 따라 물리적 또는 가상 호스팅에 대한 인터페이스가 필요하다. 이 인터페이스는 ip link
커맨드로 확인할 수 있다. 또한 192.168.1.10(A), 11(B)에 대한 ip로 assign을 하기 위해서는 ip addr add
커맨드를 통해 할 수 있다.
이렇게 link가 올라가고 ip 주소가 할당되면 컴퓨터는 스위치를 통해 서로 통신을 할 수 있게 된다.
스위치는 네트워크내에서만 통신을 활성화 할 수 있다. 즉, 네트워크의 호스트로부터 패킷을 수신하여 동일한 내트워크 내의 다른 시스템에 전달할 수 있다.
여기서 C, D라는 192.168.2.10, 2.11 ip를 가진 새로운 또 다른 네트워크가 있다면 네트워크끼리는 어떻게 통신할 수 있을까? 시스템 B는 192.168.2.10으로 시스템 C에 도달한다. 여기서 필요한것이 router
다.
라우터는 두개의 네트워크를 함께 연결하는데 사용된다. 두 개의 별도 네트워크에 연결되기 때문에 또 다른 서버라고 생각하면 된다. 두개의 별도의 네트워크에 연결되기 때문에 192.168.1.1과 192.168.2.1과 같은 두개의 네트워크에 연결된 라우터를 가진다.
B가 C로 패킷을 보낼 때, 라우터가 네트워크상의 어디에 있는지 어떻게 알 수 있을까? 라우터는 다른 수많은 장치 중 하나일 뿐이다. 여기서 gateway
나 rerouting
으로 시스템을 구성한다. 네트워크가 방이면, 게이트웨이는 다른 네트워크 또는 인터넷으로 가는 문이다.
route
명령어를 통해 현재 네트워크 라우터 구성이 어떻게 되어있는지 확인할 수 있는데, 이 구성을 추가하기 위해서는 ip route add <interface ip> via <ip>
명령어로 네트워크와 인터페이스를 연결할 수 있다.
DNS
서로 연결되어 있는 시스템 A, B가 있다고 하자. 그리고 B는 데이터베이스 시스템일 때, 시스템의 IP 주소를 기억하는 대신에 DB라고 이름을 지정하기로 한다. 앞으로 IP 주소 대신 DB라는 이름을 사용하여 시스템 B에 ping을 수행하려고 한다.
그렇다면 시스템 A의 호스트 파일(/etc/hosts
) 파일에 IP 주소와 호스트에 표시할 이름을 추가해주면 된다.
이렇게 IP주소와 명칭을 대응해놓는 곳을 DNS
라고 한다. 이렇게 DNS가 존재하면, 기존에 호스트는 이 DNS에만 연결해놓으면 된다. 그리고 특정 사이트 IP 주소가 바뀌었을 때도 DNS에 들어있는 정보값만 업데이트해주면 된다.
참고할 점은 DNS와 호스트 둘 다 존재할 경우 호스트에 적힌 정보를 우선해서 바라본다.
Namespace
namespace 구분
ip netns add red ip netns add blue
link 생성 후 namespace에 구분지어주기
ip link add veth-red type veth peer name veth-blue ip line set veth-red netns red ip line set veth-blue netns blue
ip 할당
ip -n red addr add 192.168.15.1 dev veth-red ip -n blue addr add 192.168.15.1 dev veth-blue
각 namespace 내의 각 장치에 대한 설정 명령
ip -n red link set veth-red up ip -n blue link set veth-blue up
작동 확인
ip netns exec red ping <blue ip>
네임스페이스가 둘일때는 위와 같이 직접 연결했지만 그 이상일 때는 network bridge를 사용하여 각 네임스페이스마다 bridge와 연결되는 케이블(link)을 생성하고, 네임스페이스와 브릿지에 케이블을 연결시켜준다.
Docker Network
- None
- 컨테이너는 외부와 연결할 수 없고 외부에서도 컨테이너에 접근할 수 없다.
- 다중 컨테이너를 실행하면 모든 컨테이너가 네트워크에 속하지 않고 생성되며, 서로 또는 외부로 통신할 수 없다.
- Host
- 호스트 네트워크에서는 호스트와 컨테이너 사이에 네트워크 분리가 없기 때문에 컨테이너는 호스트 네트워크에 접근할 수 있다.
- 같은 포트로 두가지의 어플리케이션이 동시에 통신할 수는 없다.
- Bridge
- 도커 호스트와 컨테이너가 연결되는 내부 private 네트워크가 생성된다.
- 네트워크 주소는 default로 172.17.0.0으로 생성되며, 이 네트워크에 연결하는 각 장치는 이 네트워크의 내부 전용 네트워크 주소를 가져온다.
- 호스트에 대한 인터페이스와 비슷하지만 호스트 내의 네임스페이스 또는 컨테이너로 전환된다.
참고) 시험에서 외부 CNI를 설치하라는 경우 가장 명령어가 잘 설명되어 있는 페이지는 아래의 페이지이다. 다른 링크로의 연결은 자세히 설명되어 있지 않다.
Creating Highly Available clusters with kubeadm
Pod Networking
클러스터 외부에서뿐만 아니라 클러스터 내에서 내부적으로도 이러한 pod에서 실행되는 서비스에 어떻게 접근할 수 있을까?
쿠버네티스에서는 이러한 솔루션을 내장으로 지원하지는 않는다. 쿠버네티스는 이러한 부분을 해결하는 네트워킹 솔루션을 구현할 수 있기를 기대한다.
쿠버네티스는 모든 pod이 고유한 IP주소를 얻고, 모든 pod이 해당 IP주소를 사용하여 동일한 노드 내의 다른 모든 pod에 연결할 수 있어야 한다고 예상한다. 이러한 요구사항을 충족시켜야한다. IP주소나 IP주소의 범위나 subnet은 상관이 없다. IP주소를 자동으로 할당하는 솔루션을 구현하고 노드의 pod와 다른 노드의 pod간에 연결을 설정할 수 있다면 된다.
- 컨테이너가 생성되면, 쿠버네티스는 상호간에 통신을 하기 위해 network namespace를 생성하고, 이 네임스페이스를 네트워크에 연결한다. 여기서 생성한 network는 bridge network이다. 즉, 각 노드에 bridge network를 생성한다.
- 각 bridge network, bridge interface에 ip 주소를 할당한다.
이후의 단계는 새 컨테이너가 생성될 때마다 각 컨테이너에 대해 수행한다.
- veth(가상 이더넷 네트워크)를 생성하고, veth를 연결하고, ip 주소를 할당하고, interface를 시작하는 하나의 스크립트를 생성 후 각 컨테이너에 적용시켜준다.
이제 각 컨테이너는 상호간의 통신을 할 수 있게 된다.
그리고 다른 노드와의 통신을 하기 위해서는 아래의 과정이 필요하.
- routing table을 이용해 모든 호스트에 대해 route를 구성한다.
수동으로 스크립트를 매번 작성하고, 실행시키지 않기 위해 도입된 것이 CNI
이다. CNI
표준에 맞춰 정의하면 실제로는 CNI를 통해 위 과정이 수행된다.
kubelet
은 노드에서 컨테이너가 생성될때마다 컨테이너를 생성하는데, 그 때마다 다음와 과정을 거친다.
--cni-conf-dir=/etc/cni/net.d
실행--cni-bin-dir=/etc/cni/bin
실행./net-script.sh add <container> <namespace>
실행
CNI in Kubernetes
cni plugin
은 클러스터의 각 노드에 있는 kubelet service에서 구성된다.
CNI로 설정된 네트워크 플러그인을 확인하고 싶으면 다음과 같이 확인할 수 있다.
- ps -aux | grep kubelet
- —cni-conf-dir: config 파일
- —cni-bin-dir: 지원되는 모든 cni 플러그인이 실행 파일로 존재
- —network-plugin: 어떤 플러그인을 사용하고 있는가?
CNI weave
라우팅 테이블은 굉장히 많은 항목까진 지원하지 않을 수 있으므로 클러스터 내 노드가 굉장히 많고, 각 노드에 pod 또한 굉장히 많은 환경에서는 다른 솔루션이 필요한데, 이 문제를 weave
라는 CNI plugin을 통해 해결할 수 있다.
- weave는 먼저 각 노드에 agent or service를 배치한다. 이들은 node, network, pod에 관한 정보를 교환하기 위해 서로 통신한다.
- 각 agent 또는 peer는 다른 node의 pod와 IP를 알기 위해 전체 설정의 topology를 설정한다.
- topology: 망구성방식이라는 뜻으로 컴퓨터 네트워크의 요소들(링크, 노드 등)을 물리적으로 연결해 놓은 것. 또는 그 연결 방식
- weave는 노드에 자체 bridge를 만들고
weave
라고 이름을 붙인다. 그런 다음 IP 주소를 각 네트워크에 할당한다.
하나의 pod은 다중 bridge network에 연결될 수 있다. 예를 들어 weave bridge로 연결된 pod가 있을 때, docker에 의해 생성된 docker bridge에도 pod은 연결될 수 있다. 패킷이 대상에 도달하기 위해 사용하는 경로는 컨테이너가 구성된 경로에 따라 다르다. weave는 pod들이 agent에 도달할 수 있도록 구성된 울바른 경로를 확보하려고 한다. 그리고 agent가 다른 pod들을 처리한다. 패킷이 하나의 pod에서 다른 노드의 pod으로 보내지면 weave는 패킷을 가로채고 별도의 network에 있음을 확인한다. 그리고 이 패킷을 새로운 소스 및 대상이 있는 새 패킷으로 캡슐화하고 네트워크를 통해 전송한다. 다른쪽에서는 다른 weave agent가 패킷을 검색하고 분해하여 패킷을 올바른 pod로 라우팅하게 된다.
IP Address Management - weave
중복 IP가 할당되지 않도록 하는 방법은 무엇일까?
- 가장 쉬운 방법은 파일에 API 목록을 저장하고, 이 파일을 제대로 관리하기 위해 스크립트에 필요한 코드가 있는지 확인하는 것이다.
- 이 파일은 각 호스트에 배치되고 해당 노드에 있는 pod의 API를 관리한다.
weave는 ip 주소를 어떻게 관리할까?
- weave는 전체 network에 10.32.0.0/12에 해당하는 범위에서 ip를 할당한다.
- peer가 ip주소를 동등하게 분할하여 각 노드에 할당한다.
- 해당 노드에서 생성된 pod은 해당 범위를 가지게 된다.
클러스터에서 사용중인 네트워크 솔루션 확인하기
- ps aux | grep kubelet
- 현재 kubelet과 관련된 프로세스 확인
--network-plugin
값 확인
- 확인하였으면 해당 폴더에서 값을 확인할 수 있다.
/etc/cni/net.d/10-weave.conflist
- 따라서
weave
솔루션을 사용중인 것
weave에서 pod ip address 확인하기
kubectl logs -n kube-system <pod name>
node에 스케쥴링 된 pod의 default gateway 값 확인
- 이 값을 확인하기 위해서는 먼저 더미 pod를 생성하여 값을 확인하여야 한다.
k run busybok --image=busybox --dry-run=client -0 yaml -- sleep 1000 > busybox.yaml
- 생성된 yaml file로 들어가서 nodeName을 문제에서 요구하는 node name으로 설정
kubectl exec busybox -- ip route
명령어로 gateway 주소를 확인할 수 있다.
Service Networking
어떻게 서비스는 IP를 얻으며 어떻게 모든 클러스터 내의 모든 노드에서 IP 주소를 사용할 수 있는걸까? 또, 각 노드의 포트를 통해 외부 사용자가 서비스를 이용할 수 있는 방법은 무엇일까?
kubelet
은 kube-apiserver
를 통해서 새로운 pod가 생성되고 그 pod가 node에 생성되는 등 클러스터 내의 모든 변화를 감시하고 있다. 그런다음 cni 플러그인을 호출하여 해당 pod에 대한 네트워킹을 구성한다.
마찬가지로 각 노드에서는 kube-proxy
를 실행한다. 클러스터에서 kube api server
로 변경되고 새 서비스가 생성될 때마다 kube-proxy
가 실행된다.
service
는 클러스터 차원의 개념이며, 이러한 service
는 클러스터의 모든 노드에 존재한다. 사실 실제로 service의 ip를 실제로 수신하는 서버나 서비스는 없다. pod에는 container가 있고, container에는 interface가 있는 namespace가 있으며, IP는 service가 있는 interface에 할당되어 있다. 따라서 서비스에 대한 process, namespace, interface는 없다. 이것은 가상의 object일 뿐이다. 그렇다면 더더욱 궁금한 것은 어떻게 ip 주소를 얻고 service를 통해 pod의 applicatio에 접근할 수 있는걸까?
service object를 생성하면 미리 정의된 범위에서 ip 주소가 할당된다. 각 node에서 실행중인 kube-proxy는 해당 ip 주소를 가져오고 cluster의 각 node에 forwarding rules(이 ip로 들어오는 traffic을 특정 ip로 보내는 rule)를 만든다.
그렇다면 이러한 룰은 어떻게 만들까?
kube-proxy는 userspace, ipvs, iptables라는 다양한 방법을 지원하며 default option은 iptables이다. 이는 다음과 같이 설정할 수 있다.
- kube-proxy —proxy-mode [userspace | iptables | ipvs ]
default 설정인 iptables에 대해 알아보도록 하자.
생성한 pod를 조회해보면 ip 주소를 확인할 수 있다. 그리고 생성한 service를 조회하면 default로 cluster-ip 타입으로 지정되어 있으며 이에 해당하는 ip 주소 또한 확인할 수 있다. 이러한 주소는 kube-api-server의 —service-cluster-ip-range 옵션으로 정해진다.
- kube-api-server —service-cluster-ip-range ipNet
kube-proxy에 의해 생성된 rule은 다음으로 확인이 가능하다.
- iptables -L -t nat | grep db-service
로그 또한 확인이 가능하다.
- cat /var/log/kube-proxy.log
- 로그 확인시 어떤 option으로 rule이 생겼으며, 어떤 service가 생성되었고, 어떤 ip에 할당되었는지도 확인이 가능하다.
DNS in kubernetes
쿠버네티스는 기본적으로 내장 DNS 서버를 배포하다. service가 생성되면 쿠버네티스 DNS 서버는 service를 위한 record를 생성하고, service name과 ip addr를 매핑한다. 이로 인해 클러스터 내 어느 pod이든 service 이름을 통해 접근할 수 있다. service의 namespace가 다르면 [Servicename].[namespace]로 domain이 생성된다.
default로 생성되는 domain name은 다음과 같다.
- service
- ServiceName.Namespace.svc.cluster.local
- pod
- pod ip with dash.namespace.svc.cluster.local
CoreDNS in kubernetes
v1.12부터 쿠버네티스가 추천하고 배포하는 DNS 서버
/etc/coredns/Corefile 에서 내용을 확인 할 수 있다.
.:53 { errors health kubernetes cluster.local ... # 최상위 도메인은 cluster.local ... }
/etc/resolv.conf file이 쿠버네티스 노드의 이름 서버를 사용하도록 설정되었다.
이 core file은 pod의 configmap으로 전달된다.
기본적으로 kube-dns 라는 이름으로 서비스가 배포되고, 이 서비스의 주소가 pod에 nameserver로 구성된다.
- /var/lib/kubelet/config.yaml 파일을 확인 시 DNS 서버 주소를 볼 수 있다.
- 이를 통해 pod가 CoreDNS 서버를 가르키게 된다.
Ingress
application이 여러개가 있다면 각 application마다 service를 생성하고 port를 열어주고 ssl 설정, 보안 설정 등을 해 주는 등 직접 해 주어야 할 일이 아주 많다. 그리고 서비스가 확장되어 application이 추가되면 그 때마다 또 많은 설정을 해주어야 한다. 이를 위해 등장한 개념이 Ingress이다.
ingress는 클러스터 외부에서 내부 서비스로 접근하는 http, https 요청들을 어떻게 처리할지 정의해둔 규칙들의 모음이다.
앞에서 간단히는 Ingress가 web server user로부터 들어오는 traffic을 처리하는 기능으로만 이해했지만 이것보다 많은 기능을 담당한다. Ingress를 사용하면 위에서 언급한 직접 해 주어야할 수많은 설정들을 Ingress를 통해 단 한번만 설정하여 사용할 수 있다. 서비스가 확장되더라도 추가된 서비스를 만들어놓은 기존의 Ingress에 매칭시키면 되기 때문에 훨씬 효율적으로 운영이 가능하다.
Ingress는 Ingress controller가 있어야 Ingress를 충족할 수 있다. Ingress resource만 생성한다면 효과가 없다.
Ingress controller
- Ingress resource가 동작하기 위해서는 Ingress controller가 반드시 필요하다.
- Ingress controller는 자동으로 실행되지 않으며, 클러스터에 가장 적합한 컨트롤러를 선택하여 구현해야한다.
- ingress를 위해서는 최소한 deployment file, service file, configmap, service accounts가 필요하다.
Ingress resource
- ingress controller에 적용되는 규칙 및 구성의 집합이다.
- 요청이 들어왔을 때, 바로 pod로 보내는 것이 아니라 service로 보낸다.
Imperative Command
- kubectl create ingress
—rule=”host/path=service:port” - e.g) kubectl create ingress
—rule=”wear.my-online-store.com/wear*=wear-service:80”
'Infrastructure > Kubernetes' 카테고리의 다른 글
[CKA] 합격 후기(feat. 잃어버린 30분을 찾아서, PSI Bridge 환경에 대해..) (0) | 2022.09.20 |
---|---|
[CKA] Storage (0) | 2022.08.03 |
[CKA] Security (0) | 2022.08.03 |
[CKA] Cluster Maintenance (0) | 2022.07.30 |
[CKA] Application Lifecycle Management (0) | 2022.07.28 |
- Total
- Today
- Yesterday
- elasticsaerch
- DP
- 백준
- Hadoop
- cka
- CS
- 네트워크
- 파이썬
- logstash
- sqoop
- Python
- GROK
- DFS
- oozie
- mahout
- kubernetes
- 빅데이터
- kafka
- 프로그래머스
- 이코테
- CSAPP
- 빅데이터를지탱하는기술
- Algorithm
- Elasticsearch
- BOJ
- Flutter
- OS
- Espher
- HDFS
- heapq
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |