E-이스티오 컨트롤 플레인 성능 최적화
개요
대규모의 클러스터를 운영하다보면 자연스레 성능 문제를 신경 쓸 수밖에 없다.
컨트롤 플레인이 데이터 플레인의 모든 리소스와 통신을 해야 하기 때문에, 컨트롤 플레인 부하를 많이 받을 가능성을 항상 내포하고 있으며, 최적화에 있어서도 중요한 고려요소가 된다.
컨트롤 플레인은 궁극적 일관성을 추구하도록 설계됐기에, 사용자의 설정이 즉각적으로 반영되지 않는다.
그렇기 때문에 부하를 받고 지연시간이 늘어나는 것은 곧 메시 환경을 불안정하게 만든다.
성능 개선 개요
컨트롤 플레인의 성능에는 크게 4가지가 영향을 주게 되는데, 이들을 개선하기 위해 다음의 방법들을 활용할 수 있다.
- 변경 속도 - 변경 속도가 빠를수록 데이터 플레인을 동기화하기 위해 더 많이 처리
- 서비스 메시와 관련 없는 이벤트 무시
- 이벤트 배치 처리 기간을 데이터 플레인 업데이트에 필요한 푸시 횟수 줄이기
- 할당된 리소스 - 프로세스는 당연히 컴퓨팅 자원에 영향 받음..
- 스케일 아웃으로 파일럿 인스턴스들이 관리할 워크로드 분할
- 스케일 업으로 엔보이 설정 생성 속도 높이고 푸시 동시 처리량 높이기
- 업데이트할 워크로드 개수 - 업데이트할 워크로드가 많을 수록 네트워크 대역폭과 처리 능력 필요
- Istio Sidecar 리소스를 통해 설정에 영향 받을 워크로드 범위 지정
- 설정 크기 - 엔보이 설정 파일이 클 수록 처리 능력과 네트워크 대역폭이 필요
- Istio Sidecar 리소스를 통해 워크로드가 필요한 설정만 받도록 설정
사이드카 리소스는 성능 최적화의 핵심이 되는 리소스라 할 수 있다.
다른 리소스들의 설정 방식도 다 그렇지만 결국 어떤 범위에 해당 설정이 적용되게 할지가 관건이 된다.
사이드카 리소스는 아예 핵심적으로 이것만 전담하는 리소스로서 메시 전체의 부하를 줄이는 효과도 있다.
사이드카 자체의 레이턴시는 동시 커넥션 수에 따라 확장된다.[1]
세팅 - 스크립트로 부하 테스트
일부러 부하가 걸릴 상황을 만들 것이다.
kubectl -n istioinaction apply -f services/catalog/kubernetes/catalog.yaml
kubectl -n istioinaction apply -f ch11/catalog-virtualservice.yaml
kubectl -n istioinaction apply -f ch11/catalog-gateway.yaml
kubectl -n istioinaction apply -f ch11/sleep-dummy-workloads.yaml
while true; do curl -K curl.conf -s http://catalog.istioinaction.io:30000/items ; date "+%Y-%m-%d %H:%M:%S" ; sleep 1; echo; done
while true; do kubectl top pod -n istio-system -l app=istiod --containers=true ; date "+%Y-%m-%d %H:%M:%S" ; sleep 1; echo; done
일단 기본적으로 많은 개수의 워크로드를 배치한다.
사실 끽해봐야 10개 남짓한 개수만 배포했는데, 실제 워크로드를 배치하지 않아도 서비스를 늘리는 것만으로 쉽게 부하를 줄 수 있다.
각 서비스에 대해 엔보이들에 설정을 반영해줘야 하기 때문이다.
이 파일을 적용해보자!
서비스와 게이트웨이, 버추얼 리소스를 무려 200개씩 때려박는 무식한 양식 파일이다.
kubectl -n istioinaction apply -f ch11/resources-600.yaml
순간 cpu, 메모리 사용량이 잠시 치솟는 것을 볼 수 있다.
그라파나 메트릭으로 확인해도 마찬가지이다.
rate(pilot_xds_pushes[$__rate_interval])
간단하게 설정을 보면 eds, 즉 엔드포인트 설정 횟수가 어마무시하게 많은 것을 볼 수 있다.
그러나 이 정도는 거뜬하다는 듯, 시간에는 거의 차이가 발생하지 않는 것을 볼 수 있다.
처리하는 요청 개수 자체는 늘었으나 시간은 전부 다 0.01 아래로 동일했다는 것이다.
여기에 본격적으로 부하 테스트를 진행할 것이다.
책에서 일부러 여러 서비스를 만들었다 지웠다하면서 컨트롤 플레인에 부하를 주는 스크립트를 제공한다.
#!/bin/bash
main(){
## Pass input args for initialization
init_args "$@"
SLEEP_POD=$(kubectl -n istioinaction get pod -l app=sleep -o jsonpath={.items..metadata.name} -n istioinaction | cut -d ' ' -f 1)
PRE_PUSHES=$(kubectl exec -n istio-system deploy/istiod -- curl -s localhost:15014/metrics | grep pilot_xds_pushes | awk '{total += $2} END {print total}')
if [[ -z "$PRE_PUSHES" ]]; then
echo "Failed to query Pilot Pushes from prometheus."
echo "Have you installed prometheus as shown in chapter 7?"
exit 1
fi
echo "Pre Pushes: $PRE_PUSHES"
INDEX="0"
while [[ $INDEX -lt $REPS ]]; do
SERVICE_NAME="service-`openssl rand -hex 2`-$INDEX"
create_random_resource $SERVICE_NAME &
sleep $DELAY
INDEX=$[$INDEX+1]
done
## Wait until the last item is distributed
while [[ "$(curl --max-time .5 -s -o /dev/null -H "Host: $SERVICE_NAME.istioinaction.io" -w ''%{http_code}'' $GATEWAY/items)" != "200" ]]; do
# curl --max-time .5 -s -o /dev/null -H "Host: $SERVICE_NAME.istioinaction.io" $GATEWAY/items
sleep .2
done
echo ==============
sleep 10
POST_PUSHES=$(kubectl exec -n istio-system deploy/istiod -- curl -s localhost:15014/metrics | grep pilot_xds_pushes | awk '{total += $2} END {print total}')
echo
LATENCY=$(kubectl -n istioinaction exec -it $SLEEP_POD -c sleep -- curl "$PROM_URL/api/v1/query" --data-urlencode "query=histogram_quantile(0.99, sum(rate(pilot_proxy_convergence_time_bucket[1m])) by (le))" | jq '.. |."value"? | select(. != null) | .[1]' -r)
echo "Push count:" `expr $POST_PUSHES - $PRE_PUSHES`
echo "Latency in the last minute: `printf "%.2f\n" $LATENCY` seconds"
}
create_random_resource() {
SERVICE_NAME=$1
cat <<EOF | kubectl apply -f -
---
kind: Gateway
apiVersion: networking.istio.io/v1alpha3
metadata:
name: $SERVICE_NAME
namespace: $NAMESPACE
spec:
servers:
- hosts:
- "$SERVICE_NAME.istioinaction.io"
port:
name: http
number: 80
protocol: HTTP
selector:
istio: ingressgateway
---
apiVersion: v1
kind: Service
metadata:
labels:
app: catalog
name: $SERVICE_NAME
namespace: $NAMESPACE
spec:
ports:
- name: http
port: 80
protocol: TCP
targetPort: 3000
selector:
app: catalog
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: $SERVICE_NAME
namespace: $NAMESPACE
spec:
hosts:
- "$SERVICE_NAME.istioinaction.io"
gateways:
- "$SERVICE_NAME"
http:
- route:
- destination:
host: $SERVICE_NAME.istioinaction.svc.cluster.local
port:
number: 80
---
EOF
}
help() {
cat <<EOF
Poor Man's Performance Test creates Services, Gateways and VirtualServices and measures Latency and Push Count needed to distribute the updates to the data plane.
--reps The number of services that will be created. E.g. --reps 20 creates services [0..19]. Default '20'
--delay The time to wait prior to proceeding with another repetition. Default '0'
--gateway URL of the ingress gateway. Defaults to 'localhost'
--namespace Namespace in which to create the resources. Default 'istioinaction'
--prom-url Prometheus URL to query metrics. Defaults to 'prom-kube-prometheus-stack-prometheus.prometheus:9090'
EOF
exit 1
}
init_args() {
while [[ $# -gt 0 ]]; do
case ${1} in
--reps)
REPS="$2"
shift
;;
--delay)
DELAY="$2"
shift
;;
--gateway)
GATEWAY="$2"
shift
;;
--namespace)
NAMESPACE="$2"
shift
;;
--prom-url)
PROM_URL="$2"
shift
;;
*)
help
;;
esac
shift
done
[ -z "${REPS}" ] && REPS="20"
[ -z "${DELAY}" ] && DELAY=0
[ -z "${GATEWAY}" ] && GATEWAY=localhost:30000
[ -z "${NAMESPACE}" ] && NAMESPACE=istioinaction
[ -z "${PROM_URL}" ] && PROM_URL="prometheus.istio-system.svc.cluster.local:9090"
}
main "$@"
원래 있던 코드에서 맨 아래 GATEWAY
, PROM_URL
만 현재 내 세팅에 맞게 수정해주었다.
이건 xDS Push수 증가량과 프록시 구성 수렴 시간(latency)을 확인한다.
이를 통해 최종적으로 Push 성능과 latency를 평가할 수 있다.
./performance-test.sh --reps 10 --delay 2.5
해당 파일에 실행권한을 준 뒤에 실행해본다.
10개의 리소스를 만들고, 만들 때 2.5의 간격을 두도록 설정했다.
흐음.. 내 컴이 생각보다 성능이 좋나..
./performance-test.sh --reps 10
지연을 없애고 해도 성능이 좋은 것 같다..
리소스를 만든 횟수는 똑같은데 푸시 횟수가 줄어든 것은 디바운스 때문인 것으로 보인다.
sum(rate(pilot_debounce_time_bucket[1m])) by (le)
간단하게 디바운싱되느라 큐에 들어가지 못하고 걸린 시간을 측정해볼 수 있는데, 1초 이상의 시간이 걸린 것들이 더러 생겼다.
원하는 결과가 안 나오는 것 같아서 delay없이 100개 때려박아봤는데, 푸시에 0.1초 가까이 걸리는 것들이 생겨나기 시작했다.
이해하고 나니까 히트맵이 굉장히 보기 좋은 것 같다
푸시된 설정 파일 사이즈 역시 조금씩 증가하는 것이 확인된다.
그런데 역시 아무리 봐도 생각한 수준의 부하가 측정되질 않는 것 같다..?
이 스크립트는 만든 리소스를 삭제하지 않는다..
그래서 마구 걸어댔더니 서비스랑 버추얼 서비스 개수가 1000개를 넘어버렸다 ㅋㅋ
기어코 cidr 범위가 꽉찼다는 에러까지 나온다...
최근 기본 리소스가 된 ServiceCIDR을 써보려했는데 Kubernetes v1.33 - Octarine에 기본으로 활성화되어서 현 클러스터에 설정할 수 없다..
apiVersion: networking.k8s.io/v1
kind: ServiceCIDR
metadata:
name: new-cidr
spec:
cidrs:
- 10.201.0.0/22
그렇다면 바로 버전 업.
어차피 추가 실습을 이어나가야 하는 마당에 cidr이 꽉찬 상황을 해결해야 했기에 잘됐다.
그런데 아무리 해봐도 레이턴시가 증가하질 않는다..
kubectl -n istioinaction exec -it sleep-5f6f494dc8-2l9kd -c sleep -- curl "prometheus.istio-system.svc.cluster.local:9090/api/v1/query" --data-urlencode "query=histogram_quantile(0.99, sum(rate(pilot_proxy_convergence_time_bucket[1m])) by (le))" | jq '.. |."value"? | select(. != null) | .[1]' -r
쿼리문을 직접 실행해서 확인해봐도 확실히 그렇고, 프로메테우스로 확인해도 마찬가지이다.
거의 변동이 없어서 뭔가 유의미한 확인을 하는 것이 어렵다.
Sidecar 리소스 활용
유의미한 가시화는 안 되지만, 일단 책에서 나온 실습 그대로 진행하는 걸로 정했다.
기본적으로는 모든 서비스가 메시의 모든 워크로드를 알도록 설정된다.
사이드카가 특히 유용할 수밖에 없는 상황은 동서 트래픽을 설정할 때이다.
버츄얼 서비스로 메시 환경 내의 트래픽을 처리하려면 진입점에 mesh
를 적어줘야 하는데, 이건 기본적으로 메시 전체 서비스가 해당 버추얼 서비스를 인식하게 만든다.
대충 설정했다간 괜한 버츄얼 서비스 하나에 모든 프록시가 업데이트를 받아야 하는 상황이 생긴다는 것.
CATALOG_POD=$(kubectl -n istioinaction get pod -l app=catalog -o jsonpath={.items..metadata.name} | cut -d ' ' -f 1)
kubectl -n istioinaction exec -ti $CATALOG_POD -c catalog -- curl -s localhost:15000/config_dump > /tmp/config_dump
du -sh /tmp/config_dump
서비스가 증가할수록 설정 파일의 크기도 증가하는 것은 위에서 확인됐다.
현재 단일 엔보이에 들어간 설정 파일의 크기는 무려 2.4메가..
이제 이를 해소하기 위해 사이드카 리소스를 적용해본다.
apiVersion: networking.istio.io/v1beta1
kind: Sidecar
metadata:
name: default
namespace: istioinaction
spec:
workloadSelector:
labels:
app: foo
egress:
-hosts:
- "./bar.istioinaction.svc.cluster.local"
- "istio-system/*"
outboundTrafficPolicy:
mode: REGISTRY_ONLY
워크로드를 고르고, 이 워크로드에 드나드는 트래픽 설정을 명확하게 제한을 건다.
인그레스 설정하면 이쪽으로 향할 호스트 방식 지정
이그레스는 해당 워크로드가 대상으로 삼을 수 있는 서비스 지정.
디폴트로서 추천하는 건 모든 프록시의 트래픽 송신에 대해 istio-system의 서비스로만 가도록 설정하는 것.
모든 프록시는 컨트롤 플레인에 연결되고 다른 서비스 간 연결은 삭제된다.
이 상태에서 프록시 간 연결이 필요한 것들에 대해 명시적으로 지정하며 네트워크 경로를 지정하면 설정을 최소화시킬 수 있다.
apiVersion: networking.istio.io/v1beta1
kind: Sidecar
metadata:
name: default # istio-system 네임스페이스의 사이드카는 메시 전체에 적용된다.
namespace: istio-system # 위 설명 동일.
spec:
egress:
- hosts:
- "istio-system/*" # istio-system 네임스페이스의 워크로드만 트래픽 송신을 할 수 있게 설정한다.
- "prometheus/*" # 프로메테우스 네임스페이스도 트래픽 송신을 할 수 있게 설정한다.
outboundTrafficPolicy:
mode: REGISTRY_ONLY # 모드는 사이드카에 설정한 서비스로만 트래픽 송신을 허용한다
이게 그 설정이다.
CATALOG_POD=$(kubectl -n istioinaction get pod -l app=catalog -o jsonpath={.items..metadata.name} | cut -d ' ' -f 1)
kubectl -n istioinaction exec -ti $CATALOG_POD -c catalog -- curl -s localhost:15000/config_dump > /tmp/config_dump
du -sh /tmp/config_dump
이걸 적용하자마자 설정 파일의 크기가 4배는 줄어들었다.
그렇다면 과연 컨트롤 플레인 부하는 줄어들었을까?
./performance-test.sh --reps 15 --delay 0.5
일단 푸시 개수는 줄어든 것이 확인된다.
그라파나로도 cpu 사용량 등이 확실하게 줄은 것은 확인할 수 있다.
이벤트를 무시할 네임스페이스 지정
이스티오는 모든 네임스페이스의 모든 리소스에 대해 추적한다..
그래서 네임스페이스 셀렉터 설정을 넣어서 범위를 제한하자.
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
namespace: istio-system
spec:
meshConfig:
discoverySelectors: # 디스커버리 셀렉터 활성화
- matchExpressions:
- key: istio-exclude
operator: NotIn
values:
- "true"
이스티오 오퍼레이터 양식 파일에서 추적할 네임스페이스를 설정했다.
exclude 라벨에 true라 적히지 않은 네임스페이스만 추적하는 설정이다.
kubectl create ns new-ns2
kubectl label namespace new-ns2 istio-injection=enabled
cat << EOF | kubectl apply -n new-ns2 -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
labels:
app: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:alpine
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
EOF
docker exec -it myk8s-control-plane istioctl proxy-config endpoint deploy/istio-ingressgateway.istio-system | grep nginx | wc -l
kubectl label ns new-ns2 istio-exclude=true
docker exec -it myk8s-control-plane istioctl proxy-config endpoint deploy/istio-ingressgateway.istio-system | grep nginx | wc -l
생각지 못한 상황 발생..!
게이트웨이 리소스 최적화를 한답시고 처음부터 게이트웨이에 필터링 설정을 넣었던 탓인지, 기본적으로 클러스터를 인식하지 않고 있다!
이게 원인이라 생각해서 없애고 게이트웨이도 재시작시켜줬으나, 결과는 실패.
원인을 잘 모르겠는데, 이건 다음에 조금 더 파봐야겠다.
동기화 작업 배치 처리
디바운스 기간을 조금 더 넓게 주는 것도 성능 최적화의 하나의 방법이다.
배치 간격이 넓어지므로 자원을 조금 더 효율적으로 사용하여 이벤트를 처리할 수 있게 된다.
3번에 걸쳐서 설정될 예정이었던 이벤트가 한번에 적용돼서 한번에 푸시만으로 해결된다면 속도 향상을 꾀할 수 있게 된다.
(물론 설정들이 병합되며 개별 설정 파일 크기가 증가할 수는 있다.)
그러나 기간이 넓어질수록 설정이 빠르게 적용되지 못하여 지연이 발생할 수 있으니, 적절한 균형 지점을 찾아야할 것이다.
관련한 istiod 프로세스의 환경 변수는 다음의 것들이 있다.[2]
- PILOT_DEBOUNCE_AFTER(기본 100ms)
- 이벤트를 큐에 넣기 전 디바운스할 시간을 지정
- sliding window 간격을 정한다고 보면 된다.
- PILOT_DEBOUNCE_MAX(기본 10초)
- 디바운스 허용할 최대 시간
- 이 시간이 지나면 현재 병합된 이벤트가 푸시 대기열에 추가된다.
- PILOT_ENABLE_EDS_DEBOUNCE(기본 true)
- 엔드포인트 업데이트가 디바운스 규칙을 준수할지, 큐에 즉시 배치할지 지정
- PILOT_PUSH_THROTTLE(기본 100개 동시 푸시)
- 동시에 처리하는 푸시 요청 개수 지정
해당 설정이 제대로 적용되는지 확인만 하기 위해 디바운스로 활용할 시간을 엄청 넓게 줘보자.
values:
pilot:
env:
ENABLE_NATIVE_SIDECARS: true
PILOT_DEBOUNCE_AFTER: "2500ms"
이번에도 이스티오 오퍼레이터 양식 파일에서 설정하면 된다.(기본값은 100ms == 0.1초)
istiod 양식 환경변수에 해당 값이 들어가면 성공
./performance-test.sh --reps 15 --delay 0.5
푸시횟수가 말도 안 되게 줄어들었다 ㅋㅋ
분명 푸시 횟수가 줄어들어서 그런지, 컴퓨팅 자원 사용량아 어마무시하게 낮아진 것을 확인할 수 있다.
(설정이 다시 되다보니 istiod가 재가동되면서 다른 파드로 찍힌다.)
메모리 할당량이 어마무시하게 줄어든 게 조금 놀랍다.
고루틴은 아예 새로 파드가 띄워지면서 변동이 크게 일어났으므로 신뢰하기 힘든 지표라고 생각한다.
어쩌면 istiod가 오래 기동되면서 적절히 작업을 마치지 못한 고루틴의 수가 늘어나고 있던 게 아닐까 싶긴 하다.
그러나 결과적으로는 설정이 디바운스되도록 기다리게 되는 양이 늘어났을 것을 감안해야 한다.
이 값은 흔히 보게 되는 convergence_time 메트릭에는 드러나지 않지만, 궁극적으로 설정에 딜레이를 부여한다는 점은 두말할 여지가 없다.
디바운스가 업데이트 전파에 끼친 영향에 대해 언급한 다른 글도 있다.[3]
그렇다면 설정을 어떻게 하는 게 좋을까?
워크로드 스케일링 등의 이슈로 발생할 수 있는 팬텀 워크로드 현상은 엔드포인트 설정이 즉각 반영되지 않기 때문에 나타나는 문제이다.
그러므로 PILOT_ENABLE_EDS_DEBOUNCE
를 false로 둬 엔드포인트는 즉각적인 업데이트가 되도록 보장해주는 편이 좋다.
리스너, 라우터 등의 설정은 대체로 사람이 설정한 리소스가 반영될 때 수정된다.
이런 것들은 정해진 배포 시간이나, 최소한 사람이 인지하고 있는 상태에서 변경이 일어나기 때문에 상대적으로 느리더라도 상관 없는 경우가 많다.
그러나 클러스터 환경을 반영하는 업데이트는 늦춰지면 곧 서비스 장애로 직결되기에 이런 부분들은 주의할 필요가 있다.
리소스 추가할당
위의 방법들을 전부 시도하고도 성능을 더 향상시켜야 한다면, 남은 방법은 아예 컨트롤 플레인에 컴퓨팅 자원을 더 할당해주는 것.
책에서는 병목 지점이 어디냐에 따라 스케일링 전략을 다르게 가져가야 한다고 말한다.
- 송신 트래픽은 스케일 아웃 - 각 istiod가 관리하는 워크로드 수를 줄여야 하기 때문.
- 수신 트래픽은 스케일 업 - 이스티오 리소스 설정을 많이 처리해야 하기 때문.
istioctl install --set profile=demo \
--set values.pilot.resources.requests.cpu=1000m \
--set values.pilot.resources.requests.memory=1Gi \
--set values.pilot.replicaCount=2 -y
오토스케일링은 좋은 전략이지만, 여기에 유념할 것이 있다.
istiod가 확장되더라도 기존에 커넥션을 유지하는 데이터플레인은 그대로 커넥션을 계속 유지한다는 것이다.
부트스트랩되어 설정된 ADS api 통로는 커넥션이 연결된 30분 간은 기본으로 연결되도록 되어 있다.
이를 수정하려면 MaxServerConnectionAge를 만져야 한다.
아무튼 이것 때문에 기존 istiod 파드에 부하가 걸려 스케일링이 알아서 되더라도 막상 새 파드로는 트래픽이 연결되지 않을 수 있다.
그럼 새 파드에는 부하가 발생하지 않고, 이로 인해 의도되지 않게 메트릭이 수집되지 않아 결국 다시 다운스케일이 돼버리는, 플래핑(flapping) 현상이 발생할 수 있다.
그래서 오토스케일링을 할 때 이 점을 유념할 필요가 있다.
대체로 컨트롤 플레인의 오토스케일링은 순간적인 부하를 대응하는 것보다는 전반적인 부하량을 바탕으로 설정하는 것이 기본이다.
그런데 이럴 거라면 사실 오토스케일링을 한다는 메리트가 그다지 있진 않은 것 같다.
결론 - 가이드라인
컨트롤 플레인 성능을 개선하기 위해 시도할 수 있는 방법 순서는 이 정도로 보면 좋다.
- 사이드카 설정 - 이것만으로도 대부분 이득 본다.
- 컨트롤 플레인이 포화 상태인데 이미 리소스를 많이 할당한 경우에는 이벤트 배치 수정
- 병목이 송신 트래픽일 때 istiod 스케일 아웃
- 병목이 수신 트래픽일 때 istiod 스케일 업
다음으로 성능을 최적화하는데 있어서 참고하면 좋을 지침을 보자면,
- 성능 문제인지 확인
- 데이터 플레인에서 컨트롤 플레인으로 연결이 제대로 이뤄지고 있는가?
- 플랫폼 문제인가? 이를테면 쿠버네티스에서 API 서버가 정상인가?
- 변경 범위를 지정하도록 Sidecar 리소스를 정의했는가?
- 성능 병목 지점 파악
- 황금 신호 기반 파악
- 컨트롤 플레인이 포화 상태도 아닌데 지연 시간이 증가하면 리소스가 최적으로 활용되지 않고 있다는 것
- 더 많은 푸시가 동시에 처리되도록 동시 푸시 임계값을 늘릴 수 있다.
- 사용률은 낮지만 부하가 걸렸을 때 빠르게 포화 상태가 되면 변경 사항이 매우 폭발적임
- 즉, 변경 사항이 없는 기간이 길다가 짧은 시간에 이벤트가 급증하는 것이다.
- 이스티오 파일럿의 복제본 수를 늘리거나, 업데이트를 미룰 여지가 있는 경우 배치 속성을 조정한다.
- 점진적 변경
- 성능 최적화에는 트레이드오프가 있는 경우가 많다.
- 그러므로 점진적으로 변화되는 지표를 확인해가면 변경을 하는 것이 좋다.
- 안전성
- istiod의 에러는 메시 장애로 이어진다.
- 리소스는 되도록 관대하게, 고가용성 구성을 해두자.
- 버스트 가능한 자원 고려
- istiod는 순간적인 cpu 리소스가 필요하기에 항상 고성능이기보다는 버스트가 가능한 자원을 사용하는 것이 비용효율
성능 문제인지 먼저 확인하라는 건 이스티오가 기본적으로 리소스를 적게 활용하면서 높은 부하를 견딜 수 있기 때문이다.
생각 이상으로 정말 잘 견디는 듯
이스티오는 새 버전이 나올 때 항상 성능 테스트를 진행하고 결과를 공개하고 있다.[4]
- 엔보이 설정을 부풀리는 쿠버네티스 서비스 1,000개
- 동기화해야 하는 워크로드 2,000개
- 서비스 메시 전체에서 초당 요청 70,000개
istiod는 이 정도의 부하를 견디는데 겨우 vcpu 하나에 메모리 1.5기가면 족하다!
그러니 성능이 저하된다면 일단 istiod를 뜯어고치는 것보다는 다름 부분에서 최적활할 부분이 있는지 찾아보는 것이 도움이 된다.
여담으로 1kb짜리 1000개의 http 요청을 보낼 때 이스티오의 프록시들이 요구하는 자원에 대한 내용도 있는데,
- 2개의 워커 쓰레드를 가진 사이드카 - 0.20 vCPU, 60 MB 메모리
- 2개의 워커 쓰레드를 가진 웨이포인트 - 0.25 vCPU, 60 MB 메모리
- ztunnel - 0.06 vCPU, 12 MB 메모리
ztunnel이 가장 성능은 좋긴 한데, 기본 사이드카 역시 굉장히 작은 자원을 사용하는 것을 볼 수 있다.
관련 문서
지식 문서, EXPLAIN
이름41 | is-folder | 생성 일자 |
---|---|---|
E-이스티오 컨트롤 플레인 메트릭 | false | 2025-05-18 15:45 |
E-이스티오 설정 트러블슈팅하기 | false | 2025-05-18 01:31 |
E-이스티오 가상머신 통합 | false | 2025-06-01 13:32 |
E-이스티오 DNS 프록시 동작 | false | 2025-06-01 12:33 |
E-앰비언트 모드에서 메시 기능 활용 | false | 2025-06-07 20:56 |
E-앰비언트 모드 헬름 세팅 | false | 2025-06-03 19:27 |
E-앰비언트 ztunnel 트래픽 경로 분석 | false | 2025-06-07 20:36 |
E-deb 파일 뜯어보기 | false | 2025-06-01 12:27 |
E-이스티오에서 엔보이 기능 확장하기 | false | 2025-06-01 14:06 |
E-이스티오 메시 스케일링 | false | 2025-06-08 23:41 |
E-istio-csr 사용 실습 | false | 2025-06-09 00:30 |
아르고 롤아웃과 이스티오 연계 | false | 2025-04-22 13:48 |
Istio VirtualService | false | 2025-04-21 10:49 |
Istio Traffic Management | true | 2025-04-21 12:01 |
Istio Sidecar | false | 2025-05-13 22:27 |
Istio ServiceEntry | false | 2025-04-17 14:12 |
Istio ProxyConfig | false | 2025-05-17 19:32 |
Istio Gateway | false | 2025-04-16 21:50 |
Istio DestinationRule | false | 2025-04-21 10:50 |
Istio Security | true | 2025-05-04 19:58 |
Istio RequestAuthentication | false | 2025-05-04 20:16 |
Istio PeerAuthentication | false | 2025-05-04 20:00 |
Istio AuthorizationPolicy | false | 2025-05-04 20:19 |
사이드카 모드 | false | 2025-05-18 03:27 |
pilot-agent | false | 2025-04-28 23:26 |
istiod | false | 2025-05-18 03:16 |
istioctl | false | 2025-05-12 08:38 |
Istio | true | 2025-04-07 14:26 |
Istio Operator | false | 2025-05-09 20:44 |
Kiali | false | 2025-04-28 23:41 |
Istio Telemetry | false | 2025-04-08 15:18 |
Istio Observability | true | 2025-04-28 00:17 |
메시 배포 모델 | false | 2025-05-21 13:36 |
Istio WorkloadGroup | false | 2025-05-26 09:27 |
Istio WorkloadEntry | false | 2025-05-26 09:32 |
Istio WasmPlugin | false | 2025-04-21 20:41 |
Istio Extenisibility | true | 2025-05-26 09:26 |
Istio EnvoyFilter | false | 2025-04-21 20:36 |
E-이스티오의 데이터 플레인 트래픽 세팅 원리 | false | 2025-05-27 21:55 |
앰비언트 모드 | false | 2025-06-02 14:51 |
Envoy | false | 2025-04-07 14:50 |
기타 문서
Z0-연관 knowledge, Z1-트러블슈팅 Z2-디자인,설계, Z3-임시, Z5-프로젝트,아카이브, Z8,9-미분류,미완이름45 | 코드 | 타입 | 생성 일자 |
---|---|---|---|
I-ztunnel이 다른 네임스페이스에서 요청 보내는 코드 분석 | Z1 | topic/idea | 2025-06-07 20:44 |
I-다른 네임스페이스 같은 포트 리스닝 서버 구현 | Z1 | topic/idea | 2025-06-07 19:39 |
T-엔보이 실습 with solo.io | Z3 | topic/temp | 2025-04-14 23:15 |
7주차 - 스케일링, 멀티 클러스터 | Z5 | project | 2025-05-18 20:04 |
25.05 테크니컬 라이팅 | Z5 | area | 2025-05-07 13:07 |
1주차 - istio 소개, 첫걸음 | Z5 | project | 2025-04-06 19:57 |
3주차 - 네트워크 복원력 | Z5 | project | 2025-04-23 21:38 |
4주차 - 이스티오 관측가능성 | Z5 | project | 2025-04-27 19:52 |
5주차 - 통신 보안 | Z5 | project | 2025-05-04 19:54 |
6주차 - 디버깅 | Z5 | project | 2025-05-11 19:50 |
P-Istio Hands-on 스터디 1기 | Z5 | project | 2025-04-03 17:52 |
스터디 내용 사전 정리 | Z5 | project | 2025-04-03 18:00 |
책 내용 정리 | Z5 | project | 2025-04-03 17:59 |
2주차 - 엔보이, 게이트웨이 | Z5 | project | 2025-04-13 20:10 |
3주차 - 트래픽 관리 | Z5 | project | 2025-04-19 15:11 |
8W - 엔보이와 iptables 뜯어먹기 | Z8 | published | 2025-06-01 12:14 |
9W - 앰비언트 모드 구조, 원리 | Z8 | published | 2025-06-07 19:17 |
1W - 서비스 메시와 이스티오 | Z8 | published | 2025-04-10 20:04 |
이스티오 스케일링 | Z8 | topic | 2025-05-18 20:01 |
엔보이에 와즘 플러그인 적용해보기 | Z8 | topic | 2025-06-09 02:29 |
1W - Gateway API를 활용한 설정 | Z8 | published | 2025-04-10 20:08 |
1W - 간단한 장애 상황 구현 후 대응 실습 | Z8 | published | 2025-04-10 20:06 |
1W - 네이티브 사이드카 컨테이너 이용 | Z8 | published | 2025-04-10 20:32 |
2W - 엔보이 | Z8 | published | 2025-04-17 22:06 |
2W - 인그레스 게이트웨이 실습 | Z8 | published | 2025-04-17 22:06 |
3W - 데스티네이션 룰을 활용한 네트워크 복원력 | Z8 | published | 2025-04-26 00:35 |
3W - 타임아웃, 재시도를 활용한 네트워크 복원력 | Z8 | published | 2025-04-26 00:41 |
3W - 버츄얼 서비스를 활용한 기본 트래픽 관리 | Z8 | published | 2025-04-22 21:56 |
3W - 서비스 엔트리와 이그레스 게이트웨이 | Z8 | published | 2025-04-22 22:01 |
3W - 트래픽 가중치 - flagger와 argo rollout을 이용한 점진적 배포 | Z8 | published | 2025-04-22 21:59 |
3W - 트래픽 미러링 패킷 캡쳐 | Z8 | published | 2025-04-22 22:00 |
4W - 이스티오 메트릭 확인 | Z8 | published | 2025-05-03 22:15 |
4W - 이스티오 메트릭 커스텀, 프로메테우스와 그라파나 | Z8 | published | 2025-05-03 22:16 |
5W - 이스티오 JWT 인증 | Z8 | published | 2025-05-11 00:03 |
5W - 이스티오 mTLS와 SPIFFE | Z8 | published | 2025-05-11 00:01 |
6W - 이스티오 설정 트러블슈팅 | Z8 | published | 2025-05-18 01:31 |
6W - 이스티오 컨트롤 플레인 성능 최적화 | Z8 | published | 2025-05-18 02:29 |
4W - 번외 - 트레이싱용 심플 메시 서버 개발 | Z8 | published | 2025-05-03 22:48 |
4W - 오픈텔레메트리 기반 트레이싱 예거 시각화, 키알리 시각화 | Z8 | published | 2025-05-03 22:49 |
5W - 이스티오 인가 정책 설정 | Z8 | published | 2025-05-11 00:04 |
7W - 이스티오 메시 스케일링 | Z8 | published | 2025-06-09 02:04 |
7W - 엔보이 필터를 통한 기능 확장 | Z8 | published | 2025-06-09 02:30 |
8W - 가상머신 통합하기 | Z8 | published | 2025-06-01 12:11 |
9W - 앰비언트 헬름 설치, 각종 리소스 실습 | Z8 | published | 2025-06-07 19:27 |
Istio 1기 - Istio Hands-on | Z8 | published | 2025-04-03 17:55 |
참고
https://istio.io/latest/blog/2019/performance-best-practices/ ↩︎
https://istio.io/latest/docs/reference/commands/pilot-discovery/#envvars ↩︎
https://medium.com/airbnb-engineering/improving-istio-propagation-delay-d4da9b5b9f90 ↩︎
https://istio.io/latest/docs/ops/deployment/performance-and-scalability/ ↩︎