본문 바로가기

Container/Kubernetes

[K8S] Secret

ConfigMap: 컨테이너 구성 정보를 한 곳에 모아서 관리

Secret: 컨테이너가 사용하는 민감한 데이터(ex: password, auth token, ssh key)와 같은 중요한 정보를 안전하게 저장하기 위한 리소스. 애플리케이션 코드와 민감한 데이터를 분리하고, 보안을 강화할 수 있다.

 

Secrets의 주요 특징

  1. 보안 데이터 저장: 비밀번호, API 토큰, SSH 키와 같은 민감한 데이터를 저장하고 관리
    • 즉, 민감하지 않은 일반 설정파일은 configMap을 사용하고, 민감한 데이터는 secret을 사용한다.
    • 민감한 데이터를 저장할 때 Kubernetes Encryption at Rest를 활성화 권장
  2. Base64 인코딩: 데이터는 Base64로 인코딩되어 저장됩니다. ( base64는 누구나 쉽게 decode할 수 있기 때문에 추가 보안 조치가 필요)
  3. Pod와 통합: Secrets는 환경 변수, 볼륨 마운트, 커맨드라인 인수를 통해 Pod에 전달 가능.
  4. RBAC과 통합: Role-Based Access Control(RBAC)을 통해 접근 권한을 세부적으로 관리 가능.
  5. 변경 가능: Secrets의 데이터를 수정하면 이를 참조하는 Pod에서 즉시 반영 가능.
apiVersion: v1
kind: Secret
metadata:
  name: my-secret
type: Opaque
data:
  username: bXl1c2VybmFtZQ==
  password: cGFzc3dvcmQ=

 

Secrets의 종류

  1. Opaque (기본):
    • 일반적으로 사용되는 Secret 유형. 임의의 키-값 데이터를 저장.
    • 예: API 키, 데이터베이스 비밀번호.
  2. Service Account Token:
    • Kubernetes API와 통신하는 데 사용되는 서비스 계정 토큰.
  3. Docker Registry:
    • Docker 이미지 풀링에 필요한 자격 증명 저장. (예: kubernetes.io/dockerconfigjson 유형)
  4. TLS Secret:
    • TLS 인증서와 키 저장. (예: HTTPS 인증서 및 프라이빗 키)
  • secret 데이터 전달 방법
    • Command-line Argument
    • Environment Variable
    • Volume Mount
Secret 만들기
# kubectl create secret <Available Commands> name [flags] [options]
√ docker-registry
√ generic        # user defined data
√ tls
→ <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/
Type 의미
Opaque 임의의 사용자 정의 데이터
kubernetes.io/service-account-token 서비스 어카운트 토큰
kubernetes.io/dockercfg 직렬화된 ~/.dockercfg 파일
kubernetes.io/dockerconfigjson 직렬화된 ~/.docker/config.json 파일
kubernetes.io/basic-auth 기본 인증을 위한 자격 증명
kubernetes.io/ssh-auth SSH를 위한 자격 증명
kubernetes.io/tls TLS 클라이언트나 서버를 위한 데이터
bootstrap.kubernetes.io/token 부트스트랩 토큰 데이터

 

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


[master ~/secret]$kubectl get secrets soyun-secret -o yaml # base64로 인코딩된 값 확인 가능
apiVersion: v1
data:
  INTERVAL: Mg==
  nginx-config.conf: c2VydmVyIHsKICAgIGxpc3RlbiAgIDgwOwogICAgc2VydmVyX25hbWUgIHd3dy5leGFtcGxlLmNvbTsKCiAgICBnemlwIG9uOwogICAgZ3ppcF90eXBlcyB0ZXh0L3BsYWluIGFwcGxpY2F0aW9uL3htbDsKCiAgICBsb2NhdGlvbiAvIHsKICAgICAgICByb290ICAgL3Vzci9zaGFyZS9uZ2lueC9odG1sOwogICAgICAgIGluZGV4ICBpbmRleC5odG1sIGluZGV4Lmh0bTsKICAgIH0KfQo=
kind: Secret
metadata:
  creationTimestamp: "2024-03-24T14:46:05Z"
  name: soyun-secret
  namespace: default
  resourceVersion: "18637"
  uid: 72be9de1-b595-4e30-8b0c-3a71826b8ace
type: Opaque

 

# Secret 사용하기

정의된 Secret을 Pod의 Container에 전달하는 방법

  • environment variable(env)로 전달
  • Command-line Argument로 전달
  • Volume에 secret을 사용하여 컨테이너 디렉토리에 Mount

 

# env로 Secret 데이터 전달 

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으로 전달.
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

 

# Secret 데이터 용량 제한

  • Secret etcd에 암호화하지 않은 텍스트로 저장되므로, secret value가 커지면 메모리 용량을 많이 사용하게 된다.
  • secret의 최대 크기는 1MB

- 참고 영상 : https://www.youtube.com/watch?v=aW2RAVnOHFY&t=596s

- 참고 자료: https://kubernetes.io/docs/concepts/configuration/secret/

- 참고 영상 :https://www.youtube.com/watch?v=MTnQW9MxnRI

반응형

'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