본문 바로가기

Kubenetes/ConfigMap & Secret

Secret (Secret 으로 컨테이너에 민감한 데이터 전달하기)

중요한 정보를 저장하고 분류하기 위해 쿠버네티스는 시크릿이라고 하는 별도의 객체를 제공

Secret은 ConfigMap과 매우 흡사하며 키/값 쌍으로 사용 가능

 

 - 환경 변수로 Secret Entry를 컨테이너에 전달할 수 있음.

 - 볼륨의 파일로서 Secret Entry를 노출할 수 있음

 

쿠버네티스는 시크릿에 액세스해야 하는 Pod를 실행하는 Node에만 배포하도록 하여 안전하게 유지할 수 있다. 또한 Node 자체에서 Secret은 항상 메모리에 저장되고 실제 스토리지에는 기록되지 않으므로 디스크에서 Secret을 삭제한 후 디스크를 완전 삭제해야 한다.

 

Secret과 ConfigMap 사이에서 선택은

 - 민감하지 않은 일반 설정 데이터를 저장할 때 ConfigMap을 사용

 - 본질적으로 민감한 데이터를 저장할 때 시크릿을 사용

 - 설정 파일에 중요한 데이터와 중요하지 않은 데이터가 모두 포함돼 있으면 파일을 시크릿으로 저장해야 함.

 

[기본 토큰 시크릿]

 

모든 포드에는 자동으로 연결된 secret 볼륨이 있다. 

시크릿은 리소스이므로 kubectl get secret 을 사용해 해당 리소스를 나열한다.

$ kubectl get secrets

NAME                           TYPE                                                      DATA     AGE

default-token-cfee9     kubernetes.io/service-account-token   3            39d

 

[시크릿 작성하기]

 

$ kubectl describe secrets

Name:         default-token-cfee9
Namespace:    default
Labels:       <none>
Annotations:  kubernetes.io/service-account.name=default
              kubernetes.io/service-account.uid=cc04bb39-b53f-42010af00237
Type:         kubernetes.io/service-account-token
Data
====
ca.crt:       1139 bytes
namespace:    7 bytes
token:        eyJhbGci0iJSuzI1NiIsInR5cC161kpxvcj9...

 

시크릿에는 세 개의 항목(ca.crt, namespace, token)이 있다.

이 항목은 포드에서 쿠버네티스 API 서버와 안전하게 통신하기 위해 필요한 모든 것을 나타낸다.

 

이상적으로는 애플리케이션이 완전 쿠버네티스 독립적이 되길 원하지만 쿠버네티스와 직접 대화하는 것외에 다른 방법이 없는 경우 secret 볼륨을 통해 제공되는 파일을 사용하게 됨

 

kubectl describe 포드 명령어는 마운트된 secret 볼륨 정보를 보여줌

default-token 시크릿이 자동으로 생성되고 해당 볼륨이 각 포드에 자동으로 마운트된다.

 

[시크릿 생성하기]

 

fortune-serving Nginx 라는 컨테이너를 HTTPS 트래픽을 제공하도록 설정하려고 한다.

이를 위해 인증서와 개인키를 만들어야 하는데 이 인증서를 시크릿에 보관하는 시나리오를 아래와 같이 구성한다.

 

먼저 인증서와 개인키 파일을 생성한다.

 

$ openssl genrsa -out https.key 2048

$ openssl req -new -x509 -key https.key -out https.cert -days 3650 -subj /CN=www.kubia-example.com

 

$ echo bar > foo

 

3개 파일의 시크릿을 생성하기 위해 kubectl create secret 명령어를 사용

$ kubectl create secret generic fortune-https --from-file=https.key --from-file=https.cert --from-file=foo

secret "fortune-https" created

 

ㅁ ConfigMap과 시크릿 비교

 

[시크릿의 YAML 정의]

 

$ kubectl get secret fortune-https -o yaml

apiVersion: v1
data:
   foo: YmFyCg==
   https.cert: LS0tLSDKUFKJLKWERMSFOJElijsKJEORIJ....
   https.key: LS0tLSICRuhdjilkjkljlksjlfaweoiurmk ...
kind: Secret
... 
   

 

[이전에 작성한 ConfigMap의 YAML 정의]

 

$ kubectl get configmap fortune-config -o yaml

apiVersion: v1
data:
   my-nginx-config.conf: |
      server {
        ...
        }
   sleep-interval: |
      25
kind: ConfigMap
...

시크릿의 내용은 Base64로 인코딩된 문자열로 표시하는 반면 ConfigMap의 내용은 일반 텍스트로 표시한다.

 

[바이너리 데이터에 시크릿 사용]

 

Base64 인코딩을 사용하는 이유는 시크릿 항목에는 일반 텍스트뿐만 아니라 이진값이 포함될 수 있다. 따라서 Base64 인코딩을 사용하면 바이너리 데이터를 일반 텍스트 형식인 YAML 또는 JSON에 포함시킬 수 있다.

 

ㅁ 포드에서 시크릿 사용

 

cert와 key 파일을 모두 포함하는 fortune-https 시크릿을 사용하려면 Nginx가 이를 사용하도록 설정해야 한다.

 

[HTTPS를 적용하기 위해 fortun-config ConfigMap 수정]

 

$ kubectl edit configmap fortune-config

...
data:
   my-nginx-config.conf: |
      server {
         listen              80;
         listen              443;
         server_name         www.kubia-example.com;
ssl_certificate              certs/https.cert;
         ssl_certificate_key certs/https.key;
         ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
         ssl_ciphers         HIGH:!aNULL:!MD5;
         location / {
            root   /usr/share/nginx/html;
            index  index/html index.html
         }
      }
   sleep-interval: |
...

이렇게 하면 /etc/nginx/certs에서 인증서와 키 파일을 읽도록 서버가 설정되므로 secret 볼륨을 마운트행 함.

 

[포드에서 fortune-https 시크릿 마운트 하기]

 

fortune-pod-https.yaml

apiVersion: v1
kind: Pod
metadata:
   name: fortune-https
spec:
   containers:
   - image: luksa/fortune:env
     name: html-generator
     env:
     - name: INTERVAL
       valueFrom:
          configMapKeyRef:
             name: fortune-config
             key: sleep-interval
     volumeMounts:
     - name: html
       mountPath: /var/htdocs
   - image: nginx:alpine
     name: web-server
     volumeMounts:
     - name: html
       mountPath: /usr/share/nginx/html
       readOnly: true
     - name: config
       mountPath: /etc/nginx/conf.d
       readOnly: true
     - name: certs                      # /etc/nginx/certs 에서 인증서와
       mountPath: /etc/nginx/certs/     # 키 파일을 읽도록 Nginx를 설정했으므로
       readOnly: true                   # secret 볼륨을 마운트해야 한다.
     ports:
     - containerPort: 80
   - containerPort: 443
     volumes:
     - name: html
       emptyDir: {}
     - name: config
       configMap
         name: fortune-config
         items:
         - key: my-nginx-config.conf
           path: https.conf
     - name: certs                      # 여기서 fortune-https 시크릿을 참조해 
       secret:                          # secret 볼륨을 정의한다.
         secretName: fortune-https

fortune-https 포드를 운영하기 위한 ConfigMap과 시크릿의 결합

 

ConfigMap 볼륨과 마찬가지로, secret 볼륨은 defaultMode 속성을 통해 볼륨에 노출된 파일에 대한 권한을 지정하는 기능도 지원한다.

 

[nginx가 시크릿에서 cert와 key 사용 여부 테스트]

 

포드가 실행되면 포드의 포트 443에 대한 포트 포워드 너털을 열고 이를 통해 curl을 사용해 서버에 요청을 보내 포드가 HTTPS 트래픽을 제공하는지 확인 할 수 있다.

 

$ kubectl port-forward fortune-https 8443:443 &

Forwarding from 127.0.0.1:8443 -> 443

Forwarding from [::1]:8443 -> 443

$ curl https://localhost:8443 -k

 

[메모리에 저장된 secret 볼륨]

 

/etc/nginx/certs의 디렉터리 트리에 secret 볼륨을 마운트하여 인증서와 개인 키를 컨테이너에 성공적으로 전달

secret 볼륨은 시크릿 파일을 위하여 인메모리 파일 시스템(tmpfs)을 사용

 

$ kubectl exec fortune-https -c web-server -- mount | grep certs

tmpfs on /etc/nginx/certs type tmpfs (ro, relatime)

 

[환경 변수로 시크릿의 엔트리 노출]

 

볼륨을 사용하는 대신 ConfigMapdptj sleep-interval을 사용해 수행한 것과 마찬가지로 환경 변수로 시크릿 엔트리의 개별 엔트리를 노출할 수 있다.

시크릿의 foo 키를 환경 변수 FOO_SECRET으로 노출하려면

env:
- name: FOO_SECRET
  valueFrom:                 
    secretKeyRef:           # 변수는 시크릿의 항목에 맞춰져야 한다.
      name: fortune-https   # 키를 보유하고 있는 시크릿의 이름
      key: foo              # 노출해야 할 시크릿의 키

이것은 ConfigMap을 참조하는데 사용되는 configMapKeyRef 대신 secretKeyRef를 사용해 시크릿을 참조하는 것을 제외하고는 INTERVAL 환경 변수를 설정할 때와 거의 비슷하게 사용

 

ㅁ 이미지 풀 시크릿

 

개인 리포지토리 스토리지의 이미지를 사용하는 포드를 실행하려면 다음 두 가지 작업을 수행해야 한다. 

 ㅇ 도커 레지스트리에 대한 자격 증명이 있는 시크릿을 만든다.

 ㅇ 포드 매니페스트의 imagePullSecrets 필드에서 ㅅ ㅣ크릿을 참조하라.

 

[도커 레지스트리 인증을 위한 시크릿 생성]

 

$ kubectl create secret docker-registry mydockerhubsecret \

   --docker-username=myusername --docker-password=mypassword \

   --docker-email=my.email@provider.com

 

generic 시크릿을 작성하는 대신 mydockerhubsecret이라는 docker-registry 시크릿을 작성

도커 허브 사용자 이름, 비밀번호, 이메일을 지정

kubectl describe로 새로 생성된 시크릿의 내용을 검사하면 .dockercfg라는 단일 항목이 포함돼 있음을 알 수 있다.

 

[포드 정의에서 도커 레지스트리 시크릿 사용]

 

pod-with-private-image.yaml

apiVersion: v1
kind: Pod
metadata:
   name: private-pod
spec:
   imagePullSecrets:
   - name: mydockerhubsecret
   conatiners:
   - image: username/private:tag
     name: main

'Kubenetes > ConfigMap & Secret' 카테고리의 다른 글

Configmap  (0) 2021.02.04