컨테이너를 디렉토리 형태로 읽어들이는 이유는 여러 설정들을 하나의 컨피그맵으로 관리하기 위함이다.
파드가 동작중일 때 컨피그맵을 업데이트하면 쿠버네티스가 수정된 파일을 컨테이너에 전달한다. 이 후의 과정은 애플리케이션이 파일을 처리하는 방식에 달려있다. 애플리케이션이 변경 감지하도록 설계했다면 애플리케이션에 반영될 것이고, 최초에만 설정을 사용한다면 별다른 일이 발생하지 않을 것이다.
아래는 컨피그맵을 적용한 후 컨테이너 내부 파일에 잘 저장되었는지 확인하는 명령어들이다.
# 변경된 configMap 적용kubectlapply-ftodo-list/configmaps/todo-web-config.yaml# configMap이 파드에 반영될 때 까지 잠깐 대기sleep120# configMap으로부터 파일이 생성되었는지 확인하기kubectlexecdeploy/todo-web--sh-c'ls -l /app/config'
mountPath는 기존 데이터를 제거하고 컨피그맵 볼륨을 저장하기 때문에 이미 데이터가 들어있는 디렉토리를 지정하면 안된다. 애플리케이션 바이너리 파일이 들어있을 경우 파드가 재실행될 수 없어 오류와 함께 종료된다.
필요한 데이터 항목만 대상 디렉터리에 전달하기
volumes 내부에 items를 통해 원하는 컨피그맵의 데이터 항목 하나를 원하는 파일에 저장할 수 있도록 지정할 수 있다.
apiVersion:apps/v1kind:Deploymentmetadata:name:todo-webspec:selector:matchLabels:app:todo-webtemplate:metadata:labels:app:todo-webspec:containers: - name:webimage:kiamol/ch04-todo-listvolumeMounts: - name:configmountPath:"/app/config"readOnly:truevolumes: - name:configconfigMap:name:todo-web-config-devitems: - key:config.json# 데이터 항목 이름path:config.json# 저장할 파일 이
비밀값을 사용해 민감한 정보 다루기
비밀값은 해당 값을 사용해야 하는 노드에만 전달되며, 디스크에 저장하지 않고 메모리에만 담긴다.
전달 과정과 저장할 때 모두 암호화가 적용된다.
아래와 같은 명령을 이용해 비밀값을 생성하고 확인할 수 있다.
# 시크릿 생성
kubectl create secret generic <비밀값 이름> --from-literal=<비밀값 항목 key>=<비밀값 항목 value>
# 시크릿 상세 정보 확인
kubectl describe secret <비밀값 이름>
# 시크릿 내용의 평문 확인을 위해 base64 디코딩 수행
kubectl get secret <비밀값 이름> -o jsonpath='{.data.secret}' | base64 -d
비밀값을 환경 변수로 전달하기
파드 정의에서는 아래와 같이 secretKeyRef를 이용해 비밀값을 환경 변수로 주입할 수 있다.
아래 명령을 이용해 디플로이먼트를 재적용한 후 파드의 환경 변수에 접근해 비밀값이 잘 적용되었는지 확인할 수 있다.
# 디플로이먼트 적용
kubectl apply -f sleep/sleep-with-secret.yaml
# 파드 속 환경 변수 확인 (비밀값 데이터의 평문이 출력된다)
kubectl exec deploy/sleep -- printenv KIAMOL_SECRET
환경 변수는 컨테이너에서 동작하는 모든 프로세스에서 접근 가능하고, 간혹 애플리케이션에서 치명적 오류가 발생했을 때 모든 환경 변수를 로그로 남기는 경우가 있다.
비밀값을 파일로 전달하기
비밀값을 환경 변수 대신 파일 형태로 전달하고 파일 권한을 볼륨에서 설정하면 더욱 안전하다.
다음은 비밀값을 정의하는 예제이다.
비밀값을 YAML로 관리하면 일관적인 애플리케이션 배치가 가능하지만 github 같은 형상 관리 도구에 노출되므로 github secret 등으로 추가적인 정보 보호를 해주어야 한다.
apiVersion:v1kind:Secret# 비밀값 유형으로 리소스 생성metadata:name:todo-db-secret-testtype:Opaque# 임의의 텍스트 데이터를 담고자 Opaque 타입 선택stringData:# 텍스트 데이터POSTGRES_PASSWORD:"kiamol-2*2*"# 저장할 데이터 (key-value)
아래 명령들을 통해 비밀값을 생성하고 인코딩된 데이터 값을 확인할 수 있다.
# 비밀값 생성kubectlapply-ftodo-db-secret-test.yaml# 인코딩된 데이터 값 확인kubectlgetsecrettodo-db-secret-test-ojsonpath='{.data.POSTGRES_PASSWORD}'
아래는 정의된 비밀값을 볼륨으로 마운트하는 파드 정의의 예시이다. 이 파드를 배치하면 /secrets/postgres_password 파일에 비밀값 데이터가 전달되고 0400 권한이므로 컨테이너 사용자만 읽을 수 있다. db 파드는 비밀값 파일을 환경 변수로 가져와 내부적으로 사용할 것이다.
spec:containers: - name:dbimage:postgres:11.6-alpineenv: - name:POSTGRES_PASSWORD_FILE# 설정파일이 마운트될 경로value:/secrets/postgres_passwordvolumeMounts: - name:secret# 마운트할 볼륨 이름mountPath:"/secrets"# 마운트 되는 경로volumes: - name:secretsecret:# 비밀값에서 볼륨 생성secretName:todo-db-secret-test# 볼륨을 만들 비밀값 이름defaultMode:0400# 파일 권한 설정items:# 비밀값의 특정 데이터 항목 지정 - key:POSTGRES_PASSWORDpath:postgres_password
애플리케이션 설정 관리
설정 업데이트
애플리케이션 중단 없이 설정 변경에 대응이 필요하다면, 기존 컨피그맵이나 시크릿을 업데이트하는 방식과 함께 볼륨 마운트를 이용해 설정 파일을 수정해야 한다.
애플리케이션을 업데이트할 때 새로운 설정 객체를 배치한 후 이를 가리키도록 애플리케이션 정의를 수정할 수도 있다. 이 과정에서 파드 교체가 발생하지만, 설정값 변경의 이력이 남고 만일의 사태에 이전 설정으로 돌아갈 수 있다는 장점이 있다.
민감 정보 관리
형상 관리 도구에 저장된 YAML 템플릿 파일로 컨피그맵과 비밀 값 정의를 두고, 외부에 절대 노출되지 말아야 하는 정보는 Azure KeyVault 등에 보관해두고 필요할 때 YAML 파일에 채워 사용할 수 있다.
설정 파일 배포를 관리하는 설정 관리 전담 팀이 있다면 컨피그맵과 비밀 값의 버전 관리 정책을 사용하면 된다. 외부에 절대 노출되지 말아야 하는 정보는 관리 팀에서 별도 시스템을 통해 저장해두고 필요할 때 kubectl create로 설정 객체를 생성해 사용할 수 있다.