From 9066c1bef0a57e091e148f901a943aaceb250c53 Mon Sep 17 00:00:00 2001 From: lsj8367 Date: Wed, 22 Mar 2023 01:30:15 +0900 Subject: [PATCH] =?UTF-8?q?:memo:=2014.=ED=81=B4=EB=9D=BC=EC=9A=B0?= =?UTF-8?q?=EB=93=9C=5F=EA=B5=AC=EC=84=B1=5F=EA=B4=80=EB=A6=AC=20=EC=A0=95?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...4\354\204\261_\352\264\200\353\246\254.md" | 352 ++++++++++++++++++ 1 file changed, 352 insertions(+) create mode 100644 "4_\355\201\264\353\235\274\354\232\260\353\223\234_\353\204\244\354\235\264\355\213\260\353\270\214_\354\212\244\355\224\204\353\247\201/14_\355\201\264\353\235\274\354\232\260\353\223\234_\352\265\254\354\204\261_\352\264\200\353\246\254.md" diff --git "a/4_\355\201\264\353\235\274\354\232\260\353\223\234_\353\204\244\354\235\264\355\213\260\353\270\214_\354\212\244\355\224\204\353\247\201/14_\355\201\264\353\235\274\354\232\260\353\223\234_\352\265\254\354\204\261_\352\264\200\353\246\254.md" "b/4_\355\201\264\353\235\274\354\232\260\353\223\234_\353\204\244\354\235\264\355\213\260\353\270\214_\354\212\244\355\224\204\353\247\201/14_\355\201\264\353\235\274\354\232\260\353\223\234_\352\265\254\354\204\261_\352\264\200\353\246\254.md" new file mode 100644 index 0000000..f45c407 --- /dev/null +++ "b/4_\355\201\264\353\235\274\354\232\260\353\223\234_\353\204\244\354\235\264\355\213\260\353\270\214_\354\212\244\355\224\204\353\247\201/14_\355\201\264\353\235\274\354\232\260\353\223\234_\352\265\254\354\204\261_\352\264\200\353\246\254.md" @@ -0,0 +1,352 @@ +# 14. 클라우드 구성 관리 + +Created: 2023년 2월 15일 오후 11:02 +Status: 정리완료 +최종 편집 일시: 2023년 3월 21일 오후 10:52 + +스프링 클라우드의 Config Server를 구축하게 되면 모든 마이크로서비스들에 대해 중앙 집중식의 구성을 할 수 있다. + +구성 서버를 사용하게 되면 모든 구성을 한 곳에서 관리할 수 있게된다. + +# 14.1 구성 공유하기 + +구성 속성이 런타임 환경을 변경하거나 런타임 환경에 고유한 것이라고 한다면, + +해당 구성들은 `자바 시스템 속성` 이나 `운영체제의 환경변수` 를 구성 속성으로 사용하는 것이 좋다. + +근데 이 환경변수들로 구성 속성을 사용하게 되면 변경이 된다면 애플리케이션이 다시 시작되어야 한다. + +그리고 jar파일 내부에 구성을 포함하는 경우는 해당 속성을 변경하거나 원래 값으로 되돌릴 때 애플리케이션을 다시 빌드하여 배포해야 한다. + +애플리케이션을 이 때문에 재배포나 재시작을 하는 것은 너무 불편하다. 이 변경으로 결함이 생길수도 있기 때문이다. + +그리고 MSA구성인 경우 모든 서비스 인스턴스에 동일한 변경을 적용하는 것이 불합리적이다. + +암호같은 보안에 민감한 값들은 속성값으로 넣어줄 때 물론 암호화를 해주겠지만, 복호화에 대한 코드 자체도 `Configuration` 자바 파일에 설정해주기 마련이다. (ex - jasypt) + +그러면서 동시에 구성 속성들을 개발자 조차 접근할 수 없게 하려면 환경변수에 저장하는 방식은 **지양해야 한다.** + +> 중앙 집중식으로 구성하면? +> +- 구성이 더 이상 애플리케이션 코드에 패키징되어 배포되지 않는다. + - 애플리케이션을 다시 빌드하거나 배포하지 않고 구성을 변경하거나 값을 되돌릴 수 있다. + - 재시작 하지 않아도 실행 중 구성을 변경할 수 있다. +- 공통적인 구성을 공유하는 마이크로서비스가 자신의 속성 설정으로 유지 관리하지 않고 동일한 속성을 공유할 수 있다. + - 속성 변경은 한곳에서 하나만 변경해도 모든 서비스에 적용시킬 수 있다. +- 보안에 민감한 구성 속성은 별도로 암호화하고 유지관리 할 수 있다. + - 복호화된 속성 값을 언제든지 애플리케이션에서 사용할 수 있기에 코드로 복호화로직을 갖고있을 필요가 없다. + +# 14.2 구성 서버 실행하기 + +스프링 클라우드 구성 서버는 집중화된 구성 데이터 소스를 제공한다. + +구성 서버는 다른 서비스들이 구성 속성을 사용할 수 있도록 REST API를 제공한다. + +구성 속성값들을 Git과 같은 저장소에 저장을 하여 사용한다. + +## 14.2.1 구성 서버 활성화하기 + +spring cloud version 설정은 예전에 다른것들과 동일하게 설정해주면 된다. + +그리고 항상 구성 서버를 활성화시켜주는 annotation이 설정되어야 한다. + +`@EnableConfigServer` 를 설정해주자. + +![%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2023-03-18_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_11 21 44](https://user-images.githubusercontent.com/74235102/226675799-61677293-adbc-4758-812c-1ac130c99196.png) + +`http://localhost:8080/default/master` 로 실행해주었는데 + +tacocloud-config를 호출했을 때 결과이다. + +api를 호출하는 양식은 다음과 같다. + +- 구성 서버의 호스트 이름과 포트 + - http://localhost:8080 +- 애플리케이션 이름 + - spring.application.name 속성 +- spring profile + - default +- git 라벨/분기 (생략 가능) + ![%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2023-03-18_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_11 45 54](https://user-images.githubusercontent.com/74235102/226675814-1e038170-8728-423f-ae2f-e5187e0f7aff.png) + - 지정하지 않는다면 main (스프링부트 3.x) + +## 14.2.2 Git Repository에 구성 속성 저장하기 + +가장 기본적이고 쉬운 방법은 root 경로에 applicaiton.properties나 application.yaml 파일을 커밋하는 것 + +13장에서 유레카 서버를 등록할 때 사용했던 설정을 구성해주면 + +유레카의 클라이언트를 git에서부터 불러와 설정해줄 수 있다. + +### Git 하위 경로로 구성 속성 저장하기 + +파일 이름만으로 구분하는게 아니라 폴더끼리 완전하게 구분해주고 싶은 경우에 아래의 설정을 진행해주면 된다. + +```yaml +spring: + cloud: + config: + server: + git: + uri: http://localhost:8080/tacocloud/tacocloud-config + search-paths: config +``` + +잘보면 paths로 구성되어 있는데 `,` 로 구분하여 계속해서 디렉토리를 나열해주면 된다. + +그래서 여러개를 설정하면 해당 경로 모두에서 속성들을 가져오게 된다. + +와일드카드 `*` 도 지원하기에 더 잘 구성할 수 있다. + +### Git Repository의 분기나 라벨에 구성 속성 저장하고 제공하기 + +기본 구성은 main 브랜치에서 구성 속성을 가져온다. + +default-label 옵션을 통해 기본 브랜치를 어디로 할 것인지 설정해줄 수 있다. + +근데 그냥 지정하지않고 url에서 요청해도 무방하다. + +### Git 백엔드를 사용한 인증 + +Git Repository는 사용자 username과 password 로 인증될 수 있다. + +git.username, git.password 속성으로 설정해줄 수있다. + +# 14.3 공유되는 구성 데이터 사용하기 + +중앙 집중식 구성 서버를 제공하는 것에 추가하여 spring cloud config server는 client 라이브러리도 제공한다. + +- build.gradle + +```groovy +implementation 'org.springframework.cloud:spring-cloud-starter-config' +``` + +자동 구성으로 설정되면 localhost의 8888 포트에서 실행중인거로 default 포트가 잡혀있는데, + +`spring.cloud.config.uri` 속성을 사용하면 구성 서버의 위치를 지정해줄 수 있다. + +```groovy +spring: + cloud: + config: + uri: http://config-url:8888 +``` + +해당 속성은 구성 서버의 클라이언트가 되는 애플리케이션 자체에 설정되어야 한다. + +중앙에서 컨트롤하는 서버가 있는 경우에는 모든 구성이 이 서버에서 제공되기에 각 마이크로서비스는 자신의 구성을 가질 필요가 없다. + +그래서 구성 서버의 위치를 지정하는 `spring.cloud.config.uri` 와 `spring.application.name` 속성만 지정해주면 된다. + +### 구성 서버와 레지스트리 중 어느것을 먼저 찾아야 하는지? + +- config-server로부터 eureka 서비스 레지스트리를 알아내도록 설정 + - 이렇게 되면 각 마이크로서비스에서 서비스 레지스트리의 명세를 갖지 않게 한다. +- 구성 서버를 유레카에 등록한 후 각 마이크로서비스가 구성 서버를 찾게 할 수 있다. + - config-server를 클라이언트로 구성한 후 `spring.cloud.config.discovery.enabled=true` 속성을 구성해주어야 한다. + - 단점 - 마이크로 서비스가 시작될 때 2번 호출을 해야한다. + - 구성서버 찾기위한 유레카호출 + - 구성 데이터를 가져오기 위한 구성 서버에 호출 + +Flow + +1. 애플리케이션 시작 +2. config-server 클라이언트가 제공하는 속성 소스가 config-server에 속성 값을 요청 +3. 응답 받으면 이 속성들을 사용 + 1. 이 속성들은 캐싱이 되기에 실행이 중단 되더라도 사용할 수 있다. + +# 14.4 애플리케이션이나 프로파일에 특정된 속성 제공하기 + +config-server가 시작될 때 애플리케이션 이름과 활성 profile 모두를 포함하는 요청 경로를 사용하여 서버에 속성을 요청한다. + +애플리케이션의 이름은 `spring.application.name` 속성을 설정하여 지정한다. + +활성할 프로필 설정은 다 알듯 `spring.profiles.active` 속성을 이용해서 구성할 수 있다. + +## 14.4.1 애플리케이션에 특정된 속성 제공하기 + +마이크로서비스에서 공통적으로 사용하는 속성들을 공통으로 사용할 수 있는게 구성서버가 존재하는 이유인데, + +하나의 서비스에만 공유하고 나머지는 공유받지 않아도 되는 속성들이 있다. + +이런 경우 spring.application.name 속성값과 동일하게 구성 파일의 이름을 지정하는 방법이 좋다. + +특정 서비스에만 적용하고 싶은 경우는 파일이름을 `서비스이름.yml` 로 만들어주면 된다. + +공통 속성은 바로 `application.yaml` 로 적용하면 된다. + +> 중복된 속성은 애플리케이션에 특정된 속성이 우선값으로 적용된다. +> + +## 14.4.2 프로파일로부터 속성 제공하기 + +- profile에 특정된 `.properties` 나 `.yaml` 파일들을 제공한다. +- 하나의 yaml 파일 내부에 여러 개의 프로파일 구성 그룹을 포함한다. + - `---` 를 추가하고 `spring.profiles` 속성을 지정해주면 된다. + +활성프로필을 prd로 한 경우 application.yaml, application-prod.yaml 두개를 모두 반환하는데, + +이 때 중복되는 속성이 있다면 application-prod.yaml 의 속성이 우선시된다. + +# 14.5 구성 속성들의 보안 유지하기 + +보안 구성을 사용할 때는 두가지 옵션이 존재한다. + +- Git Repository의 구성 파일에 암호화 된 값 사용하기 +- Git Repository에 추가하여 config-server의 백엔드 저장소로 해시코프의 Valut 사용하기 + +## 14.5.1 Git 백엔드의 속성들 암호화하기 + +암호화되지 않은 값들에 대해서 Git Repository에 저장된 구성 파일에 쓰는 암호화된 값들도 제공할 수 있다. + +이것의 핵심은 **암호화 키**이다. + +암호화된 속성을 사용하려면 당연히 암호화 키를 사용해서 구성해야 하고, 이는 복호화에 필요하다. + +구성 서버는 대칭/비대칭 키 모두 지원하고, 대칭키를 설정하려면 `encrypt.key` 속성에 암,복호화 키 값을 설정해주면 된다. + +암호화가 되면 서두에 `{cipher}` 가 붙어있는데 이게 바로 암호화된 값이라는걸 구성 서버에 알려주는 것이다. + +구성이 된 후 다시 불러보게 되면 복호화된 값이 들어있게 된다. + +→ 여기까지는 jasypt 라이브러리를 사용했을 때 처럼 같은 원리이다. + +> 복호화하지 않고 그대로 제공받기를 원한다면? +> + +`spring.cloud.config.server.encrypt.enabled=false` 를 구성해주면 된다. + +이런 구성일 때에는 받아올 때까진 전부 위에서 설명한것처럼 cipher 가 그대로 넘어오게 되는데, + +클라이언트 부분에서 이러한 값을 복호화해주면 된다. + +## 14.5.2 Valut에 보안 속성 저장하기 + +Valut는 보안 관리 도구이다. + +### Valut 서버 시작시키기 + +- 서버 실행이라 스킵 + +### 보안 데이터를 VALUT에 쓰기 + +```groovy +vault write secret/application spring.data.mongodb.password=password +``` + +secret/ 은 Vault 백엔드 서버를 나타낸다. + +application은 애플리케이션을 특정할 수 있다. + +`,` 뒤부분에 profile을 명시하면 해당 환경의 암호화값을 받아올 수 있다. + +spring.profiles.active 속성에 vault를 추가해주면 사용가능하다. + +spring.cloud.config.server.valut 내의 속성에 접속정보를 기입하면 valut를 연결할 수 있게 된다. + +# 14.6 실시간으로 구성 속성 리프레시하기 + +일반적인 경우는 애플리케이션을 유지보수 할 때는 애플리케이션을 다시 배포하거나 최소한 다시 시작해야 한다. + +근데 이부분을 스프링 클라우드 config 에서는 애플리케이션을 중단시키지 않고 구성 속성들을 refresh 해주는 기능을 제공한다. + +- 수동식 + - `/actuator/refresh` + - 스프링 액추에이터의 엔트포인트를 활성화 + - 해당 엔드포인트로 POST 요청 시 클라이언트가 가장 최근 구성을 백엔드로부터 가져옴 +- 자동식 + - git repostiory의 commit hook 이 모든 서비스의 리프레시를 촉발할 수 있다. + - 이때는 클라이언트 <> 구성서버 간의 통신을 위한 spring-cloud-bus 프로젝트가 사용된다. + +## 14.6.1 구성 속성을 수동으로 리프레시하기 + +- build.gradle + +```groovy +implementation 'org.springframework.boot:spring-boot-starter-actuator' +``` + +1. 액추에이터 구성을 주입해준다. +2. `/actuator/refresh` 호출 +3. 클라이언트에서 값 확인 + +## 14.6.2 구성 속성을 자동으로 리프레시하기 + +1. git push +2. git → spring cloud config server 적용 +3. spring cloud config server kafka produce +4. 각 서비스 애플리케이션에서 해당 topic message consume + +![%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2023-03-20_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_9 43 18](https://user-images.githubusercontent.com/74235102/226675819-20436e77-b524-4235-be21-dbd2813a39fc.png) +출처 - Spring in Action + +### 고려할 사항 + +1. 메시지 처리에 사용할 수 있는 메시지 브로커가 하나 있어야 한다. +2. WebHook을 Git에 설정해주어야 한다. +3. 모니터 의존성(git webhook 요청처리), rabbitMq, spring cloud stream kafka와 함께 활성화 +4. 로컬환경이 아니라면 세부 브로커 연결정보들을 구성서버와 클라이언트에 구성 +5. spring-cloud-bus 의존성 추가 + +### 웹훅 생성하기 + +- 문서보고 그대로 구성해주면 되기에 스킵 + +### 구성 서버에서 웹훅 처리하기 + +- build.gradle + +```groovy +implementation 'org.springframework.cloud:spring-cloud-config-monitor' + +implementation 'org.springframework.cloud:spring-cloud-starter-stream-rabbit' +implementation 'org.springframework.cloud:spring-cloud-starter-stream-kafka' +``` + +`/monitor` 엔드포인트를 활성화 시킬 수 있다. + +그러면서 동시에 스트림 의존성도 같이 넣어준다. + +git webhook은 여러가지 방법으로 받아 처리할 수 있는데, 책에서는 Gogs를 사용했다. + +### Gogs 알림 추출기 생성하기 + +spring cloud config server는 Github, GitLab, Bitbucket 등의 서버 지원 기능이 포함되어있다. + +`PropertyPathNotificationExtractor` 를 구현해주면 해당 webhook 추출이 가능하다. + +### 구성 서버 클라이언트에 자동 리프레시 활성화하기 + +```groovy +implementation 'org.springframework.cloud:spring-cloud-starter-bus-amqp' +implementation 'org.springframework.cloud:spring-cloud-starter-bus-kafka' +``` + +이 의존성 하나를 설정해준다. + +이제는 구성이 되었으니 메시지 브로커에 자동으로 바인딩 된다. + +(단, rabbitMQ나 Kafka의 접속정보를 설정해주는것은 잊지 말아야 한다.) + +# 14.7 구성 서버와 구성 클라이언트 프로젝트의 빌드 및 실행 + +- 생략 + +방법은 찾아보진 않았지만 보안상 더 안전하게 만드려면 환경변수로 저장해주는게 낫지 않을까..? + +- Github Environments +- K8s environment variable + - nhn forward 18분부터 k8s 로의 config 설정도 볼 수 있다. + +[[NHN FORWARD 22] Spring Cloud 기반 MSA 환경을 쿠버네티스로 전환하기](https://www.youtube.com/watch?v=otss__0kf-g&ab_channel=NHNCloud) + +# 요약 + +- 스프링 클라우드 구성 서버는 중앙 집중화된 구성 데이터 소스를 마이크로 서비스 기반의 더 큰 애플리케이션을 구성하는 모든 마이크로서비스에 제공한다. +- 구성 서버가 제공하는 속성들은 Git이나 Valut 리포지토리에서 유지 관리된다. +- 모든 구성 서버 클라이언트에 제공되는 전역 속성들에 추가하여 구성 서버는 프로파일에 특정된 속성과 애플리케이션에 특정된 속성도 제공이 가능하다. +- 보안에 민감한 속성들은 Git Repository에 암호화하여 저장하거나 Valut 백엔드의 보안 속성으로 저장하여 보안유지가 가능하다. +- 구성 서버 클라이언트는 새로운 속성으로 리프레시 할 수 있다. + - 액추에이터 엔드포인트 수동 리프레시 + - Spring cloud bus, git webhook 자동 리프레시 \ No newline at end of file