IT/기타

Linkerd 2.18을 다시 봤지만, 결국 옮기지 않은 이유

gfrog 2026. 5. 25. 09:16
반응형

분기 OKR 중에 "Service Mesh 운영 단순화" 항목이 있었다. 우리 팀은 Istio Ambient를 작년 가을부터 운영 중인데, ztunnel 업그레이드 때마다 신경 쓸 게 많고, waypoint를 namespace 단위로 풀 때 라우팅 정책 디버깅이 여전히 만만치 않다. 작년에 Linkerd가 stable 보안 모델로 가는 동안 우리는 "Istio가 ambient만 잘 굴리면 Linkerd보다 가벼울 거다"라고 베팅했었다.

그런데 4월에 Linkerd 2.18이 나오면서 동료 한 명이 "이제 GitOps 친화적으로 multicluster가 된다는데, 우리 멀티 리전 셋업이랑 잘 맞을 것 같지 않아?"라고 슬랙에 던졌다. 솔직히 한 번 더 비교해보지 않으면 찝찝할 것 같았다. 그래서 2주 정도 PoC를 잡고 양쪽을 같은 워크로드에 올려 비교했다. 그 회고를 정리한다.

왜 굳이 Linkerd를 다시 봤나

Istio Ambient 자체에 큰 불만이 있어서는 아니다. ztunnel + waypoint 모델은 sidecar 시절보다 메모리 사용량이 절반 이하로 줄었고, 무엇보다 application pod에 sidecar를 박지 않으니까 HPA 튜닝이나 startup probe 설정 같은 곁가지가 사라졌다. 이건 진짜 좋다.

문제는 다른 데 있었다. 첫째, waypoint proxy가 layer 7 정책을 처리할 때 라우팅이 명확하지 않은 케이스가 있다. 특히 같은 namespace 안에서 두 서비스가 서로 다른 mTLS 정책을 가져야 할 때, AuthorizationPolicy를 namespace 레벨로 거느냐 service 레벨로 거느냐에 따라 우선순위가 헷갈렸다. 매뉴얼 보면서 작업해도 디버깅에 30분씩 까먹는 일이 분기에 서너 번은 있었다.

둘째, multicluster. 우리는 ap-northeast-2 / us-east-1 두 리전을 묶어 쓰는데, Istio의 east-west gateway 모델은 잘 동작하지만 ArgoCD로 declarative하게 풀려고 하면 CR 의존 관계가 꼬인다. eastwestgateway를 먼저 띄우고, 그 다음 Gateway/VirtualService를 만들고, secret으로 cross-cluster trust를 교환하는 순서를 ArgoCD sync wave로 관리하다 보면 sync hook이 깨지는 경우가 생긴다. 작년에 한 번 incident가 나면서 "이게 정말 우리 운영 모델에 맞나" 하는 의심이 남아있었다.

그래서 PoC 목표를 두 가지로 잡았다.

  • Linkerd 2.18로 같은 워크로드를 운영했을 때, 운영 단순함이 진짜 우리에게 가치가 있는가
  • multicluster 시나리오에서 GitOps 친화성이 정말로 더 나은가

Linkerd 2.18에서 인상적이었던 것들

PoC를 진행하면서 손에 잡힌 부분이 몇 가지 있다.

Protocol declaration이 깔끔하다. 2.18부터 Service의 appProtocol 필드를 Linkerd가 읽어서 protocol detection을 스킵한다. 우리는 gRPC 서비스가 30개쯤 되는데, 그동안 Linkerd 쓰던 부서에서 자주 들었던 얘기가 "어떤 클라이언트는 HTTP/2 업그레이드를 안 해서 protocol detection이 막힌다"였다. 이걸 그냥 Service에 appProtocol: kubernetes.io/h2c 한 줄로 푸는 게 마음에 들었다. Istio Ambient에서도 비슷한 기능이 있긴 한데 정책으로 풀어야 해서 한 번 더 layer가 생긴다.

GitOps 친화적 multicluster link. Linkerd 2.18은 Link CRD 하나로 cross-cluster 신뢰 관계를 선언적으로 만든다. 인증서를 ConfigMap이나 Secret으로 두면 그걸 참조해서 동작하고, ArgoCD의 입장에서는 그냥 평범한 K8s 오브젝트다. PoC에서 두 클러스터 묶는 데 30분 안 걸렸다. Istio에서는 같은 작업이 동선이 훨씬 길다.

apiVersion: multicluster.linkerd.io/v1alpha2
kind: Link
metadata:
  name: us-east-1
  namespace: linkerd-multicluster
spec:
  targetClusterName: us-east-1
  targetClusterDomain: cluster.local
  targetClusterLinkerdNamespace: linkerd
  gatewayAddress: 10.20.30.40
  gatewayPort: 4143
  gatewayIdentity: linkerd-gateway.linkerd-multicluster.serviceaccount.identity.linkerd.cluster.local

이 CR을 ArgoCD가 평소 다른 매니페스트 다루듯이 sync하면 끝이다. sync wave 같은 거 신경 안 쓴다.

proxy 자체의 가벼움. PoC 클러스터(노드 8대, pod 약 280개)에서 측정해보니 Linkerd proxy의 p99 latency overhead는 0.7~0.9ms, Istio Ambient ztunnel은 1.4~1.8ms 정도였다. waypoint를 거치면 그보다 더 올라간다. 절대 수치가 크지는 않지만, 우리 회사 상위 5개 서비스가 SLO 300ms를 운영하는 입장에서 1ms는 무시할 정도는 아니다. 다만 이게 결정타가 되지는 않았다(뒤에서 설명).

메모리. Linkerd proxy 컨테이너의 RSS는 평균 14MB, peak 22MB 정도였다. Istio Ambient는 ztunnel이 node 단위라 비교 단위가 다르지만, ztunnel 자체는 노드당 70~110MB를 안정적으로 쓴다. 같은 워크로드를 sidecar로 했을 때보다는 훨씬 가볍지만, Linkerd proxy를 다 합쳐도 ztunnel 노드 hop만큼은 안 나온다.

그런데 옮기지 않은 이유

PoC 끝나고 팀 내부 논의를 일주일 했다. 결론은 "Linkerd가 좋은 건 인정하지만, 지금 옮기는 비용이 그 가치보다 크다"였다. 이유를 정리하면 이렇다.

우리는 이미 Istio Ambient의 학습 비용을 다 치렀다. 작년 가을 도입할 때 팀원 다섯이 sidecar에서 ambient로 마이그레이션하면서 한 분기를 갈았다. waypoint 패턴, AuthorizationPolicy 우선순위, ztunnel HBONE 디버깅 — 이런 것들을 다 익혔다. 지금 Linkerd로 옮긴다는 건 그 학습 자본을 통째로 버리고 다시 학습하는 거다. 새 기술 스택이 30% 단순해도 학습 비용이 그것보다 클 가능성이 높다.

우리 워크로드의 traffic management 요구사항이 Linkerd 범위를 살짝 넘는다. 우리는 카나리 배포할 때 header 기반 traffic splitting, retry budget 세분 설정, request mirroring 같은 걸 자주 쓴다. Istio의 VirtualService는 이걸 다 자연스럽게 한다. Linkerd 2.18에서도 Gateway API 1.2.1 지원으로 많은 게 가능해지긴 했는데, retry budget이나 mirroring 같은 고급 기능은 여전히 직접 구현하거나 다른 도구를 끼워야 한다. 우리한테는 이게 trade-off로 받아들이기 어려웠다.

multicluster GitOps 친화성은 인정하지만, 우리에게는 이미 풀어둔 문제다. 작년 incident 이후로 Istio multicluster 설치를 Terraform과 ArgoCD로 나눠서 관리하기 시작했다. eastwestgateway와 trust bundle 교환은 Terraform이 한 번 만들고, 그 위에 application 레벨 Gateway/VirtualService만 ArgoCD가 본다. 분리하니까 sync wave가 깨지는 문제가 사라졌다. 깔끔하다고는 못 하지만 안정적이다. Linkerd 2.18이 같은 일을 더 우아하게 해주는 건 맞는데, 우리가 이미 작동하는 솔루션을 가지고 있어서 매력이 반감했다.

CNCF Survey 트렌드도 무시 못 했다. 2024 CNCF 서베이에서 service mesh 채택률이 50%에서 42%로 떨어졌다고 한다. 팀 내부에서는 이걸 두 가지로 해석했다. 하나는 "사람들이 mesh를 신중하게 도입하기 시작했다", 다른 하나는 "어쩌면 우리 같은 규모는 mesh 없이도 mTLS를 다른 방식으로 풀 수 있지 않나(SPIRE + native sidecar 같은)". 지금 mesh를 갈아엎느니, 1-2년 뒤 mesh 없는 모델을 검토하는 게 우리 ROI에 더 맞을 수도 있겠다는 의견이 나왔다.

그래서 Linkerd가 매력적이지 않다는 건 아니다

오해 없게 정리하면, Linkerd 2.18은 진짜 잘 만든 릴리스다. 새로 service mesh를 도입하는 팀에게 물어보면 나도 Linkerd를 첫 번째 후보로 추천한다. proxy가 가볍고, mTLS가 즉시 켜지고, 운영 표면이 좁다. 6개월 안에 한 명이 mesh를 책임지면서 다른 일도 같이 할 수 있는 정도다. Istio Ambient는 거기까지 가려면 더 시간을 들여야 한다.

# Linkerd 설치는 정말 한 줄이다
linkerd install --crds | kubectl apply -f -
linkerd install | kubectl apply -f -
linkerd check

이 명령 세 개를 치고 5분 기다리면 mTLS가 된 mesh가 올라온다. Istio Ambient는 helm chart 두 개, ztunnel DaemonSet, gateway API CRD — 절차가 더 길다.

다만 우리 팀이 지금 마주한 질문은 "어느 게 더 좋은가"가 아니라 "지금 갈아엎을 가치가 있는가"였다. 답은 no였을 뿐이다. 신규 도입 팀이 같은 PoC를 했다면 다른 결정을 내렸을 것 같다.

한 가지 변수: Windows 지원

Linkerd 2.18의 실험적 Windows proxy 지원은 의외의 변수다. 우리 사내 시스템 중에 .NET Framework 기반의 레거시 서비스가 한 묶음 있다. 이걸 Windows containers on K8s로 운영하는데, 지금은 mesh 바깥에 두고 있다. 이게 Linkerd로 묶을 수 있게 되면 mTLS 영역이 넓어진다. 아직 실험적이라 프로덕션에 못 쓰지만, 1년 안에 GA로 가면 다시 검토할 만한 이유가 된다.

다음 분기에는 Linkerd로 Windows workload만 묶는 일종의 "이중 mesh" 구성을 PoC 할 계획이다. 같은 클러스터 안에서 두 mesh를 동시에 운영하는 게 가능한지, 두 mesh 사이의 트래픽이 어떻게 풀리는지 — 이게 잘 되면 점진적 마이그레이션의 발판이 될 수도 있고, 아니면 그냥 둘 다 운영하면서 워크로드 특성별로 나누는 것도 답일 수 있다.

정리

PoC 한 달 돌리고 얻은 결론은 이렇다.

  • Linkerd 2.18은 신규 도입한다면 1순위 후보다. operational simplicity가 정말 좋다
  • 우리는 Istio Ambient의 학습 비용을 이미 치렀고, 워크로드 요구사항이 Istio의 traffic management를 활용한다. 옮기는 비용이 효익보다 크다
  • GitOps 친화적 multicluster는 매력적이지만, 우리는 이미 Terraform + ArgoCD 분리로 같은 문제를 풀어놨다
  • Windows 지원이 GA로 가면 그 때 다시 검토한다

이런 비교를 하면서 든 생각인데, 도구 결정은 거의 항상 "지금 우리가 어디에 서 있는가"에 의존한다. 백지에서 시작하면 답이 다르고, 이미 한쪽으로 깊이 들어가 있으면 답이 또 다르다. 베스트 프랙티스를 따지는 것보다 우리 팀의 학습 곡선과 운영 자본을 정직하게 평가하는 게 더 중요했다.

혹시 비슷한 비교를 하셨거나, 우리와 다른 결정을 내리신 분이 있으면 어떤 맥락이 결정타였는지 궁금하다. 댓글이나 사내 채널로 알려주시면 감사하겠다.

반응형