1. 문제 상황
현재 EKS로 배포하고자 하는 서비스가 API Gateway를 통해 공개키 인증이 필요하도록 구현하였다.
ECR로 push하는 도커 이미지에는 비밀키에 대한 정보를 갖고있어야하는데,
만약 이미지를 탈취당하거나 노출될 경우, 경우 비밀키가 공개될 수 있는 보안 취약점이 존재한다.
또한 이미지 레이어 캐싱 구조상, 한번 포함되면 완전히 제거하기 어렵기 때문에 한번이라도 비밀키값이 포함되지않도록 유의해야한다.
따라서 도커 이미지가 실행될 때 비밀키를 사용할 수 있어야하지만, 비밀키 내용이 직접 이미지에 포함되지 않는 방법을 찾아야만 했다.
기존 spring boot로 실행할때는 key path를 인자로 넣어 key 값을 참조할 수 있도록 하였다.
2. 해결방법
사용하는 키값으로 시크릿을 생성하여, 쿠버네티스 Deplopyment에서 참조하도록 하였다.
쿠버네티스 시크릿(Secret)이란?
쿠버네티스의 Secret은 비밀번호, API 토큰, 인증서 키처럼 민감한 데이터를 안전하게 저장하고 Pod에 전달하기 위한 리소스이다.
- 기본적으로 key-value 구조로 저장되며, etcd에 Base64로 인코딩되어 보관된다.
- Pod 내부에서는 환경변수 또는 볼륨 마운트된 파일 형태로 접근할 수 있다.
- ConfigMap과 비슷하지만, 보안 민감 데이터를 다루는 경우 Secret을 사용하는 게 권장된다.
2.1 시크릿 생성
키 값들이 존재하는 로컬 위치에서,
다음 명령어를 통해 jwt-keys 라는 이름의 시크릿을 원하는 네임스페이스에 생성한다.
kubectl create secret generic jwt-keys \
--from-file=private_pkcs8.pem=./private_pkcs8.pem \
--from-file=public.pem=./public.pem \
-n [네임스페이스]
이렇게 하면 jwt-keys 라는 시크릿이 만들어지고,
실제 쿠버네티스 내부에는 key-value 형태로 파일 내용이 Base64 인코딩되어 저장된다.

2.2 volumes, volumeMounts 선언
pod와 container는 볼륨을 갖는데, jwt-keys라는 외부 데이터와 연결해서 사용할 수 있도록
Deployment에서 지정해주는 과정이 필요하다.
먼저 Pod 레벨의 volumes 정의이다.
volumes:
- name: jwt-keys
secret:
secretName: jwt-keys
- jwt-keys라는 Secert에서 가져온 데이터로 "jwt-keys"라는 볼륨을 선언한다.
다음은 Container 레벨의 volumeMounts 정의이다.
volumeMounts:
- name: jwt-keys
mountPath: /etc/jwt
readOnly: true
- Pod에 정의된 jwt-keys 볼륨을 컨테이너에서는 /etc/jwt에 붙인다는 선언이다.
- 이를 통해 컨테이너 내부에서는 /etc/jwt/private_pkcs8.pem, /etc/jwt/public.pem 파일이 자동 생성된다.
- 이때 key값들은 읽기 전용으로 생성된다.
2.3 환경변수로 지정
위 과정을 통해 키 값들이 /etc/jwt 위치에 마운트되었다.
애플리케이션이 실행할 때 키의 위치를 참조하려면 path를 알려줘야하는데,
이를 위해 환경변수 값으로 넣어준다.
이를 통해, 애플리케이션은 실행할 때 필요한 키값의 위치를 /etc/jwt에서 찾을 수 있다.
env:
- name: JWT_PRIVATE_KEY_PATH
value: /etc/jwt/private_pkcs8.pem
- name: JWT_PUBLIC_KEY_PATH
value: /etc/jwt/public.pem
위의 시크릿, 볼륨, 볼륨마운트, 환경변수 참조를 그림으로 그려보면 아래와 같다.
Deployment.yaml의 코드이다!
apiVersion: apps/v1
kind: Deployment
metadata:
name: auth-deployment
namespace: production
labels:
app: auth
spec:
template:
spec:
volumes: # Pod 레벨 선언
- name: jwt-keys
secret:
secretName: jwt-keys
containers: # Container 레벨 선언
- name: auth-service
volumeMounts:
- name: jwt-keys
mountPath: /etc/jwt
readOnly: true
env:
- name: JWT_PRIVATE_KEY_PATH
value: /etc/jwt/private_pkcs8.pem
- name: JWT_PUBLIC_KEY_PATH
value: /etc/jwt/public.pem
쿠버네티스 시크릿을 생성하고 이를 container에 볼륨 마운트하는 과정을 통해,
비밀키를 Docker 이미지에 직접 포함하지 않고도 안전하게 비밀키 값을 참조할 수 있게되었다.