일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- APM
- 티스토리챌린지
- AI
- Pinpoint
- aws
- kotlin
- 기록으로 실력을 쌓자
- kotlin querydsl
- CKA
- mysql 튜닝
- CloudWatch
- PETERICA
- Elasticsearch
- Linux
- 정보처리기사 실기
- 오블완
- Java
- AWS EKS
- kotlin coroutine
- MySQL
- 정보처리기사 실기 기출문제
- CKA 기출문제
- IntelliJ
- 코틀린 코루틴의 정석
- kotlin spring
- 공부
- 정보처리기사실기 기출문제
- Kubernetes
- Spring
- minikube
- Today
- Total
피터의 개발이야기
[EKS] EKS v1.22 업그레이드 중 Spring boot DNS Cache 트러블슈팅 본문
ㅁ 개요
현재 [EKS] Amazon EKS 클러스터(v1.20)에서 Kubernetes v1.22로 업그레이드 진행 중이다. (관련 글은 여기) 세부적으로 사용 중인 Ingress 객체를 업그레이드 하면서 ingress controller 무중단 업데이트를 테스트 중이다. 그 과정에서 운영 적용 시 최적화를 위해 시뮬레이터 테스트 환경을 구축하여 무중단 업그레이드 테스트를 진행 중 Spring boot DNS Cache 이슈를 겪게 되어 그 과정을 정리하였다.
ㅁ NLB + ingress controller(ALB) 이중화를 이용한 업데이트 시나리오
우선 ingress controller 업그레이가 필요한데, 이 부분은 여기를 참조하여 이해가 필요하다.
외부에서 들어오는 트래픽이 ingress controller를 통해서 들어올 것이기 때문에 ingress의 버전 업그레이드 시 작은 실수는 실행 중인 모든 서비스에 대한 장애로 이어질 수 있다. 실제로도 예전에 검수기에서 경험하였고, 그 경험을 [kubernetes] Ingress 수정 후 검수기 전용회선 네트워크 오류 트라블 슈팅 정리 글로 남겼었다. EKS 업그레이드를 위해 이 경험을 역이용하여 람다를 끄고 신EKS + 신ALB와 구EKS + 구ALB로 이중화하여 ALB 스위칭 전략을 수립하였다. 운영과정의 안정성을 확보하기 위해 시뮬레이터를 구현하였으며, 시뮬레이터 테스트 환경에서 무중단 업그레이드 작업 테스트를 진행하였지만, 뜻밖의 상황이 발생하였다.
ㅁ 1차 트러블슈팅, 라운드로빈
ㅇ 해당 NBL의 target그룹에서 신규로 구축된 EKS + Ingress + WorkNode의 Pod 아이피를 교체를 하였다. 예상 시나리오는 신구 ALB에 트래픽이 분산하는 것이었다.
ㅇ 하지만 트래픽을 구ALB에 직중되었고, 나중에 ALB 옵션에서 Round robin이 체크되지 않았던 부분을 발견하고 다시 테스트를 진행하였다. 2차 테스트 시에 Round robin정책이 적용되어 트래픽이 분산될 것으로 예상하였지만, 이번에도 트레픽 분산은 실패하였다. 추측컨데, 세션처럼 한번 연결되어 있던 건은 캐싱되어 지속적으로 같은 곳에 트래픽이 전달된다는 판단을 하게 되었다. 하지만 아직 네트워크에 의한 DNS cache인지 Application의 문제인지 명확하지는 않아, 이를 증명하기 위해 발송그룹을 분리하여 테스트를 진행하였다.
ㅁ 캐싱의 주체를 찾기 위한 발송그룹 분리
스프링으로 구축된 시뮬레이터 1그룹이 지속적으로 트래픽을 발생하는 상황에서 신ALB로 스위칭하였다. 예상한데로, 트래픽은 구ALB로 집중되었고, 이후 2발송그룹을 발송을 시작하였다. 결과는 신규 발송그룹이 발송을 시작하자 발송 트래픽은 동등하게 분배가 되었던 것이다. 알 수 없었던 부분이 명확히 Application 문제임을 알게 되었다. 구체적으로 원인을 파악하는 과정에서 DNS TTL이란 것을 알게 되었다.
ㅁ DNS TTL 이란
AWS와 같은 클라우드 환경 이전인 온프레미스 환경에서는 서버의 IP주소는 쉽게 변하지 않았다. 하지만 클라우드 환경에서 Load Balancer를 사용할 때에는 IP가 자주 변경이 될 수 있다. 이 때 DNS 캐시가 되어 기존 주소로 트레픽이 전달되면 503에러 발생으로 장애가 발생하게 된다. 이를 방지 하기 위해 DNS 캐시 TTL(Time To Live) 설정이 필요하다.
ㅁ Java VM 의 DNS caching TTL
Java VM 은 DNS 조회 시 TTL(time-to-live) 전략을 쓰지 않고 한 번 lookup한 도메인은 계속 캐싱을 하고 있다. 이를 갱신하기 위해서는 재기동해야한다. 이는 DNS Spoofing 공격을 막기 위한 설정이다.
ㅁ AWS에서 DNS TTL권고
AWS 리소스는 간헐적으로 변경되는 DNS 이름 항목을 사용하므로 TTL 값을 60초 이하로 하여 JVM을 구성할 것을 권고하고 있다. 이렇게 하야 JVM이 DNS를 다시 조회하여 변경된 리소스의 IP 주소로 애플리케이션이 접속할 수 있다. Java 구성에서는 JVM이 다시 시작될 때까지 DNS 항목을 새로 고치지 않도록 JVM 기본 TTL이 설정되기 때문에 IP 주소가 AWS애플리케이션이 실행 중인 동안 리소스는 변경되며, 사용자가 해당 리소스를 사용할 수 없게 된다. 수동으로 다시 시작JVM 및 캐시된 IP 정보가 새로 고쳐집니다. 이 경우 캐시된 IP 정보를 정기적으로 새로 고치도록 JVM의 TTL을 설정해야 합니다.
ㅁ JVM TTL을 설정하는 방법
값 | 정책 | 설명 |
-1 | cache forever | default |
0 | cache 하지 않음 | 매번 DNS Server 에서 lookup |
0 보다 큰 정수 | TTL 시간 | 60으로 설정시 60초가 지났을 경우 다시 DNS Server를 통해 lookup |
ㅇ 자바홈에서 변경:
JVM을 사용하는 모든 애플리케이션에 대해 한꺼번에 적용할 수 있는 방법이다.
$JAVA_HOME/jre/lib/security/java.security에 networkaddress.cache.ttl
ㅇ 애플리케이션 메인 설정
특정 애플리케이션에만 적용하려는 경우, 해당 애플리케이션의 초기화 코드에서 networkaddress.cache.ttl을 설정합니다.
java.security.Security.setProperty("networkaddress.cache.ttl" , "60");
ㅇ 도커파일 수정
RUN echo "networkaddress.cache.ttl=5" >> /opt/jdk/jre/lib/security/java.security
ㅁ 함께 보면 좋은 사이트
ㅇ ingress controller 무중단 업데이트 방법
ㅇ ingress controller 참조 페이지
ㅇ DNS TTL 적용 방법
ㅇ JAVA Networking Properties > networkaddress.cache 에 대한 설명
'AWS > EKS' 카테고리의 다른 글
[EKS] EKS Bastion 구성을 위한 kubectl, helm, eksctl, jq 설치 (0) | 2022.10.18 |
---|---|
[EKS] AWS EKS에 EFS 연동하기 (0) | 2022.10.18 |
[EKS] 쿠버네티스 etcd 클러스터 백업, #3 Velero를 이용한 AWS EKS 백업 복구 방법 (0) | 2022.10.08 |
[EKS] 쿠버네티스 etcd 클러스터 백업, #2 etcd 내장 스냅샷 (0) | 2022.10.04 |
[EKS] 쿠버네티스 etcd 클러스터 백업, #1 ETCD란, 백업과 복원을 위한 2가지 방법 (0) | 2022.10.04 |