Terug

Je weg vinden in OVHcloud File Storage met Manila CSI (RWX) op Kubernetes-clusters (MKS)

Aurélie Vache12 min leestijd

Je weg vinden in OVHcloud File Storage met Manila CSI (RWX) op Kubernetes-clusters (MKS)

Als je stateful applicaties op Kubernetes draait, is een veelvoorkomende uitdaging het bieden van gedeelde persistente opslag die toegankelijk is voor meerdere workloads.

Terwijl Kubernetes Persistent Volumes meestal vertrouwen op Block Storage met ReadWriteOnce-toegang, hebben sommige applicaties toegang tot een gedeeld bestandssysteem met ReadWriteMany (RWX)-mogelijkheden nodig.

OVHcloud File Storage biedt beheerde NFS-shares die dynamisch kunnen worden gebruikt door Kubernetes-workloads door middel van de Manila CSI-driver.

In deze blogpost bekijken we hoe je OVHcloud File Storage integreert met OVHcloud Managed Kubernetes Service (MKS) met behulp van Manila CSI en testen we de RWX-opslagmogelijkheden.

OVHcloud File Storage

OVHcloud File Storage beheerde NFS-shares voor cloud-native Kubernetes-workloads.

OVHcloud Public Cloud File Storage is een volledig gemanagede, gedeelde bestandsopslagdienst die ontworpen is voor cloud-native workloads die op Public Cloud-instances en Kubernetes-clusters draaien.

Het is gebouwd op OpenStack Manila en biedt gedeelde NFSv3-volumes die gelijktijdig door meerdere clients kunnen worden gekoppeld, waardoor het een ideale oplossing is voor applicaties die ReadWriteMany (RWX)-toegang vereisen. Volumes kunnen worden ingericht van 150 GiB tot 10 TiB, met voorspelbare, lineaire prestaties die schalen met de toegewezen capaciteit.

Omdat de service volledig wordt beheerd, hoef je niet je eigen NFS-server te implementeren of te onderhouden. File Storage integreert met het OVHcloud-platform, zoals het Control Panel, API, CLI, Terraform-provider en Kubernetes, via de Manila CSI-driver, waardoor gedeelde volumes direct vanuit je cluster dynamisch kunnen worden ingericht.

Waarom Manila CSI gebruiken?

De Kubernetes Container Storage Interface (CSI) biedt een standaardmechanisme voor het aan Kubernetes tonen van externe opslagsystemen.

In plaats van handmatig NFS-mounts en PersistentVolumes aan te maken, kan Kubernetes met de Manila CSI-driver dynamisch bestandsshares aanmaken en managen met behulp van Kubernetes-resources, zoals StorageClasses (SC), PersistentVolumeClaims (PVC) en PersistentVolumes (PV).

Vereisten

Voordat je begint, heb je het volgende nodig:

  • Een OVHcloud Public Cloud-project
  • Een OVHcloud Managed Kubernetes Service (MKS)-cluster dat verbonden is met een privénetwerk
  • Terraform CLI geïnstalleerd
  • kubectl CLI geïnstalleerd

Manila CSI stap voor stap implementeren: we gaan ervoor!

We hebben al een MKS-cluster in de regio EU-WEST-PAR, dat draait binnen een privénetwerk en een subnet. In deze blogpost zullen we:

  • een Public Cloud-gebruiker aanmaken voor de Manila CSI-driver
  • de CSI NFS-driver installeren
  • de Manila CSI-driver installeren
  • een Secret voor Manila CSI implementeren waarmee de Manila CSI-driver zich bij OpenStack kan authentificeren en Manila-resources in je cluster kan beheren
  • een gedeeld netwerk voor bestanden aanmaken
  • een ConfigMap implementeren om de Manila CSI-driver te configureren
  • csi-manila-nfs StorageClass implementeren zodat de Manila CSI-driver dynamisch Manila-shares kan aanmaken en deze als Kubernetes-volumes kan gebruiken

We gebruiken Terraform om deze architectuur eenvoudig te implementeren.

Maak een provider.tf bestand aan en vul dit met de informatie:

bash
terraform {
  required_providers {
    helm = {
      source = "hashicorp/helm"
    }

    kubectl = {
      source = "alekc/kubectl"
      version = "2.1.6"
    }

    ovh = {
      source = "ovh/ovh"
    }
  }
}

provider "helm" {
  kubernetes = {
    host                   = data.ovh_cloud_project_kube.mks_cluster.kubeconfig_attributes[0].host
    client_certificate     = base64decode(data.ovh_cloud_project_kube.mks_cluster.kubeconfig_attributes[0].client_certificate)
    client_key             = base64decode(data.ovh_cloud_project_kube.mks_cluster.kubeconfig_attributes[0].client_key)
    cluster_ca_certificate = base64decode(data.ovh_cloud_project_kube.mks_cluster.kubeconfig_attributes[0].cluster_ca_certificate)
  }
}

provider "kubectl" {
  host                   = data.ovh_cloud_project_kube.mks_cluster.kubeconfig_attributes[0].host
  client_certificate     = base64decode(data.ovh_cloud_project_kube.mks_cluster.kubeconfig_attributes[0].client_certificate)
  client_key             = base64decode(data.ovh_cloud_project_kube.mks_cluster.kubeconfig_attributes[0].client_key)
  cluster_ca_certificate = base64decode(data.ovh_cloud_project_kube.mks_cluster.kubeconfig_attributes[0].cluster_ca_certificate)
  load_config_file       = false
}

Stel de omgevingsvariabelen in voor de OVHcloud Terraform-provider met je inloggegevens:

bash
# OVHcloud provider needed keys
export OVH_ENDPOINT="ovh-eu"
export OVH_APPLICATION_KEY="xxx"
export OVH_APPLICATION_SECRET="xxx"
export OVH_CONSUMER_KEY="xxx"
export OVH_CLOUD_PROJECT_SERVICE="xxx"

Maak een variables.tf.template bestand aan en vul dit met deze informatie:

bash
variable "service_name" {
  default = "$OVH_CLOUD_PROJECT_SERVICE"
}

variable "mks_cluster_id" {
  default = "<your_mks_cluster_id>"
}

⚠️ Vervang in het bestand de MKS ID door de gegevens van uw bestaande MKS-cluster-ID.

Vervang de waarde van de OVH_CLOUD_PROJECT_SERVICE omgevingsvariabele in het variables.tf bestand:

bash
envsubst < variables.tf.template > variables.tf

Maak een nfs_share.tf bestand aan en vul dit met deze informatie:

markdown
data "ovh_cloud_project_kube" "mks_cluster" {
  service_name = var.service_name
  kube_id      = var.mks_cluster_id
}

data "ovh_cloud_network_private_vrack_subnet" "mks_cluster_subnet" {
  service_name = var.service_name
  network_id   = data.ovh_cloud_project_kube.mks_cluster.private_network_id
  id           = data.ovh_cloud_project_kube.mks_cluster.nodes_subnet_id
}

# CSI Manila

module "csi_manila" {
  source = "git::https://github.com/ovh/public-cloud-examples.git//containers-orchestration/managed-kubernetes/install-csi-manila/modules/ovhcloud/csi_manila?ref=v1.5.0"

  service_name       = var.service_name
  region             = data.ovh_cloud_project_kube.mks_cluster.region
  share_network_name = "${data.ovh_cloud_project_kube.mks_cluster.name}-share-network"
  network_id         = data.ovh_cloud_project_kube.mks_cluster.private_network_id
  subnet_id          = data.ovh_cloud_project_kube.mks_cluster.nodes_subnet_id
  subnet_cidr        = data.ovh_cloud_network_private_vrack_subnet.mks_cluster_subnet.cidr
}

output "manila-user" {
  value = module.csi_manila.manila-user
}

💡In dit Terraform-bestand gebruiken we een bestaande csi_manila Terraform-module die wordt gehost in de OVHcloud Public Cloud Examples GitHub-repository.

De Terraform-configuratie is klaar. Laten we deze initialiseren:

bash
terraform init

De output zou als volgt moeten zijn:

bash
$ terraform init

Initializing the backend...
Initializing modules...
Downloading git::https://github.com/ovh/public-cloud-examples.git?ref=v1.5.0 for csi_manila...
- csi_manila in .terraform/modules/csi_manila/containers-orchestration/managed-kubernetes/install-csi-manila/modules/ovhcloud/csi_manila
Initializing provider plugins...
- Reusing previous version of hashicorp/helm from the dependency lock file
- Reusing previous version of alekc/kubectl from the dependency lock file
- Reusing previous version of ovh/ovh from the dependency lock file
- Installing hashicorp/helm v3.2.0...
- Installed hashicorp/helm v3.2.0 (signed by HashiCorp)
- Installing alekc/kubectl v2.1.6...
- Installed alekc/kubectl v2.1.6 (self-signed, key ID 772FB27A86DAFCE7)
- Installing ovh/ovh v2.16.1...
- Installed ovh/ovh v2.16.1 (signed by a HashiCorp partner, key ID F56D1A6CBDAAADA5)
Partner and community providers are signed by their developers.
If you'd like to know more about provider signing, you can read about it here:
https://developer.hashicorp.com/terraform/cli/plugins/signing

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

Pas het toe:

bash
terraform apply

De output zou als volgt moeten zijn:

bash
$ terraform apply

data.ovh_cloud_project_kube.mks_cluster: Reading...
data.ovh_cloud_project_kube.mks_cluster: Read complete after 1s [id=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx]
data.ovh_cloud_network_private_vrack_subnet.mks_cluster_subnet: Reading...
data.ovh_cloud_network_private_vrack_subnet.mks_cluster_subnet: Read complete after 1s [id=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # module.csi_manila.helm_release.csi-driver-nfs will be created
  + resource "helm_release" "csi-driver-nfs" {
      + atomic                     = false
      + chart                      = "csi-driver-nfs"
      + cleanup_on_fail            = false
      + create_namespace           = false
      + dependency_update          = false
      + disable_crd_hooks          = false
      + disable_openapi_validation = false
      + disable_webhooks           = false
      + force_update               = false
      + id                         = (known after apply)
      + lint                       = false
      + max_history                = 0
      + metadata                   = (known after apply)
      + name                       = "csi-driver-nfs"
      + namespace                  = "kube-system"
      + pass_credentials           = false
      + recreate_pods              = false
      + render_subchart_notes      = true
      + replace                    = false
      + repository                 = "https://raw.githubusercontent.com/kubernetes-csi/csi-driver-nfs/master/charts"
      + reset_values               = false
      + reuse_values               = false
      + set_wo                     = (write-only attribute)
      + skip_crds                  = false
      + status                     = "deployed"
      + take_ownership             = false
      + timeout                    = 300
      + upgrade_install            = false
      + verify                     = false
      + version                    = "4.13.4"
      + wait                       = true
      + wait_for_jobs              = false
    }

  # module.csi_manila.helm_release.openstack-manila-csi will be created
  + resource "helm_release" "openstack-manila-csi" {
      + atomic                     = false
      + chart                      = "openstack-manila-csi"
      + cleanup_on_fail            = false
      + create_namespace           = false
      + dependency_update          = false
      + disable_crd_hooks          = false
      + disable_openapi_validation = false
      + disable_webhooks           = false
      + force_update               = false
      + id                         = (known after apply)
      + lint                       = false
      + max_history                = 0
      + metadata                   = (known after apply)
      + name                       = "openstack-manila-csi"
      + namespace                  = "kube-system"
      + pass_credentials           = false
      + recreate_pods              = false
      + render_subchart_notes      = true
      + replace                    = false
      + repository                 = "https://kubernetes.github.io/cloud-provider-openstack"
      + reset_values               = false
      + reuse_values               = false
      + set_wo                     = (write-only attribute)
      + skip_crds                  = false
      + status                     = "deployed"
      + take_ownership             = false
      + timeout                    = 300
      + upgrade_install            = false
      + verify                     = false
      + version                    = "2.36.0"
      + wait                       = true
      + wait_for_jobs              = false
    }

  # module.csi_manila.kubectl_manifest.csi-manila-secrets will be created
  + resource "kubectl_manifest" "csi-manila-secrets" {
      + api_version             = (known after apply)
      + apply_only              = false
      + field_manager           = "kubectl"
      + force_conflicts         = false
      + force_new               = false
      + id                      = (known after apply)
      + kind                    = (known after apply)
      + live_manifest_incluster = (sensitive value)
      + live_uid                = (known after apply)
      + name                    = (known after apply)
      + namespace               = (known after apply)
      + server_side_apply       = false
      + uid                     = (known after apply)
      + validate_schema         = true
      + wait_for_rollout        = true
      + yaml_body               = (sensitive value)
      + yaml_body_parsed        = (known after apply)
      + yaml_incluster          = (sensitive value)
    }

  # module.csi_manila.kubectl_manifest.manila-runtime-configmap will be created
  + resource "kubectl_manifest" "manila-runtime-configmap" {
      + api_version             = "v1"
      + apply_only              = false
      + field_manager           = "kubectl"
      + force_conflicts         = false
      + force_new               = false
      + id                      = (known after apply)
      + kind                    = "ConfigMap"
      + live_manifest_incluster = (sensitive value)
      + live_uid                = (known after apply)
      + name                    = "manila-csi-runtimeconf-cm"
      + namespace               = "default"
      + server_side_apply       = false
      + uid                     = (known after apply)
      + validate_schema         = true
      + wait_for_rollout        = true
      + yaml_body               = (sensitive value)
      + yaml_body_parsed        = <<-EOT
            apiVersion: v1
            data:
              runtimeconfig.json: |
                {
                  "nfs": {
                    "matchExportLocationAddress": "10.1.0.0/16"
                  }
                }
            kind: ConfigMap
            metadata:
              annotations:
                meta.helm.sh/release-name: manila-csi
                meta.helm.sh/release-namespace: default
              labels:
                app.kubernetes.io/managed-by: Helm
              name: manila-csi-runtimeconf-cm
              namespace: default
        EOT
      + yaml_incluster          = (sensitive value)
    }

  # module.csi_manila.kubectl_manifest.storage-class will be created
  + resource "kubectl_manifest" "storage-class" {
      + api_version             = (known after apply)
      + apply_only              = false
      + field_manager           = "kubectl"
      + force_conflicts         = false
      + force_new               = false
      + id                      = (known after apply)
      + kind                    = (known after apply)
      + live_manifest_incluster = (sensitive value)
      + live_uid                = (known after apply)
      + name                    = (known after apply)
      + namespace               = (known after apply)
      + server_side_apply       = false
      + uid                     = (known after apply)
      + validate_schema         = true
      + wait_for_rollout        = true
      + yaml_body               = (sensitive value)
      + yaml_body_parsed        = (known after apply)
      + yaml_incluster          = (sensitive value)
    }

  # module.csi_manila.ovh_cloud_project_user.manila-user will be created
  + resource "ovh_cloud_project_user" "manila-user" {
      + creation_date = (known after apply)
      + description   = "User for the Manila CSI driver"
      + id            = (known after apply)
      + openstack_rc  = (known after apply)
      + password      = (sensitive value)
      + role_name     = "share_operator"
      + roles         = (known after apply)
      + service_name  = "xxxxxxxxxxxxxxxxxxxxx"
      + status        = (known after apply)
      + username      = (known after apply)
    }

  # module.csi_manila.ovh_cloud_storage_file_share_network.sharenetwork will be created
  + resource "ovh_cloud_storage_file_share_network" "sharenetwork" {
      + checksum        = (known after apply)
      + created_at      = (known after apply)
      + current_state   = (known after apply)
      + description     = (known after apply)
      + id              = (known after apply)
      + name            = "mks_standard_3az-share-network"
      + network_id      = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx"
      + region          = "EU-WEST-PAR"
      + resource_status = (known after apply)
      + service_name    = "xxxxxxxxxxxxxxxxxxxxx"
      + subnet_id       = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx"
      + updated_at      = (known after apply)
    }

Plan: 7 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  + manila-user = (known after apply)

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

module.csi_manila.ovh_cloud_storage_file_share_network.sharenetwork: Creating...
module.csi_manila.ovh_cloud_project_user.manila-user: Creating...
module.csi_manila.kubectl_manifest.manila-runtime-configmap: Creating...
module.csi_manila.kubectl_manifest.manila-runtime-configmap: Creation complete after 0s [id=/api/v1/namespaces/default/configmaps/manila-csi-runtimeconf-cm]
module.csi_manila.helm_release.csi-driver-nfs: Creating...
module.csi_manila.ovh_cloud_storage_file_share_network.sharenetwork: Still creating... [00m10s elapsed]
module.csi_manila.ovh_cloud_project_user.manila-user: Still creating... [00m10s elapsed]
module.csi_manila.ovh_cloud_storage_file_share_network.sharenetwork: Creation complete after 12s [id=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx]
module.csi_manila.kubectl_manifest.storage-class: Creating...
module.csi_manila.ovh_cloud_project_user.manila-user: Creation complete after 13s [id=718526]
module.csi_manila.kubectl_manifest.csi-manila-secrets: Creating...
module.csi_manila.kubectl_manifest.csi-manila-secrets: Creation complete after 1s [id=/api/v1/namespaces/default/secrets/csi-manila-secrets]
...

Laten we dynamisch File Storage op Kubernetes aanmaken

Maak nu in je Kubernetes-cluster een pvc.yaml bestand aan met deze inhoud:

yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-share-fs-pvc
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 150Gi
  storageClassName: csi-manila-nfs

Pas deze Persistent Volume Claim (PVC) toe. Hierdoor kunnen Kubernetes-gebruikers gedeelde opslag aanvragen:

bash
kubectl apply -f pvc.yaml

Controleer de status van de PVC:

bash
kubectl get pvc nfs-share-fs-pvc

Wacht tot de status van de PVC verandert in Bound.

Je zou een output als volgt moeten krijgen:

bash
$ kubectl get pvc nfs-share-fs-pvc

NAME               STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS     VOLUMEATTRIBUTESCLASS   AGE
nfs-share-fs-pvc   Bound    pvc-af1349b7-eb51-43ac-b0f0-94d0e8139c57   150Gi      RWX            csi-manila-nfs   <unset>                 3h48m

Maak een deploy.yaml bestand aan en vul dit met de volgende inhoud:

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      volumes:
      - name: nfs-share-fs-pvc
        persistentVolumeClaim:
          claimName: nfs-share-fs-pvc
      containers:
      - name: nginx
        image: nginx
        ports:
          - containerPort: 80
            name: "http-server"
        volumeMounts:
          - mountPath: "/usr/share/nginx/html"
            name: nfs-share-fs-pvc

Pas deze deployment toe met één pod die een volume aan nfs-share-fs-pvc gekoppeld heeft:

bash
kubectl apply -f deploy.yaml

Controleer of de pod actief is:

bash
kubectl get pod

Je zou een output als volgt moeten krijgen:

bash
$ kubectl get pod
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-6cbf9b898c-svpzf   1/1     Running   0          6m

Controleer of je de deployment kunt schalen (multi-attach volume):

bash
kubectl scale deploy/nginx-deployment --replicas=2

Controleer of een andere pod actief is:

bash
kubectl get pod

Je zou een output als volgt moeten krijgen:

bash
$ kubectl get pod

NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-6cbf9b898c-867bq   1/1     Running   0          3m
nginx-deployment-6cbf9b898c-svpzf   1/1     Running   0          9m

Om de RWX-functionaliteit te verifiëren, maak je verbinding met één pod en maak je een bestand aan in de gemounte map (bijv. /usr/share/nginx/html).

bash
MY_POD=$(kubectl get po -o name | sed -n '1p')
echo $MY_POD

#Create a file in the pod number 1
kubectl exec $MY_POD -it -- touch /usr/share/nginx/html/index.html

Maak vervolgens verbinding met de tweede pod en bevestig dat het bestand zichtbaar is:

bash
MY_POD_2=$(kubectl get po -o name | sed -n '2p')
echo $MY_POD_2

#Display it in the pod number two
kubectl exec $MY_POD_2 -it -- ls -alrt /usr/share/nginx/html/

Je zou een output als volgt moeten krijgen:

bash
$ kubectl exec $MY_POD_2 -it -- ls -alrt /usr/share/nginx/html/

total 24
drwxr-xr-x 3 root root  4096 Jul 14 01:22 ..
drwx------ 2 root root 16384 Jul 15 09:18 lost+found
drwxrwxrwx 3 root root  4096 Jul 15 09:32 .
-rw-r--r-- 1 root root     0 Jul 15 13:09 index.html

Nu werkt je Manila-share die via NFS wordt aangeboden precies zoals je wilt! 🎉

Conclusie

In dit blogbericht hebben we laten zien dat het gebruik van Manila CSI met OVHcloud File Storage het mogelijk maakt om Kubernetes-applicaties te voorzien van dynamisch toegewezen gedeelde opslag.

We raden je aan om ook onze Cloud Roadmap & Changelog te bekijken voor een overzicht van alle toekomstige functies voor OVHcloud Public Cloud-producten.


Delen op: