본문 바로가기
Service Mesh/Linkerd

Linkerd 트래픽 Retry, Timeout

by wlsdn3004 2023. 4. 19.
728x90
반응형

 

linkerd는 ServiceProfile이라는 CRD를 사용하여 경로별 Retry, Timeout 설정을 할 수 있다.

 

Retry

서비스가 클라이언트의 요청을 받아 처리하는데, 요청이 실패할 경우 다시 보내는 기능이다.

가끔 요청이 실패할 경우 다시 보내어 클라이언트 기준 요청 성공률을 높일 수 있다. 하지만 클라이언트가 과도하게 재시도를 수행하면 서비스는 이를 처리하지 못하고 과부하 상태 및 잠재적인 장애 증상을 일으킬 수 있음에 주의해야 한다.

 

Timeout

서비스의 요청 처리 시간이 일정 시간 이상 걸릴 경우 해당 요청을 종료하는 기능이다. 
클라이언트와 서버와의 통신이 끊어져 있거나 지연되고 있는 상황에서 클라이언트가 무한정 기다리는 것을 방지할 수 있다. 하지만 처리 중인 요청을 종료하여 문제를 일으킬 수 있으니 애플리케이션의 특성에 맞게 적절히 조정해서 사용해야 한다.

 

실습을 통해 어떻게 동작 하는지 간단하게 테스트해 보자.

 

 

실습 전제 조건

 

실습 환경

  • AWS EKS 1.22

 

실습

 

1. 테스트를 위한 Client, Server 사전 구성


요청받을 nginx 서버를 배포한다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
      annotations:
        linkerd.io/inject: enabled
    spec:
      containers:
      - name: nginx
        image: nginx:latest

 

nginx서버 설정을 위한 패키지를 다운로드한다.

$ kubectl expose service nginx --port=80
$ kubectl exec -it svc/nginx -c nginx -- /bin/bash
$ apt update
$ apt-get install build-essential libpcre3 libpcre3-dev zlib1g-dev libssl-dev vim wget

 

nginx서버에서 요청에 대한 응답 지연을 발생시키기 위한 구성으로 echo-nginx-module 모듈을 사용하기 위한 구성을 아래와 같이 한다.

$ wget http://nginx.org/download/nginx-1.23.4.tar.gz
$ tar zxvf nginx-1.23.4.tar.gz
$ cd nginx-1.23.4

## nginx 1.23 버전에 호환되는 echo-nginx-module 다운
$ wget https://github.com/openresty/echo-nginx-module/archive/v0.63.tar.gz
$ tar -xvzf v0.63.tar.gz

## 모듈 컴파일
$ ./configure --with-compat --add-dynamic-module=../echo-nginx-module-0.63
make modules
cp objs/ngx_http_echo_module.so /etc/nginx/modules

 

/test 경로로 요청 오면 502 error를 반환하고, /tmout 경로로 요청 오면 10초 후 echo 메세지를 반환하는 설정이다.

$ vi /etc/nginx/conf.d/default.conf
server {
    listen       80;
    listen  [::]:80;
    server_name  localhost;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }
    
    location /test {
        return 502;
    }
    
    location /tmout {
        echo_sleep 10;
        return 200 "Hello, world!";
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }


}
$ nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

$ service nginx reload

 

같은 nginx 이미지를 사용하여 요청 보낼 nginx-client를 배포한다.

apiVersion: v1
kind: Service
metadata:
  name: nginx-client
spec:
  selector:
    app: nginx-client
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nginx-client
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-client
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx-client
  template:
    metadata:
      name: nginx-client
      labels:
        app: nginx-client
      annotations:
        linkerd.io/inject: enabled
    spec:
      containers:
        - name: nginx-client
          image: nginx

 

2. Retry  설정


ServiceProfile을 통해 nginx서버의 /test 경로에 대한 Retry 설정을 하고 nginx-client에서 요청을 보내 로그를 확인해 보자.

apiVersion: linkerd.io/v1alpha2
kind: ServiceProfile
metadata:
  name: nginx.default.svc.cluster.local
  namespace: default
spec:
  routes:
  - condition:
      method: HEAD
      pathRegex: /test
    isRetryable: true  ## Retry 설정
    name: HEAD /test
$ kubectl logs svc/nginx -c nginx -f
192.168.6.169 - - [19/Apr/2023:03:52:49 +0000] "GET /test HTTP/1.1" 502 497 "-" "curl/7.74.0" "-"
192.168.6.169 - - [19/Apr/2023:03:52:49 +0000] "GET /test HTTP/1.1" 502 497 "-" "curl/7.74.0" "-"
192.168.6.169 - - [19/Apr/2023:03:52:49 +0000] "GET /test HTTP/1.1" 502 497 "-" "curl/7.74.0" "-"
192.168.6.169 - - [19/Apr/2023:03:52:49 +0000] "GET /test HTTP/1.1" 502 497 "-" "curl/7.74.0" "-"
192.168.6.169 - - [19/Apr/2023:03:52:49 +0000] "GET /test HTTP/1.1" 502 497 "-" "curl/7.74.0" "-"
192.168.6.169 - - [19/Apr/2023:03:52:49 +0000] "GET /test HTTP/1.1" 502 497 "-" "curl/7.74.0" "-"
192.168.6.169 - - [19/Apr/2023:03:52:49 +0000] "GET /test HTTP/1.1" 502 497 "-" "curl/7.74.0" "-"
192.168.6.169 - - [19/Apr/2023:03:52:49 +0000] "GET /test HTTP/1.1" 502 497 "-" "curl/7.74.0" "-"
192.168.6.169 - - [19/Apr/2023:03:52:49 +0000] "GET /test HTTP/1.1" 502 497 "-" "curl/7.74.0" "-"
192.168.6.169 - - [19/Apr/2023:03:52:49 +0000] "GET /test HTTP/1.1" 502 497 "-" "curl/7.74.0" "-"
192.168.6.169 - - [19/Apr/2023:03:52:49 +0000] "GET /test HTTP/1.1" 502 497 "-" "curl/7.74.0" "-"
192.168.6.169 - - [19/Apr/2023:03:52:49 +0000] "GET /test HTTP/1.1" 502 497 "-" "curl/7.74.0" "-"
192.168.6.169 - - [19/Apr/2023:03:52:49 +0000] "GET /test HTTP/1.1" 502 497 "-" "curl/7.74.0" "-"

약 1번의 요청 Fail에 대한 Retry로 100번의 요청이 재시도된 것을 확인할 수 있다.

 

retry 값은 아래 설정을 통해 세세하게 설정할 수 있다.

spec:
  retryBudget:
    retryRatio: 0.2
    minRetriesPerSecond: 10
    ttl: 10s
  • retryRatio : 재시도 요청에 대한 최대 비율 (0.2 = 20%)
  • minRetriesPerSecond : retryRatio에서 허용하는 것 외에 초당 재시도 허용 수
  • ttl : retryRatio를 계산하기 위해 요청이 고려되는 시간

 

3. Timeout 설정


ServiceProfile을 통해 nginx서버의 /tmout 경로에 대한 Retry 설정을 하고 nginx-client에서 요청을 보내자.

1초간 지연이 발생하면 Timeout 되는 설정이다.

apiVersion: linkerd.io/v1alpha2
kind: ServiceProfile
metadata:
  name: nginx.default.svc.cluster.local
  namespace: default
spec:
  routes:
  - condition:
      method: GET
      pathRegex: /test
    isRetryable: true
    name: GET /test
    
  ## timeout path에 timeout 설정 추가
  - condition:
      method: GET
      pathRegex: /tmout
    name: GET /tmout
    timeout: 1000ms

 

$ kubectl exec -it svc/nginx-client -c nginx-client -- /bin/bash
$ curl nginx/tmout -vvv
*   Trying 10.100.119.208:80...
* Connected to nginx (10.100.119.208) port 80 (#0)
> GET /tmout HTTP/1.1
> Host: nginx
> User-Agent: curl/7.74.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 504 Gateway Timeout
< l5d-proxy-error: HTTP response timeout after 1s
< connection: close
< l5d-proxy-connection: close
< content-length: 0
< date: Wed, 19 Apr 2023 08:00:51 GMT
<
* Closing connection 0

1초가 지나면 504 Gateway Timeout가 발생하여 connection이 끊긴 것을 확인할 수 있다.

 

마치며


timeout과 retry는 서비스의 안정성과 가용성을 향상시키는 데 큰 역할을 한다. timeout 시간이 너무 짧으면 서버로부터 응답이 와도 클라이언트에서 에러가 발생할 수 있으며, retry 횟수나 간격이 너무 많거나 짧으면 서버의 부하를 더욱 악화시킬 수 있다. 따라서 이 기능들을 설정할 때는 애플리케이션의 특성에 맞춰 주의 깊게 고려하여 적용해야 한다.

반응형

'Service Mesh > Linkerd' 카테고리의 다른 글

Linkerd 서킷 브레이킹 (Circuit Breaking)  (1) 2023.04.19
Linkerd 버전 업그레이드  (1) 2023.04.19
Linkerd 권한 부여 정책  (0) 2023.04.05
Linkerd mTLS 통신 검증  (0) 2023.04.05
Linkerd 사이드카 주입  (0) 2023.04.05

댓글