네트워크 개요

이 페이지에서는 Google Kubernetes Engine 네트워킹의 주요 특징 개요를 설명합니다. 여기에서는 Kubernetes를 처음 시작하는 사용자는 물론 애플리케이션을 더 효과적으로 설계하거나 Kubernetes 작업 부하를 더 효과적으로 구성하기 위해 Kubernetes 네트워킹에 대해 자세히 알고 싶어하는 숙련된 클러스터 운영자 또는 애플리케이션 개발자를 위해서도 유용한 정보를 제공합니다.

Kubernetes를 사용하면 애플리케이션의 배포 방식, 애플리케이션이 서로 간에 그리고 Kubernetes 제어 영역과 통신하는 방식, 클라이언트가 애플리케이션에 연결하는 방식을 선언적으로 정의할 수 있습니다. 이 페이지에서는 또한 GKE가 네트워킹과 관련된 Google Cloud Platform 서비스를 구성하는 방식에 대한 정보도 제공합니다.

Kubernetes를 사용해서 애플리케이션을 조정할 때는 애플리케이션 및 해당 호스트의 네트워크 설계에 대한 생각을 바꾸는 것이 중요합니다. Kubernetes에서는 호스트 또는 VM이 연결되는 방식보다는 포드, 서비스, 외부 클라이언트가 통신하는 방식이 더 중요합니다.

Kubernetes는 GCP와 함께 Kubernetes 배포의 선언적 모델 및 GCP에서의 클러스터 구성에 따라 각 노드에서 IP 필터링 규칙, 라우팅 테이블, 방화벽 규칙을 동적으로 구성합니다. 노드에서 항목을 수동으로 변경하면 GKE에서 이러한 변경 사항이 재정의되고, 클러스터가 올바르게 작동하지 않을 수 있으므로, 하지 않아야 합니다. 노드에 직접 액세스하는 유일한 이유는 구성 관련 문제를 디버깅하기 위한 것입니다.

기본 요건

이 페이지에서는 HTTPDNS를 포함하여 인터넷 프로토콜전송, 인터넷, 애플리케이션 레이어와 관련된 용어가 사용되지만 이러한 개념에 대한 전문적인 지식이 필요하지는 않습니다.

또한 Linux 네트워크 관리 개념과 iptables 규칙 및 라우팅과 같은 유틸리티를 기본적으로 알고 있으면 이 페이지 내용을 더 쉽게 이해할 수 있을 것입니다.

Kubernetes 네트워킹 모델은 IP 주소에 크게 의존합니다. 서비스, 포드, 컨테이너, 노드는 IP 주소와 포트를 사용하여 통신합니다. Kubernetes는 트래픽을 올바른 포드로 전달하기 위해 다양한 유형의 부하 분산을 제공합니다. 이러한 메커니즘은 모두 이 항목의 후반부에서 자세히 설명합니다. 이 페이지를 읽는 동안 다음과 같은 용어에 유의하세요.

  • ClusterIP: 서비스에 할당된 IP 주소입니다. 다른 문서에서는 '클러스터 IP'로 표시될 수도 있습니다. 이 주소는 이 항목의 서비스 섹션에 설명된 것처럼 서비스 수명 기간 동안 안정적으로 유지됩니다.
  • 포드 IP: 특정 포드에 할당된 IP 주소입니다. 이 주소는 이 항목의 포드 섹션에 설명된 것처럼 일시적입니다.
  • 노드 IP: 특정 노드에 할당된 IP 주소입니다.

클러스터 내부의 네트워킹

이 섹션에서는 IP 할당, 포드, 서비스와 관련된 Kubernetes 클러스터 내부의 네트워킹에 대해 설명합니다.

IP 할당

Kubernetes는 다양한 IP 범위를 사용해서 노드, 포드, 서비스에 IP 주소를 할당합니다.

  • 각 노드에는 클러스터의 VPC(Virtual Private Cloud) 네트워크에서 할당되는 IP 주소가 포함됩니다. 이 노드 IP는 kube-proxykubelet과 같은 제어 구성요소에서 Kubernetes API 서버로의 연결을 제공합니다.
  • 각 포드에는 256개의 IP 주소 범위에서 할당된 IP 주소가 포함됩니다(/24 CIDR 블록). 원한다면 클러스터를 만들 때 이 범위를 지정할 수 있습니다.
  • 각 서비스에는 클러스터의 VPC 네트워크에서 할당된 ClusterIP라는 IP 주소가 포함됩니다. 원한다면 클러스터를 만들 때 VPC 네트워크를 맞춤설정할 수 있습니다.

자세한 내용은 별칭 IP를 사용하여 VPC 네이티브 클러스터 만들기를 참조하세요.

포드

Kubernetes에서 포드는 Kubernetes 클러스터 내에서 가장 기본적인 배포 가능한 단위입니다. 포드는 하나 이상의 컨테이너를 실행합니다. 한 노드에서는 0개 이상의 포드가 실행됩니다. 클러스터에 있는 각 노드는 노드 풀에 속합니다. GKE에서 이러한 노드는 Compute Engine에서 하나의 인스턴스로 실행되는 가상 머신입니다.

포드는 또한 외부 저장소 볼륨 및 다른 커스텀 리소스에 연결될 수 있습니다. 아래 다이어그램은 각각 2개의 볼륨에 연결된 2개의 포드를 실행하는 단일 노드를 보여 줍니다.

위 단락에 설명된 대로 2개 포드를 실행하는 단일 노드 다이어그램

Kubernetes는 노드에서 실행할 포드를 예약할 때 노드의 Linux 커널에 있는 포드의 네트워크 네임스페이스를 만듭니다. 이 네트워크 네임스페이스는 가상 네트워크 인터페이스를 사용하여 노드의 물리적 네트워크 인터페이스(예: eth0)를 포드와 연결하므로 패킷이 포드를 오고 갈 수 있습니다. 노드의 루트 네트워크 네임스페이스에 있는 연결될 가상 네트워크 인터페이스가 Linux 브리지에 연결되어, 동일 노드에서 포드 간 통신을 허용합니다. 또한 포드는 동일한 가상 인터페이스를 사용해서 노드 외부로 패킷을 전송할 수 있습니다.

Kubernetes는 노드의 포드에 대해 예약된 주소 범위에서 포드의 네트워크 네임스페이스에 있는 가상 네트워크 인터페이스에 IP 주소(포드 IP)를 할당합니다. 이 주소 범위는 클러스터를 만들 때 구성할 수 있는 포드의 클러스터에 할당된 IP 주소 범위의 하위 집합입니다.

포드에서 실행되는 컨테이너는 포드의 네트워크 네임스페이스를 사용합니다. 컨테이너의 관점에서 포드는 하나의 네트워크 인터페이스를 포함하는 물리적 머신으로 표시됩니다. 포드의 모든 컨테이너에는 이러한 동일한 네트워크 인터페이스가 표시됩니다. 각 컨테이너의 localhost는 포드를 통해 노드의 물리적 네트워크 인터페이스(예: eth0)에 연결됩니다.

기본적으로 각 포드에는 클러스터의 모든 노드에서 실행되는 다른 모든 포드에 대해 제한되지 않은 액세스를 갖지만, 사용자가 포드 간 액세스를 제한할 수 있습니다. Kubernetes는 포드를 정기적으로 분해하고 다시 만듭니다. 이러한 작업은 노드 풀이 업그레이드될 때, 포드의 선언적 구성을 변경하거나 컨테이너의 이미지를 변경할 때, 또는 노드가 사용 불가능하게 될 때 발생합니다. 따라서 포드의 IP 주소는 구현에 따라 달라지며, 여기에 의존해서는 안 됩니다. Kubernetes는 서비스를 사용해서 안정적인 IP 주소를 제공합니다.

서비스

Kubernetes에서는 라벨이라고 부르는 임의의 키-값 쌍을 모든 Kubernetes 리소스에 할당할 수 있습니다. Kubernetes는 라벨을 사용하여 여러 관련된 포드를 서비스라는 논리 단위로 그룹화합니다. 서비스는 안정적인 IP 주소 및 포트를 포함하며, 사용자가 서비스를 만들 때 라벨 선택기에서 정의하는 모든 라벨과 라벨이 일치하는 포드 집합 간에 부하 분산을 제공합니다.

다음 다이어그램은 2개의 개별 서비스를 보여줍니다. 이러한 각 서비스는 여러 포드로 구성됩니다. 다이어그램에 있는 각 포드에는 app=demo 라벨이 있지만 다른 라벨은 서로 다릅니다. 'frontend' 서비스는 모든 포드를 app=democomponent=frontend에 일치시키고, 'user' 서비스는 모든 포드를 app=democomponent=users에 일치시킵니다. 클라이언트 포드는 두 서비스 선택기 중 어느 것과도 정확하게 일치하지 않으므로 어느 서비스에도 속하지 않습니다. 하지만 클라이언트 포드는 동일한 클러스터에서 실행되기 때문에 서비스 중 하나와 통신할 수 있습니다.

이전 단락에 설명된 2개의 개별 서비스 다이어그램

Kubernetes는 사용 가능한 서비스 IP 주소의 클러스터 풀에서 새로 생성된 각 서비스(ClusterIP)에 안정적이고 신뢰할 수 있는 IP 주소를 할당합니다. Kubernetes는 또한 DNS 항목을 추가하여 ClusterIP에 호스트 이름을 할당합니다. ClusterIP 및 호스트 이름은 클러스터 내에서 고유하며 서비스 수명 주기 동안 변경되지 않습니다. Kubernetes는 클러스터 구성에서 서비스가 삭제될 경우에만 ClusterIP 및 호스트 이름을 해제합니다. ClusterIP 또는 서비스의 호스트 이름을 사용하여 애플리케이션을 실행하는 정상 상태의 포드에 연결할 수 있습니다.

처음에는 서비스가 애플리케이션의 단일 장애 지점인 것으로 보일 수 있습니다. 하지만 Kubernetes는 여러 노드에서 실행되는 전체 포드 집합 간에 가능한 한 고르게 트래픽을 분산하므로, 모두가 아닌 하나 이상의 노드에 영향을 주는 중단이 발생해도 클러스터가 이를 견딜 수 있습니다.

Kubernetes는 각 노드에서 실행되는 kube-proxy 구성요소를 사용하여 포드 및 서비스 간 연결을 관리합니다. 인라인 프록시가 아니지만 송신 기반 부하 분산 컨트롤러인 kube-proxy는 Kubernetes API 서버를 감시하고, 노드의 iptables 하위 시스템에 DNAT(대상 NAT) 규칙을 추가하고 삭제함으로써 ClusterIP를 정상 상태의 포드에 계속해서 매핑합니다. 포드에서 실행되는 컨테이너가 서비스의 ClusterIP에 트래픽을 전송할 때 노드는 포드를 무작위로 선택하고 이 포드로 트래픽을 라우팅합니다.

서비스를 구성할 때 porttargetPort 값을 정의하여 수신 포트를 선택적으로 다시 매핑할 수 있습니다.

  • port는 클라이언트가 애플리케이션에 연결하는 지점입니다.
  • targetPort는 애플리케이션이 포드 내에서 트래픽을 실제로 수신 대기하는 포트입니다.

kube-proxy는 노드에서 iptables 규칙을 추가 및 삭제하여 이러한 포트 다시 매핑을 관리합니다.

이 다이어그램은 클라이언트 포드에서 다른 노드의 서버 포드로의 트래픽 흐름을 보여 줍니다. 클라이언트는 172.16.12.100:80에서 서비스에 연결합니다. Kubernetes API 서버는 애플리케이션을 실행하는 포드 목록을 유지 관리합니다. 각 노드의 kube-proxy 프로세스는 이 목록을 사용해서 적절한 포드(예: 10.255.255.202:8080)로 트래픽을 보내기 위한 iptables 규칙을 만듭니다. 클라이언트 포드는 클러스터의 토폴로지 또는 내부의 개별 포드 또는 컨테이너에 대한 세부정보를 알 필요가 없습니다.

이전 단락에 설명된 대로 서비스에 연결되는 클라이언트 및 포드로 라우팅되는 클라이언트 다이어그램

클러스터 외부 네트워킹

이 섹션에서는 클러스터 외부의 트래픽이 Kubernetes 클러스터 내부에서 실행되는 애플리케이션에 연결되는 방법을 설명합니다. 이 정보는 클러스터의 애플리케이션 및 작업 부하를 디자인할 때 중요합니다.

Kubernetes가 서비스를 사용해서 포드 내에서 실행되는 애플리케이션에 안정적인 IP 주소를 제공하는 방법은 이미 살펴봤습니다. kube-proxy가 각 노드에서 모든 트래픽을 관리하기 때문에 기본적으로 포드는 외부 IP 주소를 노출하지 않습니다. 포드 및 해당 컨테이너는 자유롭게 통신할 수 있지만, 클러스터 외부의 연결은 서비스에 액세스할 수 없습니다. 예를 들어 이전 그림에서 클러스터 외부의 클라이언트는 해당 ClusterIP를 통해 frontend 서비스에 액세스할 수 없습니다.

GKE는 액세스를 제어하고 들어오는 트래픽을 클러스터 간에 가능한 한 고르게 분산하기 위해 세 가지 유형의 부하 분산기를 제공합니다. 하나의 서비스가 여러 유형의 부하 분산기를 동시에 사용하도록 구성할 수 있습니다.

  • 외부 부하 분산기는 클러스터 외부 및 GCP VPC(Virtual Private Cloud) 네트워크에서 들어오는 트래픽을 관리합니다. 외부 부하 분산기는 GCP 네트워크에 연결된 전달 규칙을 사용해서 트래픽을 Kubernetes 노드로 라우팅합니다.
  • 내부 부하 분산기는 동일한 VPC 네트워크 내에서 들어오는 트래픽을 관리합니다. 외부 부하 분산기처럼 내부 부하 분산기도 GCP 네트워크에 연결된 전달 규칙을 사용하여 트래픽을 Kubernetes 노드로 라우팅합니다.
  • HTTP(S) 부하 분산기는 HTTP(S) 트래픽에 사용되는 특별한 외부 부하 분산기입니다. 이 부하 분산기는 전달 규칙 대신 Ingress 리소스를 사용해서 트래픽을 Kubernetes 노드로 라우팅합니다.

트래픽이 Kubernetes 노드에 연결되면 부하 분산기 유형에 관계없이 동일한 방식으로 처리됩니다. 부하 분산기는 클러스터의 어떤 노드가 해당 서비스에 대해 포드를 실행 중인지 알 수 없습니다. 대신 관련 포드를 실행하지 않는 노드까지 포함해 클러스터의 모든 노드에 트래픽을 분산합니다. 리전 클러스터에서는 클러스터 리전의 모든 영역에 있는 모든 노드에 부하가 분산됩니다. 트래픽이 노드로 라우팅되면 노드는 동일 노드나 다른 노드에서 실행 중인 포드로 트래픽을 라우팅합니다. 노드는 kube-proxy가 노드에서 관리하는 iptables 규칙을 사용하여 무작위로 선택된 포드에 트래픽을 전달합니다.

다음 다이어그램에서 네트워크 부하 분산기는 중간 노드로 트래픽을 전달하고, 트래픽은 첫 번째 노드에 있는 포드로 리디렉션됩니다.

이전 단락의 설명처럼 노드에서 다른 노드의 포드로 라우팅되는 트래픽을 보여 주는 다이어그램

부하 분산기가 노드로 보내는 트래픽은 다른 노드에 있는 포드로 전달될 수 있습니다. 그러려면 추가 네트워크 홉이 필요합니다. 추가 홉을 피하려면 트래픽을 처음 수신하는 동일 노드에 있는 포드로 트래픽이 가야 한다고 지정할 수 있습니다.

동일 노드에 있는 포드로 트래픽이 가야 한다고 지정하려면 서비스 매니페스트에서 externalTrafficPolicyLocal로 설정하세요.

apiVersion: v1
kind: Service
metadata:
  name: my-lb-service
spec:
  type: LoadBalancer
  externalTrafficPolicy: Local
  selector:
    app: demo
    component: users
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080

externalTrafficPolicyLocal로 설정하면 부하 분산기는 서비스에 속한 정상적 포드가 있는 노드에만 트래픽을 보냅니다. 부하 분산기는 상태 확인을 사용하여 적절한 포드가 있는 노드를 확인합니다.

외부 부하 분산기

클러스터 외부 및 VPC 네트워크 외부에서 서비스에 연결해야 하는 경우에는 서비스를 정의할 때 서비스의 type 필드를 LoadBalancer로 설정하여 서비스를 LoadBalancer로 구성할 수 있습니다. 그러면 GKE가 서비스 앞에 네트워크 부하 분산기를 프로비저닝합니다. 네트워크 부하 분산기는 클러스터에 있는 모든 노드를 인식하고, 서비스의 외부 IP 주소를 사용하여 VPC 네트워크 외부에서 서비스에 대한 연결을 허용하도록 VPC 네트워크의 방화벽 규칙을 구성합니다. 서비스에 고정 외부 IP 주소를 할당할 수 있습니다. 자세한 내용은 고정 IP 주소를 사용하여 도메인 이름 구성을 참조하세요.

기술 세부정보

외부 부하 분산기를 사용할 때 수신 패킷은 처음에 GCP 네트워크와 연결된 전달 규칙을 사용하여 노드에 라우팅됩니다. 트래픽이 노드에 도달한 후 노드는 해당 iptables NAT 테이블을 사용하여 포드를 선택합니다. kube-proxy는 노드에서 iptables 규칙을 관리합니다.

내부 부하 분산기

동일한 VPC 네트워크 내에서 클러스터에 도달해야 하는 트래픽의 경우, 내부 부하 분산기를 프로비저닝하도록 서비스를 구성할 수 있습니다. 내부 부하 분산기는 외부 IP 주소 대신 클러스터의 VPC 서브넷에서 IP 주소를 선택합니다. VPC 네트워크 내부의 애플리케이션 또는 서비스는 이 IP 주소를 사용하여 클러스터 내부의 서비스와 통신할 수 있습니다.

기술 세부정보

내부 부하 분산 기능은 GCP에서 제공됩니다. 트래픽이 특정 노드에 도달하면 해당 노드는 포드가 다른 노드에 있더라도 iptables NAT 테이블을 사용하여 포드를 선택합니다. kube-proxy는 노드에서 iptables 규칙을 관리합니다.

내부 부하 분산기에 대한 자세한 내용은 내부 부하 분산기 문서를 참조하세요.

HTTP(S) 부하 분산기

RESTful 웹 서비스 API와 같은 많은 애플리케이션이 HTTP(S)를 사용하여 통신합니다. VPC 네트워크 외부의 클라이언트가 Kubernetes Ingress 리소스를 사용해서 이 유형의 애플리케이션에 액세스하도록 허용할 수 있습니다. Ingress 리소스를 사용하면 호스트 이름 및 URL 경로를 클러스터 내의 서비스에 매핑할 수 있습니다. HTTP(S) 부하 분산기를 사용할 때는 ClusterIP뿐 아니라 NodePort도 사용하도록 서비스를 구성해야 합니다. 트래픽이 NodePort에서 노드의 IP로 서비스에 액세스할 때 GKE는 해당 서비스를 위한 정상 상태의 포드로 트래픽을 라우팅합니다. NodePort를 지정하거나 GKE가 사용되지 않는 포트를 무작위로 할당하도록 허용할 수 있습니다.

Ingress 리소스를 만들 때, GKE는 GCP 프로젝트에서 HTTP(S) 부하 분산기를 프로비저닝합니다. 부하 분산기는 NodePort에서 노드의 IP 주소로 요청을 전송합니다. 요청이 노드에 도달한 후 노드는 해당 iptables NAT 테이블을 사용하여 포드를 선택합니다. kube-proxy는 노드에서 iptables 규칙을 관리합니다.

이 Ingress 정의는 포트 80에서 frontend라는 서비스로 demo.example.com 트래픽을 라우팅하고, 포트 8080에서 users라는 서비스로 demo-backend.example.com 트래픽을 라우팅합니다.

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: demo
spec:
  rules:
  - host: demo.example.com
    http:
      paths:
      - backend:
          serviceName: frontend
          servicePort: 80
  - host: demo-backend.example.com
    http:
      paths:
      - backend:
          serviceName: users
          servicePort: 8080

자세한 내용은 Google Cloud Platform의 Ingress를 참조하세요.

기술 세부정보

Ingress 객체를 만들 때 GKE Ingress 컨트롤러는 Ingress 매니페스트 및 연결된 서비스 매니페스트에 있는 규칙에 따라 GCP HTTP(S) 부하 분산기를 구성합니다. 클라이언트는 HTTP(S) 부하 분산기에 요청을 전송합니다. 부하 분산기는 실제 프록시입니다. 부하 분산기는 노드를 선택하고 요청을 해당 노드의 NodeIP:NodePort 조합으로 전달합니다. 노드는 해당 iptables NAT 테이블을 사용해서 포드를 선택합니다. kube-proxy는 노드에서 iptables 규칙을 관리합니다.

포드 및 서비스 연결 제한

기본적으로 동일 클러스터 내에서 실행되는 모든 포드는 자유롭게 통신할 수 있습니다. 하지만 필요에 따라 클러스터 내의 연결을 여러 방식으로 제한할 수 있습니다.

포드 간 액세스 제한

네트워크 정책을 사용하여 포드 간 액세스를 제한할 수 있습니다. 네트워크 정책 정의를 사용하면 라벨 IP 범위, 포트 번호를 임의로 조합하고 이를 기준으로 포드의 수신송신을 제한할 수 있습니다. 기본적으로는 네트워크 정책이 없으므로, 클러스터에 있는 포드 사이의 모든 트래픽이 허용됩니다. 네임스페이스에서 첫 번째 네트워크 정책을 만들면, 다른 모든 트래픽이 즉시 거부됩니다.

정책을 직접 지정하는 방법에 대한 자세한 내용은 네트워크 정책을 참조하세요.

네트워크 정책을 만든 후에는 클러스터에서 이를 명시적으로 사용 설정해야 합니다. 자세한 내용은 애플리케이션의 네트워크 정책 구성을 참조하세요.

외부 부하 분산기 액세스 제한

서비스에 외부 부하 분산기가 사용될 경우, 기본적으로 외부 IP 주소의 트래픽이 서비스에 액세스할 수 있습니다. 서비스를 구성할 때 loadBalancerSourceRanges 옵션을 구성하여 클러스터 내부의 엔드포인트에 액세스할 수 있는 IP 주소 범위를 제한할 수 있습니다. 여러 범위를 지정할 수 있고, 언제든지 실행 중인 서비스의 구성을 업데이트할 수 있습니다. 각 노드에서 실행되는 kube-proxy 인스턴스는 지정된 loadBalancerSourceRanges와 일치하지 않는 모든 트래픽을 거부하도록 노드의 iptables 규칙을 구성합니다. VPC 방화벽 규칙은 생성되지 않습니다.

HTTP(S) 부하 분산기 액세스 제한

서비스에 HTTP(S) 부하 분산기가 사용될 경우 Cloud Armor 보안 정책을 사용해서 서비스에 액세스할 수 있는 외부 IP 주소 및 보안 정책으로 인해 액세스가 거부될 때 반환할 응답을 제한할 수 있습니다. 이러한 상호작용에 대한 정보를 기록하도록 Stackdriver Logging을 구성할 수 있습니다.

Cloud Armor 보안 정책이 충분히 세밀하게 조정되지 않은 경우 엔드포인트에서 Cloud Identity-Aware Proxy를 사용 설정해서 애플리케이션에 대해 사용자 기반 인증 및 승인을 구현할 수 있습니다. 자세한 내용은 Cloud IAP 구성 세부 가이드를 참조하세요.

다음 단계

이 페이지가 도움이 되었나요? 평가를 부탁드립니다.

다음에 대한 의견 보내기...

Kubernetes Engine