Linkerd 모범 사례
지원 버전: Linkerd 2.16+ 마지막 업데이트: 2026년 2월 22일
개요
이 문서에서는 Linkerd를 프로덕션 환경에서 안정적으로 운영하기 위한 모범 사례를 다룹니다. 프로덕션 준비 체크리스트, 리소스 할당, 고가용성 구성, 업그레이드 전략, 성능 튜닝, 문제 해결 가이드를 포함합니다.
프로덕션 준비 체크리스트
필수 항목
yaml
# 프로덕션 배포 전 확인 사항
체크리스트:
인프라:
- [ ] HA 구성 적용 (컨트롤 플레인 복제본 3개)
- [ ] PodDisruptionBudget 설정
- [ ] 노드 안티-어피니티 구성
- [ ] 적절한 리소스 할당
보안:
- [ ] Trust Anchor 유효 기간 확인 (최소 1년 권장)
- [ ] Identity Issuer 유효 기간 확인
- [ ] 인증서 자동 갱신 설정
- [ ] default-deny 정책 검토
관찰성:
- [ ] Prometheus 메트릭 수집 구성
- [ ] Grafana 대시보드 설정
- [ ] 알림 규칙 구성
- [ ] 로그 수집 설정
운영:
- [ ] 백업 및 복구 절차 문서화
- [ ] 업그레이드 절차 문서화
- [ ] 롤백 절차 테스트
- [ ] 팀 교육 완료확인 명령어
bash
# 전체 상태 확인
linkerd check
# 프록시 상태 확인
linkerd check --proxy
# 인증서 만료 확인
linkerd check --proxy 2>&1 | grep -A5 "certificate"
# 컨트롤 플레인 상태
kubectl get pods -n linkerd리소스 할당 권장사항
컨트롤 플레인
yaml
# HA 프로덕션 설정
# ha-values.yaml
# Destination Controller
destination:
replicas: 3
resources:
cpu:
request: 100m
limit: 1000m
memory:
request: 50Mi
limit: 250Mi
# Identity Controller
identity:
replicas: 3
resources:
cpu:
request: 100m
limit: 1000m
memory:
request: 10Mi
limit: 250Mi
# Proxy Injector
proxyInjector:
replicas: 3
resources:
cpu:
request: 100m
limit: 1000m
memory:
request: 50Mi
limit: 250Mi데이터 플레인 (프록시)
yaml
# 워크로드 유형별 프록시 리소스 권장
# 일반 워크로드
proxy:
resources:
cpu:
request: 100m
limit: 1000m
memory:
request: 64Mi
limit: 250Mi
# 고트래픽 워크로드 (1000+ RPS)
proxy:
resources:
cpu:
request: 500m
limit: 2000m
memory:
request: 128Mi
limit: 500Mi
# 저트래픽 워크로드 (배치 작업 등)
proxy:
resources:
cpu:
request: 50m
limit: 500m
memory:
request: 32Mi
limit: 128MiPod별 리소스 오버라이드
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: high-traffic-service
spec:
template:
metadata:
annotations:
# CPU 설정
config.linkerd.io/proxy-cpu-request: "500m"
config.linkerd.io/proxy-cpu-limit: "2000m"
# 메모리 설정
config.linkerd.io/proxy-memory-request: "128Mi"
config.linkerd.io/proxy-memory-limit: "500Mi"고가용성 (HA) 구성
컨트롤 플레인 HA
yaml
# ha-control-plane.yaml
enablePodAntiAffinity: true
controllerReplicas: 3
# Pod 안티-어피니티
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: linkerd.io/control-plane-component
operator: In
values:
- destination
- identity
- proxy-injector
topologyKey: kubernetes.io/hostname
# 토폴로지 분산
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
linkerd.io/control-plane-ns: linkerd
# PDB
podDisruptionBudget:
maxUnavailable: 1Viz 확장 HA
yaml
# viz-ha-values.yaml
prometheus:
replicas: 2
resources:
cpu:
request: 300m
limit: 1000m
memory:
request: 300Mi
limit: 1Gi
persistence:
enabled: true
size: 50Gi
tap:
replicas: 2
resources:
cpu:
request: 100m
limit: 500m
memory:
request: 50Mi
limit: 250Mi
metricsAPI:
replicas: 2업그레이드 전략
Stable 채널 업그레이드
bash
# 1. 사전 준비
# 현재 버전 확인
linkerd version
# 업그레이드 가능 여부 확인
linkerd check --pre
# 2. CLI 업그레이드
curl --proto '=https' --tlsv1.2 -sSfL https://run.linkerd.io/install | sh
# 3. CRD 업그레이드 (먼저 수행)
linkerd upgrade --crds | kubectl apply -f -
# 4. 컨트롤 플레인 업그레이드
linkerd upgrade | kubectl apply -f -
# 5. 확인
linkerd check
# 6. Viz 업그레이드
linkerd viz upgrade | kubectl apply -f -
linkerd viz check
# 7. 데이터 플레인 업그레이드 (롤링 재시작)
# 중요: 한 번에 모든 서비스를 재시작하지 말 것
for ns in production staging; do
for deploy in $(kubectl get deploy -n $ns -o name); do
kubectl rollout restart $deploy -n $ns
kubectl rollout status $deploy -n $ns
sleep 30 # 안정화 대기
done
doneHelm 업그레이드
bash
# 1. Helm 저장소 업데이트
helm repo update
# 2. 현재 values 백업
helm get values linkerd-control-plane -n linkerd > current-values.yaml
# 3. CRD 업그레이드
helm upgrade linkerd-crds linkerd/linkerd-crds -n linkerd --wait
# 4. 컨트롤 플레인 업그레이드
helm upgrade linkerd-control-plane linkerd/linkerd-control-plane \
-n linkerd \
-f current-values.yaml \
--wait
# 5. Viz 업그레이드
helm upgrade linkerd-viz linkerd/linkerd-viz -n linkerd-viz --wait블루-그린 업그레이드 (고급)
bash
# 새 컨트롤 플레인 네임스페이스로 설치
linkerd install --linkerd-namespace linkerd-new | kubectl apply -f -
# 새 컨트롤 플레인 확인
linkerd --linkerd-namespace linkerd-new check
# 점진적으로 워크로드 마이그레이션
kubectl annotate namespace my-app linkerd.io/inject=enabled \
config.linkerd.io/proxy-version=stable-2.17.0
# 완전 마이그레이션 후 이전 컨트롤 플레인 제거
linkerd --linkerd-namespace linkerd uninstall | kubectl delete -f -롤백 절차
bash
# 문제 발생 시 롤백
# 1. 이전 버전 CLI 설치
curl --proto '=https' --tlsv1.2 -sSfL https://run.linkerd.io/install | \
sh -s -- --version stable-2.15.0
# 2. 컨트롤 플레인 롤백
linkerd upgrade | kubectl apply -f -
# 3. 데이터 플레인 롤백 (필요시)
kubectl rollout restart deploy -n my-app네임스페이스 및 주입 전략
네임스페이스 레벨 주입
yaml
# 권장: 네임스페이스 단위로 주입 관리
apiVersion: v1
kind: Namespace
metadata:
name: production
annotations:
linkerd.io/inject: enabled
---
# 특정 서비스 제외
apiVersion: v1
kind: Namespace
metadata:
name: legacy-services
annotations:
linkerd.io/inject: disabledPod 레벨 주입 제어
yaml
# 특정 Pod 주입 비활성화
apiVersion: apps/v1
kind: Deployment
metadata:
name: legacy-app
spec:
template:
metadata:
annotations:
linkerd.io/inject: disabled
---
# 특정 포트 제외
apiVersion: apps/v1
kind: Deployment
metadata:
name: database
spec:
template:
metadata:
annotations:
# 데이터베이스 포트는 프록시 우회
config.linkerd.io/skip-inbound-ports: "5432"
config.linkerd.io/skip-outbound-ports: "5432"Opaque 포트 설정
yaml
# 프로토콜 감지를 우회할 포트 지정
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
spec:
template:
metadata:
annotations:
# MySQL은 opaque로 처리
config.linkerd.io/opaque-ports: "3306"성능 튜닝
프록시 동시성 설정
yaml
# 고트래픽 환경에서 프록시 성능 최적화
apiVersion: apps/v1
kind: Deployment
metadata:
name: high-concurrency-service
spec:
template:
metadata:
annotations:
# 프록시 워커 스레드 수 (기본: 코어 수)
config.linkerd.io/proxy-cpu-limit: "4"연결 풀링
yaml
# 커넥션 관리 최적화
# Linkerd는 자동으로 HTTP/2 멀티플렉싱 사용
# 대부분의 경우 추가 설정 불필요
# HTTP/1.1 서비스의 경우
apiVersion: linkerd.io/v1alpha2
kind: ServiceProfile
metadata:
name: http1-service.my-app.svc.cluster.local
spec:
routes:
- name: all
condition:
pathRegex: /.*
timeout: 30s지연 시간 최적화
yaml
# 지연 시간에 민감한 서비스
apiVersion: apps/v1
kind: Deployment
metadata:
name: latency-sensitive
spec:
template:
metadata:
annotations:
# 디버그 로깅 비활성화 (성능 향상)
config.linkerd.io/proxy-log-level: "warn"
# 불필요한 포트 스킵
config.linkerd.io/skip-outbound-ports: "6379,11211"인증서 로테이션 스케줄링
자동 모니터링 설정
yaml
# CronJob으로 인증서 만료 모니터링
apiVersion: batch/v1
kind: CronJob
metadata:
name: linkerd-cert-check
namespace: linkerd
spec:
schedule: "0 9 * * *" # 매일 오전 9시
jobTemplate:
spec:
template:
spec:
containers:
- name: cert-check
image: buoyantio/linkerd-cli:stable-2.16.0
command:
- /bin/sh
- -c
- |
linkerd check --proxy 2>&1 | grep -i "certificate\|valid"
# 알림 전송 로직 추가
restartPolicy: OnFailurecert-manager 자동 갱신
yaml
# cert-manager로 자동 갱신 설정
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: linkerd-identity-issuer
namespace: linkerd
spec:
secretName: linkerd-identity-issuer
duration: 8760h # 1년
renewBefore: 720h # 30일 전 갱신
issuerRef:
name: linkerd-trust-anchor
kind: Issuer
commonName: identity.linkerd.cluster.local
isCA: true
privateKey:
algorithm: ECDSA
size: 256문제 해결 가이드
일반적인 문제와 해결 방법
프록시 주입 실패
bash
# 증상: Pod에 linkerd-proxy 컨테이너가 없음
# 진단
kubectl get ns my-app -o yaml | grep linkerd
kubectl describe pod my-pod -n my-app | grep -A5 "Annotations"
# 해결
# 1. 네임스페이스 어노테이션 확인
kubectl annotate ns my-app linkerd.io/inject=enabled --overwrite
# 2. Webhook 상태 확인
kubectl get mutatingwebhookconfiguration linkerd-proxy-injector-webhook-config
# 3. Proxy Injector 로그 확인
kubectl logs -n linkerd deploy/linkerd-proxy-injector높은 지연 시간
bash
# 증상: 메시 통과 시 지연 시간 증가
# 진단
linkerd viz stat deploy -n my-app
linkerd viz tap deploy/my-service -n my-app --max-rps 100
# 해결
# 1. 프록시 리소스 확인
kubectl top pods -n my-app -c linkerd-proxy
# 2. 리소스 증가
kubectl patch deploy my-service -n my-app -p '
{
"spec": {
"template": {
"metadata": {
"annotations": {
"config.linkerd.io/proxy-cpu-request": "500m",
"config.linkerd.io/proxy-memory-request": "128Mi"
}
}
}
}
}'
# 3. ServiceProfile 타임아웃 조정mTLS 연결 실패
bash
# 증상: 서비스 간 통신 오류
# 진단
linkerd viz tap deploy/client -n my-app --to deploy/server
linkerd viz edges deploy -n my-app
# 해결
# 1. 인증서 상태 확인
linkerd check --proxy
# 2. Identity 컨트롤러 로그 확인
kubectl logs -n linkerd deploy/linkerd-identity
# 3. 프록시 인증서 확인
kubectl exec -n my-app deploy/my-service -c linkerd-proxy -- \
cat /var/run/linkerd/identity/end-entity.crt | \
openssl x509 -noout -dates컨트롤 플레인 불안정
bash
# 증상: linkerd check 실패
# 진단
kubectl get pods -n linkerd
kubectl describe pods -n linkerd
kubectl get events -n linkerd --sort-by='.lastTimestamp'
# 해결
# 1. 리소스 부족 확인
kubectl top pods -n linkerd
# 2. 컨트롤 플레인 재시작
kubectl rollout restart deploy -n linkerd
# 3. 상태 재확인
linkerd check디버깅 명령어 모음
bash
# 전체 상태 확인
linkerd check
linkerd check --proxy
# 메트릭 확인
linkerd viz stat deploy -n my-app
linkerd viz routes deploy/my-service -n my-app
# 실시간 트래픽
linkerd viz tap deploy/my-service -n my-app
linkerd viz top deploy/my-service -n my-app
# 연결 상태
linkerd viz edges deploy -n my-app
# 프록시 로그
kubectl logs deploy/my-service -n my-app -c linkerd-proxy
# 컨트롤 플레인 로그
kubectl logs -n linkerd deploy/linkerd-destination
kubectl logs -n linkerd deploy/linkerd-identity
kubectl logs -n linkerd deploy/linkerd-proxy-injector
# 진단 메트릭
linkerd diagnostics proxy-metrics deploy/my-service -n my-appIstio에서 마이그레이션
마이그레이션 전략
기능 매핑
| Istio | Linkerd |
|---|---|
| VirtualService | ServiceProfile, HTTPRoute |
| DestinationRule | ServiceProfile |
| PeerAuthentication | 자동 mTLS (기본값) |
| AuthorizationPolicy | ServerAuthorization |
| Sidecar | 어노테이션 기반 설정 |
| Gateway | 별도 Ingress 필요 |
마이그레이션 단계
bash
# 1. 네임스페이스에서 Istio 비활성화
kubectl label namespace my-app istio-injection-
# 2. Linkerd 주입 활성화
kubectl annotate namespace my-app linkerd.io/inject=enabled
# 3. 워크로드 재시작
kubectl rollout restart deploy -n my-app
# 4. 트래픽 검증
linkerd viz stat deploy -n my-app
linkerd viz tap deploy/my-service -n my-app체크리스트 요약
yaml
프로덕션 배포 최종 체크리스트:
설치:
- [ ] 동일한 Trust Anchor로 모든 클러스터 구성
- [ ] HA 모드로 컨트롤 플레인 설치
- [ ] Viz 확장 설치 및 구성
보안:
- [ ] 인증서 유효 기간 60일 이상
- [ ] default-deny 정책 검토
- [ ] ServerAuthorization 규칙 정의
관찰성:
- [ ] Prometheus 스크레이핑 구성
- [ ] Grafana 대시보드 설정
- [ ] 알림 규칙 활성화
운영:
- [ ] ServiceProfile 정의 (주요 서비스)
- [ ] 프록시 리소스 튜닝
- [ ] 업그레이드 절차 문서화
- [ ] 롤백 절차 테스트