
앞선 시간에서 local 환경에서 application.propertis를 사용하는 요령을 살펴보았다.
이번에는 쿠버네티스 configmap 과 spring cloud config 를 활용해 배포된 환경에서 환경변수를 받아 사용하는 방법을 살펴보려한다.
⭐️ 이 방식을 했을 때의 장점
자신의 프로젝트가 쿠버네티스를 사용하고 있다면 이 방법을 활용하는 것이 좋다.
본격적으로 활용을 하기 이전에 개념을 간단하게 살펴보고 가겠다.
configMap은 키-값 쌍으로 데이터를 저장하는데 사용하는 API 오프젝트이다.
파드는 환경 변수, 커맨드-라인 인수, 구성 파일로 이 컨피그맵을 사용할 수 있다.
그런데 여기서 주의해야 할 점으로 컨피그맵 자체는 기밀이 아닌 데이터를 저장하는 목적으로 사용된다.
기밀인 데이터를 저장하려면 시크릿과 같은 도구를 사용해서 데이터를 비공개로 유지해야 한다.
ConfigMap에 저장된 데이터는 1Mib를 초과할 수 없다. 이보다 큰 설정을 저장해야 하는 경우 외부 스토리지를 연결하거나 별도의 데이터 베이스 등을 활용해야한다.
우선 간단하게 한 가지 예시를 작성해보겠다.
apiVersion: v1
kind: ConfigMap
metadata:
name: mysql
namespace: middleware
data:
ROOT_PASSWORD: root
USER: USERNAME
PASSWORD: 1234
DATABASE: DEV
이렇게 설정하면 mysql이라는 이름의 configMap이 middleware 네임스페이스에 저장되게 된다.
valueFrom.configMapKeyRef 를 통해 간단하게 바인딩하여 사용할 수 있다.
이때 파드에서 사용하려면 해당 configMap과 파드가 같은 namespace 내에 있어야 한다.
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql-db
namespace: middleware
spec:
selector:
matchLabels:
app: mysql
serviceName: "mysql"
replicas: 1
template:
metadata:
labels:
app: mysql
spec:
terminationGracePeriodSeconds: 10
containers:
- name: mysql
image: mysql:8.0.30
ports:
- containerPort: 3306
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
configMapKeyRef:
name: mysql-config
key: ROOT_PASSWORD
- name: MYSQL_USER
valueFrom:
configMapKeyRef:
name: mysql-config
key: USER
- name: MYSQL_PASSWORD
valueFrom:
configMapKeyRef:
name: mysql-config
key: PASSWORD
- name: MYSQL_DATABASE
valueFrom:
configMapKeyRef:
name: mysql-config
key: DATABASE
이밖에도 envFrom , 파일로 볼륨 마운트하기과 같은 방법이 있는데 우선은 여기까지만 살펴보려 한다.
추후 시간이 되면 작성을 할 것이다.
ConfigMap을 사용했을 때와 큰 차이는 없다.
kind 를 Secret으로 한 것과 value에 쓰이는 값이 base64로 인코딩이 된 점의 정도의 차이가 있다.
apiVersion: v1
kind: Secret
metadata:
name: mysql-secret
namespace: middleware
type: Opaque
data:
ROOT_PASSWORD: cm9vdA==
USER: VVNFUk5BTUU=
PASSWORD: MTIzNA==
DATABASE: REVW
주입 받는 방식도 비슷하다. -config 에서 -secret으로 변경해주면 된다.
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secret
key: ROOT_PASSWORD
여기서 한 번 생각해보자.
단순히 평문을 base64로 인코딩하였다고 암호화가 되었다고 보아도 되는가. 개발을 모르는 사람도 chatgpt를 돌리면 바로 base64 정도는 평문으로 바꿀 수 있을 것이다.
그래서 이 점을 보완하기 위해 시크릿에 대한 RBAC 권한 설정을 최소화하거나 외부 시크릿 저장소 제공 서비스 활용, 특정 컨테이너만 시크릿에 접근하도록 하기 등의 방안이 있다고 한다.
추후 시간이 되면 이부분에 대해서도 작성을 해 보겠다.
Spring Cloud Config는 MSA 환경에 도입하기 적합하며, 모든 환경에서 애플리케이션의 외부 속성을 중앙에서 관리할 수 있도록 해준다.
서버 저장소의 기본 구현을 git 을 사용하여서 버전 관리가 손쉽고 무엇보다 Spring 환경에서 구현을 쉽게 추가하고 적용할 수가 있다.
따라서 Spring 환경에서 별도의 쿠버네티스를 활용하지 않는다면 configMap 보다는 Spring Cloud Config 를 도입하는 것이 추천된다.
Spring Cloud Config가 기본적으로 git 기반이다.
그래서 Spring Cloud Config를 사용하려면 우선적으로 repository를 생성하여 해당 repository에 필요한 application.yml 파일을 작성해야한다.
{application-name}-{profiles}.yml 형식으로 작성을 하면 된다.
server-dev.yml
spring:
datasource:
username: dev
password: password
server-prod.yml
spring:
datasource:
username: prod
password: password
Spring intialLizer 으로 프로젝트를 생성할 때 Dependencies 에 Config Server 을 추가한다. 혹은 기존의 프로젝트에 해당 의존성을 추가해도 된다.
(IntelJ엔 손쉽게 추가할 수 있는데 다른 IDE 는 잘 모르겠다.)
sever가 될 프로젝트의 application.yml에 spring.cloud.config.sever.git 환경 변수를 설정한다.
만약 repository를 private 이 아닌 public 으로 설정을 했다면 git 아이디와 비밀번호 혹은 git ssh 키를 통해 인증을 해야한다.
private으로 하였다면 이 블로그 를 참조 바란다.
server:
port: 8080
spring:
cloud:
config:
server:
git:
uri: https://github.com/github/spring-cloud-config
default-label: main
속성을 자세히 설명하자면,
git.url은 2.1에서 작성한 github의 url을 넣으면 되고
default-label은 저장소에서 기본적으로 사용할 브랜치를 넣으면 된다.
여기서 main을 넣었으니 main 브랜치를 활용해 설정을 불러오게 된다.
이렇게 한 다음 마지막으로 @EnableConfigSever 어노테이션을 추가해주면 된다.
@EnableConfigServer
@SpringBootApplication
public class SpringCloudConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(SpringCloudConfigServerApplication.class, args);
}
}
@EnableConfigSever 은 말 그대로 해당 어플리케이션을 Config Server로 사용하겠다는 의미이다.
최종적으로 속성을 주입해줄 중앙 서버가 구축이 되었다.
먼저 Config Server와 유사하게 프로젝트를 생성 할 때 Config Client 의존성을 추가한다.
그런 다음 아래와 같이 설정을 받아오면 된다.
server:
port: 8082
spring:
config:
import: "optional:configserver:http://localhost:8080/"
cloud:
config:
name: server
profile: dev
management:
endpoints:
web:
exposure:
include: refresh
spring.config.import 는 설정을 받아올 config server 의 주소를 넣어주면 되고,
spring.cloud.config.name 에는 해당 서버의 application name 을, profile에는 활성화 할 profile을 적어주면 된다.
위의 예시에서는 server-dev.yml 이 활성화 될 것이다.
참고로 management.endpoints.web.exposure.include 을 refresh로 활성화하면 변경된 설정 정보를 프로젝트 재기동 없이 실시간으로 변경될 수 있게 된다.
이번 포스팅에는 외부 환경에서 설정을 주입받는 방법에 대해 간략히 알아보았다.
configmap, spring cloud config를 마스터하자 보다는 이것이 도입된 실무 환경에서 신입 개발자로서 최소한 application.yml이 설정이 어떻게 이뤄지는지는 파악해보자는 관점에서 살펴보았다.
같은 신입 개발자에게 조금이나마 도움이 되기를 바라며 이번 포스팅을 마친다.
혹시나 읽어 주는 사람이 있다면, 읽어주셔서 매우매우 감사하다 🎉
참조 : 쿠버네티스, Spring Cloud Config , https://beer1.tistory.com/37 , https://mangkyu.tistory.com/253