Kubernetes에서 NFS 서버는 Kubernetes 클러스터에서 실행되는 애플리케이션에 영구 스토리지를 제공하는 NFS(네트워크 파일 시스템) 서버입니다. NFS는 클라이언트가 마치 로컬에 저장된 것처럼 네트워크를 통해 파일에 액세스할 수 있도록 하는 분산 파일 시스템 프로토콜입니다. Kubernetes의 맥락에서 NFS 서버는 일반적으로 외부 스토리지 솔루션으로 사용됩니다. 이를 통해 Kubernetes 포드는 NFS 서버에서 호스팅되는 공유 스토리지 볼륨에 액세스할 수 있습니다. 이는 여러 Pod 간에 데이터를 공유하거나 개별 Pod의 수명 주기를 넘어 데이터를 유지해야 하는 시나리오에 유용합니다.
1. NFS 서버를 쓰는 배경
클러스터 내부 저장소에 마운트하면 컨테이너 생명주기와 클러스터 생명주기가 다르므로, 클러스터가 유지될 동안은 데이터가 유지될 수 있다. 그러나 클러스터가 내려가면 데이터 역시 사라진다. 그래서 데이터를 유지하려면 외부 스토리지에 마운트하여 데이터를 저장해야 한다. 클러스터 상태와 무관하게 데이터를 유지하려면 클러스터 외부의 스토리지에 컨테이너가 마운트 되어야 한다. NFS 서버를 사용하여 외부 스토리지에 데이터를 저장해보자.
💡 클러스터 상태와 무관하게 데이터를 유지하기 위하여, 클러스터 외부의 스토리지에 컨테이너가 마운트한다. 이를 위하여 NFS SERVER가 사용된다.
2. NFS 서버 생성하기
1) NFS 서버 생성하기(CentOS)
sudo yum install nfs-utils
환경이 centos환경이므로 yum 사용하여 install해준다.
- ubuntu : sudo apt install nfs-kernel-server
- ngs-kernel-server 패키지를 설치하면 nfs구축에 필요한 nfs-common패키지, rpcbind 등을 포함하고 있어 따로 설치할 필요가 없다.
- centos : yum -y install nfs-utils
- nfs-utils 마찬가지로 NFS서버 설정에 필요한 유틸리티가 포함된 패키지를 설치할 수 있다.
2) pv를 위한 셋팅하기
위에서 말한 것처럼 컨테이너를 재시작하게 되면 컨테이너 내부의 데이터는 모두 사라진다. 그러기에 호스트 서버 의 볼륨과 컨테이너 내부의 볼륨을 마운트하여 유지하기 위해 사용하는 것이 좋다. 이를 위해 PersistentVolume(PV)와 microk8s 클러스터 밖의NFS (Network File System)를 사용하여 클러스터 밖의 저장소와 데이터를 공유하도록 한다.
cd /mnt
sudo mkdir shared
sudo chmod 777 shared
- mnt라는 폴더로 이동해준다.
- 그리고 나서 그안에 shared라는 폴더를 생성해준다.
- 이에 대한 권한이 없으므로 권한을 부여해준다.
이 폴더가 NFS server의 PV 공간이 된다.
3) pv에 접근할 ip정보 설정하기
<위에서 지정한 path> client_IP(rw,sync,no_subtree_check)
위와 같이 입력한다. 아래가 그 예시이다.
sudo echo '/mnt/shared 192.168.49.2/16(rw,sync,no_subtree_check)' >> /etc/exports
앞에서 생성한 /mnt/shared에 접근할 IP정보를 설정한다. 네트워크IP + 서브넷 범위로 디렉토리에 접근할 IP 범위를 설정할 수 있다.
ifconfig를 입력하여 나의 ip를 알아내 이를 작성해주도록 한다.
sudo ufw enable# 방화벽 활성화
sudo ufw status# 방화벽 상태확인
sudo ufw allow 2049# NFS 서비스 포트 열기
sudo ufw status# 방화벽 상태확인
NFS 서비스는 2049 포트에서 동작한다. 2049 포트가 트래픽을 받을 수 있도록 열어주어야 한다.
sudo exportfs -a
sudo systemctl restart nfs-server
설정이 마무리되었다면 NFS 서비스를 재실행한다.
3) pv와 pvc 생성하기
vim nfs-pv.yml
vim nfs-pvc.yml
# nfs-pv.yml
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-storage
labels:
type: nfs
spec:
capacity:
storage: 10Gi
accessModes: ["ReadWriteMany"]
nfs:
server: [NFS_SERVER_IP] # NFS서버를 사용하고자 하는 ip
path: /mnt/shared # NFS server's shared path
# nfs-pvc.yml
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-storage-claim
spec:
storageClassName: "" # 빈 문자열을 줍니다(중요)
accessModes: ["ReadWriteMany"]
resources:
requests:
storage: 4Gi
selector:
matchExpressions:
- key: type
operator: In
values:
- nfs
위와 같이 작성했다면 아래의 명령어를 입력하여 이를 적용토록 한다 .
kubectl apply -f nfs-pv.yml
kubectl apply -f nfs-pvc.yml
kubectl get pv,pvc
pv와 pvc가 잘 생성되었는지 확인해준다.
NFS 서버의 Private IP 를 사용하여 PV, PVC 를 생성한다.
4) Nginx Service 및 Deployment 띄우기
vim nfs-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: nfs-svc
spec:
selector:
app: nginx
type: NodePort
ports:
- protocol: TCP
port: 80
targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nfs-deployment
labels:
app: nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
volumeMounts:
- name: nginx-volume
mountPath: /usr/share/nginx/html
volumes:
- name: nginx-volume
persistentVolumeClaim:
claimName: nfs-pvc
Nginx 서비스의 80포트와 Nginx 컨테이터 80포트와 포트포워딩하였다. 그리고 외부에서 접근이 가능하도록 노드포트 타입으로 서비스를 생성하여 서비스의 80포트와 노드포트를 포트포워딩하였다.
그리고 Nginx 디플로이먼트를 생성한다. volumeMounts에 /usr/share/nginx/html 경로를 설정하여 해당 경로와 PV를 마운트한다. PV와 마운트하기 위해 volumes 설정에 nfs-pvc를 설정한다.
kubectl apply -f nfs-svc.yaml
5) NFS 서버 테스트 하기
kubectl get svc nfs-svc
microk8s의 master node는 192.168.16.10이고 nfs-svc로 배포한 port번호는 31010이다. 이를 브라우저에 넣어 접속을 하면 nginx의 index.html에 접속이 가능하다.
이는 nginx 컨테이너가 NFS서버에 있는 pv에 마운트하여 index.html를 참조한 것이다.
/usr/share/nginx/html
위의 경로로 들어가보면 index.html을 접속할 수 있다. 이를 수정하면 아래와 같이 나온다.