본문 바로가기
클라우드/Kubernetes

쿠버네티스 Secret

by Cloud_Park 2020. 1. 28.

Secret

 configMap  일반적인 환경 설정이나 CONFIG정보를 저장하도록 디자인 되었다면 보인이 중요한 패스워드나 API키 인증서 파일들은 Secret에 저장할 수 있다. Secret은 안에  저장된 내용을 지키기 위하여

추가적인  보안기능을 제공한다. 

 secret의 값들은 etcd에 저장될때 암호화 된 형태로 저장되고 API server나 node의 파일에는 저장되지 않고 항상 메모리에 저장되어 있기 때문에 상대적으로 접근이 어렵다.

하나의 secret의 사이즈는 최대  1M까지 지원되는데, 메모리에 지원되는 특성 때문에 secret을 여러개 저장하게 되면 APIserver나  노드에서 이를 저장하는 kubelet의 메모리 사용량이 늘어나서 out of memory와 같은

이슈가 발생할 수 있다. 그래서 보안적으로  꼭 필요한 정보만 secret에 저장하도록 한다.

 

 사용방법에 있어서 secret와 configmap은 기본적으로 거의 유사하다. 기본적으로 key /value 형태의 저장구조를 가지고 잇으면 사용시 환경변수를 통해서 pod에 그값을 전달하거나  또는 디스크 볼륨으로 마운트가 가능한데 secret은 정의하는 방법이 차이가 있다.

language를 java로 저장할떄  configmap은  language: java식으로 일반 문자 즉 java를 base64로 한다면  amf2yQo=이 된다.

문자열 base64포맷으로  인코딩 하려면 맥이나 리눅스에서 다음과 같은 명령을 이용하면된다,

 

 

hello-secret.yaml 파일

apiVersion: v1
kind: Secret
metadata:
 name: hello-secret
data:
 language: amF2YQo=

 secret에 저장되는 내용은 패스워드와 같은 단순 문자열의 경우에는 바로 저장이 가능하지만 ssl인증서와 같은 바이너리 파일의 경우에는 문자열로 저장이 불가능하다 그래서 이러한 바이너리 파일저장을 지원하기 위해서 secret의 경우에는 저장되는 값을 base64로 인코딩하여 저장한다.

 

어플리케이션 예제

var os = require('os');

var http = require('http');

var handleRequest = function(request, response) {

 response.writeHead(200);

 response.end(" my prefered secret language is "+process.env.LANGUAGE+ "\n");

 //log

 console.log("["+

Date(Date.now()).toLocaleString()+

"] "+os.hostname());

}

var www = http.createServer(handleRequest);

www.listen(8080);

 

 

 

  이 코드는 LANGUAGE라는 환경 변수에서 값을 읽어서 출력하는 코드이다. (앞의 configmap 코드와 동일)

이 파일을 도커 컨테이너 이미지로 만든후에 gcr.io/terrycho-sandbox/hello-secret:v1 이름으로 등록한 후에, 아래와 같이 Deployment 코드를 작성해보자

 

hello-secret-literal-deployment.yaml 파일

 

apiVersion: apps/v1beta2

kind: Deployment

metadata:

 name: hello-secret-deployment

spec:

 replicas: 3

 minReadySeconds: 5

 selector:

   matchLabels:

     app: hello-secret-literal

 template:

   metadata:

     name: hello-secret-literal-pod

     labels:

       app: hello-secret-literal

   spec:

     containers:

     - name: cm

       image: gcr.io/terrycho-sandbox/hello-secret:v1

       imagePullPolicy: Always

       ports:

       - containerPort: 8080

       env:

       - name: LANGUAGE

         valueFrom:

           secretKeyRef:

              name: hello-secret

              key: language

 Deployment 파일은 configMap과 크게 다를 것이 없다. configMapKeyRef를 secrectKeyRef로 변경하였고, configMap과 마찬가지로 secret의 이름(hello-secret)을 정하고, 키 이름 (language)을 지정하였다. Deployment를 배포한후에, 서비스를 배포해서 웹으로 접속하면 아래와 같이 secret에 base64로 저장된 “java”라는 문자열이 디코딩되서 출력되는 것을 확인할 수 있다.

https://bcho.tistory.com/1268

 

파일로 마운트 하기

 secret도 configMap과 마찬가지로, 설정 값들을 환경변수 뿐만 아니라, 파일로도 넘길 수 있다. 환경변수로 넘기는 방법과 마찬가지로 파일을 base64로 인코딩해서 secret을 생성해야 하며, 인코딩된 secret을 Pod에 파일로 마운트될때는 디코딩된 상태로 마운트가 된다.

 

이번에는 secret을 파일에서 부터 만들어보자 사용자 ID를 저장한 user.property 파일과, 비밀 번호를 저장한 password.property 파일 두개가 있다고 하자.각 파일의 내용은 다음과 같다.

https://bcho.tistory.com/1268

이 두개의 파일을 secret에 저장을 할것이다. 명령은 다음과 같다.

 

kubectl create secret generic db-password --from-file=./user.property  --from-file=./password.property

 db-password라는 secret을 생성하고, user.property, password.property에서 secret을 생성하게 된다. 생성된 secret은 user.property, password.property라는 파일명을 각각 키로하여 파일의 내용이 저장된다.

이때 파일을 통해서 secret을 만들경우에는 별도로 base64 인코딩을 하지 않더라도 자동으로 base64로 인코딩 되어 저장된다.

 

 위의 명령을 보면 kubectl create secret 명령어 뒤에 generic 이라는 키워드를 붙였는데, 이는 secret을 generic이라는 타입으로 생성하기 위함이다. secret의 타입에 대해서는 뒤에서 설명하도록 한다.

 

 이렇게 생성된 secret을 확인해보면 아래와 같이 user.property, password.property 두개의 키로 데이타를 저장하고 있는 것을 확인할 수 있다.

 

kubectl describe secret db-password 

 

https://bcho.tistory.com/1268

 시크릿을 디스크로 마운트해서 읽는 것을 테스트해보기 위해서 간단하게 node.js로 server.js 라는 코드를 아래와 같이 작성한다. 아래 코드는 /tmp/db-password 디렉토리에서 user.property와 password.property 파일을 읽어서 화면에 출력하는 코드이다.

 

var os = require('os');

var fs = require('fs');

var http = require('http');




var handleRequest = function(request, response) {

 fs.readFile('/tmp/db-password/user.property',function(err,userid){

   response.writeHead(200);

   response.write("user id  is "+userid+" \n");

   fs.readFile('/tmp/db-password/password.property',function(err,password){

     response.end(" password is "+password+ "\n");

   })

 })




 //log

 console.log("["+

Date(Date.now()).toLocaleString()+

"] "+os.hostname());

}

var www = http.createServer(handleRequest);

www.listen(8080);

 

 

 

 다음 이 코드에서 user.property와 password.property 를 /tmp/db-password 디렉토리에서 읽어올 수 있도록, 앞에서 만든 db-password 라는 시크릿을 /tmp/db-password  디렉토리에 마운트 하도록 deployment를 정의한다.

 

 

hello-secret-file-deployment.yaml

apiVersion: apps/v1beta2

kind: Deployment

metadata:

 name: hello-serect-file-deployment

spec:

 replicas: 3

 minReadySeconds: 5

 selector:

   matchLabels:

     app: hello-secret-file

 template:

   metadata:

     name: hello-secret-file

     labels:

       app: hello-secret-file

   spec:

     containers:

     - name: hello-secret-file

       image: gcr.io/terrycho-sandbox/hello-secret-file:v1

       imagePullPolicy: Always

       ports:

       - containerPort: 8080

       volumeMounts:

         - name: db-password

           mountPath: "/tmp/db-password"

           readOnly: true

     volumes:

     - name: db-password

       secret:

         secretName: db-password

         defaultMode: 0600

 configMap과 차이가 거의 없다.  configMap이 secret으로만 바뀐건데, 이번에는 마운트 되는 파일의 퍼미션을 지정하였다. (configMap도 지정이 가능하다.) defaultMode로 파일의 퍼미션을 정의해놓으면, 파일 생성시, 해당 퍼미션으로 파일이 생성된다. 여기서는 0600으로 정의했기 때문에, rw-------으로 파일이 생성될것이다. 만약에 퍼미션을 지정하지 않았을 경우에는 디폴트로 0644 퍼미션으로 파일이 생성된다.

 

위의 스크립트로 생성한 Pod에 SSH로 들어가 보면 아래와 같이 /tmp/db-password에 user.property파일과 password.property 파일이 생성된것을 확인할 수 있다.

 

https://bcho.tistory.com/1268

그런데 파일 퍼미션을 보면 우리가 지정한 0600이 아닌데, 잘 보면 user.property와 password.property는 링크로 ..data/user.property 와  ..data/password.property 파일로 연결이 되어 있다.

 

 

https://bcho.tistory.com/1268

 

 

 

위 자료는 조대협블로그를 참고했습니다.

https://bcho.tistory.com/1268

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

Minikube 설치하기 1 (kubectl 설치) 우분투  (0) 2020.02.05
쿠버네티스 모니터링  (0) 2020.02.04
쿠버네티스 configMap  (0) 2020.01.16
쿠버네티스 Healthcheck  (0) 2020.01.13
쿠버네티스 Ingress  (0) 2020.01.13