오늘은 쿠버네티스의 핵심 리소스들을 집중적으로 다뤘다. Ingress Controller 설치부터 시작해서 영구 볼륨(PV/PVC), 스토리지 클래스, 그리고 설정값을 주입하는 ConfigMap과 Secret까지 쭉 이어졌다. 내용이 많았지만 하나하나 연결되는 흐름이 있어서 이해하기 좋았다.
지난 시간에 Ingress 개념을 배웠다면, 오늘은 실제로 Ingress Controller를 설치하고 path 기반 라우팅을 구성하는 실습을 했다.
Ingress는 그냥 규칙(Rule)을 정의하는 리소스고, 실제로 트래픽을 처리하는 건 Ingress Controller다. 우리는 nginx 방식을 사용했다.
rapa.com/httpd → svc-ipnginx → Pod (httpd)
rapa.com/h → svc-h → Pod (hnginx)
트래픽 흐름을 정리하면 이렇다.
사용자 → ingress-controller svc (External-IP) → Ingress (path 라우팅) → svc → Pod
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ing-ip
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: "nginx"
rules:
- host: rapa.com
http:
paths:
- path: /httpd
pathType: Prefix
backend:
service:
name: svc-ipnginx
port:
number: 80
- path: /h
pathType: Prefix
backend:
service:
name: svc-h
port:
number: 80
몇 가지 중요한 포인트가 있다.
ingressClassName: "nginx" → 어떤 Ingress Controller를 쓸지 명시rewrite-target: / → /httpd로 들어와도 실제 Pod에는 /로 전달host는 반드시 영문 도메인이어야 한다. IP는 안 됨/etc/hosts에 직접 등록해서 테스트 가능서비스의 이름을 마치 주소처럼 쓰고 있다는 게 핵심이다. 쿠버네티스 내부 DNS가 svc 이름을 IP로 해석해준다.
컨테이너는 기본적으로 삭제되면 내부 데이터도 사라진다. 이걸 해결하기 위한 게 PV/PVC다.
관계를 정리하면 이렇다.
관리자 → PV 생성 (실제 디스크 정의)
사용자 → PVC 생성 (스토리지 요청)
쿠버네티스 → 조건에 맞는 PV와 PVC를 자동으로 Bind
Pod → PVC를 참조해서 마운트
오늘 실습에서는 마스터 노드를 NFS 서버로 구성하고, 워커 노드들이 NFS 클라이언트로 마운트하는 방식을 사용했다.
# 마스터 노드 - NFS 서버 설정
mkdir /shared
apt install -y nfs-kernel-server
echo "/shared *(rw,sync,no_subtree_check,no_root_squash)" >> /etc/exports
systemctl restart nfs-server
# 워커 노드 - NFS 클라이언트 설치
apt install -y nfs-common
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv1
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
nfs:
path: /shared/pv1
server: 211.183.3.100
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-pvc1
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Gi
PVC를 만들면 조건에 맞는 PV가 있을 때 자동으로 Bound 상태가 된다. PV를 직접 선택하는 게 아니라 조건(용량, accessMode)이 맞는 PV 중에서 선택된다는 점이 포인트다.
| 모드 | 설명 |
|---|---|
| ReadWriteOnce (RWO) | 단일 노드에서 읽기/쓰기 |
| ReadOnlyMany (ROX) | 다수 노드에서 읽기만 |
| ReadWriteMany (RWX) | 다수 노드에서 읽기/쓰기 |
| ReadWriteOncePod (RWOP) | 단일 Pod에서만 읽기/쓰기 |
PV와 PVC의 accessMode는 반드시 일치해야 한다.
| 정책 | 설명 |
|---|---|
| Retain | PVC 삭제 후 PV 유지, 재활용 불가 |
| Delete | PVC 삭제 시 PV도 함께 삭제 |
| Recycle | 재활용 (현재는 정책상 사용 불가) |
스토리지 등급을 정의하는 리소스다. HDD, SSD처럼 성격에 맞게 스토리지를 분류해놓은 것이다.
AWS EKS에서 gp2, gp3 같은 스토리지 클래스가 바로 이 개념이다.
PV와 PVC에 storageClassName을 동일하게 지정하면 해당 클래스끼리만 Bind된다.
# PV에 storageClassName 지정
spec:
storageClassName: manual-sc
...
# PVC에도 동일하게 지정
spec:
storageClassName: manual-sc
...
| 방식 | 설명 |
|---|---|
| 수동(Static) Provisioning | PVC 요청 전에 PV를 미리 생성해두는 방식 |
| 자동(Dynamic) Provisioning | PVC 요청이 오면 StorageClass가 자동으로 PV를 생성 |
오늘 실습은 수동 방식이었다. 자동 방식은 StorageClass에 provisioner를 지정해야 한다.
클러스터에 존재하는 설정값이나 환경변수를 Pod에 주입할 때 사용하는 리소스다.
Pod가 생성되기 전에 적용 가능한 값이라는 점이 핵심이다.
# ConfigMap 정의
apiVersion: v1
kind: ConfigMap
metadata:
name: info
data:
db_host: 211.183.3.100
username: root
# Pod에서 ConfigMap 참조 (환경변수로 주입)
env:
- name: USERNAME
valueFrom:
configMapKeyRef:
name: info
key: username
설정 파일 자체를 Pod 안으로 마운트하는 것도 가능하다. subPath를 사용하면 컨테이너 내부의 기존 파일은 유지하면서 특정 파일만 추가/수정할 수 있다.
ConfigMap과 비슷하지만 민감한 정보(DB 비밀번호, API 키 등) 를 다루는 리소스다.
kubectl get secret으로 조회해도 실제 값은 보이지 않음apiVersion: v1
kind: Secret
metadata:
name: sec
type: Opaque
stringData:
password: test123
# Pod에서 Secret 참조
envFrom:
- secretRef:
name: sec
ConfigMap과 Secret의 차이를 한 줄로 정리하면:
ConfigMap은 일반 설정값, Secret은 노출되면 안 되는 민감한 값
오늘 실습의 하이라이트였다. PV/PVC를 활용해서 WordPress와 MySQL을 쿠버네티스 위에 올렸다.
# WordPress에서 MySQL 접근 시 svc 이름 사용
env:
- name: WORDPRESS_DB_HOST
value: wordpress-mysql # svc 이름이 곧 주소
쿠버네티스 내부 DNS가 svc 이름을 IP로 해석해주기 때문에 가능한 방식이다. 이 개념이 마이크로서비스 아키텍처에서 서비스 간 통신의 핵심이다.
오늘은 쿠버네티스의 스토리지와 설정 관리 파트를 집중적으로 다뤘다. PV/PVC의 Bind 과정, ConfigMap과 Secret의 차이, Ingress의 path 라우팅까지 실습으로 직접 확인하니까 개념이 훨씬 잘 잡혔다. 특히 svc 이름을 주소처럼 쓴다는 개념이 인상 깊었다.
이번 velog는 AWS Kiro를 통해 작성하였다.