🍳머리말
nfs server와 client설정 후 nfs provisioner로 dynamic provisioning을 하는 설명글입니다. {}로 감싼 부분은 사용자 설정이 필요합니다.
📕 NFS
📔 NFS란
net상에서 다른 computer의 filesystem을 mount해서 공유하는 것입니다.
📕 NFS provisioner
📔 NFS provisioner란
nfs를 이용해 storage를 사용하는 pod를 배포하려면 k8s cluster상에서 nfs storage를 사용할 수 있도록 설정된 provisioner가 필요합니다. 이는 serviceaccount로써 k8s cluster상에 pv를 배포할 수 있도록 권한을 부여해 주는 역할을 수행합니다.
📕 환경
📔 server
📑 KERNEL-VERSION
4.18.0-240.el8.x86_64
📔 client
📑 KERNEL-VERSION
4.18.0-193.0.1.el8.x86_64
📑 k8s VERSION
v1.22.2
📑 CONTAINER-RUNTIME
cri-o://1.22.3
📕 Prerequisite
📔 k8s cluster
📕 NFS server 구성
📔 NFS 설치
yum install -y nfs-utils
📔 server측에서 exports할 directory 설정
root경로에 nfs_test folder생성 후 하위에 a, b, c folder를 생성해줍니다.
cd /
mkdir /nfs_test
cd nfs_test
mkdir a
mkdir b
mkdir c
vi /etc/exports
📔 exports file 수정
vi /etc/exports
다음 정보를 입력 후 저장합니다.
/nfs_test *(rw,subtree_check,no_root_squash)
이는 다음과 같습니다.
/{export할 folder명} {허용할 client ip대역}(client에게 줄 권한)
client에게 줄 권한들은 여러가지가 있습니다.
rw: 읽기 쓰기 가능
ro: 읽기만 가능
sync: filesystem변경시 즉시 client동기화
no_root_squash: client와 server의 root 동일화
subtree_check: 공유 디렉토리는 서브디렉토리를 가질 수 있음
client가 특정 file 요청시 server는 subtree checking을 실행해 sub dir까지 탐색, client가 요청한 file의 위치 확인
📑 nfs server와 rpcbind실행
systemctl start nfs-server
systemctl start rpcbind
📔 export여부 확인
다음 명령어로 확인합니다.
exportfs -v
출력결과
📕 NFS client 구성
📔 NFS 설치
yum install -y nfs-utils
📔 mount해 사용할 folder생성
아래처럼 경로에 nfs_test folder를 생성해줍니다.
mkdir /root/install/nfs_test
📔 확인
server의 지정한 folder를 mount후
다음 명령어로 확인해줍니다.
mount -t nfs {server의 ip}:{export한 folder명} {mount할 client folder경로}
제 경우는 다음과 같습니다.
mount -t nfs 172.22.6.6:/nfs_test /root/install/nfs_test
실행 후 해당 folder로 접속해 ls명령어로 확인하면 server의 nfs_test로 부터 mount된 folder들인 a,b,c가 있음을 확인할 수 있습니다.
📔 NFS provisioner 설치
이제 원격으로 file을 mount함을 확인했으니 본격적으로 k8s cluster에 nfs provisioner를 배포해 봅시다.
📑 service account 생성
kind: ServiceAccount
apiVersion: v1
metadata:
name: nfs-pod-provisioner-sa
---
kind: ClusterRole # Role of kubernetes
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: nfs-provisioner-clusterRole
rules:
- apiGroups: [""] # rules on persistentvolumes
resources: ["persistentvolumes"]
verbs: ["get", "list", "watch", "create", "delete"]
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "list", "watch", "update"]
- apiGroups: ["storage.k8s.io"]
resources: ["storageclasses"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["events"]
verbs: ["create", "update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: nfs-provisioner-rolebinding
subjects:
- kind: ServiceAccount
name: nfs-pod-provisioner-sa
namespace: default
roleRef: # binding cluster role to service account
kind: ClusterRole
name: nfs-provisioner-clusterRole # name defined in clusterRole
apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: nfs-pod-provisioner-otherRoles
rules:
- apiGroups: [""]
resources: ["endpoints"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: nfs-pod-provisioner-otherRoles
subjects:
- kind: ServiceAccount
name: nfs-pod-provisioner-sa # same as top of the file
# replace with namespace where provisioner is deployed
namespace: default
roleRef:
kind: Role
name: nfs-pod-provisioner-otherRoles
apiGroup: rbac.authorization.k8s.io
📑 deployment 생성
kind: Deployment
apiVersion: apps/v1
metadata:
name: nfs-pod-provisioner
spec:
selector:
matchLabels:
app: nfs-pod-provisioner
replicas: 1
strategy:
type: Recreate
template:
metadata:
labels:
app: nfs-pod-provisioner
spec:
serviceAccountName: nfs-pod-provisioner-sa # name of service account
containers:
- name: nfs-pod-provisioner
image: quay.io/external_storage/nfs-client-provisioner:latest
volumeMounts:
- name: nfs-provisioner
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME # do not change
value: nfs-home # SAME AS PROVISIONER NAME VALUE IN STORAGECLASS
- name: NFS_SERVER # do not change
value: {server의 IP} # Ip of the NFS SERVER
- name: NFS_PATH # do not change
value: {server의 nfs설정한 folder명} # path to nfs directory setup
volumes:
- name: nfs-provisioner # same as volumemouts name
nfs:
server: {server의 IP}
path: {server의 nfs설정한 folder명}
제 경우는 다음과 같이 설정했습니다.
kind: Deployment
apiVersion: apps/v1
metadata:
name: nfs-pod-provisioner
spec:
selector:
matchLabels:
app: nfs-pod-provisioner
replicas: 1
strategy:
type: Recreate
template:
metadata:
labels:
app: nfs-pod-provisioner
spec:
serviceAccountName: nfs-pod-provisioner-sa # name of service account
containers:
- name: nfs-pod-provisioner
image: quay.io/external_storage/nfs-client-provisioner:latest
volumeMounts:
- name: nfs-provisioner
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME # do not change
value: nfs-test # SAME AS PROVISIONER NAME VALUE IN STORAGECLASS
- name: NFS_SERVER # do not change
value: 172.22.6.6 # Ip of the NFS SERVER
- name: NFS_PATH # do not change
value: /nfs_test # path to nfs directory setup
volumes:
- name: nfs-provisioner # same as volumemouts name
nfs:
server: 172.22.6.6
path: /nfs_test
📑 storageclass생성
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: nfs-storageclass
provisioner: nfs-test
parameters:
archiveOnDelete: "false"
📑 pvc 생성
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: task-pv-claim
spec:
storageClassName: nfs-storageclass
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20Gi
📑 pod생성
apiVersion: v1
kind: Pod
metadata:
name: task-pv-pod
spec:
volumes:
- name: task-pv-storage
persistentVolumeClaim:
claimName: task-pv-claim
containers:
- name: task-pv-container
image: nginx
ports:
- containerPort: 80
name: "http-server"
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: task-pv-storage
📑 container접속, 확인
하기 명령어로 pod명을 확인해줍니다.
kubectl get pods
출력결과
다음 명령어로 container로 접속합니다.
kubectl exec -it task-pv-pod -- bash
pod생성시 mount했던 path인 /usr/share/nginx/html로 들어갑니다. 이 후 nfs server에 설정했던 a, b, c folder를 확인할 수 있습니다.
📕 기타
기타 provisioner가 error logs를 남기기도 합니다.
https://github.com/kubernetes-retired/external-storage/issues/978
'Cloud' 카테고리의 다른 글
(Kubernetes) - client-go로 k8s API와 통신하기 (0) | 2022.06.14 |
---|---|
(Terraform) - 용어 정리 (0) | 2022.04.28 |
(Terraform) - Window에 설치 (0) | 2022.04.25 |
(Kubernetes) - TLS/SSL secret 생성하기 (0) | 2022.04.19 |
(Kubernetes) - redis cluster statefulset예제 (0) | 2022.04.12 |