일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- application properties
- Kubernetes
- 티스토리챌린지
- spring boot
- OOM
- JVM
- readiness probe
- configmap
- startup probe
- 오블완
- xms
- liveness probe
- property
- Heap
- Xmx
- properties
- k8s
- Java Virtual Machine
- java
- Probe
- Today
- Total
여우발개발
Spring이 application property를 인식하는 방식 본문
아니 진짜 내꺼에선 잘 되는데
그날은 거진 한 달이 미뤄진 준비의 최종준비의 진짜최종준비를 했던 배포날이었다. 오래 미뤄져 나름대로 준비가 된 상태라고 생각했고, 걱정 없이 argoCD에서 sync를 눌렀는데, 이게 웬걸 pod가 뜨질 않는다. 자꾸 readness check에 실패했다고 뜨질 않는가.
google pub/sub쪽 에러가 뭔가 와장창 뜬다. 방화벽 문제인가? 분명 오픈요청도 다 했고 잘 열어주셨다. 보안팀을 붙잡고 같이 원인파악을 해보지만 특별한 이상은 없다. 이쯤 되면 뭐라도 이상이 나와줬으면 하지만 이상이 없다는 단호한 보안팀의 답변에 일단 다른 이상한 점을 찾아보기로 한다.
test 환경에 다시 빌드를 해서 띄워본다. 어라 뜨지 않는다. 근데 이전 버전의 pod는 너무나 잘 떠있다. node 1개만 방화벽이 오픈되어 있나? 확인해 보니 같은 node인데도 뜨고 안 뜨고 가 나뉜다. 방화벽 문제는 아니고, 문제없겠지 하며 추가했던 commit이 문제임이 확실해져 버렸다.
추가된 커밋에서 달라진 점이라고는 cicd repo를 submodule로 추가한 것과 local에서 사용하기 위해서(zone 별 application properties는 configmap으로 관리한다) resource 하위에 둔 application.yaml에서 설정들의 위치 변경 조금, 그리고 server.port를 테스트 때문에 8081로 지정한 것이었다.
잠깐, port? pod의 readness probe는 8080 port로 확인하게 되어있다. 그래 이게 뭔가 수상쩍다. 바로 8080으로 변경하고 다시 띄워본다. 된다. 이게 문제구나!
그렇다. 여러 서버를 관리하고 있다 보니 어떤 서버는 resource 하위의 application을 제외하고 빌드하고, 어떤 서버는 제외하지 않고 빌드를 하고 있었다. 문제가 될 거라고 생각을 못하고 있었다.
이렇게 된 거 spring이 어떻게 property를 읽는지 조금 더 확인해 보자.
Read Properties
우리 프로젝트 소스 코드에는 기본적으로 resources/application.yaml이 있다. 그리고 zone 별 resource 파일들은 k8s configmap으로 /config 경로에 mount 하게 되어있다.
다른 프로젝트에서는 CI/CD pipeline.properties 에 build.exclude.files=src/main/resources/application.yaml 속성이 있어서 zone 별 서버에서는 /config 하위의 설정파일만 보기를 기대하고 세팅이 되어있다.
하지만 이 프로젝트에서는 jar 파일 내에 resources/application.yaml 이 같이 빌드되어 클래스패스에 포함되었고, 추가적으로 configmap으로 /config/application.yaml 파일도 mount 되었던 것이다.
이때 spring-boot는 설정값을 어떻게 인식하고 사용하게 될까?
(우리 서버 기준 스프링부트 2.4.13 버전)
여기에 spring boot에서 application properties를 인식하는 순서가 나와있다.
2.3. External Application Properties Spring Boot will automatically find and load application.properties and application.yaml files from the following locations when your application starts:
- From the classpath
- The classpath root
- The classpath /config package
- From the current directory
- The current directory
- The /config subdirectory in the current directory
- Immediate child directories of the /config subdirectory The list is ordered by precedence (with values from lower items overriding earlier ones). Documents from the loaded files are added as PropertySources to the Spring Environment.
공식 문서에 따르면, 아래로 갈수록 위의 항목을 overriding 하기 때문에, 우리가 겪었던 현상처럼 1.a 항목인 classpath root의 application.yaml 이 먼저 load 되고 그 이후에 1.b 항목인 /config/application.yaml 가 기존 값들을 overriding 하게 되는 것이다. 오버라이딩 되지 않은 값들은 그대로 남아있게 되고 말이다.
그랬으면 좋았겠다
여러 서버를 관리해야하는 입장에서 설정이 다 다르다는 것은 그만큼 머릿속에 숙지해둬야 하는 항목들이 많다는 것을 뜻한다. 일괄적으로 같은 설정이 적용되었다면 삽질하지 않았을 텐데…
유지보수는 늘 어렵다! 편하게 유지보수할 수 있는 방식을 늘 고민해야겠다.