devops

Lava Network Provider Architecture with Kubernetes 본문

DevOps/Kubernetes

Lava Network Provider Architecture with Kubernetes

vataops 2024. 10. 6. 16:29
반응형

Lava Network

Degraded된 것은 Unstaking 중인 프로토콜 (지원종료를 의미)

Lava Network는 탈중앙화된 RPC 프로바이더 플랫폼이자, 블록체인 데이터 서비스를 위한 마켓플레이스를 구축하고 있다. 이를 통해 Infura, Alchemy, AllThatNode와 같은 기존의 RPC 및 API 인프라 제공자뿐만 아니라, 개인이 직접 운영하는 RPC 노드도 탈중앙화된 네트워크를 통해 클라이언트에게 서비스를 제공할 수 있다.

Lava network는 Cosmos SDK 기반으로 구현되었으며, 현재 이더리움, 폴리곤, 솔라나 등 30여 개 이상의 블록체인에 대한 RPC 서비스를 지원한다.

Lava Network에는 크게 서비스 사용자(Customer), 서비스 제공자(Provider), 그리고 네트워크의 검증자(Validator)라는 세 가지 주요 주체가 있다. 내가 속한 팀은 다양한 프로토콜의 노드를 운영하고 있으며, 이를 Provider 역할을 통해 기존의 서비스로 제공되던 노드 리소스를 보다 효율적으로 활용하고 있다.

Lava Network Components

Lava Network의 컴포넌트의 역할에 대해서 간단히 설명하면,  Lava Nework는 Latency, Sync, Availibility 기준으로 높은 QoS를 유지하는 Provider들의 List를 Consumer에게 제공하는 Pairing 작업을 진행하며, Consumer는 Provider에게 요청(Request)을 보내고, Provider는 RPC 서비스를 Consumer에게 제공한다.

  • Latency: 클라이언트가 요청을 전송하고 응답을 받을 때까지 소요되는 시간
  • Sync:  노드가 클라이언트에게 반환하는 데이터의 정확성
  • Availability: 노드가 다운타임 없이 지속적으로 서비스를 제공하는 능력

Reward types

Lava network는 위와 같은 Reward Flow를 가지고 있는데, 특히 Provider가 Staking을 할 수 있으며, Consumer로부터 구독(Subscription) 보상을 받는 것이 특징이다.

Consumer의 Pairing부터 Provider의 QoS 평가 및 보상까지 모든 과정은 탈중앙화된 Lava Network에서 자동으로 이뤄진다. RPC 노드 운영자는 이 네트워크를 통해 Provider 등록부터 보상까지 모든 과정을 자체적으로 진행할 수 있다.

Lava Provider Architecture

기존 아키텍처에서는 단일 서버에 Provider를 Docker로 구성하여 모든 프로토콜의 요청을 nginx로 받아서 처리해왔다. Provider는 Lava Network와 통신도 필요하기 때문에  같은 서버에 Lava RPC Node도 함께 구성되어 있었다.결국, Nginx, Provider, Lava RPC Node가 하나의 서버에서 작동하면서 SPOF(단일 장애점) 리스크가 있었다. 또한, 하나의 Provider 프로세스에서 모든 프로토콜의 요청을 처리했기 때문에 프로토콜의 health 체크와 관리가 어려운 문제도 존재했다.

좌: 기존 아키텍처, 우: 개선한 아키텍처

Provider는 더 많은 요청을 받기 위해서 더 많은 Consumer와 페어링되어야 했으며, 그 기준은 Latency와 Availbility, Sync QoS로 결정된다. 그래서 프로토콜과 리전에 따라 Provider를 구성하여 트래픽 분산, 효율적인 Config 관리와 빠른 배포 등 Provider의 효율적인 관리를 통해 QoS를 높이고 서비스의 안정성을 높일 필요가 있었다.

이 점에서, 쿠버네티스(Kubernetes)가 Provider 구성을 최적화하기에 적합하다고 판단했다. Provider마다 Pod로 구하여 트래픽을 분산할 수 있으며, Helm chart를 통해 리전과 프로토콜별로 일관된 배포와 설정 관리가 가능했으며, ArgoCD를 이용한 GitOps 방식의 빠르고 효율적인 배포가 가능했다.

하지만, 현재 베어메탈 기반의 Kubernetes 클러스터를 사용하고 있어 TLS를 적용해 443 포트를 사용하기에는 한계가 있었다. 외부 통신에 NodePort를 사용해야 했기 때문에 30000-32767 범위의 포트만 서버에서 노출할 수 있었고, Lava 재단에서도 Consumer의 outbound에 443 포트만 허용한다면 요청이 차단되는 문제가 발생할 수 있다고 지적해 443 포트로 노출할 방법을 고민해야 했다.

물론 MetalLB같은 로드밸런싱 오픈소스 툴을 이용할 순 있으나, 오버엔지니어링이 될 수 있다는 판단하에, 443 port를 사용할 효율적인 방법이 필요했다. (클러스터의 안정적인 운영을 위해 api server의 --service-node-port-range 를 손대고 싶진 않았음)

http {
    server_names_hash_bucket_size 128;
    
    server {
        listen 443 ssl http2;
        server_name lavap-testnet-ftm-eu.{ domain }.com;

        ssl_certificate /etc/letsencrypt/live/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/privkey.pem;
        error_log /var/log/nginx/ftm.log debug;

        location / {
            proxy_pass http://fantom-lavap-testnet-eu-v1-provider.lavap-testnet-eu.svc.cluster.local:2200;
            grpc_pass fantom-lavap-testnet-eu-v1-provider.lavap-testnet-eu.svc.cluster.local:2200;
        }
    }

    server {
        listen 443 ssl http2;
        server_name lavap-testnet-ftm-eu-metrics.{ domain }.com;

        ssl_certificate /etc/letsencrypt/live/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/privkey.pem;
        error_log /var/log/nginx/ftm.log debug;

        location / {
            proxy_pass http://fantom-lavap-testnet-eu-v1-provider.lavap-testnet-eu.svc.cluster.local:3200;
        }
    }
   }

nginx conf

특히 현재 Kubespray로 구성한 클러스터는 Nginx 프로세스를 통해 API 서버와 kubelet이 통신하고 있어, 자칫 클러스터 통신에 영향을 줄 수 있는 부분도 고려해야 했다.

현재 구성된 클러스터의 nginx proxy - kube apiserver

다행히도, 클러스터에서 사용되는 Nginx는 시스템 프로세스로 실행되지 않았기 때문에, TLS를 적용한 Nginx를 시스템 프로세스로 실행하여 외부 요청을 받아 내부 클러스터의 서비스로 라우팅하는 방법을 고안했다. Nginx 프록시는 요청된 도메인에 따라 지정된 서비스(ClusterIP)로 요청을 라우팅하며, 클러스터 내부 서버의 Nginx 프록시이기 때문에 Kubernetes의 coreDNS를 활용해 이를 지정할 수 있었다.

Github Action - Helm chart - ArgoCD

Lava Network에서 공식적으로 지원되는 Docker 이미지가 아직 없기 때문에, 신규 버전이 릴리즈될 때마다 직접 Docker 이미지를 빌드하고 업그레이드를 진행해야 한다. 이 과정을 최대한 자동화시키기 위해서 Github action을 통해 Image를 빌드하여 Registry에 Push하면, Workflow의 마지막 단에서 Helm chart의 tag를 변경하고, ArgoCD에서 최종적으로 배포하는 파이프라인을 구성했다.

chains:
  - id: ETH1
    name: ethereum
    nodeRegion: germany
    configYaml: |
      endpoints:
        - chain-id: ETH1
          api-interface: jsonrpc
          network-address:
            address: 0.0.0.0:2200
            disable-tls: true
          node-urls:
            - url: "http://{ ip }:8545"
            - url: "http://{ ip }:8545"
              addons:
                - archive
  - id: SEP1
    name: sepolia
    nodeRegion: germany
    configYaml: |
      endpoints:
        - chain-id: SEP1
          api-interface: jsonrpc
          network-address:
            address: 0.0.0.0:2200
            disable-tls: true
          node-urls:
            - url: "http://{ ip }:8545"
            - url: "http://{ ip }:8545"
              addons:
                - archive

values.yaml

Lava network에서 작성한 Helm chart가 있지만, 아쉽게도 직접 사용해본 결과 Provider 배포에 있어서 에러가 발생했다.

 

GitHub - lavanet/helm-charts: 🌋 Helm charts for Lava services

🌋 Helm charts for Lava services. Contribute to lavanet/helm-charts development by creating an account on GitHub.

github.com

이 문제는 template/secret.yaml에서 config.yml 생성 시 잘못된 규칙이 적용되어 발생한 것이었다. 이를 해결하기 위해, 나는 각 프로토콜의 전체 config를 values.yaml에서 직접 생성할 수 있도록 Helm chart를 수정하여, 위 values.yaml처럼 쉽게 디버깅할 수 있게 했다.

또한, config에서 노출되는 정보가 node-url뿐이기 때문에, 굳이 Secret을 사용할 필요가 없어 Secret을 ConfigMap으로 변경했다.

추가적으로, 노드마다 region과 노드 이름을 기준으로 라벨을 설정하여, Deployment마다 원하는 리전이나 노드에 배포할 수 있도록 Helm chart를 구성했다. 특히, Helm chart에서는 region을 기준으로 구분하고, 하나의 Helm chart에서 여러 프로토콜의 provider를 각기 다른 Config로 배포할 수 있도록 설계했다.

EU region providers dashboard

Provider Health check

결과적으로 Provider의 효율적인 운영과 배포가 가능해졌으며, 3가지 QoS 점수도 높이고 있다. 위 Health check는 Lava Testnet이며, 아직 Mainnet에는 Lava와 Cosmos만 지원한다. 앞으로 Lava Provider를 잘 활용하면 비용만 나가는 DevOps 팀에서 직접적으로 많은 수익을 가져올 수 있지 않을까... 하는 생각...을 해본다.

반응형
Comments