- Namespace 마다 하나씩 존재하는 default 계정은 모든 명령을 사용할 수 있다
- 만약, namespace / node / pv 와 같은 namespace 에 속하지 않는 것들에 대해서는 cluster role 이라고 하며, 이를 sa 와 연결하기 위해 cluster role binding 이 필요하다
- 이때, 특정 사용자에게만 연결해줄려면, PVC 와 PV 에 storageClassName 을 붙여서 구분한다
- 위와 같이 Provisoner 에는 접속할 스토리지의 정보가 있으며, 이를 전담하는 SA 를 통해 접속한다. 이때, PVC 의 요청 사항이 전달되면, 프로비저너에서는 해당 요청 사항에 맞는 볼륨을 프로비저닝하여 Pool 에 넣고, 해당 PV 는 PVC 와 storageClassName 을 통해 자동으로 Bound 된다
- Provisoner 는 실질적으로 Pod 이므로 ns 별로 따로 만들어서, ns 별로 다른 공간을 사용하게 할 수 있다
Provisoner 는 사전에 등록한 서버 ( 주소, 디렉토리 ) 를 사용하여 볼륨을 프로비저닝 & 사용할 수 있게 해주는 Pod 이다. 이는 배포시 Pod 형태로 배포한다
이 Provisioner 를 전담할 Service Account 가 필요하다. ROLE 을 통해 이 SA 가 할 수 있는 기능을 명세한다. 이 SA 와 ROLE 을 Binding 을 통해 연결한다. 이렇게 생성된 SA 는 오직 Provisoner 만 전담한다
- Provisoner 는 스토리지와 Mount 되어 안에 물리 자원을 사용하여 볼륨을 생성해줄 수 있다. 이를 통해 사용자가 스토리지에서 직접 볼륨을 만들어 주는 것이 아닌, Provisioner 가 요청된 볼륨을 자동으로 만들어 Pool 에 담아준다
- 이때, StorageClassName 도 넣어주어, StorageClass 를 통해 요청한 사용자에게만 제공해줄 수 있게 한다. 이를 통해 PVC 와 Bound 된다
- Pod 에 해당 PVC 를 넣어 PV 와 연결해서 사용할 수 있다
- 운영자가 PV 를 직접 프로비저닝 해줄 필요가 없다
PVC 만 작성하게 되면, 자동으로 요청을 처리할 수 없으므로 수동으로 처리해줘야 한다. 이때, StorageClass 를 사용하면, 요청을 자동으로 처리할 수 있는 프로비저너를 지정한다
- aws 의 경우 eks / gcp 의 경우 gke 에는 동적 프로비저너가 있다. 이는 aws 의 경우 aws-ebs 라고 한다. aws-ebs 는 K8S 에 속해있으며, ebs 에게 명령을 내린다. ebs 가 필요한 만큼의 볼륨을 만들어 Storage Class 를 붙여서 PV 에 저장한다. 이후, 요청 사항 비교를 통해 적합하면 해당 볼륨을 사용한다
- 허나, on-premise 에서 직접 클라우드 환경을 구성하여 운영한다면, 직접 프로비저너를 준비해야 한다. 우리는 nfs 를 이용하여 볼륨 ( 디렉토리 ) 를 제공하므로, nfs-provisioner 를 생성해야 한다
- 이는 Pod 로 존재한다
- 위와 같은 구조이다
vi /etc/kubernetes/manifests/kube-apiserver.yaml
kind: ServiceAccount #서비스 계정
apiVersion: v1
metadata:
name: nfs-pod-provisioner-sa
---
kind: ClusterRole # Role of kubernetes - 클러스터 룰
apiVersion: rbac.authorization.k8s.io/v1 # auth API
metadata:
name: nfs-provisioner-clusterRole
rules:
- apiGroups: [""] # rules on persistentvolumes
resources: ["persistentvolumes"] # kind 지정, pv 라고 지정한 것
verbs: ["get", "list", "watch", "create", "delete"] #허용할 명령
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "list", "watch", "update"]
- apiGroups: ["storage.k8s.io"] # api 그룹은 있으면 지정
resources: ["storageclasses"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["events"]
verbs: ["create", "update", "patch"]
---
kind: ClusterRoleBinding # rule 과 sa 를 연결
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: nfs-provisioner-rolebinding
subjects: # sa 지정
- kind: ServiceAccount
name: nfs-pod-provisioner-sa # defined on top of file
namespace: default
roleRef: # binding cluster role to service account - 클러스터 rule 지정
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
kind: Deployment
apiVersion: apps/v1
metadata: #deployment 정의
name: nfs-pod-provisioner
spec: # replicaset 정의
selector:
matchLabels:
app: nfs-pod-provisioner
replicas: 1
strategy:
type: Recreate
template:
metadata:
labels:
app: nfs-pod-provisioner
spec:
serviceAccountName: nfs-pod-provisioner-sa # Provisoner 를 전담할 Service Account 이름
containers:
- name: nfs-pod-provisioner
image: quay.io/external_storage/nfs-client-provisioner:latest # 사용 이미지
volumeMounts: # 아래 스토리지와 연결한 볼륨을 마운트하는 것
- name: nfs-provisioner-v
mountPath: /persistentvolumes # provisioner 컨테이너에 볼륨을 마운트 될 위치
env: # 환경 변수 - Storage class 에 전달해줄
- name: PROVISIONER_NAME # do not change
value: nfs-test # SAME AS PROVISONER NAME VALUE IN STORAGECLASS
- name: NFS_SERVER # do not change
value: 211.183.3.100 # Ip of the NFS SERVER
- name: NFS_PATH # do not change
value: /shared # path to nfs directory setup
volumes: # Provisoner 는 스토리지와 연결되므로 해당 연결 정보를 가져야 한다
- name: nfs-provisioner-v # same as volumemouts name
nfs:
server: 211.183.3.100
path: /shared
- Provisoner 는 스토리지와 연결되므로 해당 연결 정보를 가져야 한다. 우리는 nfs 방식을 사용하며 211.183.3.100 nfs-server 의 /shared 디렉토리와 Bind 시킬 것이다
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: nfs-storageclass # PVC 에서는 이 이름으로 StorageClass 와 연결
provisioner: nfs-test # Provisioner 이름
parameters:
archiveOnDelete: "false"
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-pvc-test
spec:
storageClassName: nfs-storageclass # SAME NAME AS THE STORAGECLASS
accessModes:
- ReadWriteMany # must be the same as PersistentVolume
resources:
requests:
storage: 50Mi
- 이때, 프로비저너가 프로비저닝한 PV 에 storageClassName 을 요청한 사용자의 PVC 의 storageClassName 으로 자동으로 지정하여, 프로비저닝된 PV 와 요청한 사용자의 PVC 를 Bound 해준다
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nfs-nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
volumes:
- name: nfs-test # 볼륨 이름
persistentVolumeClaim:
claimName: nfs-pvc-test # same name of pvc that was created
containers:
- image: nginx
name: nginx
volumeMounts:
- name: nfs-test # name of volume should match claimName volume
mountPath: /mydata2 # mount inside of contianer
잘봤습니다 감사합니다~