이쿠의 슬기로운 개발생활

함께 성장하기 위한 보안 개발자 EverNote 내용 공유

클라우드/Kubernetes

11. Kubernetes Secret

이쿠우우 2020. 8. 17. 20:34
반응형

Kubernetes Secret

 

 

참고) 실습환경

 

[Master Node server]

OS = CentOS 7

리눅스 커널 버전 : Linux 3.10.0-1062.el7.x86_64

docker version : 1.13.1

docker api verison : 1.26

 

[Worker Node server]

OS = CentOS 7

리눅스 커널 버전 : Linux 3.10.0-1062.el7.x86_64

docker version : 1.13.1

docker api verison : 1.26

 

[Kubernetes version]

1.18

 


 

 

 

1. Kubernetes Secret Object 란?

보안유지가 필요한 자격증명 및 개인 암호화 키( Password, API Key, ssh Key 등등 ) 같은 

중요한 정보를 저장하기 위해 사용함.

이런 정보들은 컨테이너 안에 저장해두지 않고 별도로 보관해 두었다가

실제 Pod 가 실행될때 설정을 통해서 Container에 제공.

kubernetes ConfigMap Object 와 사용법이 비슷하지만 

좀 더 보안이 중요한 만큼 세분화된 사용법을 제공.

 

 

1.1. Secret 은 항상 메모리에 저장

Secret은 안에 저장된 내용을 지키기 위해서 추가적인 보안 기능을 제공.

MasterNode Server Or WorkerNode Server에 파일 형태로 저장되지 않고

항상 메모리에 저장되어 있어서 상대적으로 접근이 어려움.

 

하나의 Secret Object 는 최대 1M까지 지원 가능한데

메모리에 올라가는 특성으로 인해,

Secret을 여러개 저장하게 되면 MasterNode Server Or WorkerNode Server에서

이를 저장하는 kubelet의 메모리 사용량이 늘어나

Out Of Memory와 같은 이슈를 유발할 수 있기 때문에,

보안적으로 꼭 필요한 정보만 secret에 저장하도록 하는 게 좋다.

 

1.2. Secret 의 Key-Value에서 Value는 항상 Base64 포맷

[ ConfigMap Object 의 경우 ]

Key-Value 저장 시 

예로 "test: version1" 과 같은 형식으로 저장되는데

 

[ Secret Object 의 경우 ]

Key-Value 저장 시 

"test: dmVyc2lvbjE=" 과 같이 value 값을 base64 encoding 해서 저장해야 함

 

[ base64는 단순 인코딩이지 암호화가 아닌데 왜 base64로 인코딩을 하는 것일까? ]

secret에 저장되는 내용은 패스워드와 같은 단순 문자열의 경우에는

바로 저장이 가능 하지만,

SSL 인증서와 같은 바이너리 파일의 경우에는 문자열로 저장이 불가능함

그래서 이러한 바이너리 파일 저장을 지원하기 위해서

secret의 경우에는 저장되는 값을 base64로 인코딩을 하여 저장하도록 되어 있음

 

[ 시크릿 데이터는 etcd에 암호화되지 않은 평문으로 저장됨. ]

그래서 누군가 etcd에 직접 접근한다면 시크릿의 내용을 확인할 수 있음

 

base64로 인코딩이 되어 있지만 이를 환경변수로 넘길 때나

디스크 볼륨으로 마운트 해서 읽을 경우에는 디코딩이 돼서 확인 가능함

 

 

1.3. Secret 종류

[ Built in Secret ]

Built in Secret (내장 Secret)

클러스터 내부에서 API 이용 시 사용됨

내부에서 사용되는 계정인 Service account를 생성하면 자동으로 secret 생성

만들어진 secret으로 해당 service account가 권한을 가지고 있는 API 접근 가능

Service Account 란?
클라이언트가 쿠버네티스 API를 호출하거나,
콘솔이나 기타 클라이언트가 쿠버네티스 API를 접근하고자 할 때,
이는 실제 사람인 사용자가 아니라 시스템이 됨.
그래서, 쿠버네티스에서는 이를 일반 사용자와 분리해서 관리하는데
이를 Service Account라고 함

 

[ Creating your own Secret ]

사용자 정의 Secret

말 그대로 사용자가 정의한 시크릿

create 명령어를 사용하여 생성할 수 있고, yaml 파일에 정의해서 생성할 수도 있음

 

 


 

 

 

2. Secret을 환경변수로 전달

2.1. Secret 설정 중 일부만 전달

Secret 전체 data 중 선택한 일부만 가져와서 적용

 

[ Secret.yaml 파일 예제 ]

ConfigMap 설정과 매우 동일하지만

value 값이 base64 encoding 된 차이점만 있음

apiVersion: v1

kind: Secret

metadata:

  name: iksoon-secret-test

data:

# data 하위에 전달할 Key-Value를 명시

  K8S_VERSION_TEST: "a3ViZXJuZXRlc192ZXJzaW9uX3Rlc3Qx"  

# Key : K8S_CONFIGMAP_TEST, Value : Kubernetes_configMap_1 을 base64 encofing

  K8S_CONFIGMAP_TEST: "S3ViZXJuZXRlc19jb25maWdNYXBfMQ==" 

# Key :K8S_TEST, Value :iksoon_TEST_1 을 base64 encofing

  K8S_TEST: "aWtzb29uX1RFU1RfMQ=="               

kubectl apply -f secret.yaml 

생성 후 결과 확인

kubectl describe secret

 

[ 결과 ]

secret에 사용된 token과

key는 확인할 수 있지만

value는 숨겨져 있음

 

 

[ deployment.yaml 파일 예제 ]

apiVersion: apps/v1

kind: Deployment

metadata:

  name: iksoon-deployment

  labels:

    app: iksoon-tomcat

spec:

  replicas: 1

  selector:

    matchLabels:

      app: iksoon-pod

  template:

    metadata:

      labels:

        app: iksoon-pod

    spec:

      containers:

      - name: iksoon-tomcat

        image: peksoon/iksoon_tomcat:1.0.4

        ports:

        - containerPort: 8080

        env:                                    env : 항목을 추가해서 secret 설정을 적용함

        - name: VERSION_TEST          # - name : 해당 Pod에 적용될 환경변수 이름 

                                                 #             (만들어진 Pod의 환경변수 조회 시 해당 이름이 있음)

          valueFrom:                        # valueFrom : name에서 명시한 환경변수에 올 값을 설정함

            secretKeyRef:                   # secretKeyRef : 불러올 Secret과 key를 명시함

              name: iksoon-secret-test name: 항목에 secret 파일의 metadata:  name 이 들어가야 함

              key: K8S_VERSION_TEST  # key : 항목에 secret에 설정되어있는 data의 key 이름이 들어가야 함

        - name: K8S_CONFIGMAP       # - name을 추가해서 다수의 환경변수를 설정할 수 있음

          valueFrom:

            secretKeyRef:

              name: iksoon-secret-test

              key: K8S_CONFIGMAP_TEST

        - name: TEST_IKSOON

          valueFrom:

            secretKeyRef:

              name: iksoon-secret-test

              key: K8S_TEST

 

 

---

apiVersion: v1

kind: Service

metadata:

  name: iksoon-service

spec:

  ports:

  - port: 8080

    targetPort: 8080

  selector:

    app: iksoon-pod

 

[ 결과 ]

VERSION_TEST, K8S_CONFIGMAP 환경 변수 값에 secret에서 설정한 값이 들어갔음을 확인 가능

page 접속해서 확인하는 방법 이외에 pod의 container에 접속해서 env 명령으로도 확인 가능

 

 

 

2.2. Secret 설정 모두 전달

Secret 전체 data를 한꺼번에 가져와서 사용하는 방법

 

 

[ Secret.yaml 파일 예제 ]

apiVersion: v1

kind: Secret

metadata:

  name: iksoon-configmap-test

data:

  K8S_VERSION_TEST: "a3ViZXJuZXRlc192ZXJzaW9uX3Rlc3Qx"  

  K8S_CONFIGMAP_TEST: "S3ViZXJuZXRlc19jb25maWdNYXBfMQ=="

  K8S_TEST: "aWtzb29uX1RFU1RfMQ=="     

 

[ deployment.yaml 파일 예제 ]

apiVersion: apps/v1

kind: Deployment

metadata:

  name: iksoon-deployment

  labels:

    app: iksoon-tomcat

spec:

  replicas: 1

  selector:

    matchLabels:

      app: iksoon-pod

  template:

    metadata:

      labels:

        app: iksoon-pod

    spec:

      containers:

      - name: iksoon-tomcat

        image: peksoon/iksoon_tomcat:1.0.4

        ports:

        - containerPort: 8080

        envFrom:                        envFrom : 항목을 추가해서 configmap 설정을 적용함 

                                            #           configmap 설정 중 일부의 경우 env였는데 전체 적용은 envFrom을 사용

        - secretRef:                     # secret : 불러올 secret을 명시함  

            name: iksoon-secret-test   # name: 항목에 secret 파일의 metadata:  name 이 들어가야 함

 

 

---

apiVersion: v1

kind: Service

metadata:

  name: iksoon-service

spec:

  ports:

  - port: 8080

    targetPort: 8080

  selector:

    app: iksoon-pod

 

 

[ 결과 ]

VERSION_TEST, K8S_CONFIGMAP, K8S_TEST 환경 변수 값에 Secrect에서 설정한 값이 들어갔음을 확인 가능

page 접속해서 확인하는 방법 이외에 pod의 container에 접속해서 env 명령으로도 확인 가능

 

 


 

 

 

3. Secret을 File 형태로 전달

File의 내용을 환경변수 형태로 Deployment에 전달하는 방법.

 

[ testVersion.properties 파일 예제 ]

  kubernetes_version_test1

 

[ testConfigmap.proerties 파일 예제 ]

  Kubernetes_configMap_1

 

 

3.1. File로 Secret 생성해서 Deployment에 전달

상위에서 생성한 testKeyValue.proerites 파일로

configMap을 생성한 후 

해당 configMap을 deployment에 전달하는 방법

 

[ Secret 생성 명령어 ]

kubectl create secret generic iksoon-secret-test --from-file=./testVersion.properties --from-file=./testConfigmap.properties

 

name이 iksoon-secret-test 인 secret를 생성

참고) File 추가 시 --from-file 설정을 뒤에 추가하면 됨

 

예) kubectl create secret iksoon-configmap-test --from-file=./testKeyValue1.proerites --from-file=./testKeyValue2.proerites

 

[ Secret 생성 결과 ]

아래의 내용을 보면

Key : 파일명으로 생성되고 describe 명령으로 확인 가능

Value : 파일 내용이 저장되지만 확인이 불가능함

로 secret이 생성되는 것을 확인할 수 있음

 

 

 

 

 

[ deployment.yaml 파일 예제 ]

apiVersion: apps/v1

kind: Deployment

metadata:

  name: iksoon-deployment

  labels:

    app: iksoon-tomcat

spec:

  replicas: 1

  selector:

    matchLabels:

      app: iksoon-pod

  template:

    metadata:

      labels:

        app: iksoon-pod

    spec:

      containers:

      - name: iksoon-tomcat

        image: peksoon/iksoon_tomcat:1.0.4

        ports:

        - containerPort: 8080

        envFrom:                        envFrom : 항목을 추가해서 secret 설정을 적용함 

                                            #                secret 설정 중 일부의 경우 env였는데 전체 적용은 envFrom을 사용

        - secretRef:                    # secretRef : 불러올 secret을 명시함  

            name: iksoon-secret-testname: 항목에 secret 파일의 metadata:  name 이 들어가야 함

 

 

---

apiVersion: v1

kind: Service

metadata:

  name: iksoon-service

spec:

  ports:

  - port: 8080

    targetPort: 8080

  selector:

    app: iksoon-pod

 

 

[ 결과 ]

testVersion.proerites, testConfigmap.proerites 환경 변수를 확인할 수 있음

Secret 이름에서

Key가 testVersion.proerites, testConfigmap.proerites (파일명) 인 값을 가져와서

환경변수로 저장하는 것을 확인할 수 있음

 

[ 주의 ]

설정된 환경변수에 파일내용이 모두 포함됨

파일 내용이 key-value 형태로 저장되어 있더라도

개행을 구분하여 key-value 형식으로 인식하는 것이 아니라

파일 전체 내용을 하나의 문자열로 처리하여

각각 testVersion.proerites, testConfigmap.proerites 에 저장함.

 

 


 

 

 

4. Secret Volume Object로 전달

Secret 정보를 Volume Object 형식으로 Pod의 디스크 Volume으로 마운트 해서

Container에 파일 형대로 제공해 주는 것도 가능함

 

4.1. Secret 설정 모두 전달

Secret 전체 data 모두를 Volume으로 가져옴

 

[ Secret.yaml 파일 예제 ]

apiVersion: v1

kind: Secret

metadata:

  name: iksoon-secret-test

data:

  K8S_VERSION: "a3ViZXJuZXRlc192ZXJzaW9uX3Rlc3Qx"  

  K8S_CONFIGMAP: "S3ViZXJuZXRlc19jb25maWdNYXBfMQ=="

  K8S_TEST: "aWtzb29uX1RFU1RfMQ==" 

 

[ deployment.yaml 파일 예제 ]

apiVersion: apps/v1

kind: Deployment

metadata:

  name: iksoon-deployment

  labels:

    app: iksoon-tomcat

spec:

  replicas: 1

  selector:

    matchLabels:

      app: iksoon-pod

  template:

    metadata:

      labels:

        app: iksoon-pod

    spec:

      containers:

      - name: iksoon-tomcat

        image: peksoon/iksoon_tomcat:1.0.4

        ports:

        - containerPort: 8080

        volumeMounts:                           # pod 에 mount 할 voloume을 설정함

        - name: iksoon-volume                 # name이 iksoon-volume인 volume을 mount 함.

          mountPath: /iksoon/SecretTest    # mount할 경로 설정

      volumes:                                 # volume 설정

      - name: iksoon-volume              # volume name은 iksoon-volume으로 함

        secret:                                  # volume에 Secret 내용을 적용함

          secretName: iksoon-secret-test       # name: 항목에 Secret 파일의 metadata:name 이 들어가야 함

 

 

---

apiVersion: v1

kind: Service

metadata:

  name: iksoon-service

spec:

  ports:

  - port: 8080

    targetPort: 8080

  selector:

    app: iksoon-pod

 

 

[ 결과 ]

pod로 들어가서 확인.

volume이 mount 된 /iksoon/SecretTest 로 이동해보면

아래와 같이 파일을 확인할 수 있음

key : 파일이 되어있음

value : 파일의 내용이 되어있음 (평문으로 저장되어 있음)

 

 

4.2. Secret 설정 중 일부만 전달

ConfigMap 전체 data 중 선택한 일부만 Volume으로 가져옴

 

[ secret.yaml 파일 예제 ]

apiVersion: v1

kind: Secret

metadata:

  name: iksoon-secret-test

data:

  K8S_VERSION: "kubernetes_version_test1"       # data 하위에 전달할 Key-Value 를 명시

  K8S_CONFIGMAP: "Kubernetes_configMap_1"  # Key : K8S_CONFIGMAP_TEST, Value : Kubernetes_configMap_1

  K8S_TEST: "iksoon_TEST_1"                          # Key :K8S_TEST, Value :iksoon_TEST_1

 

[ deployment.yaml 파일 예제 ]

apiVersion: apps/v1

kind: Deployment

metadata:

  name: iksoon-deployment

  labels:

    app: iksoon-tomcat

spec:

  replicas: 1

  selector:

    matchLabels:

      app: iksoon-pod

  template:

    metadata:

      labels:

        app: iksoon-pod

    spec:

      containers:

      - name: iksoon-tomcat

        image: peksoon/iksoon_tomcat:1.0.4

        ports:

        - containerPort: 8080

        volumeMounts:                           # pod에 mount 할 voloume을 설정함

        - name: iksoon-volume                # name이 iksoon-volume인 volume을 mount 함.

          mountPath: /iksoon/SecretTest    # mount 할 경로 설정

      volumes:                                 # volume 설정

      - name: iksoon-volume              # volume name은 iksoon-volume으로 함

        secret:                                   # volume에 Secret 내용을 적용함

          secretName: iksoon-secret-test  # name: 항목에 Secret 파일의 metadata:name 이 들어가야 함

          items:                                 # Secret의 data 항목 중에 가져올 key를 선정함 

          - key: K8S_VERSION              # Secret에 포함되어있는 Key

            path: Iksoon_K8S_VERSION   # Volume에 저장되는 파일 이름

          - key: K8S_CONFIGMAP         # Secret에 포함되어있는 Key

            path: Iksoon_K8S_CONFIGMAP # Volume에 저장되는 파일 이름

 

---

apiVersion: v1

kind: Service

metadata:

  name: iksoon-service

spec:

  ports:

  - port: 8080

    targetPort: 8080

  selector:

    app: iksoon-pod

 

 

[ 결과 ]

pod로 들어가서 확인.

volume이 mount 된 /iksoon/ConfigMapTest로 이동해보면

아래와 같이 items에서 추가한 

Iksoon_K8S_CONFIGMAP, Iksoon_K8S_VERSION 2개의 파일만 확인할 수 있음

key : 파일이 되어있음

value : 파일의 내용이 되어있음

[ 추가 참고 옵션 ]

volumeMounts: 옵션

 

[ subPath ] 

Container에서 Volume을 Mount 하는 방식으로 접근할 때 발생하는 문제로

Mount 할 지점에 기존에 파일이 있을 경우가 있음

Mount가 되면 해당 Volume을 볼 수 있지만 그렇다면 기존 파일들은 어떻게 되는 것일까?

리눅스에서는 보통 파일이 사라지는 것이 아니라 

숨겨진 파일로 살아만 있음.

(즉, 숨겨지는 것뿐만 아니라 접근이 되지 않음.)

때문에 k8s에서는 Mount를 할 때 이를 회피할 수 있는 옵션인 subPath 옵션이 존재함

 

[ defaultMode: 6600 ]

접근 권한과 관련하여 ConfigMap은 Volume을 생성할 때 Permission을 부여

기본적으로는 644 권한을 가지고 있지만

defaultMode를 통해 접근 권한이 있는 리소스(사용자, 그룹 등)만 접근할 수 있음.

 

 


 

 

 

5. Secret을 사용한 Private Registry Container image Pull

일반적으로 Container Image를 Pull 할 때는 대부분 공개되어 있는 Public 이미지를 사용함.

  • 대표적으로 Docker Hub와 같은 Site.

하지만 사설(Private) 이미지를 이용할 때는 인증 정보가 필요함.

Kubernetes는 Docker Private Registry에 접근할 수 있음

사용자 정보를 Secret으로 저장하여 사용할 수 있음

 

5.1. Docker와 kubernetes의 Private Registry에 접근하기 위한 방법 차이

[ docker 환경에서 Private Registry 에 접근하는 방법 ]

docker login

 

[ Kubernetes 환경에서 Private Registry 에 접근하는 방법 ]

docker login 명령 대신 Private Registry의 인증 정보를 저장하는 Secret을 생성해야 함 

 

5.2. Docker login 성공 시 생성되는 config.json 파일을 사용해서 Secret 생성하기

5.2.1. 설정을 하지 않은 상태에서 docker private registry로부터 image pull 해보기

docker private registry에 저장되어 있는 image 확인

참고) server.crt 는 docker private registry Server에서 

[ iksoon_centos 이미지를 받아오는 deployment 예제 ]

apiVersion: apps/v1

kind: Deployment

metadata:

  name: iksoon-deployment

  labels:

    app: iksoon-tomcat

spec:

  replicas: 1

  selector:

    matchLabels:

      app: iksoon-pod

  template:

    metadata:

      labels:

        app: iksoon-pod

    spec:

      containers:

      - name: iksoon-tomcat

        image: 10.0.2.5:5000/peksoon_tomcat_test   # docker private registry에 저장되어있는 images

        ports:

        - containerPort: 8080

      imagePullSecrets:                # 해당 images를 받아올 때 사용할 secret ojbect 설정

      - name: iksoon-secret-test    # 이 설정을 하지 않으면 images를 받아오지 못함

 

 

---

apiVersion: v1

kind: Service

metadata:

  name: iksoon-service

spec:

  ports:

  - port: 8080

    targetPort: 8080

  selector:

    app: iksoon-pod

상위 deployment를 생성하면

ErrImagePull 이 발생하며 pod 가 생성이 안됨

image를 pull 해오지 못하기 때문.

kubernetes에 해당 이미지를 받아오기 위해 secret을 생성해줘야 함

 

5.2.2. docker login 전에는 config.json 파일이 존재하지 않음

config.json 파일 찾기 : 

 cd ~/.docker

 

5.2.3. docker login 해서 config.json 파일 생성

docker login 10.0.2.5:5000 

참고) 10.0.2.5:5000  : docker private registry 주소

주의) : docker private registry에서 생성한 인증서의 도메인과 일치해야 함

 

명령 이후에 config.json 파일 확인 가능

vi ~/.docker/config.json

 

5.2.4. Config.json 파일을 사용해서 Kubernetes Secret 생성

[ 명령어 ]

kubectl create secret generic iksoon-secret-test --from-file=.dockerconfigjson=/root/.docker/config.json --type=kubernetes.io/dockerconfigjson

 

[ 참고 ]

--from-file=.dockerconfigjson=/root/.docker/config.json

상위 docker login 명령으로 생성한 config.json의 경로

 

[ Yaml 형식 ]

.dockerconfigjson 설정에 들어갈 내용

cat ~/.docker/config.json | base64 

apiVersion: v1

kind: Secret

metadata:

  name: iksoon-secret-test

data:

  #.dockerconfigjson: <base-64-encoded-json-here>

  .dockerconfigjson: ewoJImF1dGhzIjogewoJCSIxMC4wLjIuNTo1MDAwIjogewoJCQkiYXV0aCI6ICJhV3R6YjI5dU9uRjNaWEl4TWpNMCIKCQl9Cgl9Cn0=

type: kubernetes.io/dockerconfigjson

[ Secret 생성 확인 ]

kubectl get secret

kubectl describe secret

kubectl get secret iksoon-secret-test  --output=yaml

5.2.5. Secret 생성 후 다시 deployment 생성해보기

정상적으로 image 받아와서 pods 생성됨

 

 

5.3. ID와 Password를 직접 입력하여 Secret 생성

5.3.1. ID Password 입력 Kubernetes Secret 생성

[ 명령어 ]

kubectl create secret docker-registry iksoon-secret-test --docker-server=10.0.2.5:5000 --docker-username=iksoon --docker-password=qwer1234

 

[ 명령어 참고 ]

kubectl create secret \

docker-registry [secret 이름]\

--docker-server=[사설 레지스트리 주소 (포트 포함) 도메인의 경우 도메인만 입력 ]\

--docker-username=[docker 아이디]\

--docker-password=[docker 비번]

 

5.3.2. Secret 생성 확인

[ 명령어 ]

kubectl get secret

kubectl describe secret

kubectl get secret iksoon-secret-test  --output=yaml

 

결과 : 정상 동작

 

 


 

 

 

참고) web에서 접근해서 확인하기 위한 Test용도 ingress.yaml 예제

apiVersion: extensions/v1beta1

kind: Ingress

metadata:

  name: iksoon-ingress-nginx

  namespace: default

  annotations:

    nginx.ingress.kubernetes.io/rewrite-target: /$2

spec:

  rules:

  - host: iksoon.test.com

    http:

      paths:

      - path: /app1(/|$)(.*)

        backend:

          serviceName: iksoon-service

          servicePort: 8080

 

 

 


제 글을 복사할 시 출처를 명시해주세요.
글에 오타, 오류가 있다면 댓글로 알려주세요! 바로 수정하겠습니다!


 

 

 

 

 

 

 

참고

https://kubernetes.io/docs/concepts/configuration/secret/

https://arisu1000.tistory.com/27844

https://bcho.tistory.com/1268

https://hoony-gunputer.tistory.com/entry/kubernetes-%EB%A6%AC%EC%86%8C%EC%8A%A4%EC%9D%98-%EA%B4%80%EB%A6%AC%EC%99%80-%EC%84%A4%EC%A0%95-Configmap-Secret

 

kubernetse 인증 참고

https://bcho.tistory.com/1272

 

 

 

반응형

'클라우드 > Kubernetes' 카테고리의 다른 글

13. Kubernetes 인증(Authentication) 이론  (0) 2020.08.23
12. Kubernetes Update ( Deployment )  (2) 2020.08.23
10. Kubernetes ConfigMap  (0) 2020.08.17
09. Kubernetes Volume 개념  (0) 2020.08.17
08. Kubernetes Network (Ingress)  (2) 2020.08.12