GlusterFS como armazenamento externo para o Kubernetes

imagem
Encontrar o armazenamento ideal é um processo bastante complicado, tudo tem seus prós e contras. Obviamente, o líder nesta categoria é o CEPH, mas é um sistema bastante complexo, embora com uma funcionalidade muito rica. Para nós, esse sistema é redundante, uma vez que precisávamos de um armazenamento replicado simples no modo mestre-mestre por alguns terabytes. Tendo estudado muito material, decidiu-se testar o produto mais moderno do mercado para o circuito em que estamos interessados. Devido ao fato de não ter sido encontrada uma solução pronta para esse plano, gostaria de compartilhar minhas práticas recomendadas sobre este tópico e descrever os problemas que encontramos no processo de implantação.

Metas


O que esperávamos do novo repositório:

  • Capacidade de trabalhar com um número par de nós para replicação.
  • Fácil instalação, configuração, suporte
  • O sistema deve ser adulto, testado pelo tempo e usuários
  • Capacidade de expandir o espaço de armazenamento sem tempo de inatividade
  • O armazenamento deve ser compatível com o Kubernetes
  • Deve haver um failover automático quando um dos nós falha

É no último ponto que temos muitas perguntas.

Desdobramento, desenvolvimento


Para implantação, duas máquinas virtuais foram criadas no CentOs 8. Cada uma delas é conectada através de um disco adicional com armazenamento.

Preparação preliminar


Para o GlusterFS, você precisa alocar um disco separado com o XFS para que ele não afete o sistema de nenhuma maneira.

Selecione a partição:

$ fdisk /dev/sdb
Command (m for help): n
Partition type
   p   primary (0 primary, 0 extended, 4 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (1-4, default 1):  1
First sector (2048-16777215, default 2048): 
Last sector, +sectors or +size{K,M,G,T,P} (2048-16777215, default 16777215): 
 
Created a new partition 1 of type ‘Linux’ and of size 8 GiB.
Command (m for help): w 

The partition table has been altered.
Calling ioctl() to re-read partition table. Syncing disks.

Formate no XFS e monte:

$ mkfs.xfs /dev/sdb1
$ mkdir /gluster
$ mount /dev/sdb1 /gluster

E ainda por cima, solte a entrada em / etc / fstab para montar automaticamente o diretório na inicialização do sistema:

/dev/sdb1       /gluster        xfs     defaults        0       0

Instalação


Em relação à instalação, muitos artigos foram escritos; nesse contexto, não iremos aprofundar o processo, apenas consideraremos o que vale a pena prestar atenção.

Nos dois nós, instale e execute a versão mais recente glusterfs:

$ wget -P /etc/yum.repos.d  https://download.gluster.org/pub/gluster/glusterfs/LATEST/CentOS/glusterfs-rhel8.repo
$ yum -y install yum-utils
$ yum-config-manager --enable PowerTools
$ yum install -y glusterfs-server
$ systemctl start glusterd

Em seguida, você precisa informar ao glaster onde está o nó vizinho. Isso é feito com apenas um nó. Um ponto importante: se você possui uma rede de domínio, deve especificar o nome do servidor com o domínio; caso contrário, no futuro, precisará refazer tudo.

$ gluster peer probe gluster-02.example.com

Se foi bem-sucedido, verificamos a conexão com o comando de ambos os servidores:

$ gluster peer status
Number of Peers: 1

Hostname: gluster-02.example.com
Uuid: a6de3b23-ee31-4394-8bff-0bd97bd54f46
State: Peer in Cluster (Connected)
Other names:
10.10.6.72

Agora você pode criar um volume no qual iremos escrever.

gluster volume create main replica 2 gluster-01.example.com:/gluster/main gluster-02.example.com:/gluster/main force

Onde:

  • main - nome Volume
  • réplica - tipo Volume (mais detalhes podem ser encontrados na documentação oficial )
  • 2 - número de réplicas

Execute o Volume e verifique seu desempenho:

gluster volume start main
gluster volume status main

Para o volume replicado, é recomendável que você defina os seguintes parâmetros:

$ gluster volume set main network.ping-timeout 5
$ gluster volume set main cluster.quorum-type fixed
$ gluster volume set main cluster.quorum-count 1
$ gluster volume set main performance.quick-read on

Com essas etapas simples, criamos um cluster GlusterFS. Resta conectar-se a ele e verificar o desempenho. O Ubuntu está instalado na máquina cliente, para a montagem você precisa instalar o cliente:

$ add-apt-repository ppa:gluster/glusterfs-7
$ apt install glusterfs-client
$ mkdir /gluster
$ mount.glusterfs gluster-01.example.com:/main /gluster

O Gluster, quando conectado a um dos nós, fornece os endereços de todos os nós e se conecta automaticamente a todos. Se o cliente já estiver conectado, a falha de um dos nós não levará a uma parada. Mas se o primeiro nó estiver indisponível, não será possível conectar-se no caso de uma interrupção da sessão. Para fazer isso, ao montar, você pode passar o parâmetro backupvolfile indicando o segundo nó.
mount.glusterfs gluster-01.example.com:/main /gluster -o backupvolfile-server=gluster-02.example.com

Um ponto importante: o gluster sincroniza os arquivos entre os nós apenas se as alterações ocorrerem no volume montado. Se você fizer alterações diretamente nos nós, o arquivo ficará fora de sincronia.

Conecte-se ao Kubernetes


Nesse estágio, começaram as perguntas: “Como conectá-lo?”. E há várias opções. Considere-os.

Heketi


O mais popular e recomendado é usar um serviço externo: heketi. O heketi é uma camada entre o kubernetes e o gluster, que permite gerenciar e trabalhar com armazenamento por meio de http. Mas heketi será esse único ponto de falha, porque serviço não está em cluster. A segunda instância deste serviço não poderá funcionar independentemente, porque quaisquer alterações são armazenadas no banco de dados local. A execução deste serviço no kubernetes também não é adequada, porque ele precisa de um disco estático no qual seu banco de dados será armazenado. Nesse sentido, essa opção acabou sendo a mais inadequada.

Endpoint na Kubernetes


Se você possui o Kubernetes em sistemas com gerenciadores de pacotes, essa é uma opção muito conveniente. O ponto é que, para todos os servidores GlusteFS no Kubernetes, um Endpoint comum é criado. Um serviço está suspenso neste nó de extremidade e já estaremos montados nesse serviço. Para que essa opção funcione, é necessário instalar o glusterfs-client em cada nó do Kubernetes e garantir que ele possa ser montado. No Kubernetes, implante a seguinte configuração:

apiVersion: v1
kind: Endpoints
metadata: 
  name: glusterfs-cluster
subsets:
  - addresses:
      #  ip  
      - ip: 10.10.6.71
    ports:
      #    1,    
      - port: 1
  - addresses:
      - ip: 10.10.6.72
    ports:
      - port: 1

---
apiVersion: v1
kind: Service
metadata:
  name: glusterfs-cluster
spec:
  ports:
  - port: 1

Agora podemos criar uma implantação de teste simples e verificar como a montagem funciona. Abaixo está um exemplo de uma implantação de teste simples:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: gluster-test
spec:
  replicas: 1
  selector:
    matchLabels:
      app: gluster-test
  template:
    metadata:
      labels:
        app: gluster-test
    spec:
      volumes:
      - name: gluster
        glusterfs:
          endpoints: glusterfs-cluster
          path: main
      containers:
      - name: gluster-test
        image: nginx
        volumeMounts:
        - name: gluster
          mountPath: /gluster

Esta opção não nos convinha, porque temos container-linux em todos os nós do Kubernetes. O gerenciador de pacotes não está lá, portanto, não foi possível instalar o gluster-client para montagem. Nesse sentido, foi encontrada a terceira opção, que foi decidida a sua utilização.

GlusterFS + NFS + keepalived


Até recentemente, o GlusterFS oferecia seu próprio servidor NFS, mas agora o serviço externo nfs-ganesha é usado para NFS. Muito já foi escrito sobre isso, em conexão com isso, vamos descobrir como configurá-lo.

O repositório deve ser registrado manualmente. Para fazer isso, no arquivo /etc/yum.repos.d/nfs-ganesha.repo, adicionamos:

[nfs-ganesha]
name=nfs-ganesha
baseurl=https://download.nfs-ganesha.org/2.8/2.8.0/RHEL/el-8/$basearch/
enabled=1
gpgcheck=1
[nfs-ganesha-noarch]
name=nfs-ganesha-noarch
baseurl=https://download.nfs-ganesha.org/2.8/2.8.0/RHEL/el-8/noarch/
enabled=1
gpgcheck=1

E instale:

yum -y install nfs-ganesha-gluster --nogpgcheck

Após a instalação, realizamos a configuração básica no arquivo /etc/ganesha/ganesha.conf.

# create new
NFS_CORE_PARAM {
    # possible to mount with NFSv3 to NFSv4 Pseudo path
    mount_path_pseudo = true;
    # NFS protocol
    Protocols = 3,4;
}
EXPORT_DEFAULTS {
    # default access mode
    Access_Type = RW;
}
EXPORT {
    # uniq ID
    Export_Id = 101;
    # mount path of Gluster Volume
    Path = "/gluster/main";
    FSAL {
        # any name
        name = GLUSTER;
        # hostname or IP address of this Node
        hostname="gluster-01.example.com";
        # Gluster volume name
        volume="main";
    }
    # config for root Squash
    Squash="No_root_squash";
    # NFSv4 Pseudo path
    Pseudo="/main";
    # allowed security options
    SecType = "sys";
}
LOG {
    # default log level
    Default_Log_Level = WARN;
}

Precisamos iniciar o serviço, ativar nfs para o nosso volume e verificar se ele está ativado.

$ systemctl start nfs-ganesha
$ systemctl enable nfs-ganesha
$ gluster volume set main nfs.disable off
$ gluster volume status main

Como resultado, o status deve indicar que o servidor nfs foi iniciado para o nosso volume. Você precisa montar e verificar.

mkdir /gluster-nfs
mount.nfs gluster-01.example.com:/main /gluster-nfs

Mas essa opção não é tolerante a falhas, portanto, você precisa criar um endereço VIP que viaje entre nossos dois nós e ajude a mudar o tráfego se um dos nós cair.

A instalação de keepalived no CentOs é feita imediatamente através do gerenciador de pacotes.

$ yum install -y keepalived

Configuramos o serviço no arquivo /etc/keepalived/keepalived.conf:

global_defs {
    notification_email {
        admin@example.com
    }
    notification_email_from alarm@example.com
    smtp_server mail.example.com
    smtp_connect_timeout 30

    vrrp_garp_interval 10
    vrrp_garp_master_refresh 30
}

#C   ,   .    , VIP .
vrrp_script chk_gluster {
    script "pgrep glusterd"
    interval 2
}

vrrp_instance gluster {
    interface ens192
    state MASTER #     BACKUP
    priority 200 #      ,  100
    virtual_router_id 1
    virtual_ipaddress {
        10.10.6.70/24
    }

    unicast_peer {
        10.10.6.72 #        
    }

    track_script {
        chk_gluster
    }
}

Agora podemos iniciar o serviço e verificar se o VIP no nó aparece:

$ systemctl start keepalived
$ systemctl enable keepalived
$ ip addr
1: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:50:56:97:55:eb brd ff:ff:ff:ff:ff:ff
    inet 10.10.6.72/24 brd 10.10.6.255 scope global noprefixroute ens192
       valid_lft forever preferred_lft forever
    inet 10.10.6.70/24 scope global secondary ens192
       valid_lft forever preferred_lft forever

Se tudo funcionou para nós, resta adicionar o PersistentVolume ao Kubernetes e criar um serviço de teste para verificar a operação.

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: gluster-nfs
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  nfs:
    server: 10.10.6.70
    path: /main

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
 name: gluster-nfs
spec:
 accessModes:
 - ReadWriteMany
 resources:
   requests:
     storage: 10Gi
 volumeName: "gluster-nfs"

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: gluster-test
  labels:
    app: gluster-test
spec:
  replicas: 1
  selector:
    matchLabels:
      app: gluster-test
  template:
    metadata:
      labels:
        app: gluster-test
    spec:
      volumes:
      - name: gluster
        persistentVolumeClaim:
          claimName: gluster-nfs
      containers:
      - name: gluster-test
        image: nginx
        volumeMounts:
        - name: gluster
          mountPath: /gluster

Com essa configuração, no caso de uma queda do nó principal, ele fica ocioso por cerca de um minuto até que a montagem caia no tempo limite e nos comutadores. Simples por um minuto para esse armazenamento, digamos que essa não seja uma situação regular e raramente a encontraremos, mas nesse caso o sistema alternará automaticamente e continuará funcionando, e seremos capazes de resolver o problema e realizar a recuperação sem se preocupar com o simples.

Sumário


Neste artigo, examinamos três opções possíveis para conectar o GlusterFS ao Kubernetes. Em nossa versão, é possível adicionar um provisionador ao Kubernetes, mas ainda não precisamos dele. Resta adicionar os resultados dos testes de desempenho entre o NFS e o Gluster nos mesmos nós.

Arquivos em 1Mb:

sync; dd if=/dev/zero of=tempfile bs=1M count=1024; sync
Gluster: 1073741824 bytes (1.1 GB, 1.0 GiB) copied, 2.63496 s, 407 MB/s
NFS: 1073741824 bytes (1.1 GB, 1.0 GiB) copied, 5.4527 s, 197 MB/s

Arquivos em 1Kb:

sync; dd if=/dev/zero of=tempfile bs=1K count=1048576; sync
Gluster: 1073741824 bytes (1.1 GB, 1.0 GiB) copied, 70.0508 s, 15.3 MB/s
NFS: 1073741824 bytes (1.1 GB, 1.0 GiB) copied, 6.95208 s, 154 MB/s

O NFS funciona da mesma forma para qualquer tamanho de arquivo, a diferença de velocidade não é particularmente perceptível, ao contrário do GlusterFS, que é muito degradado com arquivos pequenos. Mas, ao mesmo tempo, com tamanhos de arquivo grandes, o NFS mostra desempenho 2-3 vezes menor que o Gluster.

All Articles