본문 바로가기
WIKI 기술 지식 베이스

Linkerd 장애 주입하기

원문 보기 위키 갱신

Linkerd 장애 주입하기 (Injecting Faults)

HTTPRoute 리소스를 사용해 트래픽의 일정 비율을 특정 백엔드로 리다이렉트하면 애플리케이션에 장애를 쉽게 주입할 수 있어요. 이 백엔드는 완전히 자유롭게 구성할 수 있어서 500 응답, 타임아웃, 심지어 엉뚱한 페이로드까지 원하는 대로 반환하게 할 수 있어요.

Books 데모는 이 동작을 보여주기에 아주 좋아요. 전체 토폴로지는 다음과 같아요: Topology

이 가이드에서는 webapp에서 books로 가는 요청 중 일부를 분리할 거예요. 대부분의 요청은 올바른 books 목적지에 도달하지만, 일부는 잘못된 백엔드로 리다이렉트될 거예요. 이 백엔드는 모든 요청에 대해 500을 반환해 webapp 서비스에 장애를 주입해요. 코드 변경은 필요 없고, 이 방법은 구성 기반이기 때문에 통합 테스트와 CI 파이프라인에 추가할 수 있는 절차예요. 카오스 엔지니어링을 진짜로 실천하고 있다면 장애 주입을 프로덕션에서도 사용할 수 있어요.

사전 요구사항

이 가이드를 사용하려면 다음이 실행되는 Kubernetes 클러스터가 필요해요:

  • Linkerd 및 Linkerd-Viz. 아직 설치하지 않았다면 Installing Linkerd 가이드를 따라 하세요.

서비스 설정

먼저 books 샘플 애플리케이션을 클러스터에 추가하세요:

kubectl create ns booksapp && \
  linkerd inject https://run.linkerd.io/booksapp.yml | \
  kubectl -n booksapp apply -f -

이 매니페스트는 다른 데모에서도 사용되므로 오류율이 구성되어 있어요. 장애 주입이 어떻게 동작하는지 보여주려면 오류율을 제거해서 신뢰할 수 있는 기준선을 만들어야 해요. booksapp의 성공률을 100%로 올리려면 다음을 실행하세요:

kubectl -n booksapp patch deploy authors \
  --type='json' \
  -p='[{"op":"remove", "path":"/spec/template/spec/containers/0/env/2"}]'

잠시 후 통계에 100% 성공률이 표시될 거예요. 다음 명령으로 확인할 수 있어요:

linkerd viz -n booksapp stat-inbound deploy

출력은 대략 다음과 같이 보일 거예요:

NAME     SERVER          ROUTE      TYPE  SUCCESS   RPS  LATENCY_P50  LATENCY_P95  LATENCY_P99
authors  [default]:4191  [default]        100.00%  0.20          0ms          1ms          1ms
authors  [default]:7001  [default]        100.00%  3.00          2ms         36ms         43ms
books    [default]:4191  [default]        100.00%  0.23          4ms          4ms          4ms
books    [default]:7002  [default]        100.00%  3.60          2ms          2ms          2ms
traffic  [default]:4191  [default]        100.00%  0.22          0ms          3ms          1ms
webapp   [default]:4191  [default]        100.00%  0.72          4ms          5ms          1ms
webapp   [default]:7000  [default]        100.00%  3.25          2ms          2ms         65ms

잘못된 백엔드 만들기

booksapp에 장애를 주입하려면 오류를 반환하도록 구성된 서비스가 필요해요. 이렇게 하려면 NGINX를 시작하고 500을 반환하도록 구성하면 돼요:

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
  name: error-injector
  namespace: booksapp
data:
 nginx.conf: |-
    events {}
    http {
        server {
          listen 8080;
            location / {
                return 500;
            }
        }
    }
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: error-injector
  namespace: booksapp
  labels:
    app: error-injector
spec:
  selector:
    matchLabels:
      app: error-injector
  replicas: 1
  template:
    metadata:
      labels:
        app: error-injector
    spec:
      containers:
        - name: nginx
          image: nginx:alpine
          volumeMounts:
            - name: nginx-config
              mountPath: /etc/nginx/nginx.conf
              subPath: nginx.conf
      volumes:
        - name: nginx-config
          configMap:
            name: error-injector
---
apiVersion: v1
kind: Service
metadata:
  name: error-injector
  namespace: booksapp
spec:
  ports:
  - name: service
    port: 8080
  selector:
    app: error-injector
EOF

장애 주입

booksapp과 NGINX가 실행되면 이제 기존 백엔드인 books와 새로 만든 error-injector 사이에 트래픽을 부분적으로 분리할 차례예요. 이는 클러스터에 HTTPRoute 구성을 추가해서 수행해요:

cat <<EOF | kubectl apply -f -
apiVersion: policy.linkerd.io/v1beta2
kind: HTTPRoute
metadata:
  name: error-split
  namespace: booksapp
spec:
  parentRefs:
    - name: books
      kind: Service
      group: core
      port: 7002
  rules:
    - backendRefs:
      - name: books
        port: 7002
        weight: 90
      - name: error-injector
        port: 8080
        weight: 10
EOF

참고

HTTPRoute 리소스의 두 가지 버전을 Linkerd와 함께 사용할 수 있어요:

  • Gateway API가 제공하는 업스트림 버전(gateway.networking.k8s.io API 그룹)
  • Linkerd가 제공하는 Linkerd 특화 CRD(policy.linkerd.io API 그룹)

두 HTTPRoute 리소스 정의는 비슷하지만, Linkerd 버전은 업스트림 Gateway API 리소스 정의에는 아직 없는 실험적 기능을 구현해요. 자세한 내용은 HTTPRoute 레퍼런스 문서를 참고하세요.

Linkerd가 books 서비스로 가는 트래픽을 보면, 요청 10개 중 9개를 원래 서비스로, 1개를 오류 주입기로 보내요. stat-outbound를 실행하면 이 모습을 확인할 수 있어요:

linkerd viz stat-outbound -n booksapp deploy/webapp
NAME    SERVICE       ROUTE        TYPE       BACKEND              SUCCESS   RPS  LATENCY_P50  LATENCY_P95  LATENCY_P99  TIMEOUTS  RETRIES
webapp  authors:7001  [default]                                     98.44%  4.28         25ms         47ms         50ms     0.00%    0.00%
                      └────────────────────►  authors:7001          98.44%  4.28         15ms         42ms         48ms     0.00%
webapp  books:7002    error-split  HTTPRoute                        87.76%  7.22         26ms         49ms        333ms     0.00%    0.00%
                      ├────────────────────►  books:7002           100.00%  6.33         14ms         42ms         83ms     0.00%
                      └────────────────────►  error-injector:8080    0.00%  0.88         12ms         24ms         25ms     0.00%

여기서 초당 0.88개의 요청이 오류 주입기로 보내지고 있으며 전체 성공률은 87.76%인 것을 확인할 수 있어요.

정리

이 가이드의 모든 것을 클러스터에서 제거하려면 다음을 실행하세요:

kubectl delete ns booksapp

출처: Linkerd Injecting Faults

본문

HTTPRoute 리소스를 사용해 트래픽의 일정 비율을 특정 백엔드로 리다이렉트하면 애플리케이션에 장애를 쉽게 주입할 수 있어요. 이 백엔드는 완전히 자유롭게 구성할 수 있어서 500 응답, 타임아웃, 심지어 엉뚱한 페이로드까지 원하는 대로 반환하게 할 수 있어요.

Books 데모는 이 동작을 보여주기에 아주 좋아요. 전체 토폴로지는 다음과 같아요: Topology

이 가이드에서는 webapp에서 books로 가는 요청 중 일부를 분리할 거예요. 대부분의 요청은 올바른 books 목적지에 도달하지만, 일부는 잘못된 백엔드로 리다이렉트될 거예요. 이 백엔드는 모든 요청에 대해 500을 반환해 webapp 서비스에 장애를 주입해요. 코드 변경은 필요 없고, 이 방법은 구성 기반이기 때문에 통합 테스트와 CI 파이프라인에 추가할 수 있는 절차예요. 카오스 엔지니어링을 진짜로 실천하고 있다면 장애 주입을 프로덕션에서도 사용할 수 있어요.

사전 요구사항

이 가이드를 사용하려면 다음이 실행되는 Kubernetes 클러스터가 필요해요:

  • Linkerd 및 Linkerd-Viz. 아직 설치하지 않았다면 Installing Linkerd 가이드를 따라 하세요.

서비스 설정

먼저 books 샘플 애플리케이션을 클러스터에 추가하세요:

kubectl create ns booksapp && \
  linkerd inject https://run.linkerd.io/booksapp.yml | \
  kubectl -n booksapp apply -f -

이 매니페스트는 다른 데모에서도 사용되므로 오류율이 구성되어 있어요. 장애 주입이 어떻게 동작하는지 보여주려면 오류율을 제거해서 신뢰할 수 있는 기준선을 만들어야 해요. booksapp의 성공률을 100%로 올리려면 다음을 실행하세요:

kubectl -n booksapp patch deploy authors \
  --type='json' \
  -p='[{"op":"remove", "path":"/spec/template/spec/containers/0/env/2"}]'

잠시 후 통계에 100% 성공률이 표시될 거예요. 다음 명령으로 확인할 수 있어요:

linkerd viz -n booksapp stat-inbound deploy

출력은 대략 다음과 같이 보일 거예요:

NAME     SERVER          ROUTE      TYPE  SUCCESS   RPS  LATENCY_P50  LATENCY_P95  LATENCY_P99
authors  [default]:4191  [default]        100.00%  0.20          0ms          1ms          1ms
authors  [default]:7001  [default]        100.00%  3.00          2ms         36ms         43ms
books    [default]:4191  [default]        100.00%  0.23          4ms          4ms          4ms
books    [default]:7002  [default]        100.00%  3.60          2ms          2ms          2ms
traffic  [default]:4191  [default]        100.00%  0.22          0ms          3ms          1ms
webapp   [default]:4191  [default]        100.00%  0.72          4ms          5ms          1ms
webapp   [default]:7000  [default]        100.00%  3.25          2ms          2ms         65ms

잘못된 백엔드 만들기

booksapp에 장애를 주입하려면 오류를 반환하도록 구성된 서비스가 필요해요. 이렇게 하려면 NGINX를 시작하고 500을 반환하도록 구성하면 돼요:

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
  name: error-injector
  namespace: booksapp
data:
 nginx.conf: |-
    events {}
    http {
        server {
          listen 8080;
            location / {
                return 500;
            }
        }
    }
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: error-injector
  namespace: booksapp
  labels:
    app: error-injector
spec:
  selector:
    matchLabels:
      app: error-injector
  replicas: 1
  template:
    metadata:
      labels:
        app: error-injector
    spec:
      containers:
        - name: nginx
          image: nginx:alpine
          volumeMounts:
            - name: nginx-config
              mountPath: /etc/nginx/nginx.conf
              subPath: nginx.conf
      volumes:
        - name: nginx-config
          configMap:
            name: error-injector
---
apiVersion: v1
kind: Service
metadata:
  name: error-injector
  namespace: booksapp
spec:
  ports:
  - name: service
    port: 8080
  selector:
    app: error-injector
EOF

장애 주입

booksapp과 NGINX가 실행되면 이제 기존 백엔드인 books와 새로 만든 error-injector 사이에 트래픽을 부분적으로 분리할 차례예요. 이는 클러스터에 HTTPRoute 구성을 추가해서 수행해요:

cat <<EOF | kubectl apply -f -
apiVersion: policy.linkerd.io/v1beta2
kind: HTTPRoute
metadata:
  name: error-split
  namespace: booksapp
spec:
  parentRefs:
    - name: books
      kind: Service
      group: core
      port: 7002
  rules:
    - backendRefs:
      - name: books
        port: 7002
        weight: 90
      - name: error-injector
        port: 8080
        weight: 10
EOF

참고

HTTPRoute 리소스의 두 가지 버전을 Linkerd와 함께 사용할 수 있어요:

  • Gateway API가 제공하는 업스트림 버전(gateway.networking.k8s.io API 그룹)
  • Linkerd가 제공하는 Linkerd 특화 CRD(policy.linkerd.io API 그룹)

두 HTTPRoute 리소스 정의는 비슷하지만, Linkerd 버전은 업스트림 Gateway API 리소스 정의에는 아직 없는 실험적 기능을 구현해요. 자세한 내용은 HTTPRoute 레퍼런스 문서를 참고하세요.

Linkerd가 books 서비스로 가는 트래픽을 보면, 요청 10개 중 9개를 원래 서비스로, 1개를 오류 주입기로 보내요. stat-outbound를 실행하면 이 모습을 확인할 수 있어요:

linkerd viz stat-outbound -n booksapp deploy/webapp
NAME    SERVICE       ROUTE        TYPE       BACKEND              SUCCESS   RPS  LATENCY_P50  LATENCY_P95  LATENCY_P99  TIMEOUTS  RETRIES
webapp  authors:7001  [default]                                     98.44%  4.28         25ms         47ms         50ms     0.00%    0.00%
                      └────────────────────►  authors:7001          98.44%  4.28         15ms         42ms         48ms     0.00%
webapp  books:7002    error-split  HTTPRoute                        87.76%  7.22         26ms         49ms        333ms     0.00%    0.00%
                      ├────────────────────►  books:7002           100.00%  6.33         14ms         42ms         83ms     0.00%
                      └────────────────────►  error-injector:8080    0.00%  0.88         12ms         24ms         25ms     0.00%

여기서 초당 0.88개의 요청이 오류 주입기로 보내지고 있으며 전체 성공률은 87.76%인 것을 확인할 수 있어요.

정리

이 가이드의 모든 것을 클러스터에서 제거하려면 다음을 실행하세요:

kubectl delete ns booksapp

더 알아보기 (Learn more)