파드를 다시 띄웠더니 사용자 계정과 스키마 변경이 모두 사라졌다. 확인해 보니 볼륨이 emptyDir 이었다.
volumes:
- name: ldap-data
emptyDir: {}
- name: ldap-config
emptyDir: {}
- name: ldap-certs
emptyDir: {}
emptyDir 은 파드가 노드에 배치될 때 만들어지고 파드가 사라질 때 함께 지워진다. 여기서 갈리는 지점이 중요하다.
| 상황 | emptyDir |
|---|---|
| 컨테이너만 재시작 (crash · liveness 실패) | 유지된다. 파드는 그대로다 |
| 파드 재생성 (배포 롤아웃 · 수동 삭제 · 노드 재부팅 · eviction) | 초기화된다 |
| 노드 이동 | 초기화된다 |
"그동안 서버를 여러 번 재기동했는데 멀쩡했다"가 성립하는 이유가 이것이다. 컨테이너만 죽었다 살아난 경우에는 데이터가 남는다. 이번에 사라졌다면 파드 자체가 새로 만들어진 것이다.
# UID 가 바뀌었으면 파드가 재생성된 것이다
kubectl get pod <pod> -n <ns> -o jsonpath='{.metadata.uid}{"\n"}{.metadata.creationTimestamp}{"\n"}'
# 컨테이너 재시작 횟수
kubectl get pod <pod> -n <ns> -o jsonpath='{.status.containerStatuses[*].restartCount}{"\n"}'
# 축출 · 재스케줄 흔적
kubectl describe pod <pod> -n <ns> | egrep -i 'Evict|Killing|Scheduled|Preempt'
kubectl rollout history deploy/<deploy> -n <ns>
| 내용 | 경로(이미지에 따라 다름) | 보존 방식 |
|---|---|---|
| 데이터베이스 | /var/lib/ldap 또는 /bitnami/openldap |
PVC |
설정(slapd.d) |
/etc/ldap/slapd.d |
PVC. 스키마 · 오버레이 · ACL 이 여기 있다 |
| 인증서 · 키 | 이미지별 경로 | Secret |
| 부트스트랩 LDIF | - | ConfigMap 또는 Secret |
설정을 휘발성으로 두면 ACL 이나 오버레이 변경이 재시작 때 사라져 "어제 고친 권한이 오늘 없다"가 된다. 데이터만 PVC 로 옮기고 설정을 빠뜨리는 실수가 흔하다.
비밀번호 해시가 들어간 부트스트랩 LDIF 는 ConfigMap 이 아니라 Secret 에 둔다.
LDAP 은 상태를 가진 서비스이므로 StatefulSet 이 맞다. 파드 이름이 고정되고 PVC 가 파드별로 유지된다.
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: openldap
spec:
serviceName: openldap
replicas: 1
selector:
matchLabels:
app: openldap
template:
metadata:
labels:
app: openldap
spec:
securityContext:
fsGroup: 1001
containers:
- name: openldap
image: <레지스트리>/openldap:<태그>
ports:
- containerPort: 389
- containerPort: 636
volumeMounts:
- name: ldap-data
mountPath: /var/lib/ldap
- name: ldap-config
mountPath: /etc/ldap/slapd.d
- name: ldap-certs
mountPath: /certs
readOnly: true
readinessProbe:
tcpSocket:
port: 389
initialDelaySeconds: 10
livenessProbe:
tcpSocket:
port: 389
initialDelaySeconds: 30
volumes:
- name: ldap-certs
secret:
secretName: openldap-tls
defaultMode: 0440
volumeClaimTemplates:
- metadata:
name: ldap-data
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: <스토리지클래스>
resources:
requests:
storage: 20Gi
- metadata:
name: ldap-config
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: <스토리지클래스>
resources:
requests:
storage: 1Gi
마운트 경로는 이미지마다 다르다. 쓰는 이미지의 문서를 확인하고, 데이터와 설정을 한 디렉터리에 모아 두는 이미지라면 PVC 하나로 충분하다.
fsGroup 은 컨테이너가 쓰는 UID · GID 에 맞춘다. 값이 맞지 않으면 파드는 뜨는데 slapd 가 디렉터리에 쓰지 못해 기동에 실패한다.
이미 운영 중인 데이터가 있다면 먼저 빼낸다.
# 1) 백업
kubectl exec -n <ns> <pod> -- slapcat -n 0 > config-backup.ldif
kubectl exec -n <ns> <pod> -- slapcat -n 1 > data-backup.ldif
# 2) 매니페스트를 PVC 기반으로 바꿔 재배포
# 3) 필요하면 복원
kubectl cp data-backup.ldif <ns>/<pod>:/tmp/
kubectl exec -n <ns> <pod> -- slapadd -n 1 -l /tmp/data-backup.ldif
slapcat · slapadd 는 slapd 가 멈춘 상태에서 쓰는 것이 원칙이다. 돌아가는 상태에서 뜬 덤프는 일관성이 보장되지 않으므로, 가능하면 복제본을 0으로 내리거나 유지보수 창에서 수행한다.
데이터베이스 번호(-n)는 환경에 따라 다르다. slapcat -n 0 은 설정, 데이터는 보통 -n 1 또는 -n 2 다.
# CronJob 에서 실행할 명령 예
slapcat -n 1 -l /backup/ldap-$(date +%F).ldif
PVC 를 붙였다고 백업이 되는 것은 아니다. 잘못된 ldapdelete 한 번이면 볼륨이 살아 있어도 데이터는 사라진다. 주기 백업과 보관 주기를 함께 정한다.
slapcat · slapadd 의 데이터베이스 번호 확인.