Экосистема Kubernetes очень динамична и включает в себя различные компоненты, взаимодействующие между собой. Управление хранением данных в Kubernetes является отдельной задачей, в рамках которой вводятся понятия Persistent Volumes (постоянных томов, PVs) и Persistent Volume Claims (запросов на выделение постоянного тома, PVCs).

В этой статье мы рассмотрим, как с помощью Storage Class (классов хранилища) автоматически предоставлять NFS (Network File System) в качестве постоянного тома для Kubernetes. Для автоматизации мы будем использовать Ansible для настройки сервера NFS и Terraform вместе с Helm для настройки NFS-клиента.
Начальные условия
- Работающий кластер Kubernetes. 
- Helm, установленный на вашей локальной машине или в кластере Kubernetes 
- Ansible, установленный на локальной машине 
- Terraform, установленный на локальной машине. 
Настройка NFS-сервера с помощью Ansible
- Создайте плейбук Ansible для настройки NFS-сервера. Пример: 
---
- hosts: nfs-server
  become: yes
  tasks:
    - name: Update all packages
      apt:
        update_cache: yes
    - name: Install NFS server package
      apt: 
        name: nfs-kernel-server
        state: present
    - name: Create a directory to share
      file:
        path: /var/nfs_share
        state: directory
        mode: '777'
    - name: Modify ownership & permissions of the shared directory
      file:
        path: /var/nfs_share
        owner: nobody
        group: nogroup
        mode: '777'
    - name: Add the directory to the NFS configuration file
      lineinfile:
        path: /etc/exports
        line: '/var/nfs_share *(rw,sync,no_subtree_check,no_root_squash)'
    - name: Export the shared directory and restart NFS service
      command:
        cmd: exportfs -a && systemctl restart nfs-kernel-serverЗапустите плейбук с помощью Ansible. Вот пример того, как это может выглядеть в вашей командной оболочке:
ansible-playbook -i inventory.ini nfs_server.yamlЭтот плейбук установит NFS-сервер на целевой хост, создаст и сконфигурирует общий каталог (NFS-экспорт), и перезапустит службу NFS.
Настройка NFS-клиента с помощью Terraform и Helm
Для развертывания Helm Charts в кластере Kubernetes можно использовать Terraform. Ниже приведен пример сценария Terraform для установки NFS-клиента с использованием Helm-чарта nfs-subdir-external-provisioner.
- Установите провайдер Terraform для работы с Helm: 
provider "helm" {
  kubernetes {
    config_path = "~/.kube/config"
  }
}- Добавьте репозиторий, содержащий Helm-чарт - “nfs-subdir-external-provisioner”:
data "helm_repository" "nfs" {
  name = "nfs-subdir-external-provisioner"
  url  = "https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/"
}- Установите клиент NFS provisioner. Замените шаблоны - <nfs-server>и- <nfs-path>на IP-адрес вашего NFS-сервера и путь к экспортированному NFS-каталогу:
resource "helm_release" "nfs_client_provisioner" {
  name       = "nfs-client-provisioner"
  repository = data.helm_repository.nfs.metadata[0].name
  chart      = "nfs-subdir-external-provisioner"
  set {
    name  = "nfs.server"
    value = "<nfs-server>"
  }
  set {
    name  = "nfs.path"
    value = "<nfs-path>"
  }
}- Выполните сценарий Terraform. Вот пример того, как это может выглядеть в вашей среде: 
terraform init
terraform applyСценарий Terraform инициализирует Helm-провайдер, добавит Helm-репозиторий, содержащий nfs-subdir-external-provisioner и установит NFS client provisioner в кластер Kubernetes.
Проверка установки
- Проверьте, запущен ли NFS client provisioner: 
kubectl get podsВы должны увидеть pod с названием nfs-client-provisioner-... в статусе RUNNING.
- Проверьте, создан ли Storage Class: 
kubectl get scВ списке должен появиться Storage Class с именем nfs-client (или тем именем, которое вы указали при установке).
Теперь, когда вы создаете Persistent Volume Claim со Storage Class “nfs-client”, Kubernetes будет динамически предоставлять Persistent Volume, используя указанный вами NFS-сервер и путь.
Установка Postgresql с помощью провайдера
Создадим ресурс Terraform helm_release для установки чарта PostgreSQL:
data "helm_repository" "bitnami" {
  name = "bitnami"
  url  = "https://charts.bitnami.com/bitnami"
}
resource "helm_release" "postgresql" {
  name       = "postgresql"
  chart      = "bitnami/postgresql"
  repository = data.helm_repository.bitnami.metadata[0].name
  set {
    name  = "persistence.storageClass"
    value = "nfs-client"
  }
  set {
    name  = "persistence.size"
    value = "1Gi"
  }
}Этот Helm-чарт создаст Deployment c базой данных PostgreSQL, которая использует PersistentVolumeClaim для хранения данных. PVC использует Storage Class nfs-client, задействующий сервер NFS и путь, указанные в нашем предыдущем сценарии Terraform.
После добавления вышеуказанных ресурсов в сценарий Terraform, вы можете применить конфигурацию:
terraform applyПосле завершения работы сценария убедитесь, что Kubernetes Deployment и Service для PostgreSQL запущены:
kubectl get deployments
kubectl get svcЧтобы дополнительно убедиться в том, что данные PostgreSQL действительно хранятся на NFS-сервере, можно проверить точки подключения пода:
kubectl describe pod <postgresql-pod-name>Вы увидите подключение (mount) для /bitnami/postgresql, а его PersistentVolumeClaim должен использовать класс хранения NFS.  
Текст подготовлен при помощи инженеров Southbridge
От редакции
Говорить об Ansible можно очень много: этим-то мы и планируем заняться! Уже 10 августа пройдет первая встреча из цикла «IaC с Ansible». Наши инженеры поделятся подходами и покажут практическую сторону дела — решения, которые использовали в реальном продакшене. И их можно забрать в своё пользование!
Первая встреча пройдет 10 августа.
Зарегистрироваться на встречи можно по этой ссылке: https://southbridge.io/iac-ansible-southbridge
 
           
 
atshaman
Не очень понятна цель упражнения - раздать nfs со сторажки в кластер - ок, норм, пусть и не самый сладкий сахарн.
Делать самому... отказоустойчиовсти у решения нет - single point of failure на пустом месте. Делать nfs поверх кластеризованной ФС - того же gluster'а конечно можно - но прям такоЭ. Использовать для stateful-приложений, которые самостоятельно умеют в кластеризацию и репликацию данных - нуууу ооок, но не проще ли тогда local persistent volumes обмазаться - в плане удобства работы\управления\отказоустойчивости то на то будет минус оверхед на nfs. Опять же надо на структуру хранения смотреть - nfsv4 прям не любит большое количество файлов в одном каталоге, в tencent cloud для аналогичного сетапа прям непосредственная рекомендация - приколачивайте гвоздями nfsv3.
Если уж nfs нам зачем-то нужен - то почему kernel реализация, а не nfs-ganesha? Последний определенно быстрее и лучше себя ведет при разрывах связи - с ним я с ситуацией "полного зависания сервера" не сталкивался, а вот с kernel nfs - было.
В общем, троллейбус из буханки конечно почти как настоящий - но зачем?