docker에서 환경변수를 전달할 때는 다음과 같이 전달할 수 있다.
docker run -e APP_COLOR=pink simple-webapp-color
pod역시도 마찬가지인데, 다음과 같다.
apiVersion: v1
kind: Pod
metadata:
name: simple-webapp-color
spec:
containers:
- name: simple-webapp-color
image: simple-webapp-color
ports:
- containerPort: 8080
env:
- name: APP_COLOR
value: pink
simple-webapp-color
container의 환경변수로 APP_COLOR
key로 pink
value가 들어가는 것이다.
이렇게 직접 environment variable을 써주는 방법도 있지만 configmap
이나 secret
과 같은 kubernetes object를 활용하여 환경변수를 숨기거나 다르게하여 pod에 넘겨줄 수 있다.
env:
- name: APP_COLOR
valueFrom:
configMapKeyRef:
env:
- name: APP_COLOR
valueFrom:
secretKeyRef:
configMapKeyRef
와 secretKeyRef
에 각 kubernetes object 이름들을 넣어주면 되는 것이다.
configmap은 key-value pair로 수많은 환경변수와 데이터들을 저장하여 pod에 제공할 수 있다.
kubectl create configmap {config-name} --from-literal={key}={value}
from-literal
뒤에 key=value
형식으로 넣어주면 된다.
kubectl create configmap {config-name} --from-literal=APP_COLOR=blue
여러 개의 환경 변수를 추가하고 싶으면 --from-literal
을 여러번쓰면 된다. 단, 이렇게 쓰기에는 너무 번거로우므로 file
로 key-value형식의 환경변수를 제공하는 방법이 있다.
kubectl create configmap {config-name} --from-file={path-to-file}
가령 환경변수를 담은 file이름이 app_config.properties
라면 다음과 같다.
kubectl create configmap app-config --from-file=app_config.properties
APP_COLOR: blue
APP_MODE: prod
다음과 같이 key-value 형식의 환경변수를 제공해주면 configmap
이 file
을 읽어 환경변수를 설정해주는 것이다.
위와 같이 configmap을 imperative
방식으로 만드는 것 이외에 declarative
방식으로 만드는 방법이 있다.
kubectl create -f ./config-map.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
APP_COLOR: blue
APP_MODE: prod
data
아래에 있는 환경변수들이 pod에 들어가게 되는 것이다.
kubectl get configmaps
kubectl describe configmaps
각 configmap에 어떤 data가 있는 지 알 수 있다.
이제 pod에 configmap을 넣어주어 환경변수를 설정해주도록 하자.
apiVersion: v1
kind: Pod
metadata:
name: simple-webapp-color
spec:
containers:
- name: simple-webapp-color
image: simple-webapp-color
ports:
- containerPort: 8080
envFrom:
- configMapRef:
name: app-config
envFrom.configMapRef.name
에 우리가 만든 configmap
이름을 넣어주면 된다.
이렇게 configmap자체를 제공해주어, configmap에 있는 황경변수를 모두 pod에 설정하도록 할 수 있다.
그러나, 이러한 방법 이외에 configmap
내부의 일부 환경변수만 가져오고 싶다면 다음과 같이 쓸 수 있다.
env:
- name: APP_COLOR
valueFrom:
configMapKeyRef:
name: app-config
key: APP_COLOR
app-config
configmap에서 APP_COLOR
key를 가진 환경변수를 pod의 APP_COLOR
환경변수로 넣으라는 것이다.
이외에 volume을 통해서 넣는 방법도 있다.
volumes:
- name: app-config-volume
configMap:
name: app-config
app-config
configmap안에 있는 모든 환경변수가 해당 pod안에 다 들어가게 된다.
secret은 kubernetes cluster에 민감한 정보를 저장하기 위해서 사용한다. 가령, DB에 접근하는 환경변수들이나 API key과 같은 것들이 있다.
secret을 사용하는 방법은 두 단계로 이루어진다고 생각하면 된다.
1. Secret를 만들어, 중요한 정보를 넣고
2. pod에 해당 secret를 주입시켜준다. 즉, 읽을 수 있게 만들어준다.
다음의 방법으로 쉽게 secret을 만들 수 있다.
kubectl create secret generic <secret-name> --from-literal=<key>=<value>
generic
은 secret의 type이다.
가령 다음과 같이 쓸 수 있다.
kubectl create secret generic app-secret -from-literal=DB_Host=mysql \
-from-literal=DB_User=root \
-from-literal=DB_Password=paswrd
app-secret
secret을 만들어 DB_Host=mysql
, DB_User=root
, DB_Password=paswrd
정보를 저장하도록 한다.
그러나 이렇게 작성하는 방법은 매우 번잡하다. 매번 key=value를 써주는 방식은 귀찮기 때문이다. 따라서, 다음과 같이 key-value
의 환경변수가 적힌 파일 이름을 넘겨 secret에 content를 채우는 방법이 있따.
kubectl create secret generic <secret-name> --from-env-file=<path-to-file>
가령 다음과 같이 쓸 수 있다.
DB_Host=sql01
DB_user=root
DB_Password=password123
kubectl create secret generic app-secret --from-env-file=temp.env
temp.env
파일의 데이터를 읽어 secret를 만드는 방법이다.
다음으로는 declarative방식으로 secret을 만드는 방식이다.
apiVersion: v1
kind: Secret
metadata:
name: app-secret
data:
DB_Host: mysql
DB_User: root
DB_Password: paswrd
실행하는 방법은 다음과 같다.
kubectl create -f ./secret-data.yaml
관례상 secret 데이터는 민감한 데이터이므로 인코딩하여 데이터를 저장하는 것이 좋다. 따라서, base64
를 이용하여 데이터를 인코딩하면되는데 linux에서는 다음의 명령어를 사용하면 된다.
echo -n 'target' | base64
target
이 base64
인코딩되어 결과로 나오게 될 것이다.
echo -n 'mysql' | base64
bXlzcWw=
echo -n 'root' | base64
cm9vdA==
echo -n 'paswrd' | base64
cGFzd3Jk
이 정보들을 secert
의 data에 넣어주면 된다.
DB_Host: bXlzcWw=
DB_User: cm9vdA==
DB_Password: cGFzd3Jk
만들어진 secret
을 보는 방법은 kubectl get
과 kubectl describe
를 쓰면 된다. 재밌는 것은 describe를 호출해도 데이터가 숨겨져 있다는 것이다.
만약 데이터를 보고 싶다면 kubectl get secret <secret-name> -o yaml
을 사용하도록 하자.
kubectl get secret app-secret -o yaml
apiVersion: v1
data:
DB_Host: cWwwMQ==
DB_Password: cGFzc3dvcmQxMjM=
DB_user: cm9vdA==
kind: Secret
metadata:
creationTimestamp: "2024-07-06T15:33:10Z"
name: app-secret
namespace: default
resourceVersion: "1066"
uid: 91b2798f-1517-4467-9b9f-cea6f209d00a
type: Opaque
인코딩된 data결과가 보일 것이다.
인코딩된 data를 디코딩하여 보여주기 위해서는 어떻게해야할까?? 이 역시도 echo
를 사용하면 된다.
echo -n 'bXlzcWw=' | base64 --decode
mysql
이제 두 번째 step으로 pod에 secret를 넣어주도록 하자. 여기에는 3가지 방법이 존재하는데, 먼저 환경변수로 집어넣는 방법이다.
apiVersion: v1
kind: Pod
metadata:
name: simple-webapp-color
spec:
containers:
- name: simple-webapp-color
image: simple-webapp-color
ports:
- containerPort: 8080
envFrom:
- secretRef:
name: app-secret
envFrom.secretRef.name
에 secret이름을 적어주면 된다. secret이 환경변수로 제공된다.
다음은 secret에 있는 특정 data만 가져오는 방법이다.
apiVersion: v1
kind: Pod
metadata:
name: simple-webapp-color
spec:
containers:
- name: simple-webapp-color
image: simple-webapp-color
ports:
- containerPort: 8080
env:
- name: DB_Password
valueFrom:
secretKeyRef:
name: app-secret
key: DB_password
마지막으로 file로 secret을 가져오는 방법으로 volume을 이용한다.
apiVersion: v1
kind: Pod
metadata:
name: simple-webapp-color
spec:
containers:
- name: simple-webapp-color
image: simple-webapp-color
ports:
- containerPort: 8080
volumes:
- name: app-secret-volume
secret:
secretName: app-secret
secret을 volume을 통해 배포하게 된다면 pod안에 secret의 각 data들이 file로 존재하게 된다.
ls /opt/app-secret-volumes
DB_Host DB_Password DB_User
각 file에 value가 들어있는 것이다.
Secret에 민감한 data를 집어넣는다고 했지만, secret data는 사실 encrypted data를 넣는 곳이 아니다. encoded 데이터를 넣는 곳이다. 즉, 암호화되지 않는다는 것이다. 따라서 cluster에 접근하는 누군가라도 해당 정보를 볼 수 있다는 것이다.
secret data뿐만 아니라 secret자체도 etcd안에서 암호화되지 않는다.