[Kubernetes] Configmap & Secret

ConfigMap

공식문서: https://kubernetes.io/ko/docs/concepts/configuration/configmap/

ConfigMap은 쿠버네티스에서 애플리케이션이 사용할 설정 데이터를 관리하기 위한 객체이다.
ConfigMap은 주로 환경 변수, 설정 파일, 명령줄 매개변수 등의 형태로 사용되며 코드와 설정 데이터를 분리하여 애플리케이션을 구성할 수 있는 역할을 한다. 

  • 텍스트 기반 데이터(key-value 형식)를 저장 가능.
  • Pod에서 환경 변수, Command-line 인자, Volume으로 마운트하여 사용할 수 있음.
  • YAML 또는 JSON 형식으로 정의 가능.

ConfigMap YAML 생성

example-configmap.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: example-configmap
data:
  database_url: "mysql://example-db:3306"
  redis_url: "redis://example-redis:6379"

ConfigMap 데이터를 Pod의 환경 변수에 주입 

Pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: example-pod
spec:
  containers:
    - name: app-container
      image: nginx
      env:
        - name: DATABASE_URL
          valueFrom:
            configMapKeyRef:
              name: example-configmap
              key: database_url
        - name: REDIS_URL
          valueFrom:
            configMapKeyRef:
              name: example-configmap
              key: redis_url

위 Pod는 환경 변수 DATABASE_URL과 REDIS_URL에 ConfigMap의 값을 끌어온다. 

볼륨으로 사용

ConfigMap 데이터를 파일로 마운트하여 사용하는 방법이다. 

apiVersion: v1
kind: Pod
metadata:
  name: example-pod-volume
spec:
  containers:
    - name: app-container
      image: nginx
      volumeMounts:
        - name: config-volume
          mountPath: "/etc/config"
  volumes:
    - name: config-volume
      configMap:
        name: example-configmap

위 설정은 ConfigMap 데이터를 /etc/config 디렉터리에 파일 형태로 마운트한다. 
결과적으로 아래와 같은 파일들이 생성된다. 

  • /etc/config/database_url
  • /etc/config/redis_url

Secret 

공식문서: https://kubernetes.io/ko/docs/concepts/configuration/secret/

Secret은 쿠버네티스에서 비밀번호, 인증 토큰, SSH 키와 같은 소량의 민감한 데이터를 안전하게 저장하고 관리하기 위한 객체이다. 
만약 Secret을 사용하지 않으면 중요한 정보가 Pod의 spec 또는 컨테이너 이미지에 하드코딩될 수 있다. Secret을 활용하면 민감한 데이터를 애플리케이션 코드와 분리할 수 있으며, 필요한 경우만 Pod에 제공된다. 

  • Secret에 저장된 데이터는 Base64로 인코딩된다. 
    이는 암호화가 아니라 단순히 데이터를 인코딩하는 방식이므로 그렇게 안전하지는 않다. 그래서 추가적인 보안을 위해 AWS KMS,AWS Secret Manager, Hashicorp Vault 등 외부 암호화 서비스와 연동하여 사용할 수 있다. 
  • Pod와 독립적으로 생성한다. Secret은 Pod와 독립적으로 생성, 수정, 관리할 수 있으므로 민감한 데이터의 노출 위험을 줄여준다. 
  • ConfigMap과 비슷하지만, 민감한 데이터를 저장하는 데 초점을 맞춘 리소스이다. 주로 Configmap 보다는 Secret을 많이 사용하는  것 같다. 

Secret의 주요 유형

Secret은 다양한 타입으로 생성할 수 있으며, 쿠버네티스는 일반적인 사용 사례에 대해 몇 가지 빌트인 타입을 제공한다. 

  • Opaque: 기본 타입으로, 사용자 정의 데이터를 저장한다. 
  • kubernetes.io/service-account-token: 서비스 계정 토큰을 저장한다. 
  • kubernetes.io/dockerconfigjson: Docker Registry 인증 정보를 저장한다. 

Secret 생성 (Opaque 타입)

Secret.opaque.yaml

apiVersion: v1
kind: Secret
metadata:
  name: example-secret
type: Opaque
data:
  username: dXNlcm5hbWU=  # Base64로 인코딩된 값 ('username')
  password: cGFzc3dvcmQ=  # Base64로 인코딩된 값 ('password')

위 YAML 파일에서 data 필드에 저장된 값은 Base64로 인코딩된 형태dlek. 이를 디코딩하면 원래 데이터를 확인할 수 있다.

echo "dXNlcm5hbWU=" | base64 --decode
# 출력: username

echo "cGFzc3dvcmQ=" | base64 --decode
# 출력: password

Kubectl 을이용한 Secret 생성

kubectl create secret generic example-secret \
  --from-literal=username=username \
  --from-literal=password=password

Secret을 Pod에서 사용하는 방법

apiVersion: v1
kind: Pod
metadata:
  name: secret-env-pod
spec:
  containers:
    - name: app-container
      image: nginx
      env:
        - name: USERNAME
          valueFrom:
            secretKeyRef:
              name: example-secret
              key: username
        - name: PASSWORD
          valueFrom:
            secretKeyRef:
              name: example-secret
              key: password

볼륨으로 사용

apiVersion: v1
kind: Pod
metadata:
  name: secret-volume-pod
spec:
  containers:
    - name: app-container
      image: nginx
      volumeMounts:
        - name: secret-volume
          mountPath: "/etc/secret"
  volumes:
    - name: secret-volume
      secret:
        secretName: example-secret

설정은 Secret 데이터를 /etc/secret 디렉토리에 파일 형태로 마운트한다. 

  • /etc/secret/username
  • /etc/secret/password

TLS 설정을통한 HTTPS 통신 테스트 

Nginx에 HTTPS를 적용하는 과정과 관련된 단계를 Kubernetes 환경에서 설정 할것이다. 아래의 단계는 자체 서명 인증서를 생성하고 이를 Kubernetes Secret으로 생성한 뒤, Nginx Pod에서 HTTPS 설정을 적용하는 테스트를 진행보도록 하겠다. 

자체 서명 인증서 생성

프라이빗 키 & CSR (인증서 서명 요청) 생성 & CRT (인증서) 생성

openssl genrsa -out nginx-tls.key 2048
openssl req -new -key nginx-tls.key -out nginx-tls.csr
openssl x509 -req -days 3650 -in nginx-tls.csr -signkey nginx-tls.key -out nginx-tls.crt

CSR 생성 과정에서 필요한 정보를 입력한다. 

  • Country Name: KR
  • State or Province Name: Seoul
  • Common Name: www.example.com

Kubernetes Secret 생성

생성한 인증서를 기반으로 Secret으로 Kubernetes에 추가한다. 

 

Base64 인코딩

nginx-tls.crt와 nginx-tls.key 파일을 base64로 인코딩한다. 

base64 nginx-tls.crt -w 0
base64 nginx-tls.key -w 0

Secret YAML 생성

apiVersion: v1
kind: Secret
metadata:
  name: nginx-secret
type: kubernetes.io/tls
data:
  tls.crt: <base64로 인코딩한 crt 내용>
  tls.key: <base64로 인코딩한 key 내용>

Nginx 설정

ConfigMap 생성

apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config
data:
  nginx-tls.conf: |
    server {
        listen 80;
        listen 443 ssl;
        server_name www.example.com;

        ssl_certificate /etc/nginx/ssl/tls.crt;
        ssl_certificate_key /etc/nginx/ssl/tls.key;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers HIGH:!aNULL:!MD5;

        location / {
            root /usr/share/nginx/html;
            index index.html;
        }
    }

Nginx Deployment.yaml & Servce.yaml 설정 

# nginx.deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
        - containerPort: 443
        volumeMounts:
        - name: ssl-certs
          mountPath: /etc/nginx/ssl
        - name: nginx-config
          mountPath: /etc/nginx/conf.d
      volumes:
      - name: ssl-certs
        secret:
          secretName: nginx-secret
      - name: nginx-config
        configMap:
          name: nginx-config
----------------------------------------
# service.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  type: LoadBalancer
  ports:
  - port: 80
    targetPort: 80
  - port: 443
    targetPort: 443
  selector:
    app: nginx

 

'kubernetes' 카테고리의 다른 글

[Kubernetes] DeamonSet & Job, Cronjob  (0) 2024.12.06
[Kubernetes] Ambassador Pod Design Pattern  (0) 2024.12.05
[Kubernetes] Volume(PV, PVC)  (0) 2024.12.04
[kubernetes] Service & Ingress  (0) 2024.12.03
[Kubernetes] Pod Lifecycle(Probe)  (0) 2024.12.03