Kubernetes + Heketi

February 01, 2018 0 Comments Kubernetes, GlusterFS, Heketi

Passiamo ora a parlare dello storage in Kubernetes. Il modo più ovvio per creare i persistent volumes e i persistent volume claims è il modo manuale.
Si sceglie l'eventuale driver e si confiugrano i persistent volumes che poi verranno utilizzati dai persistent volume claims.

Tutto ciò però rende macchinosa e lenta la gestione dello storage in kubernetes. Per questo motivo sono stati creati dei sistemi di volume management con i quali si possono creare persistent volumes on demand tramite i persistent volume claims che vengono richiesti. Questa funzionalità si basa su un altro concetto di Kubernetes chiamato Storage Classes.

In questa guida vedremo come attivare Heketi, un provisioner che gestisce volumi basati su tecnologia GlusterFS. Questi volumi avranno come proprietà intrinseca la ridondanza e l'HA, perché creeremo una topologia basata sul mirroring di 3 nodi.

Il requisito per poter seguire questa guida passo passo è:

  • Un cluster Kubernetes esistente
  • Poter aggiungere 3 nodi kubernetes i quali hanno ognuno un disco aggiuntivo collegato alla macchina (in parole povere un /dev/sdb non formattato)

Nel mio caso ho 3 nodi aggiuntivi che ho chiamato diversamente per poterli riconoscere:

> kubectl get nodes
NAME                                          STATUS    ROLES     AGE       VERSION  
nodokube-1.c.nth-passage-183120.internal      Ready     <none>    1d        v1.8.10-rancher1  
nodokube-2.c.nth-passage-183120.internal      Ready     <none>    1d        v1.8.10-rancher1  
nodokube-3.c.nth-passage-183120.internal      Ready     <none>    1d        v1.8.10-rancher1  
nodokube-4.c.nth-passage-183120.internal      Ready     <none>    1d        v1.8.10-rancher1  
nodokube-6-g1.c.nth-passage-183120.internal   Ready     <none>    1d        v1.8.10-rancher1  
nodokube-7-g2.c.nth-passage-183120.internal   Ready     <none>    1d        v1.8.10-rancher1  
nodokube-8-g3.c.nth-passage-183120.internal   Ready     <none>    1d        v1.8.10-rancher1  
  • nodokube-6-g1
  • nodokube-7-g2
  • nodokube-8-g3

Questi 3 nodi contengono un disco aggiuntivo ssd da 30GB l'uno collegato in /dev/sdb.

Quello che faremo sarà seguire la guida presente in https://github.com/heketi/heketi/blob/master/docs/admin/install-kubernetes.md

Verifichiamo il firewall

Nel mio caso i nodi sono tutti ubuntu, quindi non ho bisogno di aprire alcuna porta nel firewall. Nel caso in cui siano CentOs o altre distribuizioni, bisogna lanciare i comandi di iptables per aprire le porte di gluster nei nodi interessati:

iptables -N HEKETI  
iptables -A HEKETI -p tcp -m state --state NEW -m tcp --dport 24007 -j ACCEPT  
iptables -A HEKETI -p tcp -m state --state NEW -m tcp --dport 24008 -j ACCEPT  
iptables -A HEKETI -p tcp -m state --state NEW -m tcp --dport 2222 -j ACCEPT  
iptables -A HEKETI -p tcp -m state --state NEW -m multiport --dports 49152:49251 -j ACCEPT  
service iptables save  


Prerequisiti aggiuntivi

Nella guida ufficiale non sono indicati alcuni passaggi fondamentali, tra cui aggiungere in tutti i nodi del cluster il driver per il collegamento ad un volume gluster e ai 3 nodi che conterranno i pod di glusterfs la possibilità di gestire volumi in thin provision.

Dobbiamo quindi fare in tutti i nodi questi due comandi:

apt-get install -y glusterfs-client  
modprobe dm_thin_pool  


Deploy

GlusterFS daemonset

Creiamo il primo file, glusterfs-daemonset.json

{
    "kind": "DaemonSet",
    "apiVersion": "extensions/v1beta1",
    "metadata": {
        "name": "glusterfs",
        "labels": {
            "glusterfs": "deployment"
        },
        "annotations": {
            "description": "GlusterFS Daemon Set",
            "tags": "glusterfs"
        }
    },
    "spec": {
        "template": {
            "metadata": {
                "name": "glusterfs",
                "labels": {
                    "glusterfs-node": "daemonset"
                }
            },
            "spec": {
                "nodeSelector": {
                    "storagenode" : "glusterfs"
                },
                "hostNetwork": true,
                "containers": [
                    {
                        "image": "gluster/gluster-centos:latest",
                        "imagePullPolicy": "Always",
                        "name": "glusterfs",
                        "volumeMounts": [
                            {
                                "name": "glusterfs-heketi",
                                "mountPath": "/var/lib/heketi"
                            },
                            {
                                "name": "glusterfs-run",
                                "mountPath": "/run"
                            },
                            {
                                "name": "glusterfs-lvm",
                                "mountPath": "/run/lvm"
                            },
                            {
                                "name": "glusterfs-etc",
                                "mountPath": "/etc/glusterfs"
                            },
                            {
                                "name": "glusterfs-logs",
                                "mountPath": "/var/log/glusterfs"
                            },
                            {
                                "name": "glusterfs-config",
                                "mountPath": "/var/lib/glusterd"
                            },
                            {
                                "name": "glusterfs-dev",
                                "mountPath": "/dev"
                            },
                            {
                                "name": "glusterfs-cgroup",
                                "mountPath": "/sys/fs/cgroup"
                            }
                        ],
                        "securityContext": {
                            "capabilities": {},
                            "privileged": true
                        },
                        "readinessProbe": {
                            "timeoutSeconds": 3,
                            "initialDelaySeconds": 60,
                            "exec": {
                                "command": [
                                    "/bin/bash",
                                    "-c",
                                    "systemctl status glusterd.service"
                                ]
                            }
                        },
                        "livenessProbe": {
                            "timeoutSeconds": 3,
                            "initialDelaySeconds": 60,
                            "exec": {
                                "command": [
                                    "/bin/bash",
                                    "-c",
                                    "systemctl status glusterd.service"
                                ]
                            }
                        }
                    }
                ],
                "volumes": [
                    {
                        "name": "glusterfs-heketi",
                        "hostPath": {
                            "path": "/var/lib/heketi"
                        }
                    },
                    {
                        "name": "glusterfs-run"
                    },
                    {
                        "name": "glusterfs-lvm",
                        "hostPath": {
                            "path": "/run/lvm"
                        }
                    },
                    {
                        "name": "glusterfs-etc",
                        "hostPath": {
                            "path": "/etc/glusterfs"
                        }
                    },
                    {
                        "name": "glusterfs-logs",
                        "hostPath": {
                            "path": "/var/log/glusterfs"
                        }
                    },
                    {
                        "name": "glusterfs-config",
                        "hostPath": {
                            "path": "/var/lib/glusterd"
                        }
                    },
                    {
                        "name": "glusterfs-dev",
                        "hostPath": {
                            "path": "/dev"
                        }
                    },
                    {
                        "name": "glusterfs-cgroup",
                        "hostPath": {
                            "path": "/sys/fs/cgroup"
                        }
                    }
                ]
            }
        }
    }
}

E lanciamo il comando di creazione

$ kubectl create -f glusterfs-daemonset.json
daemonset "glusterfs" created  

A questo punto non abbiamo ancora i pod di glusterfs avviati, bisogna prima taggare i nodi con la chiave corretta. Procediamo quindi al tag come indicato nel daemonset

"spec": {
                "nodeSelector": {
                    "storagenode" : "glusterfs"
                }
$ kubectl label node nodokube-6-g1.c.nth-passage-183120.internal storagenode=glusterfs
node "nodokube-6-g1.c.nth-passage-183120.internal" labeled  
$ kubectl label node nodokube-7-g2.c.nth-passage-183120.internal storagenode=glusterfs
node "nodokube-7-g2.c.nth-passage-183120.internal" labeled  
$ kubectl label node nodokube-8-g3.c.nth-passage-183120.internal storagenode=glusterfs
node "nodokube-8-g3.c.nth-passage-183120.internal" labeled  

A questo punto il daemonset troverà i nodi con il tag corretto e procederà alla creazione dei pod:

$ kubectl get pods
NAME              READY     STATUS    RESTARTS   AGE  
glusterfs-296z2   0/1       Running   0          36s  
glusterfs-4cd5v   0/1       Running   0          32s  
glusterfs-pgvgt   0/1       Running   0          40s  
$ kubectl get pods
NAME              READY     STATUS    RESTARTS   AGE  
glusterfs-296z2   1/1       Running   0          2m  
glusterfs-4cd5v   1/1       Running   0          1m  
glusterfs-pgvgt   1/1       Running   0          2m  


Heketi service account

Ora dobbiamo creare un service account per heketi, creiamo il file heketi-service-account.json

{
  "apiVersion": "v1",
  "kind": "ServiceAccount",
  "metadata": {
    "name": "heketi-service-account"
  }
}

e lanciamo quindi il comando di creazione:

$ kubectl create -f heketi-service-account.json
serviceaccount "heketi-service-account" created  

Ora dobbiamo fare in modo che questo service account possa controllare i pod glusterfs. Creiamo quindi un role binding al service account appena creato

$ kubectl create clusterrolebinding heketi-gluster-admin --clusterrole=edit --serviceaccount=default:heketi-service-account
clusterrolebinding "heketi-gluster-admin" created  

A questo punto creiamo un secret che avrà al suo interno le configurazioni dell'istanza di Heketi. La configurazione dovrà contenere il kubernetes executor per far si che il server Heketi possa controllare i pod glusterfs.

Creiamo quindi il file heketi.json

{
  "_port_comment": "Heketi Server Port Number",
  "port": "8080",

  "_use_auth": "Enable JWT authorization. Please enable for deployment",
  "use_auth": false,

  "_jwt": "Private keys for access",
  "jwt": {
    "_admin": "Admin has access to all APIs",
    "admin": {
      "key": "My Secret"
    },
    "_user": "User only has access to /volumes endpoint",
    "user": {
      "key": "My Secret"
    }
  },

  "_glusterfs_comment": "GlusterFS Configuration",
  "glusterfs": {
    "_executor_comment": "Execute plugin. Possible choices: mock, kubernetes, ssh",
    "executor": "kubernetes",

    "_db_comment": "Database file name",
    "db": "/var/lib/heketi/heketi.db",

    "kubeexec": {
      "rebalance_on_expansion": true
    },

    "sshexec": {
      "rebalance_on_expansion": true,
      "keyfile": "/etc/heketi/private_key",
      "fstab": "/etc/fstab",
      "port": "22",
      "user": "root",
      "sudo": false
    }
  },

  "_backup_db_to_kube_secret": "Backup the heketi database to a Kubernetes secret when running in Kubernetes. Default is off.",
  "backup_db_to_kube_secret": false
}

ATTENZIONE in questo esempio abbiamo disattivato l'autenticazione.

Lanciamo la creazione di questo secret:

$ kubectl create secret generic heketi-config-secret --from-file=./heketi.json
secret "heketi-config-secret" created  


Avvio del pod di bootstrap di Heketi

A questo punto lanciamo un pod di bootstrap che si occuperà di creare il nostro cluster e di salvare la configurazione di heketi per il deploy successivo di produzione.

Creiamo il file heketi-bootstrap.json

{
  "kind": "List",
  "apiVersion": "v1",
  "items": [
    {
      "kind": "Service",
      "apiVersion": "v1",
      "metadata": {
        "name": "deploy-heketi",
        "labels": {
          "glusterfs": "heketi-service",
          "deploy-heketi": "support"
        },
        "annotations": {
          "description": "Exposes Heketi Service"
        }
      },
      "spec": {
        "selector": {
          "name": "deploy-heketi"
        },
        "ports": [
          {
            "name": "deploy-heketi",
            "port": 8080,
            "targetPort": 8080
          }
        ]
      }
    },
    {
      "kind": "Deployment",
      "apiVersion": "extensions/v1beta1",
      "metadata": {
        "name": "deploy-heketi",
        "labels": {
          "glusterfs": "heketi-deployment",
          "deploy-heketi": "deployment"
        },
        "annotations": {
          "description": "Defines how to deploy Heketi"
        }
      },
      "spec": {
        "replicas": 1,
        "template": {
          "metadata": {
            "name": "deploy-heketi",
            "labels": {
              "name": "deploy-heketi",
              "glusterfs": "heketi-pod",
              "deploy-heketi": "pod"
            }
          },
          "spec": {
            "serviceAccountName": "heketi-service-account",
            "containers": [
              {
                "image": "heketi/heketi:dev",
                "imagePullPolicy": "Always",
                "name": "deploy-heketi",
                "env": [
                  {
                    "name": "HEKETI_EXECUTOR",
                    "value": "kubernetes"
                  },
                  {
                    "name": "HEKETI_FSTAB",
                    "value": "/var/lib/heketi/fstab"
                  },
                  {
                    "name": "HEKETI_SNAPSHOT_LIMIT",
                    "value": "14"
                  },
                  {
                    "name": "HEKETI_KUBE_GLUSTER_DAEMONSET",
                    "value": "y"
                  }
                ],
                "ports": [
                  {
                    "containerPort": 8080
                  }
                ],
                "volumeMounts": [
                  {
                    "name": "db",
                    "mountPath": "/var/lib/heketi"
                  },
                  {
                    "name": "config",
                    "mountPath": "/etc/heketi"
                  }
                ],
                "readinessProbe": {
                  "timeoutSeconds": 3,
                  "initialDelaySeconds": 3,
                  "httpGet": {
                    "path": "/hello",
                    "port": 8080
                  }
                },
                "livenessProbe": {
                  "timeoutSeconds": 3,
                  "initialDelaySeconds": 30,
                  "httpGet": {
                    "path": "/hello",
                    "port": 8080
                  }
                }
              }
            ],
            "volumes": [
              {
                "name": "db"
              },
              {
                "name": "config",
                "secret": {
                  "secretName": "heketi-config-secret"
                }
              }
            ]
          }
        }
      }
    }
  ]
}

e quindi lanciamolo, verra creato un service e un deployment chiamati deploy-heketi:

$ kubectl create -f heketi-bootstrap.json
service "deploy-heketi" created  
deployment "deploy-heketi" created  

Verifichiamo lo stato del pod:

$ kubectl get pods
NAME                             READY     STATUS    RESTARTS   AGE  
deploy-heketi-6b496b5777-9f2rp   0/1       Running   0          26s  
glusterfs-296z2                  1/1       Running   0          1h  
glusterfs-4cd5v                  1/1       Running   0          1h  
glusterfs-pgvgt                  1/1       Running   0          1h  
kubectl get pods  
NAME                             READY     STATUS    RESTARTS   AGE  
deploy-heketi-6b496b5777-9f2rp   1/1       Running   0          1m  
glusterfs-296z2                  1/1       Running   0          1h  
glusterfs-4cd5v                  1/1       Running   0          1h  
glusterfs-pgvgt                  1/1       Running   0          1h  

Ora che abbiamo lanciato il pod di bootstrap possiamo configurare il portforwarding nella nostra macchina per utilizzare heketi-cli (scaricate heketi-cli da https://github.com/heketi/heketi/releases/).

Prendiamo il nome del pod di heketi, nel mio caso deploy-heketi-6b496b5777-9f2rp e lanciamo il seguente comando

$ kubectl port-forward deploy-heketi-6b496b5777-9f2rp :8080
Forwarding from 127.0.0.1:64622 -> 8080  

Nel mio caso è stato fatto il forward della porta 64622 del mio host verso il pod di deploy-heketi.

Verifichiamone il funzionamento:

$ curl http://localhost:64622/hello
Hello from Heketi  

Settiamoci per comidita la variabile d'ambiente contenente l'indirizzo di heketi in modo da non dover scrivere ogni volta l'indirizzo del pod

$ export HEKETI_CLI_SERVER=http://localhost:64622


Caricamento topologia server gluster

A questo punto dobbiamo caricare la topologia dei nostri nodi contenenti i pod daemonset di glusterfs, indicando anche qual'è il disco della macchina che verrà formattato per l'utilizzo con i volumi di glusterfs.

Creiamo il file topology-load.json

{
  "clusters": [
    {
      "nodes": [
        {
          "node": {
            "hostnames": {
              "manage": [
                "nodokube-6-g1.c.nth-passage-183120.internal"
              ],
              "storage": [
                "10.142.0.8"
              ]
            },
            "zone": 1
          },
          "devices": [
            "/dev/sdb"
          ]
        },
        {
          "node": {
            "hostnames": {
              "manage": [
                "nodokube-7-g2.c.nth-passage-183120.internal"
              ],
              "storage": [
                "10.142.0.9"
              ]
            },
            "zone": 1
          },
          "devices": [
            "/dev/sdb"
          ]
        },
        {
          "node": {
            "hostnames": {
              "manage": [
                "nodokube-8-g3.c.nth-passage-183120.internal"
              ],
              "storage": [
                "10.142.0.7"
              ]
            },
            "zone": 1
          },
          "devices": [
            "/dev/sdb"
          ]
        }
      ]
    }
  ]
}

Notiamo alcuni parametri:

  • storage: è stato inserito l'ip fisso del nodo contenente il pod
  • manage: è stato inserito l'hostname del nodo, nel mio caso nodokube-6-g1.c.nth-passage-183120.internal, etc
  • devices: è stato inserito il path del disco aggiunto alla macchina virtuale

Carichiamo quindi la topologia via heketi-cli nel nostro pod heketi:

$ ./heketi-cli topology load --json=topology-load.json
Creating cluster ... ID: 9ed46f67a517d5e46b9245e1214c2c03  
    Allowing file volumes on cluster.
    Allowing block volumes on cluster.
    Creating node nodokube-6-g1.c.nth-passage-183120.internal ... ID: 0379d0bb941a80c6ec65fed344306602
        Adding device /dev/sdb ... OK
    Creating node nodokube-7-g2.c.nth-passage-183120.internal ... ID: 7d271bdb173887adc09ecfc677604378
        Adding device /dev/sdb ... OK
    Creating node nodokube-8-g3.c.nth-passage-183120.internal ... ID: 8a547e452d0442f7e44a317e75c9fba8
        Adding device /dev/sdb ... OK


Salvataggio database di heketi in un volume gluster

Qui arriva un punto abbastanza "magico". Dobbiamo creare un volume provisionato da deploy-heketi che verrà poi usato dal vero pod heketi che utlizzeremo.

Chidiamo a heketi di crearci il volume

$ ./heketi-cli setup-openshift-heketi-storage
Saving heketi-storage.json  
$ kubectl create -f heketi-storage.json
secret "heketi-storage-secret" created  
endpoints "heketi-storage-endpoints" created  
service "heketi-storage-endpoints" created  
job "heketi-storage-copy-job" created  

Dobbiamo attendere che il job sia completato, dopodiché possiamo procedere all'eliminazione dei pod di deploy

Verifichiamo lo stato con:

$ kubectl get jobs
NAME                      DESIRED   SUCCESSFUL   AGE  
heketi-storage-copy-job   1         1            1m  

Eliminiamo il deploy di bootstrap:

$ kubectl delete all,service,jobs,deployment,secret --selector="deploy-heketi"
deployment "deploy-heketi" deleted  
job "heketi-storage-copy-job" deleted  
pod "deploy-heketi-6b496b5777-9f2rp" deleted  
service "deploy-heketi" deleted  
secret "heketi-storage-secret" deleted  


Creazione del long-term Heketi

Creiamo il file di deploy di heketi finale, heketi-deployment.json

{
  "kind": "List",
  "apiVersion": "v1",
  "items": [
    {
      "kind": "Secret",
      "apiVersion": "v1",
      "metadata": {
        "name": "heketi-db-backup",
        "labels": {
          "glusterfs": "heketi-db",
          "heketi": "db"
        }
      },
      "data": {
      },
      "type": "Opaque"
    },
    {
      "kind": "Service",
      "apiVersion": "v1",
      "metadata": {
        "name": "heketi",
        "labels": {
          "glusterfs": "heketi-service",
          "deploy-heketi": "support"
        },
        "annotations": {
          "description": "Exposes Heketi Service"
        }
      },
      "spec": {
        "selector": {
          "name": "heketi"
        },
        "ports": [
          {
            "name": "heketi",
            "port": 8080,
            "targetPort": 8080
          }
        ]
      }
    },
    {
      "kind": "Deployment",
      "apiVersion": "extensions/v1beta1",
      "metadata": {
        "name": "heketi",
        "labels": {
          "glusterfs": "heketi-deployment"
        },
        "annotations": {
          "description": "Defines how to deploy Heketi"
        }
      },
      "spec": {
        "replicas": 1,
        "template": {
          "metadata": {
            "name": "heketi",
            "labels": {
              "name": "heketi",
              "glusterfs": "heketi-pod"
            }
          },
          "spec": {
            "serviceAccountName": "heketi-service-account",
            "containers": [
              {
                "image": "heketi/heketi:dev",
                "imagePullPolicy": "Always",
                "name": "heketi",
                "env": [
                  {
                    "name": "HEKETI_EXECUTOR",
                    "value": "kubernetes"
                  },
                  {
                    "name": "HEKETI_FSTAB",
                    "value": "/var/lib/heketi/fstab"
                  },
                  {
                    "name": "HEKETI_SNAPSHOT_LIMIT",
                    "value": "14"
                  },
                  {
                    "name": "HEKETI_KUBE_GLUSTER_DAEMONSET",
                    "value": "y"
                  }
                ],
                "ports": [
                  {
                    "containerPort": 8080
                  }
                ],
                "volumeMounts": [
                  {
                    "mountPath": "/backupdb",
                    "name": "heketi-db-secret"
                  },
                  {
                    "name": "db",
                    "mountPath": "/var/lib/heketi"
                  },
                  {
                    "name": "config",
                    "mountPath": "/etc/heketi"
                  }
                ],
                "readinessProbe": {
                  "timeoutSeconds": 3,
                  "initialDelaySeconds": 3,
                  "httpGet": {
                    "path": "/hello",
                    "port": 8080
                  }
                },
                "livenessProbe": {
                  "timeoutSeconds": 3,
                  "initialDelaySeconds": 30,
                  "httpGet": {
                    "path": "/hello",
                    "port": 8080
                  }
                }
              }
            ],
            "volumes": [
              {
                "name": "db",
                "glusterfs": {
                  "endpoints": "heketi-storage-endpoints",
                  "path": "heketidbstorage"
                }
              },
              {
                "name": "heketi-db-secret",
                "secret": {
                  "secretName": "heketi-db-backup"
                }
              },
              {
                "name": "config",
                "secret": {
                  "secretName": "heketi-config-secret"
                }
              }
            ]
          }
        }
      }
    }
  ]
}

Lanciamo il deploy:

$ kubectl create -f heketi-deployment.json
service "heketi" created  
deployment "heketi" created  

Ricreiamoci la regola di forward per testare che heketi funzioni

$ kubectl get pods
NAME                     READY     STATUS    RESTARTS   AGE  
glusterfs-296z2          1/1       Running   0          2h  
glusterfs-4cd5v          1/1       Running   0          2h  
glusterfs-pgvgt          1/1       Running   0          2h  
heketi-84684b87c-hqgld   1/1       Running   0          24s  
$ kubectl port-forward heketi-84684b87c-hqgld :8080
Forwarding from 127.0.0.1:49337 -> 8080  
$ export HEKETI_CLI_SERVER=http://localhost:49337

Verifichiamo il cluster:

$ ./heketi-cli cluster list
Clusters:  
Id:9ed46f67a517d5e46b9245e1214c2c03 [file][block]  
$ ./heketi-cli volume list
Id:e38d822489a5a5401f30c41d3c24fb8c    Cluster:9ed46f67a517d5e46b9245e1214c2c03    Name:heketidbstorage  


Creiamo una Storage Classes

Per prima cosa dobbiamo scoprire qual'è il clusterip del pod heketi:

$ kubectl get svc
NAME                       TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE  
heketi                     ClusterIP   10.43.105.131   <none>        8080/TCP   9m  
heketi-storage-endpoints   ClusterIP   10.43.124.82    <none>        1/TCP      14m  
kubernetes                 ClusterIP   10.43.0.1       <none>        443/TCP    1d  

Nel mio caso 10.43.105.131. Creiamo il file heketi-storageclasses.yaml

apiVersion: storage.k8s.io/v1beta1  
kind: StorageClass  
metadata:  
  name: gluster-heketi
provisioner: kubernetes.io/glusterfs  
parameters:  
  resturl: "http://10.43.105.131:8080"
  restuser: "joe" # non servono nell'esempio non essendoci autenticazione
  restuserkey: "My Secret Life" # non servono nell'esempio non essendoci autenticazione

E creiamola con:

$ kubectl create -f heketi-storageclasses.yaml
storageclass "gluster-heketi" created  

Rendiamola default per tutti i prossimi deployment che utilizzando persistent volume claim:

$ kubectl patch storageclass gluster-heketi -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
storageclass "gluster-heketi" patched  


PVC di test!

Creiamo finalmente il nostro persistent volume claim di test, chiamiamolo test-pvc.yml:

apiVersion: v1  
kind: PersistentVolumeClaim  
metadata:  
 name: gluster1
 annotations:
   volume.beta.kubernetes.io/storage-class: gluster-heketi
spec:  
 accessModes:
  - ReadWriteMany
 resources:
   requests:
     storage: 2Gi

Ora arriva il momento della verità, la richiesta di creare un persistent volume al volo a heketi.

$ kubectl create -f test-pvc.yaml
persistentvolumeclaim "gluster1" created  

Verifichiamo:

$ kubectl get pvc,pv
NAME           STATUS    VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS     AGE  
pvc/gluster1   Bound     pvc-9fd5feda-3725-11e8-902a-02611b0ceca9   2Gi        RWX            gluster-heketi   25s

NAME                                          CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS    CLAIM              STORAGECLASS     REASON    AGE  
pv/pvc-9fd5feda-3725-11e8-902a-02611b0ceca9   2Gi        RWX            Delete           Bound     default/gluster1   gluster-heketi             19s  

YEAH ci siamo riusciti! Ora non dovremo più preoccuparci di dover creare manualmente i pv all'interno di kubernetes!

Samuele Chiocca
Padova, italy Website