CLI 파라메터 추가

 

 

Prometheus 메트릭 추가

 

 

async를 통해 현재 peer의 ping을 한꺼번에 수행

 

 

추가된 메트릭을 웹으로 렌더링

 

 

Prometheus에 연동 후 지연시간 수집

'[2023동계 모각코] 모각코' 카테고리의 다른 글

wireguard active healthcheck - 1  (0) 2024.02.13
NetMaker 컨트리뷰션 준비  (0) 2024.01.24
rqlite 클러스터링 2  (0) 2024.01.23
rqlite 클러스터링  (1) 2024.01.23
NetMaker 오픈소스 분석  (0) 2024.01.23

2024-02-11 일요일 오전 11시 00분 ~ 오후 2시 00분

 

일모 : https://moil-develop.tistory.com/221

시온 : https://skadost.tistory.com/7

형곤 : https://blog.naver.com/9hrack/223350123154

성빈 : https://vertextoedge.tistory.com/30

세희 : https://blog.naver.com/jungsehui/223351936592

 

 

'[2023동계 모각코] 모각코 일지' 카테고리의 다른 글

모각코 5회차  (0) 2024.02.17
[모각코] 4회차  (0) 2024.01.21
[모각코] 3회차  (0) 2024.01.21
[모각코] 2회차  (0) 2024.01.21
[모각코] 1회차  (0) 2024.01.17

2024-02-10 일요일 오전 11시 00분 ~ 오후 2시 00분

 

일모 : https://moil-develop.tistory.com/220

시온 : https://skadost.tistory.com/6

형곤 : https://blog.naver.com/9hrack/223348060305

성빈 : https://vertextoedge.tistory.com/27

세희 : https://blog.naver.com/jungsehui/223351417544

 

 

 

'[2023동계 모각코] 모각코 일지' 카테고리의 다른 글

모각코 6회차  (0) 2024.02.17
[모각코] 4회차  (0) 2024.01.21
[모각코] 3회차  (0) 2024.01.21
[모각코] 2회차  (0) 2024.01.21
[모각코] 1회차  (0) 2024.01.17

Netmaker로 Mesh VPN을 구축하고 나서 특정 피어간의 연결이 원활하게 되지 않는 현상을 발견했다.

이상한 점은 트러블 슈팅을 진행하다가 3~4시간이 지나니 연결이 원활하게 되는것이다.

(아마 wireguard에서 본으로 바인딩하는 포트가 막혀있다가 중간에 STUN을 거쳤든 포트를 재할당하다가 연결되는것으로 추측중)

 

단순히 개발 환경을 구성하고 편의성을 위해 사용하는게 아니라 인프라 구성요소로 작동하기 때문에, 네트워크의 신뢰성을 측정하고 평가하는 방안이 필요하다는 생각이 들었다. 

 

따라서 Peer간의 연결에 대한 상태 지표를 개발하고 이를 모니터링 하기로 결정했다.

 

Netmaker는 Wireguard를 기반으로 작동하기 때문에, 결국 Wireguard를 대상으로 Metric을 수집 및 개발하면 되겠다는 판단을 했다.

 

Netmaker에서는 Prometheus 로 각종 Metric을 Export해주는 기능이 내장되어있다.

하지만 유료기 때문에 이를 직접 구현하고자 한다.

 

 

export하는 Metric을 확인해보니 Rx, Tx같은 와이어가드에서 자체적으로 기록하는 지표에 더불어 Connected, Uptime, TotalTime, Latency 등 Active Health에 대한 지표를 상세하게 쪼개놨다.

 

결국 내가 개발하고자 하는 Peer간 연결에 대한 상태 지표를 개발하는 가장 쉬운 방법은,

이미 누군가 개발했을법한 Wireguard Exporter에 Peer에 대한 Ping 결과를 export하는 것이다.

Ping 결과 하나만으로 Connectivity, Uptime 등을 모두 표현할 수 있기 때문이다.

 

 

WireGuard: fast, modern, secure VPN tunnel

먼저 WireGuard의 특성에 대해 요약하자면 Connectionless가 가장 대표적인 특징이다. UDP를 기반으로 Peer간의 연결이란 개념이 없다. 전송 할 데이터가 발생하면 상대방이 bind중인 UDP 포트로 패킷을 캡슐링해서 던진다. 이로 인해 불필요한 세션 유지를 위한 Heartbeat가 발생하지 않는다(하지만 이게 필요한 경우가 있음). Peer간의 식별은 IP나 Port가 아닌, Cryptographic 기반의 비대칭 키를 이용한다. (public key와 private key) 따라서 로밍같이 물리적인 이동에 의해 Peer의 아이피가 바뀌는 상황에서도 Seamless하게 터널링이 유지된다.

 

WireGuard는 Chatty하지 않은 프로토콜인 점이 장점이지만, 네트워크 환경에 의해 주기적으로 연결 유지를 위해 Persistent Keepalive 옵션을 제공한다. NAT나 Firewall에 의해 UDP 포트의 외부 내부 포트 매핑이 유지되지 않는 상황을 방지하기 위해 Persistent Keepalived 로 지정한 초 마다 패킷을 전송해서 포트 매핑을 유지할 수 있다. 

 

WireGuard 프로토콜 설계상 주기적으로 Peer를 대상으로 ping을 전송하는게 일종의 안티패턴으로 작용할 것이지만, 현재 Netmaker를 사용하는 상황에서 꼭 측정해야 하는 모니터링 지표이고, 네트워크 부하도 영향을 끼칠 정도는 아니니 추가해도 좋겠다는 판단을 했다.

 

 

 

MindFlavor/prometheus_wireguard_exporter: A Prometheus exporter for WireGuard, written in Rust. (github.com)

 

GitHub - MindFlavor/prometheus_wireguard_exporter: A Prometheus exporter for WireGuard, written in Rust.

A Prometheus exporter for WireGuard, written in Rust. - MindFlavor/prometheus_wireguard_exporter

github.com

오픈소스 WireGuard exporter는 대략 2개 정도 있었는데 그나마 Star 개수가 많은 레포를 선정해서 기능을 추가하기로 했다. 둘 다 러스트로 작성된 프로젝트라 어쩔 수 없이 러스트를 추가적으로 공부했다.

 

 

ping을 전송하는 러스틀 라이브러리는 surge-ping을 선택했다

kolapapa/surge-ping: Asynchronous implementation of ping in rust, based on tokio 1.x (github.com)

 

GitHub - kolapapa/surge-ping: Asynchronous implementation of ping in rust, based on tokio 1.x

Asynchronous implementation of ping in rust, based on tokio 1.x - kolapapa/surge-ping

github.com

Ping이 timeout나는 경우 4초정도 block이 발생하게 될텐데, peer에 대해 순차적으로 날리는 ping이 모두 timeout나면, prometheus scrap 주기인 10초를 훌쩍 뛰어넘어서 수집에 문제가 생길것이라는 생각이 들었다.

정확도는 조금 떨어지더라도 비동기로 묶어서 HOL을 해소하기로 했다.

 

 

'[2023동계 모각코] 모각코' 카테고리의 다른 글

wireguard active healthcheck - 2  (0) 2024.02.17
NetMaker 컨트리뷰션 준비  (0) 2024.01.24
rqlite 클러스터링 2  (0) 2024.01.23
rqlite 클러스터링  (1) 2024.01.23
NetMaker 오픈소스 분석  (0) 2024.01.23

회사에서 NetMaker HA 구성을 완료하고 테스트를 진행했는데 문제가 생겼다.

rqlite 클러스터에서 리더를 죽이고, raft를 거쳐서 새로운 리더가 선출되어 클러스터가 유지됐음에도 불구하고, NetMaker 서버에서 새로 선출된 리더를 찾지 못해서 failover에 실패하는 것 이었다.

 

기존 리더인 rqlite node 1을 죽인 직후. 다른 rqlite들은 새로 리더를 선출하고 죽은 node1이 다시 연결되길 기다리는 중인데, netmaker는 새로운 리더로 failover 하지 못하는 모습을 보여준다.

 

찾아보니 해당 에러 로그는 netmaker것이 아니라 netmaker에서 rqlite로 접속할때 사용하는 gorqlite라는 라이브러리에서 내는 것이엇다.

코드를 더 분석해보기로 했다.

 

 

찾아보니 netmaker는 3년 전 gorqlite 버전을 사용하고 있었다.

해당 커밋으로 이동했는데 현재와 코드가 많이 달랐다.

코드를 읽고 의아한 점은 분명 코드는 내가 가지고 있는 모든 피어들에게 요청을 보내보고 그중에 하나라도 성공하면 결과를 리턴하는데, 위의 에러 출력은 단 하나의 피어에만 시도했다는 것이다.

 

즉 정리하자면 현재 peersToTry에는 단 하나의 피어, 정확히는 Leader 하나만 존재하기 때문에 문제가 된다. 왜냐면 leader는 이미 죽었기 때문이다.

 

peersToTry에 어떻게 피어들이 담기는지 확인해보자.

조금만 스크롤을 올려보면 cluster.makePeerList()를 통해 그 결과를 가져오는 것을 알 수 있다.

 

해당 함수는 

이렇게 생겼다. rc.leader와 rc.otherPeers를 합쳐서 리턴하고 있다.

 

에러 메시지로 보건데, 아무래도 leader만 append 되었고, otherPeers는 저 시점에서 비어있다는 것을 알 수 있다.

그렇다면 문제는 otherPeers를 누군가 잘 채워넣어야 하는데 채워넣지 않았다는 것을 추측해볼 수 있다.

 

otherPeers의 referrences를 찾아보자.

찾는 과정은 좀 생략하면 결론적으로는 

updateClusterInfo라는 함수에서 갱신한다.

 

235번 라인의 for문이 있는데, 웃긴건 leader면 추가하는데 leader가 아닌 경우에는 모두 무시한다. 이런 이유로 otherPeers는 항상 비어있게 된다.

 

물론 최신버전에는 잘 고쳐져 있다.

 

//////////////////////////////////////////////////////////////////////////////////////////////

2024년 2월 6일 머지됨

'[2023동계 모각코] 모각코' 카테고리의 다른 글

wireguard active healthcheck - 2  (0) 2024.02.17
wireguard active healthcheck - 1  (0) 2024.02.13
rqlite 클러스터링 2  (0) 2024.01.23
rqlite 클러스터링  (1) 2024.01.23
NetMaker 오픈소스 분석  (0) 2024.01.23

저번주에 만든 클러스터링 예제를 가지고 리더 선출과 failover에 대해 공부해보았다.

저번에 작성한 docker-compose.yml을 실행하면 순식간에 클러스터링을 진행하고 자기들끼리 리더를 선출한다.

 

 

curl http://localhost:4001/status?pretty

에서  store.leader를 보면 현재 선출된 leader를 확인할 수 있다.

 

1번 노드가 leader가 되었음을 알 수 있다.

leader를 죽여보자.

 

 

로그를 확인해보면 바로 3번 노드가 leader를 승계받는다. 왜 2번이 아니라 3번이 승계를 받는지는 RAFT 알고리즘이 정하는데, 그냥 누가 더 빨리 선거를 생성하는지에 따라 달려있다. 정하지 못하면 해당 선거는 파기하고 다시 선거를 시작하도록 되어있다.

 

죽인 1번 노드를 다시 실행해보자.

바로 Cluster 멤버로 추가된다. 현재는 아무 데이터베이스에 쓰기 작업이 이뤄지지 않아서 아무 일도 일어나지 않지만, 실제로는 그 사이에 데이터베이스에 커밋된 이력을 넘겨받아서 동기화한다.

 

3개의 노드로 구성된 클러스터에서 1개의 노드에 장애가 발생하면 어찌됐건 failover를 진행할 수 있다. 만약 2대를 죽이면 어떻게 될까?

 

 

현재 리더가 1번 노드로 선출되어 있으므로 먼저 리더를 중지시켰다.

 

 

 

 

 

3번 노드가 리더로 선출되었다.

 

3번 노드도 중지시켜보겠다.

 

리더가 선출되지 않고 공석으로 남아있다. 왜냐하면 나를 제외한 Voter가 존재하지 않기 때문에 선거를 열더라도 리더를 선출할 수 없기 때문이다.

'[2023동계 모각코] 모각코' 카테고리의 다른 글

wireguard active healthcheck - 2  (0) 2024.02.17
wireguard active healthcheck - 1  (0) 2024.02.13
NetMaker 컨트리뷰션 준비  (0) 2024.01.24
rqlite 클러스터링  (1) 2024.01.23
NetMaker 오픈소스 분석  (0) 2024.01.23

NetMaker High Availibility 구성을 시작했다.

NetMaker 는 몇 가지 컴포넌트로 구성되어 있다.

 

NetMaker : NetMaker 네트워크의 백엔드 역할. VPN Host에 대한 control plane 및 여러 백엔드 api 제공

NetMaker-ui : NetMaker 대시보드로 웹 프론트엔드 역할을 함.

CoreDNS : VPN 네트워크 내부에서 사용하는 DNS 서버

Database : NetMaker의 데이터를 저장하는 역할. sqlite, rqlite, postgresql 세개중에 하나를 고를 수 있다.

Message Broker : NetMaker 서버에서 각 Host들에게 명령을 실시간 전파하는 용도. mosquitto나 emqx 둘 중에 하나를 선택 가능하다.

LoadBalancer : 기본 예제는 Caddy로 되어있지만 Nginx나 HAProxy 등 아무 리버스 프록시 서버를 사용해도 무관하다.

 

NetMaker를 HA로 구성하려면 저런 컴포넌트에 대해 Redundancy을 구성해야 하는데 그 중에서도 가장 중요한 것은 Database이고 그 다음으로 중요한 것은 LoadBalancer이다.

사실 이 외에는 이중화 구성하지 않아도 크게 무관하다. 레플리카 중 하나가 통째로 날아가더라도 결국 Message Broker나 NetMaker, CoreDNS의 데이터는 모두 Database에서 필요할 때 마다 가져오기 때문이다.

 

데이터베이스는 뭘 사용할까 고민하다가 rqlite를 사용해보기로 결정했다. 물론 PostgreSQL이 훨씬 역사도 오래되고 HA 구성에 대한 자료나 사례가 훨씬 많았는데, NetMaker에서 저장하는 데이터의 양 자체가 그리 크지 않고, rqlite 오픈소스 레포를 검토해보니 프로젝트 자체가 클러스터링 기능을 특화시키는 방향으로 꽤 오래 개발되어왔기 때문에 rqlite를 선택했다.

rqlite를 간단하게 설명하자면 분산 기능이 갖춰진 sqlite이다. RAFT 알고리즘으로 클러스터링을 하여 노드간 데이터 정합성을 동기화한다.

 

오늘 모각코에서는 rqlite를 이용해 클러스터링을 진행해보았다. 다음 공식 문서를 참고했다.

https://rqlite.io/docs/clustering/automatic-clustering/

공식 문서와 더불어 rqlite Docker Image 문서도 참조하여 컨테이너에서 사용하는 환경 변수들을 파악했다.

https://hub.docker.com/r/rqlite/rqlite

 

하여 만들어진 클러스터 예제는 다음과 같다.

 

version: '3'

services:
  rqlite1:
    image: rqlite/rqlite:latest
    restart: always
    ports:
      - 4001:4001
    environment:
      - NODE_ID=1
      - HTTP_ADDR=0.0.0.0:4001
      - RAFT_ADDR=0.0.0.0:4002
      - HTTP_ADV_ADDR=rqlite1:4001
      - RAFT_ADV_ADDR=rqlite1:4002
    networks:
      - rqlite-net
    command:
      [
        "-bootstrap-expect",
        "3",
        "-join",
        "rqlite1:4002,rqlite2:4004,rqlite3:4006",
        "-raft-log-level",
        "INFO"
      ]

  rqlite2:
    image: rqlite/rqlite:latest
    restart: always
    ports:
      - 4003:4003
    environment:
      - NODE_ID=2
      - HTTP_ADDR=0.0.0.0:4003
      - RAFT_ADDR=0.0.0.0:4004
      - HTTP_ADV_ADDR=rqlite2:4003
      - RAFT_ADV_ADDR=rqlite2:4004
    networks:
      - rqlite-net
    command:
      [
        "-bootstrap-expect",
        "3",
        "-join",
        "rqlite1:4002,rqlite2:4004,rqlite3:4006",
        "-raft-log-level",
        "INFO"
      ]

  rqlite3:
    image: rqlite/rqlite:latest
    restart: always
    ports:
      - 4005:4005
    environment:
      - NODE_ID=3
      - HTTP_ADDR=0.0.0.0:4005
      - RAFT_ADDR=0.0.0.0:4006
      - HTTP_ADV_ADDR=rqlite3:4005
      - RAFT_ADV_ADDR=rqlite3:4006
    networks:
      - rqlite-net
    command:
      [
        "-bootstrap-expect",
        "3",
        "-join",
        "rqlite1:4002,rqlite2:4004,rqlite3:4006",
        "-raft-log-level",
        "INFO"
      ]
networks:
  rqlite-net:
    driver: bridge

 

노드 개수는 최소 정족수(Quorum)가 확보되면서도 1개의 장애를 허용하는 3대로 구성했다.

 

'[2023동계 모각코] 모각코' 카테고리의 다른 글

wireguard active healthcheck - 2  (0) 2024.02.17
wireguard active healthcheck - 1  (0) 2024.02.13
NetMaker 컨트리뷰션 준비  (0) 2024.01.24
rqlite 클러스터링 2  (0) 2024.01.23
NetMaker 오픈소스 분석  (0) 2024.01.23

인턴중인 회사에서 NetMaker를 이용해 멀티 테넌트 환경의 인프라에 대해 Overlay Network를 구성하고 있다.

그 중에서 Private DNS 관련 버그를 몇 가지 발견했고, 해당 이슈 해결을 위해 NetMaker의 DNS 전파 과정을 파악해보기로 했다.

 

먼저 NetMaker를 간단하게 소개하자면, kernel level WireGuard를 이용해 MeshVPN을 구성해주는 오픈소스 프로젝트(일부 엔터프라이즈 기능은 별도의 라이센스 적용. 운영상 크게 문제가 되는 기능들은 아님)로, VPN 네트워크에 참여하는 호스트에 대한 Control Plane을 제공한다.  Endpoint 간의 WireGuard 터널링을 수행할 때 알아서 STUN으로 홀펀칭도 해주고, 구성된 VPN 네트워크에 CoreDNS를 통해 사설 DNS 기능도 제공한다. Ingress를 통해 외부망간의 포워딩도 간편하게 할 수 있다. Self-Hosted 설치는 다른 MeshVPN 플젝에 비하면 좀 복잡하긴 한데 그래도 크게 어렵진 않다.

 

Private DNS 기능.

기본적으로 VPN 네트워크를 생성하고 새로운 호스트를 추가하면 각 호스트의 이름(기본적으로 해당 엔드포인트의 hostname) + 네트워크 명의 DNS 레코드가 생긴다.

예를 들면 다음과 같다.

엔드포인트 A, B의 호스트명이 hostname_a, hostname_b이고, 네트워크 명이 vertex 라고 한다면,

A와 B를 각각 가리키는 hostname_a.vertex, hostname_b.vertex 라는 도메인이 등록된다.

그 외에도 사용자가 원하는 임의의 커스텀 도메인을 추가할 수 있고, 해당 커스텀 도메인은 데이터베이스에 저장된다.

저장된 도메인은 새로운 호스트가 추가 또는 삭제, Private DNS에 수정 사항이 생기면 NetMaker 서버가 데이터베이스에 있는 DNS 레코드와 기본 생성 가능한 레코드를 CoreDNS에 갱신시킨다.

 

원래(v0.22.0 버전 이전)는 각 호스트에 있는 NetMaker에서 DNS의 변경이 생길 때 마다 Message Broker로 변경 사항을 각 호스트에 전파하고, 각 호스트에 있는 NetClient는 해당 DNS 변경사항을 전달 받아 /etc/hosts 파일을 직접 수정함으로써 Private DNS 기능을 구현했다.

'[2023동계 모각코] 모각코' 카테고리의 다른 글

wireguard active healthcheck - 2  (0) 2024.02.17
wireguard active healthcheck - 1  (0) 2024.02.13
NetMaker 컨트리뷰션 준비  (0) 2024.01.24
rqlite 클러스터링 2  (0) 2024.01.23
rqlite 클러스터링  (1) 2024.01.23

+ Recent posts