3.2. 오토스케일링 (APM HPA)
개요
APM 의 애플리케이션 지표(TPS)를 기준으로 파드를 자동 확장·축소합니다. CPU/메모리만으로는 잡기 어려운 실제 트래픽에 맞춰 스케일할 수 있습니다.
1. 동작 방식
APM HPA 는 Kubernetes 의 External Metrics API(external.metrics.k8s.io/v1beta1)를 구현합니다. HPA 가 외부 지표를 요청하면, APM HPA 가 OPENMARU APM 서버에 해당 그룹의 지표를 질의해 값을 돌려줍니다.
groupName: OPENMARU APM 의 애플리케이션 그룹 이름.apmAlias: 어느 APM 서버에 물어볼지 고르 는 별칭(설치 시envHpa에 등록한name). 등록되지 않은 이름을 적으면 오류로 거부합니다. 다른 서버로 조용히 질의하지 않습니다.
쓸 수 있는 지표
| 지표 | 무엇 | 범위 | target.type |
|---|---|---|---|
tps | 초당 처리 건수 | — | AverageValue |
activeUser | 접속 사용자 수 | — | AverageValue |
loginUser | 로그인 사용자 수 | — | AverageValue |
avgRT | 평균 응답시간 (밀리초) | — | Value |
errorRate | 오류율 | 0~100 | Value |
apdexDeficit | 100 - apdex. 클수록 응답이 나쁩니다 | 0~100 | Value |
🔴 target.type 을 표대로 쓰십시오. AverageValue 는 받은 값을 파드 수로 나눕니다.
tps 처럼 파드마다 쌓이는 값에는 맞지만, 이미 평균이나 비율인 avgRT·errorRate·
apdexDeficit 을 나누면 뜻이 달라집니다 — 응답시간 200 밀리초가 파드 4 개에서 50 밀리초로
읽힙니다.
apdex는 오토스케일링에 쓸 수 없습니다. 값이 클수록 좋은데 HorizontalPodAutoscaler 는 "목표를 넘으면 늘린다" 만 표현할 수 있어, 그대로 걸면 응답이 좋을 때 파드가 늘고 나빠질 때 줄어듭니다. 응답 품질로 조절하려면apdexDeficit을 쓰십시오.apdex자체는 조회만 됩니다.
소수는 밀리 단위로 실려 옵니다 — tps 가 27.667 이면 27667m 으로 나옵니다.
2. 사용법 — HPA 만들기
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: tomcat-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: tomcat
minReplicas: 1
maxReplicas: 3
metrics:
- type: External
external:
metric:
name: tps # 위 표의 지표 이름
selector:
matchLabels:
apmAlias: APM-SERVER # 어느 APM 서버 (envHpa 의 name 과 일치)
groupName: TOMCAT # APM 애플리케이션 그룹 이름
target:
type: AverageValue
value: 50 # 파드당 평균 TPS 50 을 목표로 스케일
적용은 다음과 같습니다.
kubectl apply -f tomcat-hpa.yaml
kubectl get hpa tomcat-hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
tomcat-hpa Deployment/tomcat 0/50 1 3 1 8s
TARGETS의 왼쪽 값(현재 TPS)이 정상적으로 표시되면 연동 성공입니다.
3. 동작 확인 (부하 테스트)
# 부하 생성
ab -n 18000 -c 10 http://tomcat-openmaru-test1.apps.example.local/
# TPS 가 목표를 넘으면 파드가 늘어남
kubectl get hpa tomcat-hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
tomcat-hpa Deployment/tomcat 506/50 1 3 3 24m
직접 외부 지표 API 를 확인할 수도 있습니다.
kubectl get --raw "/apis/external.metrics.k8s.io/v1beta1/namespaces/<namespace>/tps?labelSelector=groupName%3D<그룹이름>%2CapmAlias%3D<별칭>" | jq .
값을 못 가져오면 오류 메시지가 그대로 나옵니다. 무엇이 잘못됐는지 여기에 적혀 있습니다.
Error from server: 메트릭 "tps" 를 가져오지 못했다 (그룹 "wrong-name"): ...
Error from server: labelSelector 에 groupName 이 필요하다 (받은 것: "")
Error from server: apmAlias "APM-TYPO" 에 해당하는 환경변수가 없다
3.1 🔴 애플리케이션 그룹 이름이 재배포 때마다 바뀝니다
groupName 은 APM 이 인식한 애플리케이션 그룹 이름이고, 그 값은 계측 대상 파드의
OMAPM_APPLICATION_NAME 환경변수에서 정해집니다. 자동 계측이 넣는 기본값에는 ReplicaSet
해시가 들어갑니다.
파드 이름 helloworld-55cb78b54c-7276g
그룹 이름 helloworld-55cb78b54c ← ReplicaSet 해시가 들어 있다
확장·축소는 같은 ReplicaSet 안에서 일어나므로 문제가 없습니다. 그러나 Deployment 를 다시
배포하면 해시가 바뀌어 그룹 이름도 바뀌고, HPA 의 groupName 이 맞지 않게 됩니다.
이때 HPA 는 지표를 못 가져오는데 파드 수를 줄이지 않고 그대로 둡니다. 오류가 겉으로 드러나지 않으므로 한참 뒤에야 알아채게 됩니다.
고정하려면 파드 템플릿에 OMAPM_APPLICATION_NAME 을 직접 지정하십시오. 지정한 값이
있으면 자동 계측이 덮어쓰지 않습니다.
spec:
template:
metadata:
labels:
openmaru.io/was-agent: 'true'
spec:
containers:
- name: tomcat
env:
- name: OMAPM_APPLICATION_NAME
value: "tomcat-prod" # 재배포해도 바뀌지 않는다
그리고 HPA 에서 같은 이름을 씁니다.
matchLabels:
groupName: tomcat-prod
지금 쓰는 그룹 이름을 확인하려면 계측된 파드의 환경변수를 보거나 위 kubectl get --raw
명령으로 값이 나오는지 시험합니다.
kubectl get pod <파드> -o jsonpath='{.spec.containers[0].env[?(@.name=="OMAPM_APPLICATION_NAME")].value}'
4. 여러 APM 서버 사용
APM 서버가 여러 대면, 설치 시 envHpa 에 서로 다른 name(=apmAlias)으로 등록합니다.
envHpa:
- name: APM-INTERNAL
value: "http://openmaru-apm-server.openmaru-apm.svc.cluster.local:8080"
- name: APM-SERVER
value: "http://192.168.80.190"
- name: APM-INTERNAL_ACCESS_KEY # 별칭마다 액세스 키를 짝지어 둡니다
value: "<APM API access key>"
- name: APM-SERVER_ACCESS_KEY # 해당 APM 서버 API 액세스 키 (<apmAlias>_ACCESS_KEY)
value: "<APM API access key>"
🔴 별칭마다 <apmAlias>_ACCESS_KEY 를 반드시 짝지어 두십시오. 키가 없으면 APM 서버가
HTTP 403 을 돌려주고 지표를 가져오지 못합니다.
그리고 HPA 의 matchLabels.apmAlias 로 골라 씁니다.
matchLabels:
apmAlias: APM-INTERNAL # 내부 APM 서버로 질의
groupName: TOMCAT
apmAlias가envHpa의 어떤name과도 맞지 않으면 오류로 거부합니다 (apmAlias "..." 에 해당하는 환경변수가 없다). 다른 서버로 조용히 질의하지 않으므로, 이름을 잘못 적으면 곧바로 드러납니다.
5. 핵심 설정 요약
| HPA 필드 | 값 | 의미 |
|---|---|---|
metrics[].type | External | 외부 지표 기반 스케일 |
metric.name | tps | 사용할 지표. 쓸 수 있는 것은 1절의 표 참고 |
selector.matchLabels.apmAlias | 예: APM-SERVER | 질의할 APM 서버 별칭(envHpa name) |
selector.matchLabels.groupName | 예: TOMCAT | APM 애플리케이션 그룹 |
target.type / target.value | AverageValue / 50 | 파드당 목표 TPS |
6. 잘 안 될 때
| 증상 | 점검 |
|---|---|
TARGETS 가 <unknown> | kubectl describe hpa <이름> 의 Events 를 보십시오. 왜 못 가져왔는지 메시지로 나옵니다 |
| 재배포 뒤로 스케일이 멈춤 | 🔴 그룹 이름이 바뀌었을 가능성이 큽니다. 3.1 참고 |
HTTP 403 | 별칭에 <apmAlias>_ACCESS_KEY 가 짝지어져 있는지 확인하십시오 |
apmAlias ... 에 해당하는 환경변수가 없다 | apmAlias 가 envHpa 의 name 과 정확히 일치하는지(대소문자 포함) |
labelSelector 에 groupName 이 필요하다 | selector.matchLabels.groupName 이 빠졌습니다 |
| 항상 0 으로만 나옴 | 해당 그룹에 실제 트래픽이 있는지, APM 서버가 지표를 집계 중인지 |
apdex 로 걸었더니 반대로 움직임 | apdex 는 클수록 좋은 값이라 HPA 에 쓸 수 없습니다. apdexDeficit 을 쓰십시오 |
| 응답시간·오류율이 파드 수만큼 작게 나옴 | target.type 을 AverageValue 로 두었습니다. 1절 표대로 Value 를 쓰십시오 |
| 스케일이 안 일어남 | minReplicas/maxReplicas 범위, target.value 가 너무 큰지 확인 |