[Kubernetes] Secret

pingping·2021년 2월 18일
0

Kubernetes

목록 보기
10/10
post-thumbnail

Secret 개요

  • 비밀번호, OAuth 토큰, SSH 키 같은 민감한 정보들을 저장하는 용도로 사용한다. 이런 정보들은 컨테이너 내부에 저장하지 않고 별도로 보관했다가 실제 파드를 실행할 때 Template으로 컨테이너에 제공하게 된다.

  • Secret : Password, Token or Key와 같은 중요한 Data를 포함하는 Object

Overview

  • Secret을 사용하기 위해서는 Pod가 Secret을 참조해야 하며 아래 3가지 방법으로 사용할 수 있음
    1. 하나 이상의 Container에 Mount된 Volume 내의 파일로써 사용
    2. 컨테이너의 환경 변수로써 사용
    3. 파드의 이미지를 가져올 때 Kubelet에 의해 사용

Secret Type

opaque

  • Default 시크릿 타입이다.
kubectl create secret generic empty-secret

kubectl get secret empty-secret

서비스 어카운트 토큰

  • 서비스 어카운트를 확인하는 토큰을 저장하기 위해서 사용한다.
apiVersion: v1
kind: Secret
metadata:
  name: secret-sa-sample
  annotations:
    kubernetes.io/service-account.name: "sa-name"
type: kubernetes.io/service-account-token
data:
  # 사용자는 불투명 시크릿을 사용하므로 추가적인 키 값 쌍을 포함할 수 있다.
  extra: YmFyCg==

도커 컨피그

  • 이미지에 대한 도커 레지스트리 접속 자격 증명을 저장하기 위한 시크릿을 생성하기 위해 사용

    • kubernetes.io/dockercfg

      data 필드가 base64 포맷으로 인코딩된 ~/.dockercfg 파일의 콘텐츠를 값으로 가지는 .dockercfg 키를 포함하고 있는지 확실히 확인해야 한다.

    • kubernetes.io/dockerconfigjson

      data 필드가 .dockerconfigjson 키를 꼭 포함해야 하며 base64로 인코딩되어야 함

apiVersion: v1
kind: Secret
metadata:
  name: secret-dockercfg
type: kubernetes.io/dockercfg
data:
  .dockercfg: |
        "<base64 encoded ~/.dockercfg file>"
kubectl create secret docker-registry secret-tiger-docker \
	--docker-username=tiger \
	--docker-password=pass113 \
	--docker-email=tiger@acme.com
  • 만약 data 필드로부터 .dockerconfigjson 컨텐츠를 복사해오면, 다음과 같은 유효한 JSON 컨텐츠를 즉석에서 얻게 될 것이다.
{
  "auths": {
    "https://index.docker.io/v1/": {
      "username": "tiger",
      "password": "pass113",
      "email": "tiger@acme.com",
      "auth": "dGlnZXI6cGFzczExMw=="
    }
  }
}

기본 인증 시크릿

  • 기본 인증을 위한 자격 증명을 저장하기 위해 제공된다. 이 시크릿 타입을 사용할 때는 시크릿의 data 필드가 다음의 두 키를 포함해야 한다.

    • username : 인증을 위한 사용자 이름

    • password : 인증을 위한 암호 or 토큰

      ⇒ 두 키에 대한 두 값은 base64로 인코딩된 문자열이다.

      ⇒ stringData를 사용하여 평문 텍스트 컨텐츠를 제공할 수도 있음

apiVersion: v1
kind: Secret
metadata:
  name: secret-basic-auth
type: kubernetes.io/basic-auth
stringData:
  username: admin
  password: t0p-Secret

SSH 인증

  • ssh 인증에 사용되는 데이터를 저장하기 위해 제공된다. 이 시크릿 타입을 사용할 때는 ssh-privatekey 키-값 쌍을 사용할 SSH 자격 증명으로 data 필드에 명시해야 할 것이다.
apiVersion: v1
kind: Secret
metadata:
  name: secret-ssh-auth
type: kubernetes.io/ssh-auth
data:
  # 본 예시를 위해 축약된 데이터임
  ssh-privatekey: |
          MIIEpQIBAAKCAQEAulqb/Y ...

TLS

  • TLS를 위해 사용되는 인증서와 관련된 키를 저장하기 위한 빌트인 시크릿 타입이다.
  • 인그레스 리소스의 TLS Termination에 주로 사용되지만, 다른 리소스나 워크로드에 의해 직접적으로 사용될 수도 있다.
apiVersion: v1
kind: Secret
metadata:
  name: secret-tls
type: kubernetes.io/tls
data:
  # 본 예시를 위해 축약된 데이터임
  tls.crt: |
        MIIC2DCCAcCgAwIBAgIBATANBgkqh ...
  tls.key: |
        MIIEpgIBAAKCAQEA7yn3bRHQ5FHMQ ...
  • CLI 명령
    • 공개 키 인증서는 .pem으로 인코딩 (Base64로 인코딩된 DER 포맷) 되어야 하며 - -key를 위해 주어진 개인키에 맞아야 한다.
    • 개인키는 일반적으로 pem 개인 키 포맷이라고 하는 unencrypted이어야 한다.
kubectl create secret tls web-secret \
	--cert=path/to/cert/file \
	--key=path/to/cert/file

Secret 만들기

[1] 명령 사용하여 Secret 생성

  • kubectl 명령으로 secret 생성
# File 생성
root@instance-1:~# echo -n 'testuser' > ./username.txt
root@instance-1:~# echo -n 'dkagh123!' > ./password.txt

# secret 생성
root@instance-1:~# kubectl create secret generic user-pass-secret --from-file=./username.txt --from-file=./
password.txt 
secret/user-pass-secret created

# 확인
root@instance-1:~# kubectl get secrets user-pass-secret -o yaml
apiVersion: v1
data:
  password.txt: ZGthZ2gxMjMh
  username.txt: dGVzdHVzZXI=
kind: Secret
metadata:
  creationTimestamp: "2021-02-18T11:49:45Z"
  managedFields:
  - apiVersion: v1
    fieldsType: FieldsV1
    fieldsV1:
      f:data:
        .: {}
        f:password.txt: {}
        f:username.txt: {}
      f:type: {}
    manager: kubectl-create
    operation: Update
    time: "2021-02-18T11:49:45Z"
  name: user-pass-secret
  namespace: default
  resourceVersion: "151756"
  uid: 74a627d4-abec-4f62-9ed6-068ca2cc09e1
type: Opaque

## Check
root@instance-1:~# echo ZGthZ2gxMjMh | base64 --decode 
dkagh123!

root@instance-1:~# echo dGVzdHVzZXI= | base64 --decode 
testuser

[2] 템플릿으로 Secret 생성

root@instance-1:~/kubernetes-sample/secret# echo -n testuser | base64
dGVzdHVzZXI=
root@instance-1:~/kubernetes-sample/secret# echo -n dkagh123! | base64
ZGthZ2gxMjMh

# vi user-pass.yaml
apiVersion: v1
kind: Secret
metadata:
  name: user-pass
type: Opaque
data:
  username: dGVzdHVzZXI=
  password: ZGthZ2gxMjMh

root@instance-1:~/kubernetes-sample/secret# kubectl apply -f user-pass.yaml 
secret/user-pass created

root@instance-1:~/kubernetes-sample/secret# kubectl get secrets 
NAME                  TYPE                                  DATA   AGE
default-token-v59hc   kubernetes.io/service-account-token   3      11d
foo-secret            kubernetes.io/tls                     2      3d20h
user-pass             Opaque                                2      5s

Secret 사용하기

  • 시크릿은 데이터 볼륨으로 마운트되거나 파드의 컨테이너에서 사용할 환경 변수로 노출될 수 있다.
  • 또한, 시크릿은 파드에 직접 노출되지 않고, 시스템의 다른 부분에서도 사용할 수 있다. 예를 들어, 시크릿은 시스템의 다른 부분이 사용자를 대신해서 외부 시스템과 상호 작용하는데 사용해야 하는 자격 증명을 보유할 수 있다.

[1] Pod의 환경 변수로 사용

# vi secret-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: secret-env-pod
spec:
  restartPolicy: Never
  containers:
  - name: secret-pod
    image: redis
    **env:
      - name: SECRET_USERNAME
        valueFrom:
          secretKeyRef:
            name: user-pass
            key: username
      - name: SECRET_PASSWORD
        valueFrom:
          secretKeyRef:
            name: user-pass
            key: password**

kubectl apply -f secret-pod.yaml
  • Pod의 내부 컨테이너로 접속 후 환경 변수가 잘 설정되었는지 확인
root@instance-1:~/kubernetes-sample/secret# kubectl exec -it secret-env-pod -- bash
root@secret-env-pod:/data#
root@secret-env-pod:/data# echo $SECRET_USERNAME 
testuser

root@secret-env-pod:/data# echo $SECRET_PASSWORD  
dkagh123!
  • 시크릿 업데이트 후 환경 변수가 자동으로 업데이트 되지 않는다.

    ⇒ 컨테이너가 환경 변수에서 이미 시크릿을 사용하는 경우, 다시 시작하지 않는 한 컨테이너에서 시크릿 업데이트를 볼 수 없다. 시크릿이 변경될 때 재시작을 트리거하는 Third Party 솔루션이 있으니 참고할 것 !

[2] Volume 형식으로 Pod에 secret 제공

  • 볼륨 형식을 이용하여 secret을 제공할 때 volumeMounts[ ] 필드와 volumes[ ] 필드를 설정한다.
# vi secret-vol-pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: secret-vol-pod
spec:
  containers:
  - name: secret-vol-pod
    image: redis
    volumeMounts:
    - name: vol-secret
      mountPath: "/etc/foo"
      readOnly: true
  volumes:
  - name: vol-secret
    secret:
      secretName: user-pass
  • Check
root@instance-1:~/kubernetes-sample/secret# kubectl apply -f secret-vol-pod.yaml 
pod/secret-vol-pod created
 
root@instance-1:~/kubernetes-sample/secret# kubectl get pods secret-vol-pod
NAME             READY   STATUS    RESTARTS   AGE
secret-vol-pod   1/1     Running   0          57s

root@instance-1:~/kubernetes-sample/secret# kubectl exec -it secret-vol-pod -- bash

root@secret-vol-pod:/data# cd /etc/foo/ 

root@secret-vol-pod:/etc/foo# ls
password  username

root@secret-vol-pod:/etc/foo# cat username 
testuserroot@secret-vol-pod:/etc/foo# 

root@secret-vol-pod:/etc/foo# cat password 
dkagh123!root@secret-vol-pod:/etc/foo#
  • 특정 경로에 대한 secret 키 삽입
root@instance-1:~/kubernetes-sample/secret# kubectl describe secrets user-pass
Name:         user-pass
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  Opaque

Data
====
password:  9 bytes
username:  8 bytes

# vi secret-vol-pod.yaml 을 수정함
 
apiVersion: v1
kind: Pod
metadata:
  name: secret-vol-pod
spec:
  containers:
  - name: secret-vol-pod
    image: redis
    volumeMounts:
    - name: vol-secret
      mountPath: "/etc/foo"
      readOnly: true
  volumes:
  - name: vol-secret
    secret:
      secretName: user-pass
      items:
      - key: username
        path: my-group/my-username
  • user-pass 시크릿에는 username과 password가 있다.

    ⇒ username 시크릿 : /etc/foo/my-group/my-username 아래의 파일에 저장된다.

    ⇒ password 시크릿 : 생성 X

profile
Cloud Infra Engineer & interested in python, IaC, k8s

0개의 댓글