Kubernetes를 운영하면서 자주 발생하는 문제들과 해결 방법을 정리합니다.
Node가 삭제되지 않을 때
노드가 삭제되지 않고 계속 남아 있는 경우 다음 단계를 순서대로 시도합니다.
가급적 노드에 문제가 있을 때만 이 방식으로 조치하고, 중요한 노드의 경우 백업을 하고 진행하는 것이 좋습니다.
(저는 Karpenter 노드가 정리되지 않을 때 이 방식으로 조치를 했었습니다.)
- 먼저 노드에서 실행 중인 Pod들을 안전하게 제거합니다.
kubectl drain <node-name> --delete-emptydir-data --force --grace-period=0옵션 설명:
--delete-emptydir-data: emptyDir 볼륨을 사용하는 Pod도 강제로 제거--force: DaemonSet에 의해 관리되지 않는 Pod도 강제로 제거--grace-period=0: 대기 시간 없이 즉시 종료
- Drain이 완료되면 노드를 클러스터에서 제거합니다.
kubectl delete node <node-name>- 위 단계로도 삭제되지 않는다면, Finalizer가 남아있을 가능성이 있습니다. Finalizer를 확인하고 제거합니다.
(대용량) 파일을 Pod에서 사용하기
파일을 Kubernetes 상에서 마운트하여 사용해야 하는 경우 다음 방법들을 고려할 수 있습니다.
- 외부 저장소 사용
- S3, GCS 등 클라우드 스토리지를 사용하는 것이 가장 권장되는 방법입니다.
- 하지만 보안, 네트워크, 비용 등의 이유로 항상 가능한 것은 아닙니다.
- ConfigMap
- 기본적으로 key-value 형식 데이터는 ConfigMap을 사용하면 됩니다.
- 제한사항: ConfigMap에 저장 가능한 데이터는 1MB 제한이 있습니다. 따라서 대용량 설정 파일에는 사용할 수 없습니다.
- PVC (Persistent Volume Claim)
- 저장소를 따로 할당하여 파일을 두고 이를 마운트하여 컨테이너에서 사용할 수 있습니다.
- 로컬 환경에서는
hostPath옵션을 사용할 수 있습니다. - 프로덕션 환경에서는 클라우드 서비스의 스토리지 클래스를 사용하는 것이 좋습니다.
- Init Containers1
- Pod 내에 초기화용 컨테이너를 두어 파일을 볼륨에 배치합니다.
emptyDir볼륨을 통해 init container에서 다운로드한 파일을 메인 컨테이너와 공유할 수 있습니다.- 동적으로 파일을 다운로드하거나 생성해야 하는 경우 유용합니다.
Pod 내부에서 호스트로 접근하기
Pod 내부에서 호스트(노드)에 올라가 있는 서비스를 호출해야 하는 상황이 있을 수 있습니다. 이 경우 EndpointSlice를 활용하여 해결할 수 있습니다.
EndpointSlice와 연결되는 Service에 원하는 노드의 IP를 명시하면 Pod 내부에서 Service를 통해 호스트에 접근할 수 있습니다.
apiVersion: v1
kind: Service
metadata:
name: host-service
spec:
type: ClusterIP
clusterIP: None
externalIPs:
- 1.2.3.4 # Node IP
ports:
# ...
---
apiVersion: discovery.k8s.io/v1
kind: EndpointSlice
metadata:
labels:
kubernetes.io/service-name: host-service
name: host-service-eps
addressType: IPv4
endpoints:
- addresses:
- 1.2.3.4 # Node IP
conditions:
ready: true
ports:
# ...위와 같이 작성한 뒤 다음 주소를 통해 호스트 서비스에 접근할 수 있습니다:
host-service.<namespace>.svc.cluster.local:<port>