✔️ ConfigMap: 컨테이너 구성 정보를 한 곳에 모아서 관리
✔️ Secret: 컨테이너가 사용하는 민감한 데이터(ex: password, auth token, ssh key)와 같은 중요한 정보를 안전하게 저장하기 위한 리소스. 애플리케이션 코드와 민감한 데이터를 분리하고, base64로 인코딩하여 보안을 강화할 수 있다.
Secrets의 주요 특징
- 보안 데이터 저장: 비밀번호, API 토큰, SSH 키와 같은 민감한 데이터를 저장하고 관리
- 즉, 민감하지 않은 일반 설정파일은 configMap을 사용하고, 민감한 데이터는 secret을 사용한다.
- 민감한 데이터를 저장할 때 Encryption at Rest를 활성화 권장
- Base64 인코딩: 데이터는 Base64로 인코딩되어 저장된다. ( base64는 누구나 쉽게 decode할 수 있기 때문에 추가 보안 조치가 필요함)
- Pod와 통합: Secrets는 환경 변수, 볼륨 마운트, 커맨드라인 인수를 통해 Pod에 전달 가능.
- RBAC과 통합: Role-Based Access Control(RBAC)을 통해 접근 권한을 세부적으로 관리 가능.
- 변경 가능: Secrets의 데이터를 수정하면 이를 참조하는 Pod에서 즉시 반영 가능.
Secret 데이터 용량 제한
- Secret은 etcd에 암호화하지 않은 텍스트로 저장되므로, secret value가 커지면 메모리 용량을 많이 사용하게 된다.
- secret의 최대 크기는 1MB
apiVersion: v1
kind: Secret
metadata:
name: my-secret
type: Opaque
data:
username: bXl1c2VybmFtZQ==
password: cGFzc3dvcmQ=
Secrets의 종류
- Opaque (기본):
- 일반적으로 사용되는 Secret 유형. 임의의 키-값 데이터를 저장
- 예: API 키, 데이터베이스 비밀번호.
- Service Account Token:
- Kubernetes API와 통신하는 데 사용되는 서비스 계정 토큰
- Docker Registry:
- Docker 이미지 풀링에 필요한 자격 증명 저장. (예: kubernetes.io/dockerconfigjson 유형)
- TLS Secret:
- TLS 인증서와 키 저장. (예: HTTPS 인증서 및 프라이빗 키)
- secret 데이터 전달 방법
- Command-line Argument
- Environment Variable (env)
- Volume Mount
Secret 만들기
# kubectl create secret <Available Commands> name [flags] [options]
✔️ docker-registry : docker-registry 접속 관련
✔️ generic # user defined data (local file, dir, ..)
✔️ tls (Transport Layer Secret): 인증서 전용 Secret
→ <Available Commands> 에 따라서 들어가는 옵션이 달라진다.
$ kubectl create secret tls my-secret --cert=path/to/cert/file --key=path/to/key/file
$ kubectl create secret docker-registry reg-secret --docker-username=tiger --docker-password=pass --docker-email=tiger@acme.com
$ kubectl create secret generic soyun-secret --from-literal=INTERVAL=2 --from-file=./genid-web-config/
[ 실습 ]
1. Secret 만들기
controlplane:~$ kubectl create secret generic super-secret --from-literal=Password=bob
secret/super-secret created
controlplane:~$ kubectl get secret
NAME TYPE DATA AGE
super-secret Opaque 1 4s
2. 해당 Secret을 사용하는 Pod 만들기 (Volume Mount)
controlplane:~$ cat pod-secret-via-file.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-secret-via-file
spec:
containers:
- image: redis
name: pod-secret-via-file
volumeMounts:
- name: foo
mountPath: "/secrets" #이 위치에 Secret Mount하기
volumes:
- name: foo
secret:
secretName: super-secret
controlplane:~$ kubectl apply -f pod-secret-via-file.yaml
pod/pod-secret-via-file created
→ Secret이 제대로 작동중인지 확인하기
controlplane:~$ kubectl exec pod-secret-via-file -it -- /bin/bash
root@pod-secret-via-file:/data# cd /secrets/
root@pod-secret-via-file:/secrets# ls
Password
root@pod-secret-via-file:/secrets# cat Password
bob # Mount 잘 됐는지 확인 가능!!
3. Secret을 통해 evn 정의하는 Pod 만들기 (Environment Variable)
controlplane:~$ cat pod-secret-via-env.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-secret-via-env
spec:
containers:
- image: redis
name: pod-secret-via-env
env:
- name: CONFIDENTIAL
valueFrom:
secretKeyRef:
name: super-secret
key: Password
controlplane:~$ kubectl apply -f pod-secret-via-env.yaml
pod/pod-secret-via-env created
controlplane:~$ kubectl get pods
NAME READY STATUS RESTARTS AGE
pod-secret-via-env 1/1 Running 0 6s
pod-secret-via-file 1/1 Running 0 5m55s
controlplane:~$ kubectl exec -it pod-secret-via-env -- /bin/bash
root@pod-secret-via-env:/data# env | grep CONFIDENTIAL
CONFIDENTIAL=bob
root@master:~/configMap# kubectl create secret generic soyun-secret --from-literal=INTERVAL=2 --from-file=./genid-web-config/
secret/soyun-secret created
root@master:~/configMap# kubectl get secrets
NAME TYPE DATA AGE
soyun-secret Opaque 2 10s #Opaque는 사용자 정의 secret
# default-token- # (K8S가 내부적으로 사용) default라는 service account로 사용되는 것
[master ~/secret]$ kubectl describe secret soyun-secret
Name: soyun-secret
Namespace: default
Labels: <none>
Annotations: <none>
Type: Opaque
Data
====
INTERVAL: 1 bytes
nginx-config.conf: 218 bytes # --from-file=
[ 실습 ] env로 Secret 데이터 전달
ex 1)
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: my-container
image: nginx
env:
- name: USERNAME
valueFrom:
secretKeyRef:
name: my-secret
key: username
# Secret의 username 값을 환경 변수 USERNAME으로 전달.
ex 2)
root@master:~/configMap# cat genid-env-secret.yaml
apiVersion: v1
kind: Pod
metadata:
name: genid-env-secret
spec:
containers:
- image: smlinux/genid:env
env: # 여기
- name: INTERVAL
valueFrom:
secretKeyRef:
name: soyun-secret
key: INTERVAL
name: fakeid-generator
volumeMounts:
- name: html
mountPath: /webdata
- image: nginx:1.14
name: web-server
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
readOnly: true
ports:
- containerPort: 80
volumes:
- name: html
emptyDir: {}
root@master:~/configMap# kubectl create -f genid-env-secret.yaml
pod/genid-env-secret created
root@master:~/configMap# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
genid-env-secret 2/2 Running 0 16s 10.36.0.1 node2.example.com <none> <none>
root@master:~/configMap# curl 10.36.0.1 # 2초마다 fakeid생성되는 것 확인
+------------------------+
| Audrey Rose |
| 47 Buncaneer Dr |
| Minneapolis, MN 55401 |
| (612) xxx-xxxx |
+------------------------+
[ 실습 ] Volume-mount로 전달하기
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: my-container
image: nginx
volumeMounts:
- name: secret-volume
mountPath: /etc/secret # Secret 데이터를 파일 형태로 /etc/secret에 마운트.
readOnly: true
volumes:
- name: secret-volume
secret:
secretName: my-secret
root@master:~/configMap# cat genid-volume-secret.yaml
apiVersion: v1
kind: Pod
metadata:
name: genid-volume-secret
spec:
containers:
- image: smlinux/genid:env
env:
- name: INTERVAL
valueFrom:
secretKeyRef:
name: soyun-secret
key: INTERVAL
name: fakeid-generator
volumeMounts:
- name: html
mountPath: /webdata
- image: nginx:1.14
name: web-server
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
readOnly: true
- name: config
mountPath: /etc/nginx/conf.d
readOnly: true
ports:
- containerPort: 80
volumes:
- name: html
emptyDir: {}
- name: config
secret:
secretName: soyun-secret
items:
- key: nginx-config.conf
path: nginx-config.conf
root@master:~/configMap# kubectl create -f genid-volume-secret.yaml
pod/genid-volume-secret created
root@master:~/configMap# kubectl get pods
NAME READY STATUS RESTARTS AGE
genid-env-secret 2/2 Running 0 10m
genid-volume-secret 2/2 Running 0 10s
# 컨테이너 접속
root@master:~/configMap# kubectl exec -it genid-volume-secret -c web-server -- /bin/bash
root@genid-volume-secret:/# cd /etc/nginx/conf.d/
root@genid-volume-secret:/etc/nginx/conf.d# ls -al
total 4
drwxrwxrwt 3 root root 100 Mar 24 15:10 .
drwxr-xr-x 3 root root 4096 Mar 26 2019 ..
drwxr-xr-x 2 root root 60 Mar 24 15:10 ..2024_03_24_15_10_34.3846287265
lrwxrwxrwx 1 root root 32 Mar 24 15:10 ..data -> ..2024_03_24_15_10_34.3846287265
lrwxrwxrwx 1 root root 24 Mar 24 15:10 nginx-config.conf -> ..data/nginx-config.conf
# 진짜 파일이 아닌 symbolic link로 되어 있다.
root@genid-volume-secret:/etc/nginx/conf.d# cat nginx-config.conf # 애플리케이션 안에서는 디코딩 되어서 TEXT형식으로 보여준다.
server {
listen 80;
server_name www.example.com;
gzip on;
gzip_types text/plain application/xml;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
# 마운트 확인하기
root@genid-volume-secret:/etc/nginx/conf.d# df -h
Filesystem Size Used Avail Use% Mounted on
overlay 20G 9.0G 9.6G 49% /
tmpfs 64M 0 64M 0% /dev
tmpfs 994M 0 994M 0% /sys/fs/cgroup
/dev/sda1 20G 9.0G 9.6G 49% /etc/hosts
shm 64M 0 64M 0% /dev/shm
tmpfs 1.9G 4.0K 1.9G 1% /etc/nginx/conf.d # 이렇게
tmpfs 1.9G 12K 1.9G 1% /run/secrets/kubernetes.io/serviceaccount
tmpfs 994M 0 994M 0% /proc/asound
tmpfs 994M 0 994M 0% /proc/acpi
tmpfs 994M 0 994M 0% /proc/scsi
tmpfs 994M 0 994M 0% /sys/firmware
- 참고 영상 : https://www.youtube.com/watch?v=aW2RAVnOHFY&t=596s
- 참고 자료: https://kubernetes.io/docs/concepts/configuration/secret/
반응형
'Container > Kubernetes' 카테고리의 다른 글
[K8S] Taint & Toleration (0) | 2024.04.12 |
---|---|
[K8S] Affinity & antiAffinity (0) | 2024.03.25 |
[K8S] Canary Deployment (0) | 2024.03.20 |
[K8S] Annotation (0) | 2024.03.17 |
[K8S] Node Label & Selector (0) | 2024.03.17 |