AISpeech가 k8s Ingress Controller로 NGINX 대신 Apache APISIX를 선택한 이유

Wei Jin

May 7, 2020

Case Study

서문

안녕하세요, 저는 컴퓨터 음성 인식 및 분석에 특화된 하이테크 기업인 AISpeech의 Jin Wei입니다. 오늘은 네이티브 인그레스 대신 Apache APISIX와 K8s의 통합에 대해 이야기하려고 합니다.

작성 시점에서 Apache APISIX는 이미 우리의 프로덕션 환경에 적용되어 일부 비즈니스 진입 트래픽을 처리하고 있습니다. 아래 그림과 같이 네이티브 인그레스 트래픽을 점차적으로 이전하고 있습니다.

아키텍처 다이어그램

사실, APISIX-ingress-controller는 pod IP를 업스트림 노드에 등록하여 비즈니스 트래픽이 kube DNS를 우회하고 직접 pod에 접근할 수 있도록 합니다. 이를 기반으로 플러그인을 통해 특정 로드 밸런싱 정책을 구현할 수 있습니다. 따라서 한편으로는 Apache APISIX의 동적 라우팅 기능에 의존하여 트래픽 분배를 수행하고, 다른 한편으로는 비즈니스 요구를 충족시키기 위해 몇 가지 커스텀 플러그인을 추가합니다.

위 다이어그램에서 APISIX-ingress-controller는 네이티브 인그레스와 중복되어 보입니다. 이 글에서는 왜 네이티브 인그레스를 포기하고 Apache APISIX를 기반으로 자체 인그레스 컨트롤러를 구축했는지 간단히 설명하겠습니다.

인그레스란 무엇인가

한 마디로, 인그레스는 Kubernetes가 외부 트래픽을 처리하는 방법입니다.

인그레스가 해결하는 문제

Kubernetes 클러스터 내의 서비스는 가상 네트워크이기 때문에, 외부 트래픽은 클러스터 내부 서비스에 접근하기 위해 최소한 공인 IP와 적절히 매핑된 포트가 필요합니다.

Kubernetes는 Kubernetes 내부 서비스에 접근하기 위한 다양한 방법(NodePort, LoadBalancer, Ingress 등)을 제공합니다. 비교했을 때, 인그레스는 제한된 수의 공인 IP를 노출하여 역방향 프록시를 달성하는 더 경제적인 방법입니다.

역방향 프록시에 대해 말하자면, NGINX를 직접 구축하여 이를 수행할 수도 있지만, Kubernetes에서 쉽게 변할 수 있는 서비스 상태를 NGINX와 동기화하는 것은 상당히 어렵습니다.

좋은 소식은 Kubernetes가 공식적으로 NGINX 인그레스 컨트롤러를 제공하고 유지하여 역방향 프록시를 돕는다는 것입니다. 이 NGINX 인그레스 컨트롤러를 사용하면 Kubernetes에 접근하려는 모든 트래픽을 프록시하고 이를 백엔드 서비스로 올바르게 지시할 수 있습니다.

Kubernetes 네이티브 인그레스 컨트롤러의 문제점

NGINX 인그레스 컨트롤러는 Kubernetes 클러스터와 NGINX 간의 상태 동기화를 유지하고 기본적인 역방향 프록시 기능을 제공합니다. 그렇다면 왜 우리는 자체 인그레스를 구축했을까요? 우리는 더 많은 비즈니스 요구를 충족시키기 위해 인그레스 컨트롤러로부터 더 많은 것을 기대합니다.

Kubernetes 네이티브 인그레스 컨트롤러를 사용한 후, 우리는 다음과 같은 문제가 두드러진다는 것을 발견했습니다:

  1. 리로딩 문제

    Kubernetes 네이티브 인그레스는 YAML 구성 파일을 인그레스 컨트롤러에 전달하고, 이를 NGINX 구성 파일로 변환한 후 리로딩을 트리거하여 구성이 적용되도록 설계되었습니다.

    이는 특히 트래픽이 장기 연결을 사용할 때 사고로 이어질 수 있어 받아들이기 어렵습니다.

    반면, Apache APISIX는 구성의 핫 리로딩을 지원하므로 NGINX 리로드를 트리거하지 않고도 언제든지 라우트를 정의하고 수정할 수 있습니다.

  2. 어노테이션에 스크립트 작성 및 매개변수 입력

    네이티브 인그레스 컨트롤러는 YAML 파일의 어노테이션에 정의된 스크립트 조각을 지원하며, 이는 고급 기능을 지원하기 위한 임시 해결책처럼 느껴지고 관리하기가 매우 어렵습니다. 많은 수의 어노테이션 스크립트는 DevOps 직원에게 문제를 일으킵니다.

    Apache APISIX에서는 플러그인 코드를 통해 로직을 작성하고 간단한 구성 인터페이스를 노출시켜 구성 유지 관리를 용이하게 하고 DevOps 직원에게 스크립트 간섭을 피할 수 있습니다.

  3. 상태 저장 로드 밸런싱 지원 부족

    "세션 지속성"과 같은 고급 로드 밸런싱 정책이 지원되지 않습니다. Kubernetes는 운영 지향적인 컨테이너화된 애플리케이션 관리 시스템으로, Kubernetes가 상태 비저장 배포 방식을 장려하기 때문에 이러한 모순된 로드 밸런싱 정책을 공식적으로 지원하지 않을 것입니다. 사실, Google은 이미 서비스 메시 솔루션(Istio)으로 이러한 문제를 해결하려고 시도했습니다. Istio의 아키텍처는 완벽하지만 성능을 희생해야 하며, 이는 mixer v2로 해결될 수 있습니다.

    Kubernetes가 확장을 지원하기 때문에, Apache APISIX를 확장하여 고급 로드 밸런싱 요구를 충족시킬 수 있습니다. Apache APISIX는 "세션 지속성" 및 기타 로드 밸런싱을 기본적으로 지원할 뿐만 아니라 밸런서 단계를 확장할 수 있는 능력도 있습니다.

  4. 동적 가중치

    비즈니스 서비스는 종종 퍼센트로 트래픽을 제어해야 하는데, 이는 Kubernetes에서 문제가 됩니다.

    Kubernetes는 1.8 이후 IPVS(IP Virtual Server)를 지원하지만, "kube-proxy"의 시작 매개변수나 "kube-route"의 어노테이션은 Apache APISIX만큼 사용하기 쉽지 않습니다. Apache APISIX는 내부적으로 라우트, 서비스, 소비자, 업스트림, 플러그인 등의 주요 객체를 추상화합니다. 이러한 작업의 가중치를 조정하는 것은 자연스럽게 지원되며, 단순히 "업스트림" 아래의 "노드 가중치"를 수정하면 됩니다.

  5. 유연하지 않은 확장 기능

    인그레스는 원래 외부 트래픽을 처리하기 위해 설계되었지만, 외부 트래픽에 대한 요구는 내부 트래픽에 비해 적지 않습니다.

    서비스 수준의 카나리 릴리스, 서킷 브레이커, 흐름 제어, 인증, 트래픽 제어 등의 요구 사항은 인그레스에서 더 일반적으로 구현됩니다.

    Apache APISIX는 확장성을 위한 플러그인 지원을 제공하며, 공식 플러그인 외에도 자신의 특성을 충족시키기 위해 커스텀 플러그인을 만들 수 있습니다.

    ConfigMap 및 Namespaces로 인한 몇 가지 구성 문제도 있지만, 이는 우리가 사용하는 방식과 관련이 있으며 일반적이지 않으므로 여기서는 다루지 않겠습니다.

Apache APISIX 인그레스 컨트롤러

Apache APISIX의 강력한 라우팅 및 확장 기능으로 인해, Apache APISIX를 인그레스의 구현으로 사용하면 위에서 언급한 문제점을 쉽게 해결할 수 있으며, 커뮤니티에 추가적인 인그레스 컨트롤러 옵션을 제공할 수 있습니다. 타이밍 다이어그램은 다음과 같습니다:

타이밍 다이어그램

Apache APISIX 인그레스 컨트롤러를 구현하기 위해, 우리는 두 가지 기본 문제를 해결해야 합니다: 하나는 Kubernetes 클러스터와 Apache APISIX 상태 간의 동기화를 해결하는 것이고, 다른 하나는 Apache APISIX의 객체를 Kubernetes에서 정의하는 것입니다(CRD).

Apache APISIX를 빠르게 통합하고 그 장점을 활용하기 위해, 우리는 Apache APISIX 인그레스 컨트롤러 프로젝트를 만들었습니다(모두 참여를 환영합니다). 현재는 첫 번째 기본 문제인 Kubernetes pod 정보를 Apache APISIX 업스트림에 동기화하는 것을 구현했으며, 자체 고가용성 문제를 해결하기 위해 기본 백업을 구현했습니다.

Kubernetes는 YAML을 사용하여 클러스터 상태를 선언적으로 정의하기 때문에, Apache APISIX의 객체(route/service/upstream/plugin)를 Kubernetes에 통합하기 위해 CRD(Custom Resource Definitions)를 정의해야 합니다.

또한, 기존 Kubernetes 인그레스 사용자의 마이그레이션을 용이하게 하기 위해, 기존 인그레스 구성 항목과의 호환성을 유지하려고 노력할 것입니다.

이러한 기능들은 우리의 다음 노력의 목표가 될 것이며, 여러분의 참여를 환영합니다.

Tags: