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-test # name: 항목에 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
kubernetse 인증 참고
'Kubernetes > Kubernetes 이론' 카테고리의 다른 글
Helm (0) | 2020.09.07 |
---|---|
Kubernetes Update (2) | 2020.08.23 |
Kubernetes ConfigMap (0) | 2020.08.17 |
Kubernetes Pod 더 자세히 알아보기 (2) | 2020.08.07 |
Kubernetes 설치 과정 (0) | 2020.08.07 |