본문 바로가기
MLOps/Doker & Kubernetes

Udemy CKA 강의 정리 219: Service-Networking

by 공부하는 무니 2023. 1. 25.
반응형

해당 내용은 Udemy의 Certified Kubernetes Administrator (CKA) with Practice Tests 강의를 공부한 내용입니다. 내용을 그대로 번역하기보다는, 제가 이해하기 쉬운 대로 수정한 부분들이 있습니다.

⚠️ 영어 독해가 많이 부족합니다. 틀린 내용이 있으면 알려주시면 감사하겠습니다.


이 강의에서는 서비스 네트워킹에 대해 논의할 것입니다. 이전 강의에서는 파드 네트워킹에 대해 이야기했습니다. 각 노드 내에서 브리지 네트워크를 생성하는 방법, 파드가 네임스페이스를 생성하는 방법, 파드가 이러한 네임스페이스에 연결되는 방법, 파드가 해당 노드에 할당된 이 서브넷 내에서 브리지 네트워크에 할당된 IP 주소를 얻는 방법을 살펴보고 route나 다른 오버레이 기술을 통해 우리는 다른 노드에 있는 파드들이 서로 대화하도록 하여 모든 파드들이 서로 연결될 수 있는 큰 가상 네트워크를 형성할 수 있다는 것을 보았습니다.

이제 파드가 서로 직접 통신하도록 구성하는 경우는 거의 없습니다. 다른 파드에서 호스팅되는 서비스에 액세스하려면 항상 서비스를 사용해야 합니다. 다양한 종류의 서비스에 대해 간단히 요약해 보겠습니다. blue 파드가 orange 파드에 접근할 수 있도록, 우리는 orange 서비스를 만듭니다. orange 서비스는 IP 주소와 할당된 이름을 가져옵니다. 이제 blue 파드는 orange 서비스 IP 또는 해당 이름을 통해 orange 파드에 액세스할 수 있습니다. 우리는 이번 강의에서 name resolution에 대해 이야기할 것입니다.

지금은 IP 주소에만 집중합시다. blue과 orange 보드가 같은 노드에 있습니다. 다른 파드나 다른 노드에서 액세스하는 것은 어떻습니까? 서비스가 생성되면 파드가 어떤 노드에 있는지에 관계없이 클러스터의 모든 파드에서 서비스에 액세스할 수 있습니다. 파드가 노드에서 호스팅되는 동안 서비스는 클러스터 전체에서 호스팅됩니다. 이 서비스는 특정 노드에 바인딩되지 않지만 클러스터 내에서만 액세스할 수 있습니다. 이러한 유형의 서비스를 클러스터 IP라고 합니다. orange 파드가 클러스터 내에서만 액세스할 수 있는 데이터베이스 애플리케이션을 호스팅하고 있었다면 이러한 유형의 서비스는 제대로 작동합니다.

Service Types

clusterIP.yaml

apiVersion: v1
kind: Service
metadata:
  name: local-cluster
spec:
  ports:
  - port: 80
    targetPort: 80
  selector:
    app: nginx
nodeportIP.yaml

apiVersion: v1
kind: Service
metadata:
  name: nodeport-wide
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: 80
  selector:
    app: nginx

예를 들어, purple 파드가 클러스터 외부에서 파드의 애플리케이션에 액세스할 수 있도록 웹 애플리케이션을 호스팅하고 있었다고 가정해 보겠습니다. 노드 포트 유형의 다른 서비스를 생성합니다. 또한 이 서비스는 할당된 IP 주소를 가져오고 클러스터 IP와 마찬가지로 작동합니다. 다른 모든 파드에서는 IP를 사용하여 서비스에 액세스할 수 있습니다.

또한 클러스터의 모든 노드에 있는 포트에 애플리케이션이 노출됩니다. 이렇게 하면 외부 사용자 또는 응용프로그램이 서비스에 액세스할 수 있습니다. 이것이 이번 강의의 주제입니다. 우리는 파드보다는 서비스에 더 초점을 맞추고 있습니다. 서비스는 어떻게 이러한 IP 주소를 가져오고 클러스터의 모든 노드에서 이러한 IP 주소를 사용할 수 있을까요? 각 노드의 포트를 통해 외부 사용자가 서비스를 이용할 수 있는 방법은 무엇인가요? 누가, 어떻게, 그리고 어디에서 그것을 볼 수 있을까요? 그럼 시작해볼게요. 백지상태에서 시작합시다.

세 노드 클러스터가 있고 파드나 서비스는 아직 없습니다. 우리는 모든 Kubernetes 노드가 파드를 만드는 kubelet 프로세스를 실행한다는 것을 알고 있습니다. 각 노드의 각 kubelet 서비스는 kube API 서버를 통해 클러스터의 변경 사항을 모니터링하며, 새로운 파드가 생성될 때마다 노드에 파드를 생성합니다. 그런 다음 CNI 플러그인을 호출하여 해당 파드에 대한 네트워킹을 구성합니다.

비슷하게, 각 노드는 Kube-proxy로 알려진 또 다른 컴포넌트를 실행합니다. Kube-proxy는 Kube API 서버를 통해 클러스터의 변화를 감시하고, 새로운 서비스가 생성될 때마다 Kube-proxy가 실행됩니다.

파드와 달리 서비스는 각 노드에 생성되거나 각 노드에 할당되지 않습니다. 서비스는 클러스터 차원의 개념입니다. 클러스터의 모든 노드에 존재합니다. 사실, 그들은 전혀 존재하지 않습니다. 서비스의 IP를 실제로 수신하는 서버나 서비스가 없습니다. 파드에는 컨테이너가 있고 컨테이너에는 인터페이스와 Ip가 할당된 네임스페이스가 있습니다. 서비스와 함께라면, 그런 것은 존재하지 않는다. 서비스에 대한 프로세스, 네임스페이스 또는 인터페이스가 없습니다. 그것은 단지 가상의 물체일 뿐입니다. 그렇다면 그들은 어떻게 IP 주소를 얻고 우리는 어떻게 서비스를 통해 파드의 애플리케이션에 액세스할 수 있을까요?

To create the service

$ kubectl create -f clusterIP.yaml
service/local-cluster created

$ kubectl create -f nodeportIP.yaml
service/nodeport-wide created

To get the Additional Information

$ kubectl get pods -o wide
NAME    READY   STATUS    RESTARTS   AGE   IP           NODE     NOMINATED NODE   READINESS GATES
nginx   1/1     Running   0          1m   10.244.1.3   node01   <none>           <no

Kubernetes에서 서비스 오브젝트를 만들면 미리 정의된 범위의 IP 주소가 할당됩니다. 이 노드에서 실행 중인 kube-proxy 컴포넌트는 해당 IP 주소를 가져오고 클러스터의 각 노드에 전달 rule을 생성합니다. 즉, 서비스의 IP인 이 IP로 오는 트래픽은 파드의 IP로 가야 합니다. 일단 서비스가 설치되면 파드가 서비스의 IP에 도달하려고 할 때마다 서비스는 클러스터의 모든 노드에서 액세스할 수 있는 파드의 IP 주소로 전달됩니다. IP뿐만 아니라 IP와 포트의 조합이라는 점을 기억하세요. 서비스가 생성되거나 삭제될 때마다 kube-proxy 컴포넌트는 이러한 rule을 생성하거나 삭제합니다.

그렇다면 이 rule들은 어떻게 만들어졌을까요? kube-proxy는 각 서비스에 대해 포트에서 수신 대기하는 사용자 공간과 같은 다양한 방식을 지원하며, IPVS rule을 만들어 파드에 대한 연결을 프록시합니다. 우리에게 익숙한 것은 IP 테이블을 사용하는 것입니다. 프록시 모드는 kube-proxy 서비스를 구성하는 동안 프록시 모드 옵션을 사용하여 설정할 수 있습니다. 이 옵션을 설정하지 않으면 default로 IP 테이블로 설정됩니다.

To check the Service Cluster IP Range

$ ps -aux | grep kube-apiserver
--secure-port=6443 --service-account-key-file=/etc/kubernetes/pki/sa.pub --
service-cluster-ip-range=10.96.0.0/12

이제 IP 테이블이 kube-proxy에 의해 구성되는 방법과 노드에서 이를 볼 수 있는 방법을 살펴보겠습니다. 노드 1에 배치된 DB라는 파드가 있습니다. IP 주소는 10.244.1.2입니다. 클러스터 내에서 이 파드를 사용할 수 있도록 클러스터 IP 유형의 서비스를 생성합니다. 서비스가 생성되면 Kubernetes는 서비스에 IP 주소를 할당합니다. 10.103.132.104로 설정됩니다. 이 범위는 서비스 클러스터 IP 범위라고 하는 Kube API 서버 옵션에 지정되며, default로 10.0.0/24로 설정됩니다. 이 경우,  Kube API 서버 옵션을 보면 10.96.0.0/12로 설정되어 있습니다. 이를 통해 10.96.0.0에서 10.111.255.255 사이의 서비스 IP를 얻을 수 있습니다. 여기서 언급해야 할 상대적인 사항은 POD 네트워킹을 설정할 때 10244.0.0/16 범위의 파드 네트워크 CIDR을 제공하여 1024400에서 10244.255.255 사이의 파드 IP 주소를 제공했다는 것입니다. 제가 이 문제를 제기한 이유는 각 네트워크에 대해 어떤 범위를 지정하든 중복되지 않아야 하기 때문입니다.

To check the rules created by kube-proxy in the iptables

$ iptables -L -t nat | grep local-cluster
KUBE-MARK-MASQ  all  --  10.244.1.3           anywhere             /* default/local-cluster: */
DNAT       tcp  --  anywhere             anywhere             /* default/local-cluster: */ tcp to:10.244.1.3:80
KUBE-MARK-MASQ  tcp  -- !10.244.0.0/16        10.101.67.139        /* default/local-cluster: cluster IP */ tcp dpt:http
KUBE-SVC-SDGXHD6P3SINP7QJ  tcp  --  anywhere             10.101.67.139        /* default/local-cluster: cluster IP */ tcp dpt:http
KUBE-SEP-GEKJR4UBUI5ONAYW  all  --  anywhere             anywhere             /* default/local-cluster: */

이 경우에는 그렇지 않습니다. 이 두 가지 모두 사용할 수 있는 전용 IP 범위가 있어야 합니다. 파드와 서비스에 동일한 IP 주소가 할당되는 경우는 없어야 합니다. 서비스로 돌아가면 서비스가 10.103.132.104의 IP 주소를 얻게 됩니다. IP 테이블 넷 테이블 출력에서 Kube-proxy에 의해 생성된 rule을 확인할 수 있습니다. Kube-proxy에 의해 생성된 모든 rule에 서비스 이름이 포함된 주석이 있으므로 서비스 이름을 검색합니다. 이러한 rule은 서비스의 IP인 포트 3306의 IP 주소 10103132.104로 가는 트래픽은 대상 주소가 10244.1.2로 변경되고 파드의 IP인 포트 3306이 변경되어야 함을 의미합니다. 이 작업은 IP 테이블에 Dnet rule을 추가하여 수행됩니다. 마찬가지로 노드 포트 유형의 서비스를 생성할 때 Kube-proxy는 모든 노드의 포트에서 들어오는 모든 트래픽을 해당 백엔드 파드로 전달하는 IP 테이블 rule을 생성합니다.

To check the logs of kube-proxy

$ cat /var/log/kube-proxy.log

또한 kube-proxy 로그 자체에서 이러한 항목을 생성하는 것을 볼 수 있습니다. 로그에서 어떤 프록시를 사용하는지 확인할 수 있습니다. 이 경우에는 IP 테이블이며, 데이터베이스에 대한 새 서비스를 추가할 때 항목을 추가합니다. 이 파일의 위치는 설치에 따라 다를 수 있습니다. 이러한 항목이 표시되지 않으면 verbosity level도 확인해야 합니다. 그게 바로 서비스 네트워킹에 관한 것입니다. 다음 강의 때 뵙겠습니다.

반응형

댓글