Differences
This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
k8s_basic_storage [2020/05/22 15:34] – [Create PVC] andonovj | k8s_basic_storage [2020/05/25 12:49] (current) – [Dynamic Provisioning] andonovj | ||
---|---|---|---|
Line 56: | Line 56: | ||
storageClassName: | storageClassName: | ||
capacity: | capacity: | ||
- | storage: | + | storage: |
persistentVolumeReclaimPolicy: | persistentVolumeReclaimPolicy: | ||
# ^ | # ^ | ||
Line 85: | Line 85: | ||
ubuntu@k8s-master: | ubuntu@k8s-master: | ||
NAME CAPACITY | NAME CAPACITY | ||
- | ps-pv 10Gi RWO Retain | + | ps-pv 50Gi RWO Retain |
ubuntu@k8s-master: | ubuntu@k8s-master: | ||
No resources found in default namespace. | No resources found in default namespace. | ||
Line 109: | Line 109: | ||
resources: | resources: | ||
requests: | requests: | ||
- | storage: | + | storage: |
</ | </ | ||
Line 119: | Line 119: | ||
ubuntu@k8s-master: | ubuntu@k8s-master: | ||
NAME | NAME | ||
- | ps-pvc | + | ps-pvc |
ubuntu@k8s-master: | ubuntu@k8s-master: | ||
NAME CAPACITY | NAME CAPACITY | ||
- | ps-pv 10Gi RWO Retain | + | ps-pv 50Gi RWO Retain |
ubuntu@k8s-master: | ubuntu@k8s-master: | ||
</ | </ | ||
We see that, we have bounded them and we see the claim in the Persistent Volume description. | We see that, we have bounded them and we see the claim in the Persistent Volume description. | ||
- | It is important to note that the PVC will bind to ANY PV which has the SAME or MORE of the requested storage. For example if the PVC wants to claim 10 GBs and we have PV with 20 GBs, it will bind. | + | It is important to note that the PVC will bind to ANY PV which has the SAME or MORE of the requested storage. For example if the PVC wants to claim 50 GBs and we have PV with 20 GBs, it will bind. |
- | However, if our PVC wants to claim 20GBs and we have only 10 GB PV, then we are screwed and the PVC won't bind. | + | However, if our PVC wants to claim 20GBs and we have only 50 GB PV, then we are screwed and the PVC won't bind. |
Congrats, we have a pvc to present to any pod we want to have storage. | Congrats, we have a pvc to present to any pod we want to have storage. | ||
Line 138: | Line 138: | ||
< | < | ||
+ | apiVersion: v1 | ||
kind: Pod | kind: Pod | ||
metadata: | metadata: | ||
Line 143: | Line 144: | ||
spec: | spec: | ||
volumes: | volumes: | ||
- | - name: fast10g | + | - name: fast50g |
persistentVolumeClaim: | persistentVolumeClaim: | ||
claimName: ps-pvc | claimName: ps-pvc | ||
Line 155: | Line 156: | ||
volumeMounts: | volumeMounts: | ||
- mountPath: "/ | - mountPath: "/ | ||
- | name: fast10g | + | name: fast50g |
</ | </ | ||
Line 232: | Line 233: | ||
root@node-1:/ | root@node-1:/ | ||
</ | </ | ||
- | Lo and behold, the simple text file is on persistent storage and won't be affected | + | Lo and behold, the simple text file is on persistent storage and won't be affected |
- | As we mentioned, that kind of persistent storage allocation DOESN' | + | As we mentioned, that kind of persistent storage allocation DOESN' |
+ | |||
+ | {{ : | ||
+ | |||
+ | You see that, mapping and mapping and mapping | ||
=====Dynamic Provisioning===== | =====Dynamic Provisioning===== | ||
- | Let's configure Dynamic storage. | + | Let's configure Dynamic storage. |
+ | |||
+ | Now, for Dynamic provisioning with NFS I had to re-configure the cluster. In a nutshell make sure that teh API IP which you give when you initiate the cluster has the same subnet of the pod network. | ||
+ | |||
+ | For example: | ||
+ | |||
+ | < | ||
+ | kubeadm init --ignore-preflight-errors=NumCPU --apiserver-advertise-address=192.168.50.10 --pod-network-cidr=192.168.50.0/ | ||
+ | </ | ||
+ | |||
+ | Calico by default is using: 192.168.0.0/ | ||
+ | |||
+ | So let's get going. In the begining, I had something like that: | ||
+ | |||
+ | < | ||
+ | NAMESPACE | ||
+ | kube-system | ||
+ | kube-system | ||
+ | kube-system | ||
+ | kube-system | ||
+ | kube-system | ||
+ | kube-system | ||
+ | kube-system | ||
+ | kube-system | ||
+ | kube-system | ||
+ | kube-system | ||
+ | kube-system | ||
+ | kube-system | ||
+ | kube-system | ||
+ | ubuntu@k8s-master: | ||
+ | </ | ||
+ | |||
+ | So we have to create the following: | ||
+ | |||
+ | * Deployment | ||
+ | * Service Account | ||
+ | * Service | ||
+ | * RBAC | ||
+ | * Storage Class | ||
+ | * Claim | ||
+ | |||
+ | ====Create the Deployment, | ||
+ | You can see the deployment, | ||
+ | |||
+ | < | ||
+ | apiVersion: v1 | ||
+ | kind: ServiceAccount | ||
+ | metadata: | ||
+ | name: nfs-provisioner | ||
+ | --- | ||
+ | kind: Service | ||
+ | apiVersion: v1 | ||
+ | metadata: | ||
+ | name: nfs-provisioner | ||
+ | labels: | ||
+ | app: nfs-provisioner | ||
+ | spec: | ||
+ | ports: | ||
+ | - name: nfs | ||
+ | port: 2049 | ||
+ | - name: nfs-udp | ||
+ | port: 2049 | ||
+ | protocol: UDP | ||
+ | - name: nlockmgr | ||
+ | port: 32803 | ||
+ | - name: nlockmgr-udp | ||
+ | port: 32803 | ||
+ | protocol: UDP | ||
+ | - name: mountd | ||
+ | port: 20048 | ||
+ | - name: mountd-udp | ||
+ | port: 20048 | ||
+ | protocol: UDP | ||
+ | - name: rquotad | ||
+ | port: 875 | ||
+ | - name: rquotad-udp | ||
+ | port: 875 | ||
+ | protocol: UDP | ||
+ | - name: rpcbind | ||
+ | port: 111 | ||
+ | - name: rpcbind-udp | ||
+ | port: 111 | ||
+ | protocol: UDP | ||
+ | - name: statd | ||
+ | port: 662 | ||
+ | - name: statd-udp | ||
+ | port: 662 | ||
+ | protocol: UDP | ||
+ | selector: | ||
+ | app: nfs-provisioner | ||
+ | --- | ||
+ | kind: Deployment | ||
+ | apiVersion: apps/v1 | ||
+ | metadata: | ||
+ | name: nfs-provisioner | ||
+ | spec: | ||
+ | selector: | ||
+ | matchLabels: | ||
+ | app: nfs-provisioner | ||
+ | replicas: 1 | ||
+ | strategy: | ||
+ | type: Recreate | ||
+ | template: | ||
+ | metadata: | ||
+ | labels: | ||
+ | app: nfs-provisioner | ||
+ | spec: | ||
+ | serviceAccount: | ||
+ | containers: | ||
+ | - name: nfs-provisioner | ||
+ | image: quay.io/ | ||
+ | ports: | ||
+ | - name: nfs | ||
+ | containerPort: | ||
+ | - name: nfs-udp | ||
+ | containerPort: | ||
+ | protocol: UDP | ||
+ | - name: nlockmgr | ||
+ | containerPort: | ||
+ | - name: nlockmgr-udp | ||
+ | containerPort: | ||
+ | protocol: UDP | ||
+ | - name: mountd | ||
+ | containerPort: | ||
+ | - name: mountd-udp | ||
+ | containerPort: | ||
+ | protocol: UDP | ||
+ | - name: rquotad | ||
+ | containerPort: | ||
+ | - name: rquotad-udp | ||
+ | containerPort: | ||
+ | protocol: UDP | ||
+ | - name: rpcbind | ||
+ | containerPort: | ||
+ | - name: rpcbind-udp | ||
+ | containerPort: | ||
+ | protocol: UDP | ||
+ | - name: statd | ||
+ | containerPort: | ||
+ | - name: statd-udp | ||
+ | containerPort: | ||
+ | protocol: UDP | ||
+ | securityContext: | ||
+ | capabilities: | ||
+ | add: | ||
+ | - DAC_READ_SEARCH | ||
+ | - SYS_RESOURCE | ||
+ | args: | ||
+ | - " | ||
+ | env: | ||
+ | - name: POD_IP | ||
+ | valueFrom: | ||
+ | fieldRef: | ||
+ | fieldPath: status.podIP | ||
+ | - name: SERVICE_NAME | ||
+ | value: nfs-provisioner | ||
+ | - name: POD_NAMESPACE | ||
+ | valueFrom: | ||
+ | fieldRef: | ||
+ | fieldPath: metadata.namespace | ||
+ | imagePullPolicy: | ||
+ | volumeMounts: | ||
+ | - name: export-volume | ||
+ | mountPath: /export | ||
+ | volumes: | ||
+ | - name: export-volume | ||
+ | hostPath: | ||
+ | path: /srv | ||
+ | ubuntu@k8s-master: | ||
+ | serviceaccount/ | ||
+ | service/ | ||
+ | deployment.apps/ | ||
+ | </ | ||
+ | |||
+ | Then let's create the RBAC, which created the Cluster roles and maps them and of course the storage class | ||
+ | |||
+ | ===Create RBAC and Storage Class=== | ||
+ | < | ||
+ | kind: ClusterRole | ||
+ | apiVersion: rbac.authorization.k8s.io/ | ||
+ | metadata: | ||
+ | name: nfs-provisioner-runner | ||
+ | rules: | ||
+ | - apiGroups: ["" | ||
+ | resources: [" | ||
+ | verbs: [" | ||
+ | - apiGroups: ["" | ||
+ | resources: [" | ||
+ | verbs: [" | ||
+ | - apiGroups: [" | ||
+ | resources: [" | ||
+ | verbs: [" | ||
+ | - apiGroups: ["" | ||
+ | resources: [" | ||
+ | verbs: [" | ||
+ | - apiGroups: ["" | ||
+ | resources: [" | ||
+ | verbs: [" | ||
+ | - apiGroups: [" | ||
+ | resources: [" | ||
+ | resourceNames: | ||
+ | verbs: [" | ||
+ | --- | ||
+ | kind: ClusterRoleBinding | ||
+ | apiVersion: rbac.authorization.k8s.io/ | ||
+ | metadata: | ||
+ | name: run-nfs-provisioner | ||
+ | subjects: | ||
+ | - kind: ServiceAccount | ||
+ | name: nfs-provisioner | ||
+ | # replace with namespace where provisioner is deployed | ||
+ | namespace: default | ||
+ | roleRef: | ||
+ | kind: ClusterRole | ||
+ | name: nfs-provisioner-runner | ||
+ | apiGroup: rbac.authorization.k8s.io | ||
+ | --- | ||
+ | kind: Role | ||
+ | apiVersion: rbac.authorization.k8s.io/ | ||
+ | metadata: | ||
+ | name: leader-locking-nfs-provisioner | ||
+ | rules: | ||
+ | - apiGroups: ["" | ||
+ | resources: [" | ||
+ | verbs: [" | ||
+ | --- | ||
+ | kind: RoleBinding | ||
+ | apiVersion: rbac.authorization.k8s.io/ | ||
+ | metadata: | ||
+ | name: leader-locking-nfs-provisioner | ||
+ | subjects: | ||
+ | - kind: ServiceAccount | ||
+ | name: nfs-provisioner | ||
+ | # replace with namespace where provisioner is deployed | ||
+ | namespace: default | ||
+ | roleRef: | ||
+ | kind: Role | ||
+ | name: leader-locking-nfs-provisioner | ||
+ | apiGroup: rbac.authorization.k8s.io | ||
+ | ubuntu@k8s-master: | ||
+ | kind: StorageClass | ||
+ | apiVersion: storage.k8s.io/ | ||
+ | metadata: | ||
+ | name: example-nfs | ||
+ | provisioner: | ||
+ | mountOptions: | ||
+ | - vers=4.1 | ||
+ | ubuntu@k8s-master: | ||
+ | clusterrole.rbac.authorization.k8s.io/ | ||
+ | clusterrolebinding.rbac.authorization.k8s.io/ | ||
+ | role.rbac.authorization.k8s.io/ | ||
+ | rolebinding.rbac.authorization.k8s.io/ | ||
+ | ubuntu@k8s-master: | ||
+ | storageclass.storage.k8s.io/ | ||
+ | </ | ||
+ | |||
+ | ====Create Storage Claim==== | ||
+ | With Dynamic provisioning, | ||
+ | |||
+ | < | ||
+ | ubuntu@k8s-master: | ||
+ | kind: PersistentVolumeClaim | ||
+ | apiVersion: v1 | ||
+ | metadata: | ||
+ | name: nfs | ||
+ | annotations: | ||
+ | volume.beta.kubernetes.io/ | ||
+ | spec: | ||
+ | accessModes: | ||
+ | - ReadWriteMany | ||
+ | resources: | ||
+ | requests: | ||
+ | storage: 10Mi | ||
+ | ubuntu@k8s-master: | ||
+ | </ | ||
+ | |||
+ | ====Verify==== | ||
+ | We can verify the configuration as follows: | ||
+ | |||
+ | |||
+ | < | ||
+ | ubuntu@k8s-master: | ||
+ | NAME CAPACITY | ||
+ | persistentvolume/ | ||
+ | |||
+ | NAME STATUS | ||
+ | persistentvolumeclaim/ | ||
+ | ubuntu@k8s-master: | ||
+ | </ | ||
+ | |||
+ | Finally, we have a bounded PVC using Dynamic Provision. There is one very good git with all this files: | ||
+ | |||
+ | < | ||
+ | ubuntu@k8s-master: | ||
+ | ubuntu@k8s-master: | ||
+ | ubuntu@k8s-master: | ||
+ | total 32 | ||
+ | -rw-r--r-- | ||
+ | -rw-r--r-- | ||
+ | -rw-r--r-- | ||
+ | drwxr-xr-x | ||
+ | drwx------ | ||
+ | -rw-r--r-- | ||
+ | drwxrwxr-x | ||
+ | drwxr-xr-x | ||
+ | drwxrwxr-x 17 ubuntu ubuntu 4096 May 25 11:27 external-storage | ||
+ | </ | ||
+ | |||
+ | ====Create a Pod with Dynamic Provisioning==== | ||
+ | We can of course create a pod which will be using the NFS, let's create NGINX pod for example: | ||
+ | |||
+ | < | ||
+ | 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 # | ||
+ | persistentVolumeClaim: | ||
+ | claimName: nfs # same name of pvc that was created | ||
+ | containers: | ||
+ | - image: nginx | ||
+ | name: nginx | ||
+ | volumeMounts: | ||
+ | - name: nfs # name of volume should match claimName volume | ||
+ | mountPath: mydata2 # mount inside of contianer | ||
+ | ubuntu@k8s-master: | ||
+ | deployment.apps/ | ||
+ | ubuntu@k8s-master: | ||
+ | NAME READY | ||
+ | nfs-nginx-6b4db6f57-4mczr | ||
+ | nfs-provisioner-7795cf6f4-d7m2l | ||
+ | ubuntu@k8s-master: | ||
+ | </ | ||
+ | |||
+ | Even an ubuntu pod: | ||
+ | < | ||
+ | ubuntu@k8s-master: | ||
+ | apiVersion: v1 | ||
+ | kind: Pod | ||
+ | metadata: | ||
+ | name: first-pod | ||
+ | spec: | ||
+ | volumes: | ||
+ | - name: fast10m | ||
+ | persistentVolumeClaim: | ||
+ | claimName: nfs | ||
+ | containers: | ||
+ | - name: ctr1 | ||
+ | image: ubuntu: | ||
+ | command: | ||
+ | - /bin/bash | ||
+ | - " | ||
+ | - "sleep 60m" | ||
+ | volumeMounts: | ||
+ | - mountPath: "/ | ||
+ | name: fast10m | ||
+ | ubuntu@k8s-master: | ||
+ | NAME READY | ||
+ | first-pod | ||
+ | nfs-nginx-6b4db6f57-4mczr | ||
+ | nfs-provisioner-7795cf6f4-d7m2l | ||
+ | ubuntu@k8s-master: | ||
+ | </ | ||
+ | |||
+ | Eurika, finally we are done with both types of privisioning |