리소스의 관리와 설정
- 7.1 네임스페이스(Namespace)
- 7.2 컨피그맵(ConfigMap)
- 7.3 시크릿(Secret)
쿠버네티스에서 리소스를 논리적으로 분리하고, 설정 데이터를 컨테이너 이미지와 분리하는 건 운영의 기본이야. 네임스페이스로 그룹을 나누고, 컨피그맵과 시크릿으로 설정과 민감 정보를 관리하는 패턴을 알아야 하거든.
네임스페이스는 하나의 쿠버네티스 클러스터를 논리적으로 분리하는 가상의 공간이야. 같은 클러스터에서 개발팀, QA팀, 프로덕션 환경을 분리하거나, 프로젝트별로 리소스를 격리할 때 사용하지. 기본으로 존재하는 네임스페이스가 몇 개 있어 — default(별도 지정 없으면 여기에 생성됨), kube-system(쿠버네티스 시스템 컴포넌트들이 있는 곳), kube-public(모든 사용자가 읽을 수 있는 공용), kube-node-lease(노드 하트비트 정보 관리).
kubectl create namespace dev
kubectl get namespaces
네임스페이스를 지정해서 리소스를 생성하려면:
kubectl apply -f pod.yaml -n dev
kubectl get pods -n dev
YAML에서 직접 지정할 수도 있어:
metadata:
name: my-pod
namespace: dev
여기서 기억해야 할 건, 네임스페이스 간에는 기본적으로 네트워크가 격리되지 않는다는 거야. 네트워크 격리를 원하면 NetworkPolicy를 별도로 설정해야 해. 네임스페이스는 논리적 분리이지 물리적 분리가 아니거든. 다른 네임스페이스의 서비스에 접근하려면 서비스이름.네임스페이스이름.svc.cluster.local 형태의 FQDN을 사용해. 예를 들어 dev 네임스페이스의 my-service에 접근하려면 my-service.dev.svc.cluster.local로 호출하면 되지. ResourceQuota를 네임스페이스에 설정하면 해당 네임스페이스에서 사용할 수 있는 CPU, 메모리, 파드 수 등을 제한할 수 있어.
컨피그맵은 설정 데이터를 키-값 쌍으로 저장하는 쿠버네티스 오브젝트야. 애플리케이션의 설정을 컨테이너 이미지에 하드코딩하지 않고 외부에서 주입할 수 있게 해주지. 만드는 방법은 여러 가지가 있어:
# 명령어로 생성
kubectl create configmap my-config --from-literal=DB_HOST=mysql --from-literal=DB_PORT=3306
# 파일에서 생성
kubectl create configmap app-config --from-file=config.properties
YAML로도 만들 수 있고:
apiVersion: v1
kind: ConfigMap
metadata:
name: my-config
data:
DB_HOST: mysql
DB_PORT: "3306"
app.properties: |
server.port=8080
log.level=info
파드에서 컨피그맵을 사용하는 방법은 두 가지야. 환경 변수로 주입하는 방식이 있어:
spec:
containers:
- name: app
image: my-app
envFrom:
- configMapRef:
name: my-config
개별 키를 선택할 수도 있지:
env:
- name: DATABASE_HOST
valueFrom:
configMapKeyRef:
name: my-config
key: DB_HOST
그리고 볼륨으로 마운트하는 방식도 있어:
spec:
containers:
- name: app
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: my-config
이렇게 하면 컨피그맵의 각 키가 /etc/config/ 디렉터리 안에 파일로 생성돼. 볼륨으로 마운트하면 컨피그맵이 업데이트될 때 파드를 재시작하지 않아도 파일이 자동으로 갱신된다는 장점이 있어. 단, 환경 변수로 주입한 경우에는 파드를 재시작해야 반영되지.
시크릿은 컨피그맵과 구조가 거의 같지만, 비밀번호, API 키, 인증서 같은 민감한 데이터를 저장하기 위한 오브젝트야:
kubectl create secret generic my-secret \
--from-literal=DB_PASSWORD=supersecret \
--from-literal=API_KEY=abc123
apiVersion: v1
kind: Secret
metadata:
name: my-secret
type: Opaque
data:
DB_PASSWORD: c3VwZXJzZWNyZXQ= # base64 인코딩
API_KEY: YWJjMTIz
시크릿의 data 필드에는 base64로 인코딩된 값을 넣어야 해. stringData 필드를 사용하면 평문으로 입력 가능하고, 쿠버네티스가 자동으로 인코딩해주지. 여기서 정말 중요한 점 — base64는 인코딩이지 암호화가 아니야. echo "c3VwZXJzZWNyZXQ=" | base64 -d로 바로 복호화돼. 시크릿의 보안은 base64가 아니라 RBAC(역할 기반 접근 제어)과 etcd 암호화로 달성해야 해. etcd에 저장되는 시크릿을 암호화하려면 EncryptionConfiguration을 설정해야 하고.
파드에서 사용하는 방법은 컨피그맵과 동일해:
spec:
containers:
- name: app
envFrom:
- secretRef:
name: my-secret
시크릿 타입은 몇 가지가 있는데 — Opaque(기본 타입, 임의의 키-값 데이터 저장), kubernetes.io/dockerconfigjson(프라이빗 레지스트리 인증 정보), kubernetes.io/tls(TLS 인증서와 키)가 있어. 프라이빗 레지스트리에서 이미지를 받으려면 imagePullSecrets에 dockerconfigjson 타입의 시크릿을 지정해야 하지:
spec:
imagePullSecrets:
- name: my-registry-secret
containers:
- name: app
image: private-registry.com/my-app:latest
정리
7장 읽고 기억할 거 세 가지:
- 네임스페이스는 논리적 분리다. 네트워크 격리는 기본 제공되지 않으며, ResourceQuota로 자원 사용량을 제한할 수 있다.
- 컨피그맵으로 설정을 이미지에서 분리한다. 환경 변수 또는 볼륨 마운트로 주입 가능. 볼륨 마운트 시 자동 갱신 지원.
- 시크릿은 컨피그맵과 구조가 같지만 민감 정보용이다. base64는 암호화가 아니니까, 실제 보안은 RBAC과 etcd 암호화로 확보해야 한다.