본문으로 바로가기 본문 바로가기
WIKI 기술 지식 베이스

Kubernetes 서비스 IP 주소 광고

원문 보기 위키 갱신

Kubernetes 서비스 IP 주소 광고 (Advertise Kubernetes service IP addresses)

Calico가 Kubernetes 서비스 IP를 클러스터 밖으로 광고(advertise)하도록 활성화하면 외부 클라이언트가 서비스에 직접 라우팅할 수 있어요. 서비스의 클러스터 IP와 외부 IP 모두 BGP로 광고할 수 있고, 별도의 로드 밸런서 없이도 외부 접근이 가능해져요. 이 문서는 그 설정 방법을 차근차근 안내해요.

출처: 문서

본문

큰 그림 (Big picture)

Calico가 Kubernetes 서비스 IP를 클러스터 밖으로 광고하도록 활성화해요. Calico는 서비스의 클러스터 IP와 외부 IP 광고를 모두 지원해요.

가치 (Value)

일반적으로 Kubernetes 서비스 클러스터 IP는 클러스터 내부에서만 접근할 수 있어서, 서비스를 외부에서 접근하려면 별도의 로드 밸런서나 인그레스 컨트롤러가 필요해요. 서비스의 클러스터 IP가 라우팅 불가능한 경우에는 외부 IP(external IP)를 사용해 서비스에 접근할 수 있어요.

Calico가 팟 IP를 BGP로 광고하는 것처럼, Kubernetes 서비스 IP도 BGP로 클러스터 밖에 광고할 수 있어요. 이렇게 하면 별도의 로드 밸런서가 필요 없어져요. 이 기능은 클러스터 내 노드 간 ECMP(equal cost multi-path) 로드 밸런싱도 지원하고, 더 세밀한 제어가 필요할 때 로컬 서비스의 소스 IP 보존도 지원해요.

개념 (Concepts)

BGP가 편의를 제공해요

Kubernetes에서 서비스로 향하는 모든 요청은 그 서비스를 지원하는 적절한 엔드포인트(팟)로 리다이렉트돼요. Calico는 BGP를 사용하기 때문에, Kubernetes 서비스 IP를 BGP 네트워크에 광고하면 외부 트래픽이 Kubernetes 서비스로 직접 라우팅될 수 있어요.

배포가 클러스터 밖의 BGP 라우터와 피어링되어 있으면, 그 라우터들(그리고 라우터가 라우트를 전파하는 다른 모든 업스트림 지점)이 Kubernetes 서비스 IP로 트래픽을 보낼 수 있고, 그 트래픽은 해당 서비스의 가용 엔드포인트 중 하나로 라우팅돼요.

서비스 IP 광고 한눈에 보기

Calico는 kube-proxy를 사용해 Kubernetes externalTrafficPolicy를 구현하고, 들어오는 트래픽을 올바른 팟으로 보내요. 광고 방식은 서비스에 설정한 서비스 유형에 따라 달라져요.

서비스 모드 클러스터 IP 광고 트래픽 흐름은... 소스 IP 주소는...
Cluster (기본값) 클러스터의 모든 노드가 서비스 CIDR로의 라우트를 정적으로 광고해요. ECMP로 클러스터 내 노드들에 걸쳐 로드 밸런싱된 뒤, SNAT를 거쳐 서비스의 적절한 팟으로 포워딩돼요. 다른 노드로의 두 번째 홉이 발생할 수 있지만 전반적인 로드 밸런싱은 좋아요. SNAT로 가려져요
Local 서비스를 지원하는 팟이 있는 노드만 서비스 IP로의 특정 라우트(/32 또는 /128)를 광고해요. 해당 서비스의 엔드포인트가 있는 노드들에 걸쳐 로드 밸런싱돼요. LoadBalancer와 NodePort 유형 서비스에서는 두 번째 홉을 피하고, 트래픽이 고르게 분배되지 않을 수 있어요. (다른 트래픽은 클러스터 내 노드들에 걸쳐 로드 밸런싱돼요.) 보존돼요

Calico 배포가 클러스터 밖의 BGP 라우터와 피어링되어 있으면, 그 라우터들과 라우터가 라우트를 전파하는 더 상위의 지점들이 Kubernetes 서비스 클러스터 IP로 트래픽을 보낼 수 있고, 그 트래픽은 해당 서비스의 가용 엔드포인트 중 하나로 라우팅돼요.

성공을 위한 팁

  • 일반적으로 다음 이유로 "Local"을 사용하는 것을 권장해요.

    • 네트워크 정책에서 특정 소스 IP 주소로 매칭하는 규칙을 사용한다면 Local이 분명히 좋은 선택이에요. 소스 IP 주소가 변경되지 않아서 정책이 그대로 동작하거든요.
    • "Local" 서비스는 소스 NAT를 되돌릴 필요가 없기 때문에(Cluster 서비스와 달리) 응답 트래픽이 소스 IP로 직접 라우팅돼요.
  • 클러스터 IP 광고는 ECMP를 지원하는 ToR과 함께 사용할 때 가장 잘 동작해요. 그렇지 않으면 특정 라우트로 향하는 모든 트래픽이 단일 노드로 향하게 돼요.

시작하기 전에

필수 사항

  • Calico와 네트워크 인프라 간에 BGP 피어링 구성
  • 서비스로의 ECMP 로드 밸런싱을 위해 업스트림 라우터가 BGP 멀티패스를 사용하도록 구성되어 있어야 해요.
  • 클러스터 내부의 calico 노드와 피어링되는 라우터, 라우트 리플렉터, ToR 역할을 하는 외부 노드가 최소 하나 필요해요.
  • 서비스가 구현에 맞는 올바른 서비스 모드("Cluster" 또는 "Local")로 구성되어 있어야 해요. externalTrafficPolicy: Local이라면 서비스 유형이 LoadBalancer 또는 NodePort여야 해요.

제한 사항

  • OpenShift, 버전 4.5와 4.6
    NodePort 서비스나 externalTrafficPolicy:Local인 Service ExternalIP 트래픽에서 소스 IP가 보존되지 않는 버그가 있어요.

    v4.5 또는 v4.6 OpenShift 사용자는 이 우회 방법으로 ExternalIP의 SNAT를 피할 수 있어요.

      oc edit featuregates.config.openshift.io cluster
       spec:
         customNoUpgrade:
           enabled:
           - ExternalPolicyForExternalIP
    

    Kubernetes v1.18 또는 v1.19 사용자는 ExternalPolicyForExternalIP 기능 게이트로 NodePort 서비스의 소스 IP 보존을 활성화할 수 있어요.

    NodePort 서비스와 ExternalIP의 소스 IP 보존은 OpenShift v4.7+와 Kubernetes v1.20+에서는 기본 활성화되어 있어요.

방법 (How to)

서비스 클러스터 IP 주소 광고

  1. 서비스 클러스터 IP 범위를 파악하세요. (클러스터가 듀얼 스택이라면 범위 여러 개일 수 있어요.)

    클러스터의 범위는 Kubernetes API 서버에 전달된 --service-cluster-ip-range 옵션에서 유추할 수 있어요. 도움이 필요하면 Kubernetes API 서버 레퍼런스 가이드를 참고하세요.

  2. 기본 BGPConfiguration이 있는지 확인하세요.

    calicoctl get bgpconfig default
    
  3. 위 결과에 따라 BGPConfiguration을 업데이트하거나 새로 만드세요.

    기본 BGPConfiguration 업데이트 다음 명령으로 BGPConfiguration을 패치하세요. "10.0.0.0/24" 자리에 자신의 서비스 클러스터 IP CIDR을 넣으세요.

    calicoctl patch bgpconfig default --patch \
       '{"spec": {"serviceClusterIPs": [{"cidr": "10.0.0.0/24"}]}}'
    

    기본 BGPConfiguration 생성 다음 샘플 명령으로 기본 BGPConfiguration을 만드세요. 광고할 클러스터 IP를 커버하는 CIDR 블록을 serviceClusterIPs 필드에 추가하면 돼요. 예를 들면 다음과 같아요.

    calicoctl create -f - <<EOF
    apiVersion: projectcalico.org/v3
    kind: BGPConfiguration
    metadata:
      name: default
    spec:
      serviceClusterIPs:
      - cidr: 10.96.0.0/16
      - cidr: fd00:1234::/112
    EOF
    

    도움이 필요하면 BGP 구성 리소스를 참고하세요.

참고 (SECONDARY): 구버전 Calico에서는 IPv4에 한해 서비스 클러스터 IP 광고를 환경 변수 CALICO_ADVERTISE_CLUSTER_IPS로 구성했어요. 이 환경 변수는 기본 BGPConfiguration에 구성된 serviceClusterIPs보다 우선해요. 더 이상 권장되지 않는 CALICO_ADVERTISE_CLUSTER_IPS는 BGPConfiguration으로 교체하기를 권해요.

서비스 외부 IP 주소 광고

  1. Calico 클러스터 밖으로 광고하려는 모든 서비스의 외부 IP 범위를 파악하세요.

  2. 기본 BGPConfiguration이 있는지 확인하세요.

    calicoctl get bgpconfig default
    
  3. 위 결과에 따라 BGPConfiguration을 업데이트하거나 새로 만드세요.

    기본 BGPConfiguration 업데이트 다음 명령으로 BGPConfiguration을 패치하면서 자신의 서비스 외부 IP CIDR을 추가하세요.

    calicoctl patch bgpconfig default --patch \
       '{"spec": {"serviceExternalIPs": [{"cidr": "x.x.x.x"}, {"cidr": "y.y.y.y"}]}}'
    

    기본 BGPConfiguration 생성 다음 샘플 명령으로 기본 BGPConfiguration을 만드세요. 광고할 외부 IP의 CIDR 블록을 serviceExternalIPs 필드에 추가하세요.

    calicoctl create -f - <<EOF
    apiVersion: projectcalico.org/v3
    kind: BGPConfiguration
    metadata:
      name: default
    spec:
      serviceExternalIPs:
      - cidr: x.x.x.x/16
      - cidr: y.y.y.y/32
    EOF
    

    도움이 필요하면 BGP 구성 리소스를 참고하세요.

서비스 로드 밸런서 IP 주소 광고

다음 단계는 Service status.LoadBalancer.Ingress.IP 주소를 광고하도록 Calico를 구성해요.

  1. Service LoadBalancer 주소 할당에 사용할 IP 범위를 파악하세요.

  2. 기본 BGPConfiguration이 있는지 확인하세요.

    calicoctl get bgpconfig default
    
  3. 위 결과에 따라 BGPConfiguration을 업데이트하거나 새로 만드세요.

    기본 BGPConfiguration 업데이트 다음 명령으로 BGPConfiguration을 패치하면서 자신의 서비스 로드 밸런서 IP CIDR을 추가하세요.

    calicoctl patch bgpconfig default --patch '{"spec": {"serviceLoadBalancerIPs": [{"cidr": "x.x.x.x/16"}]}}'
    

    기본 BGPConfiguration 생성 다음 샘플 명령으로 기본 BGPConfiguration을 만드세요. 광고할 로드 밸런서 IP의 CIDR 블록을 serviceLoadBalancerIPs 필드에 추가하세요.

    calicoctl create -f - <<EOF
    apiVersion: projectcalico.org/v3
    kind: BGPConfiguration
    metadata:
      name: default
    spec:
      serviceLoadBalancerIPs:
      - cidr: x.x.x.x/16
    EOF
    

    도움이 필요하면 BGP 구성 리소스를 참고하세요.

Calico IPAM은 LoadBalancerController와 함께 LoadBalancer 유형 Service의 주소 할당을 관리할 수 있어요. Calico IPAM이 Service 주소 관리를 시작하게 하려면 LoadBalancer용 IPPool을 설정하세요.

kubectl apply -f - <<EOF
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
 name: loadbalancer-ip-pool
spec:
 cidr: 192.210.0.0/20
 blockSize: 24
 natOutgoing: true
 disabled: false
 assignmentMode: Automatic
 allowedUses:
  - LoadBalancer
EOF

자세한 내용은 LoadBalancer IP 주소 관리를 참고하세요.

참고 (SECONDARY): 이전에 LoadBalancer 유형 Service 주소 관리에 다른 IPAM 솔루션을 사용했고 그것을 계속 쓰고 싶다면, LoadBalancer용 Calico IPPool을 만들지 마세요.

특정 노드를 광고에서 제외

때로는 특정 노드를 서비스 주소 광고에서 제외하고 싶을 수 있어요. 예를 들어 스스로 어떤 서비스도 호스팅하지 않는 컨트롤 플레인 노드 같은 경우죠.

노드를 서비스 광고에서 제외하려면 node.kubernetes.io/exclude-from-external-load-balancers=true 라벨을 적용하세요.

예를 들어 노드 control-plane-01을 서비스 광고에서 제외하려면 다음 명령을 실행하면 돼요.

kubectl label node control-plane-01 node.kubernetes.io/exclude-from-external-load-balancers=true

튜토리얼

Calico에서 서비스 광고가 어떻게 동작하는지에 대한 튜토리얼은 Kubernetes Service IP Route Advertisement 블로그를 참고하세요.

추가 리소스

Kubernetes 서비스를 위한 네트워크 정책 작성 관련 다른 주제들:

더 알아보기 (Learn more)

서비스 IP를 BGP로 광고하면 별도 로드 밸런서 없이 외부 클라이언트가 서비스에 직접 라우팅할 수 있어요. 소스 IP를 보존하려면 externalTrafficPolicy를 Local로 설정하는 게 좋아요. 광고할 IP 범위는 BGPConfiguration의 serviceClusterIPs, serviceExternalIPs, serviceLoadBalancerIPs 필드로 설정해요.