Neste post teremos uma introdução de como o Storage utilizado no Kubernetes gerenciado do Azure funciona, no ultimo post vimos como provisionar o cluster.
No Azure temos diversos tipos de serviços que nos entregam capacidade de armazenamento, como (Fonte: Azure Storage):
Armazenamento em bloco de alto desempenho para aplicações críticas | Armazenamento em Disco do Azure |
Armazenamento de objetos altamente escalável e seguro para arquivos de diversos tipos, data lakes, computação de alto desempenho e machine learning | Armazenamento de Blobs do Azure |
Data lake altamente escalável e seguro para as workloads analiticos de alto desempenho | Azure Data Lake Storage |
Compartilhamento de arquivos em nuvem de nível empresarial simples, seguro e serverless | Arquivos do Azure |
Compartilhamento de arquivos de nível empresarial do Azure, da plataforma NetApp | Azure NetApp Files |
Compartilhamento de arquivos na nuvem híbrida para armazenar em cache seus dados locais | Sincronização de Arquivos do Azure |
Gateway de armazenamento em nuvem para transferir dados de maneira fácil e eficiente entre a nuvem e a borda | Azure Stack Edge |
Dispositivos e soluções para transferir dados de e para o Azure de forma rápida e econômica | Azure Data Box |
Exposto os tipos de storage disponíveis no Azure, passamos agora para falar um pouco mais de como os Volumes (que é o objeto do Kubernetes que entrega capacidade de storage) funcionam. Por padrão um container possui um armazenamento efêmero, ou seja, quando o container é recriado ou excluído os dados são perdidos, consideramos este comportamento como stateless ou ausência de armazenamento de estado\dados.
Desta forma para que haja um armazenamento duradouro de dados por parte dos Pods que estão em uso e mesmo que esses sejam recriados no mesmo worker ou em outro nó do cluster precisamos implementar Volumes para nossas aplicações provisionadas no kubernetes. Mas o que compõe um Volume? Vamos ver:
Storage Class
Um SC ou StorageClass é o tipo ou classe de storage que será alocado quando estamos provisionando um Volume no k8s. Um StorageClass é baseado em provisioners dos quais podemos considerar como tipo de storage a ser selecionado mas que na verdade são API focadas na entrega do recurso fim de armazenamento de dados:
Volume Plugin | Internal Provisioner | Config Example |
---|---|---|
AWSElasticBlockStore | ✓ | AWS EBS |
AzureFile | ✓ | Azure File |
AzureDisk | ✓ | Azure Disk |
CephFS | – | – |
Cinder | ✓ | OpenStack Cinder |
FC | – | – |
FlexVolume | – | – |
GCEPersistentDisk | ✓ | GCE PD |
iSCSI | – | – |
NFS | – | NFS |
RBD | ✓ | Ceph RBD |
VsphereVolume | ✓ | vSphere |
PortworxVolume | ✓ | Portworx Volume |
Local | – | Local |
Podemos ver acima vários tipos de Storage distintos: Nativos de Nuvem (AWS EBS, Azure Disk e GCE PD por exemplo), objeto (CephFS), etc.
Como estamos utilizando um k8s gerenciado na Azure, por padrão o AKS já disponibiliza alguns StorageClass no cluster, para verificar basta executar o comando:
kubectl get storageclass

Temos 3 tipos de provisioners disponíveis:
- kubernetes.io/azure-disk: que é o provisioner padrão do k8s para provisionar Azure Disk;
- file.csi.azure.com: provisioner (API) nativo da Azure para provisionamento volume utilizando de Azure File;
- disk.csi.azure.com: provisioner (API) nativo da Azure para entregar volumes de bloco via Azure Disk (idem ao primeiro tipo, porém, com um endpoint diferente).
O primeiro e o terceiro são basicamente iguais, sendo assim qual é a diferença do File para o Disk? A forma de acesso aos volumes por parte do Pod (que é determinada no PVC):
- File: este tipo pode disponibilizar volumes com os tipos de acesso ReadOnlyMany e ReadWeriteMany onde mais de um Pod poderá acessar o mesmo volume de uma vez, este tipo é voltado para aplicações que podem compartilhar volumes como file shares, WordPress, entre outros;
- Disk: já este tipo é mais restritivo que o outro onde apenas os tipos de acesso ReadWriteOnce é suportado, ou seja, apenas um Pod poderá acessar o volume o qual foi vinculado, esse tipo é mais voltado para aplicações que não podem compartilhar volumes como bancos de dados e aplicações Stateful como o Kafka.
Para quem esta com curiosidade sobre a sigla CSI (Assim como eu), a mesma é uma abreviação para Container Storage Interface que é um padrão adotado para disponibilizar volumes em Orquestradores de Containers como Kubernetes, Mesos e Nomad. Para quem quiser saber mais sugiro a documentação do K8s e o projeto CSI no Github:
https://kubernetes-csi.github.io/docs/
https://github.com/container-storage-interface/spec
Em nossa série, por estarmos utilizando apenas bancos de dados que, por consequência, são aplicações Stateful, por natureza iremos utilizar apenas Storage Class do tipo managed, onde:
- managed e managed-csi: são discos Azure Standard SSD com redundancia local ou LRS (Locally Redundancy Storage);
- managed-premium e managed-csi-premium: são discos Azure Premium SSD com redundancia local ou LRS (Locally Redundancy Storage).
Para mais detalhes sobre cada tipo temos a tabela comparativa abaixo:
Disco Ultra | SSD Premium v2 | SSD Premium | SSD Standard | HDD Standard | |
---|---|---|---|---|---|
Tipo de disco | SSD | SSD | SSD | SSD | HDD |
Cenário | Cargas de trabalho de E/S intensiva, como SAP HANA, bancos de dados de camada superior (por exemplo, SQL, Oracle) e outras cargas de trabalho de transações pesadas. | Cargas de trabalho sensíveis à produção e ao desempenho que exigem consistentemente baixa latência e alta IOPS e taxa de transferência | Cargas de trabalho sensíveis à produção e ao desempenho | Servidores Web, aplicativos empresariais pouco usados e desenvolvimento/teste | Backup, não crítico, acesso não frequente |
Tamanho máximo do disco | 65.536 GiB (GibiByte) | 65.536 GiB | 32.767 GiB | 32.767 GiB | 32.767 GiB |
Taxa de transferência máxima | 4\.000 MB/s | 1\.200 MB/s | 900 MB/s | 750 MB/s | 500 MB/s |
IOPS Máxima | 160.000 | 80.000 | 20.000 | 6.000 | 2.000 |
Utilizável como disco do sistema operacional? | No | Não | Sim | Sim | Sim |
Persistent Volume Claim
Um PVC ou Persistent Volume Claim é uma requisição a um Storage Class por um Volume com as especificações bem definidas no yaml de criação deste componente ou uma requisição por um volume já existente para ser disponibilizado para um ou mais Pods (Dependendo do seu tipo de acesso). Abaixo temos um exemplo de um PVC:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-exemplo
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
volumeName: pv-exemplo
storageClassName: managed-csi
Os pontos mais importantes que podemos destacar nos PVC’s são: capacidade bem determinada, modo de acesso e Storage Class.
Um item importante de ser destacado é o persistentVolumeReclaimPolicy que possui 3 tipos, onde:
- Retain: caso um PVC seja excluido o Persistent Volume é mantido e caso precise ser reutilizado por outro PVC precisa ser ajustado manualmente;
- Recycle: o PV será formatado e disponibilizado para algum outro PVC consumi-lo;
- Delete: remove o PV quando o PVC o qual o mesmo faz relação for removido.
Persistent Volume
Um Persistent Volume é o volume em si que será “attachado” a um Pod quando solicitado, geralmente por meio de um PVC. Abaixo um exemplo de yaml para criação de um PV:
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-exemplo
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: managed-csi
Para mais detalhes sobre volumes persistentes no Kubernetes consultem a documentação deste recursos que utilizaremos muito em nossa série:
https://kubernetes.io/docs/concepts/storage/persistent-volumes/
https://learn.microsoft.com/en-us/azure/aks/azure-csi-disk-storage-provision
Bom, acho que é isso para este post, a ideia aqui era dar uma ideia de como utilizaremos volumes no AKS em nossos bancos de dados e é um item que eu considero importante destacar quando falamos de StatefulSets que utilizaremos bastante também mas que eu explicarei ao longo da série e que formos provisionando nossas infraestruturas.
Desde já agradeço por me acompanhar aqui em mais um capitulo e até a próxima!