Если вы запускаете stateful-приложения на Kubernetes, одна из распространенных проблем — обеспечение общего постоянного хранилища, к которому могут обращаться несколько рабочих нагрузок.
В то время как Persistent Volumes в Kubernetes обычно полагаются на блочное хранилище с доступом ReadWriteOnce, некоторым приложениям требуется общий доступ к файловой системе с возможностями ReadWriteMany (RWX).
OVHcloud File Storage предоставляет управляемые NFS-ресурсы, которые могут динамически использоваться рабочими нагрузками Kubernetes через драйвер Manila CSI.
В этом посте мы рассмотрим, как интегрировать OVHcloud File Storage с управляемым Kubernetes-сервисом OVHcloud (MKS) с помощью Manila CSI и протестируем возможности RWX-хранилища.
OVHcloud File Storage
OVHcloud Public Cloud File Storage — это полностью управляемый сервис общего файлового хранилища, предназначенный для облачных рабочих нагрузок, работающих на инстансах Public Cloud и кластерах Kubernetes.
Построенный на базе OpenStack Manila, он предоставляет общие NFSv3-разделы, которые могут быть одновременно смонтированы несколькими клиентами, что делает его идеальным решением для приложений, требующих доступа ReadWriteMany (RWX). Разделы можно выделить размером от 150 ГБ до 10 ТБ с предсказуемой линейной производительностью, масштабируемой пропорционально выделенной емкости.
Поскольку сервис полностью управляемый, вам не нужно развертывать или поддерживать собственный NFS-сервер. File Storage интегрируется с платформой OVHcloud через панель управления, API, CLI, Terraform-провайдер и Kubernetes через драйвер Manila CSI, что позволяет динамически подготавливать общие разделы непосредственно из вашего кластера.
Зачем использовать Manila CSI?
Интерфейс Container Storage Interface (CSI) в Kubernetes предоставляет стандартный механизм для подключения внешних систем хранения к Kubernetes.
Вместо ручного создания NFS-монтирований и PersistentVolumes драйвер Manila CSI позволяет Kubernetes динамически создавать и управлять файловыми ресурсами, используя такие ресурсы Kubernetes, как StorageClasses (SC), PersistentVolumeClaims (PVC) и PersistentVolumes (PV).
Предварительные требования
Перед началом вам потребуется:
- Проект OVHcloud Public Cloud
- Кластер управляемого Kubernetes-сервиса OVHcloud (MKS), подключенный к частной сети
- Установленный Terraform CLI
- Установленный kubectl CLI
Пошаговое развертывание Manila CSI: давайте сделаем это!
У нас уже есть кластер MKS в регионе EU-WEST-PAR, работающий внутри частной сети и подсети. В этом посте мы:
- создадим пользователя Public Cloud для драйвера Manila CSI
- установим драйвер CSI NFS
- установим драйвер Manila CSI
- развернем секрет (Secret) для Manila CSI, который позволит драйверу Manila CSI аутентифицироваться в OpenStack и управлять ресурсами Manila в вашем кластере
- создадим файловую общую сеть
- развернем ConfigMap для настройки драйвера Manila CSI
- развернем StorageClass csi-manila-nfs для того, чтобы драйвер Manila CSI мог динамически создавать ресурсы Manila и использовать их как тома Kubernetes
Мы будем использовать Terraform для простоты развертывания этой архитектуры.
Создайте файл provider.tf и заполните его следующей информацией:
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
}
Установите переменные окружения для Terraform-провайдера OVHcloud, используя свои учетные данные:
# 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"
Создайте файл variables.tf.template и заполните его этими данными:
variable "service_name" {
default = "$OVH_CLOUD_PROJECT_SERVICE"
}
variable "mks_cluster_id" {
default = "<your_mks_cluster_id>"
}
⚠️ В файле замените ID MKS на ID вашего существующего кластера MKS.
Замените значение переменной окружения OVH_CLOUD_PROJECT_SERVICE в файле variables.tf:
envsubst < variables.tf.template > variables.tf
Создайте файл nfs_share.tf и заполните его этими данными:
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
}
💡 В этом Terraform-файле мы используем существующий Terraform-модуль csi_manila, размещенный в GitHub-репозитории OVHcloud Public Cloud Examples.
Конфигурация Terraform готова. Давайте инициализируем её:
terraform init
Вывод должен быть примерно таким:
$ terraform init
Инициализация бэкенда...
Инициализация модулей...
Загрузка git::https://github.com/ovh/public-cloud-examples.git?ref=v1.5.0 для csi_manila...
- csi_manila в .terraform/modules/csi_manila/containers-orchestration/managed-kubernetes/install-csi-manila/modules/ovhcloud/csi_manila
Инициализация плагинов провайдера...
- Повторное использование предыдущей версии hashicorp/helm из файла блокировки зависимостей
- Повторное использование предыдущей версии alekc/kubectl из файла блокировки зависимостей
- Повторное использование предыдущей версии ovh/ovh из файла блокировки зависимостей
- Установка hashicorp/helm v3.2.0...
- Установлен hashicorp/helm v3.2.0 (подписано HashiCorp)
- Установка alekc/kubectl v2.1.6...
- Установлен alekc/kubectl v2.1.6 (самоподписанный, ID ключа 772FB27A86DAFCE7)
- Установка ovh/ovh v2.16.1...
- Установлен ovh/ovh v2.16.1 (подписано партнёром HashiCorp, ID ключа F56D1A6CBDAAADA5)
Провайдеры партнёров и сообщества подписаны их разработчиками.
Если вы хотите узнать больше о подписании провайдеров, вы можете прочитать об этом здесь:
https://developer.hashicorp.com/terraform/cli/plugins/signing
Terraform успешно инициализирован!
Теперь вы можете начать работу с Terraform. Попробуйте запустить "terraform plan", чтобы увидеть любые изменения, необходимые для вашей инфраструктуры. Все команды Terraform теперь должны работать.
Если вы когда-либо устанавливаете или изменяете модули или конфигурацию бэкенда для Terraform, повторно запустите эту команду для переинициализации вашего рабочего каталога. Если вы забудете, другие команды обнаружат это и напомнят вам сделать это при необходимости.
Примените:
terraform apply
Вывод должен быть таким:
$ terraform apply
data.ovh_cloud_project_kube.mks_cluster: Чтение...
data.ovh_cloud_project_kube.mks_cluster: Чтение завершено через 1с [id=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx]
data.ovh_cloud_network_private_vrack_subnet.mks_cluster_subnet: Чтение...
data.ovh_cloud_network_private_vrack_subnet.mks_cluster_subnet: Чтение завершено через 1с [id=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx]
Terraform использовал выбранные провайдеры для создания следующего плана выполнения. Действия с ресурсами обозначены следующими символами:
+ create (создать)
Terraform выполнит следующие действия:
# module.csi_manila.helm_release.csi-driver-nfs будет создан
+ 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 = (известно после применения)
+ lint = false
+ max_history = 0
+ metadata = (известно после применения)
+ 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 = (атрибут только для записи)
+ 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 будет создан
+ 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 = (известно после применения)
+ lint = false
+ max_history = 0
+ metadata = (известно после применения)
+ 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 = (атрибут только для записи)
+ 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 будет создан
+ resource "kubectl_manifest" "csi-manila-secrets" {
+ api_version = (известно после применения)
+ apply_only = false
+ field_manager = "kubectl"
+ force_conflicts = false
+ force_new = false
+ id = (известно после применения)
+ kind = (известно после применения)
+ live_manifest_incluster = (чувствительное значение)
+ live_uid = (известно после применения)
+ name = (известно после применения)
+ namespace = (известно после применения)
+ server_side_apply = false
+ uid = (известно после применения)
+ validate_schema = true
+ wait_for_rollout = true
+ yaml_body = (чувствительное значение)
+ yaml_body_parsed = (известно после применения)
+ yaml_incluster = (чувствительное значение)
}
# module.csi_manila.kubectl_manifest.manila-runtime-configmap будет создан
+ resource "kubectl_manifest" "manila-runtime-configmap" {
+ api_version = "v1"
+ apply_only = false
+ field_manager = "kubectl"
+ force_conflicts = false
+ force_new = false
+ id = (известно после применения)
+ kind = "ConfigMap"
+ live_manifest_incluster = (чувствительное значение)
+ live_uid = (известно после применения)
+ name = "manila-csi-runtimeconf-cm"
+ namespace = "default"
+ server_side_apply = false
+ uid = (известно после применения)
+ validate_schema = true
+ wait_for_rollout = true
+ yaml_body = (чувствительное значение)
+ 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 = (чувствительное значение)
}
# module.csi_manila.kubectl_manifest.storage-class будет создан
+ resource "kubectl_manifest" "storage-class" {
+ api_version = (известно после применения)
+ apply_only = false
+ field_manager = "kubectl"
+ force_conflicts = false
+ force_new = false
+ id = (известно после применения)
+ kind = (известно после применения)
+ live_manifest_incluster = (чувствительное значение)
+ live_uid = (известно после применения)
+ name = (известно после применения)
+ namespace = (известно после применения)
+ server_side_apply = false
+ uid = (известно после применения)
+ validate_schema = true
+ wait_for_rollout = true
+ yaml_body = (чувствительное значение)
+ yaml_body_parsed = (известно после применения)
+ yaml_incluster = (чувствительное значение)
}
# module.csi_manila.ovh_cloud_project_user.manila-user будет создан
+ resource "ovh_cloud_project_user" "manila-user" {
+ creation_date = (известно после применения)
+ description = "Пользователь для драйвера Manila CSI"
+ id = (известно после применения)
+ openstack_rc = (известно после применения)
+ password = (чувствительное значение)
+ role_name = "share_operator"
+ roles = (известно после применения)
+ service_name = "xxxxxxxxxxxxxxxxxxxxx"
+ status = (известно после применения)
+ username = (известно после применения)
}
# module.csi_manila.ovh_cloud_storage_file_share_network.sharenetwork будет создан
+ resource "ovh_cloud_storage_file_share_network" "sharenetwork" {
+ checksum = (известно после применения)
+ created_at = (известно после применения)
+ current_state = (известно после применения)
+ description = (известно после применения)
+ id = (известно после применения)
+ name = "mks_standard_3az-share-network"
+ network_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx"
+ region = "EU-WEST-PAR"
+ resource_status = (известно после применения)
+ service_name = "xxxxxxxxxxxxxxxxxxxxx"
+ subnet_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx"
+ updated_at = (известно после применения)
}
План: 7 к добавлению, 0 к изменению, 0 к уничтожению.
Изменения в выводах:
+ manila-user = (известно после применения)
Вы хотите выполнить эти действия?
Terraform выполнит действия, описанные выше.
Для подтверждения будет принято только 'yes'.
Введите значение: yes
module.csi_manila.ovh_cloud_storage_file_share_network.sharenetwork: Создание...
module.csi_manila.ovh_cloud_project_user.manila-user: Создание...
module.csi_manila.kubectl_manifest.manila-runtime-configmap: Создание...
module.csi_manila.kubectl_manifest.manila-runtime-configmap: Создание завершено за 0с [id=/api/v1/namespaces/default/configmaps/manila-csi-runtimeconf-cm]
module.csi_manila.helm_release.csi-driver-nfs: Создание...
module.csi_manila.ovh_cloud_storage_file_share_network.sharenetwork: Ещё создаётся... [00м10с прошло]
module.csi_manila.ovh_cloud_project_user.manila-user: Ещё создаётся... [00м10с прошло]
module.csi_manila.ovh_cloud_storage_file_share_network.sharenetwork: Создание завершено за 12с [id=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx]
module.csi_manila.kubectl_manifest.storage-class: Создание...
module.csi_manila.ovh_cloud_project_user.manila-user: Создание завершено за 13с [id=718526]
module.csi_manila.kubectl_manifest.csi-manila-secrets: Создание...
module.csi_manila.kubectl_manifest.csi-manila-secrets: Создание завершено за 1с [id=/api/v1/namespaces/default/secrets/csi-manila-secrets]
...
Давайте динамически создадим File Storage в Kubernetes
Теперь в вашем кластере Kubernetes создайте файл pvc.yaml с следующим содержимым:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-share-fs-pvc
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 150Gi
storageClassName: csi-manila-nfs
Примените этот Persistent Volume Claim (PVC), благодаря которому пользователи Kubernetes могут запрашивать общее хранилище:
kubectl apply -f pvc.yaml
Проверьте статус PVC:
kubectl get pvc nfs-share-fs-pvc
Дождитесь, пока статус PVC изменится на Bound.
Вы должны получить вывод, подобный этому:
$ 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
Создайте файл deploy.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
Примените этот Deployment с одним подом, к которому подключен том nfs-share-fs-pvc:
kubectl apply -f deploy.yaml
Убедитесь, что под запущен:
kubectl get pod
Вы должны получить вывод, подобный этому:
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-deployment-6cbf9b898c-svpzf 1/1 Running 0 6m
Проверьте возможность масштабирования Deployment (том с множественным подключением):
kubectl scale deploy/nginx-deployment --replicas=2
Проверьте, что другой под запущен:
kubectl get pod
Вы должны получить вывод, подобный этому:
$ 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
Чтобы проверить функциональность RWX, подключитесь к одному поду и создайте файл в смонтированном каталоге (например, /usr/share/nginx/html).
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
Затем подключитесь ко второму поду и убедитесь, что файл видим:
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/
Вы должны получить вывод, подобный этому:
$ 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
Теперь ваша общая папка Manila, предоставленная через NFS, работает так, как вы хотели! 🎉
Заключение
В этом сообщении блога мы показали, что использование Manila CSI с OVHcloud File Storage позволяет предоставлять приложениям Kubernetes динамически подготавливаемое общее хранилище.
Комментарии
Категории
Случайное

Партнёрский маркетинг для новичков: как

Подключите Google Analytics к

Усильте цифровое присутствие бизнеса

Почему ваш IP в черном списке?
