쿠버네티스에서 설정정보를 저장하고 활용하는 내부구조
.
Data_Engineering_TIL(20210911)
[학습자료]
“클라우드 네이티브를 위한 쿠버네티스 실전 프로젝트” 책을 읽고 정리한 내용입니다.
** 동양북스, 아이자와 고지&사토 가즈히코 지음, 박상욱 옮김
참고자료 URL : https://github.com/dybooksIT/k8s-aws-book
“쿠버네티스 서비스 리소스(ELB)에 HTTPS 적용하기”에 이어서 공부한 내용을 정리한 내용임
** URL : https://minman2115.github.io/DE_TIL277
[학습내용]
- 시크릿을 이용한 비밀정보 전달
“EKS 클러스터에 API 어플리케이션 배포하기” 에서 아래와 같이 디비접속을 위한 시크릿을 등록을 했다.
** URL : https://minman2115.github.io/DE_TIL253
사용자 이름, 비밀번호 등 누구나 접근할 수 있는 장소에 저장하면 위험하다. 그래서 미리 안전한 장소에 해당 정보들을 등록해두고 그 정보를 참조하는 방법으로 서비스를 구성해야 한다. 쿠버네티스에서는 시크릿이라는 리소스를 이용해 이러한 구조를 구현할 수 있다.
아래에 명령어에서 backend-app이 사용하는 디비 접속정보를 미리 쿠버네티스의 시크릿에 등록해놓는다. 그리고 파드의 매니패스트는 해당 시크릿에서 값을 읽어들여 파드 내부의 환경변수에 설정하도록 정의한다.
[ec2-user@ip-10-10-1-236 ~]$ cd /home/ec2-user/k8s-aws-book/eks-env
[ec2-user@ip-10-10-1-236 eks-env]$ cat 21_db_config_k8s.yaml.template
apiVersion: v1
kind: Secret
type: Opaque
metadata:
name: db-config
stringData:
db-url: ${DB_URL}
db-username: mywork
db-password: ${DB_PASSWORD}
# STEP 3) 디비 접속용 시크릿 등록
# API 어플리케이션이 디비에 접속하기 위한 비밀번호 등을 저장하는 '시크릿' 이라는 것을 아래와 같이 생성한다.
# rds 엔드포인트는 클라우드 포메이션의 출력값을 확인하면 되고, 디비 패스워드는 시크릿 매니저 서비스에서 확인하면 된다.
[ec2-user@ip-10-0-1-236 eks-env]$ DB_URL=jdbc:postgresql://eks-work-db.xxxxxxxx.ap-northeast-2.rds.amazonaws.com/myworkdb DB_PASSWORD='wdivF6S}_gC#Ifog' envsubst < 21_db_config_k8s.yaml.template | kubectl apply -f -
secret/db-config created
아래의 명령어는 파드에서 시크릿을 참조하는 구조에 대한 내용이다.
# API 어플리케이션 배포
# 디플로이먼트 오브젝트를 생성한다. 디플로이먼트를 생성하면 그 뒤에 레플리카 셋이 생성되며 레플리카셋 뒤에는 파드가 생성된다.
[ec2-user@ip-10-0-1-236 eks-env]$ ECR_HOST=xxxxxxxxxx.dkr.ecr.ap-northeast-2.amazonaws.com envsubst < 22_deployment_backend-app_k8s.yaml.template | kubectl apply -f -
deployment.apps/backend-app created
[ec2-user@ip-10-0-1-236 eks-env]$ cat 22_deployment_backend-app_k8s.yaml.template
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend-app
labels:
app: backend-app
spec:
replicas: 2
selector:
matchLabels:
app: backend-app
template:
metadata:
labels:
app: backend-app
spec:
containers:
- name: backend-app
image: ${ECR_HOST}/k8sbook/backend-app:1.0.0
imagePullPolicy: Always
ports:
- containerPort: 8080
env:
- name: DB_URL
valueFrom:
secretKeyRef:
key: db-url
name: db-config
- name: DB_USERNAME
valueFrom:
secretKeyRef:
key: db-username
name: db-config
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
key: db-password
name: db-config
readinessProbe:
httpGet:
port: 8080
path: /health
initialDelaySeconds: 15
periodSeconds: 30
livenessProbe:
httpGet:
port: 8080
path: /health
initialDelaySeconds: 30
periodSeconds: 30
resources:
requests:
cpu: 100m
memory: 512Mi
limits:
cpu: 250m
memory: 768Mi
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 2"]
실제 동작중인 파드 내부의 환경변수는 아래와 같이 조회할 수 있다. 환경변수에 시크릿 값이 설정된 것을 알 수 있다.
[ec2-user@ip-10-10-1-236 ~]$ kubectl get pod
NAME READY STATUS RESTARTS AGE
backend-app-7fb899969-mm5dw 1/1 Running 0 45h
backend-app-7fb899969-txg5x 1/1 Running 0 45h
[ec2-user@ip-10-10-1-236 ~]$ kubectl exec backend-app-7fb899969-mm5dw -it -- env | grep DB
DB_URL=jdbc:postgresql://eks-work-db.xxxxxxxxx.ap-northeast-2.rds.amazonaws.com/myworkdb
DB_USERNAME=mywork
DB_PASSWORD=xxxxxxxxx
시크릿에 민감한 정보의 설정값들을 저장해두는 것만으로는 보안을 보장해주는 것이라고 말할 수 없다. 그리고 주의해야할 점이 쿠버네티스 매니페스트 파일이 대부분 infra as a code이기 때문에 깃허브에 업로드하는 실수도 발생할 수 있다.
시크릿 내용은 base64로 인코딩되어 저장되어 있지만 base64는 아래와 같이 해독이 가능하기 때문이다.
[ec2-user@ip-10-10-1-236 ~]$ sudo yum install jq -y
[ec2-user@ip-10-10-1-236 ~]$ kubectl get secret db-config -o json | jq -r '.data'
{
"db-password": "yyyyyyyyyyyyyyyyyyyyy",
"db-url": "zzzzzzzzzzzzzzzzzzzzzzzzz",
"db-username": "tttttttttt"
}
[ec2-user@ip-10-10-1-236 k8s-aws-book]$ kubectl get secret db-config -o json | jq -r '.data["db-password"]' | base64 -d
yyyyyyyyyyyyyyyyyyyyy
- 컨피그맵을 이용한 설정정보 전달
“EKS 클러스터에 배치 어플리케이션 배포하기” 블로그글 참고할 것
** URL : https://minman2115.github.io/DE_TIL259/
비밀정보가 아닌 일반정보일 경우에는 시크릿을 이용해서 암호화할 필요가 없기 때문에 평문으로 등록해도 된다. 이러한 용도에는 컨피그맵을 이용한다.
아래와 같이 컨피그맵을 등록해주고 그것을 파드에서 참조하는 구조이다.
[ec2-user@ip-10-10-1-236 ~]$ cd /home/ec2-user/k8s-aws-book/eks-env
[ec2-user@ip-10-10-1-236 eks-env]$ cat 41_config_map_batch_k8s.yaml.template
apiVersion: v1
kind: ConfigMap
metadata:
name: batch-app-config
data:
bucket-name: eks-work-batch-${BUCKET_SUFFIX}
folder-name: locationData
batch-run: "true"
aws-region: ap-northeast-2
[ec2-user@ip-10-10-1-236 eks-env]$ BUCKET_SUFFIX=xxx envsubst < 41_config_map_batch_k8s.yaml.template | kubectl apply -f -
configmap/batch-app-config created
[ec2-user@ip-10-10-1-236 eks-env]$ kubectl describe configmap batch-app-config
Name: batch-app-config
Namespace: eks-work
Labels: <none>
Annotations: <none>
Data
====
aws-region:
----
ap-northeast-2
batch-run:
----
true
bucket-name:
----
eks-work-batch-pms
folder-name:
----
locationData
BinaryData
====
Events: <none>
컨피그맵은 배치 어플리케이션(43_cronjob_k8s.yaml.template)에서 참조하게 된다.
“EKS 클러스터에 배치 어플리케이션 배포하기” 블로그글을 보면 시크릿(AWS accesskey, secret key가 저장된 시크릿)도 참조하고, 컨피그맵도 참조하는 것을 알 수 있다.
[ec2-user@ip-10-10-1-181 eks-env]$ cat 42_batch_secrets_k8s.yaml.template
apiVersion: v1
kind: Secret
type: Opaque
metadata:
name: batch-secret-config
stringData:
aws-accesskey: ${AWS_ACCESSKEY}
aws-secretkey: ${AWS_SECRETKEY}
[ec2-user@ip-10-10-1-181 eks-env]$ AWS_ACCESSKEY=xxxxxxx AWS_SECRETKEY=yyyyyyy envsubst < 42_batch_secrets_k8s.yaml.template | kubectl apply -f -
secret/batch-secret-config created
[ec2-user@ip-10-10-1-236 eks-env]$ kubectl get secret batch-secret-config -o json | jq -r '.data'
{
"aws-accesskey": "xxxxxxxxxxxxxx",
"aws-secretkey": "yyyyyyyyyyyyyy"
}
[ec2-user@ip-10-10-1-236 eks-env]$ cat 43_cronjob_k8s.yaml.template
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: batch-app
spec:
schedule: "*/5 * * * *" # min hour day-of-month month day-of-week
jobTemplate:
spec:
template:
spec:
containers:
- name: batch-app
image: ${ECR_HOST}/k8sbook/batch-app:1.0.0
imagePullPolicy: Always
env:
- name: DB_URL
valueFrom:
secretKeyRef:
key: db-url
name: db-config
- name: DB_USERNAME
valueFrom:
secretKeyRef:
key: db-username
name: db-config
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
key: db-password
name: db-config
- name: CLOUD_AWS_CREDENTIALS_ACCESSKEY
valueFrom:
secretKeyRef:
key: aws-accesskey
name: batch-secret-config
- name: CLOUD_AWS_CREDENTIALS_SECRETKEY
valueFrom:
secretKeyRef:
key: aws-secretkey
name: batch-secret-config
- name: CLOUD_AWS_REGION_STATIC
valueFrom:
configMapKeyRef:
key: aws-region
name: batch-app-config
- name: SAMPLE_APP_BATCH_BUCKET_NAME
valueFrom:
configMapKeyRef:
key: bucket-name
name: batch-app-config
- name: SAMPLE_APP_BATCH_FOLDER_NAME
valueFrom:
configMapKeyRef:
key: folder-name
name: batch-app-config
- name: SAMPLE_APP_BATCH_RUN
valueFrom:
configMapKeyRef:
key: batch-run
name: batch-app-config
restartPolicy: OnFailure
시크릿과 컨피그맵은 환경변수가 아닌 파드 내부의 볼륨으로 마운트하여 파일로 전달할 수도 있다. 어플리케이션 특성상 환경변수로는 전달할 수 없거나, 미들웨어의 사용제약으로 파일을 참조할 수 밖에 없는 경우 등에는 마운트하는 방식을 사용할 수도 있다.