Azure Storage Account + Kubernetes for Persistent Volumes

Previously we saw how to create an NFS Server and mount it in a Kubernetes cluster to have PV (Persistent volumes) this is super useful because allows you to keep your data in separate storage… but what happens when you need to have a lot of persistent volumes. An NFS server could turn into madness. 💀

This is because you have to modify the etc/fstab file to be sure that that volume will be mounted once you restart or deallocates your server.

To get more details you could go to this post: http://www.regner.com.mx/nfs-network-file-system-storage-for-persistent-volume-claim-part-2/

As people say in my country, a lo que te truje chencha…

This time we will mount an a Volume using an azure storage account in Kubernetes.

Necessary requirements :

  • A Kubernetes cluster
  • An Azure storage account
  • A file share

So, first of all, we going to create a new Service Account. usually, a storage account is created when you create a virtual machine, so, its enough with a standard LRS plan. less than 0.06 USD per GB 😎

Once we have our Storage account we are able to create a File share where we could mount a pv.

Basically we will need the name of your storage account, its principal key connection and the name of your file share. you could get that info in Access Keys link or typing in az az storage account keys list --resource-group test_rg --account-name global_test --query "[0].value" -o tsv

az storage account keys list --resource-group your_resorce_group_name --account-name your_storage_accout_name --query "[0].value" -o tsv

We need to create a Kubernetes secret to store the az storage account credentials so we need to apply a simple YAML file with this info.

kubectl apply -f secret.yaml

apiVersion: v1 
kind: Secret
metadata:   
  name: azure-secret   
  namespace: deafult
type: Opaque 
stringData:   
  azurestorageaccountname: storageaccountname 
  azurestorageaccountkey: TRDdT21e3FdeebecwenenGYUOHlg==

Cool, now we have a secret we could refer to this azure-secret in our PV.

Now we going to create a simple Nginx service with a volume mounted in our az storage account.

Here is the YAML file

apiVersion: v1
kind: PersistentVolume
metadata:
  labels:
    usage: fileshare-pv
  name: fileshare-pv
spec:
  accessModes:
    - ReadWriteMany
  azureFile:
    readOnly: false
    secretName: azure-secret
    shareName: test-pv-az
  capacity:
    storage: 10Gi
  persistentVolumeReclaimPolicy: Retain

---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: fileshare-pvc
  namespace: default
  annotations:
    volume.beta.kubernetes.io/storage-class: ""
spec:
  accessModes:
    - ReadWriteMany
  volumeName: fileshare-pv
  resources:
    requests:
      storage: 10Gi

If you analyze this first we create a PV then we claim that PV, and we use the secret to refer our storage account.

ok to deploy our Nginx it is enough to apply this:

apiVersion: v1
kind: Service
metadata:
  name: my-nginx
  namespace: default
  labels:
    run: my-nginx
spec:
  ports:
  - port: 9080
    targetPort: 80
    name: http
  selector:
    run: my-nginx

---
apiVersion: apps/v1
kind: Deployment
metadata:
 name: my-nginx
 namespace: default
spec:
  selector:
    matchLabels:
      run: my-nginx
  replicas: 2
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
       - image: nginx
         name: my-nginx
         ports:
         - containerPort: 80
         volumeMounts:
           - name: azure
             mountPath: /data
      volumes:
        - name: azure
          persistentVolumeClaim:
            claimName: fileshare-pvc

kubectl apply -f nginx-test.yaml

if you get access to the node like kubectl exec or using the dashboard you could check the df -h to see your volumes

to test this you could type: touch hello-world.txt and you will be able to see in your file share storage a file hello-world.

Hope this will be useful to keep your data in a safe place. of course, if you are using an AKS or GKS or any Kubernetes on the cloud you could forget all this masochist process. 💆🏼‍♂

Crear una VM en Azure con múltiples IPs públicas.

Algunas veces por alguna razón nos vemos en la necesidad de tener múltiples ips en un servidor, una de estas razones puede ser que tengas configurado un master de kubernetes y tengas más de un namespace y por ende dos ingress-gateways. O simplemente tienes dos DNS y quieres que cada apunte a una aplicación web diferente pero dentro del mismo server.

Sin duda un reverse-proxy puede ayudarnos o un load balancer de azure pero en esta ocasión vemos un caso simple en donde añadiremos dos IP publicas a una vm de azure.

Lo primero es tener una VM, por lo regular esta se crea ya con una ip privada y una ip publica, en el caso de la publica puede ser dinámica o estática. la diferencia es que si apagas la maquina y tienes una ip dinámica esta cambiara cada vez que prendas la VM.

La maquina virtual tiene una tarjeta de Red virtual o Network interface, esta es la que vamos a modificar para agregar nuestra nueva ip.

Nuestra network interface: test282

Ahora ya tenemos dos ip’s atachadas y vamos a agregar una más por lo que podemos acceder a la maquina con cualquiera de las ip’s publicas por ssh.

en IP configuration podemos agregar las ip’s necesarias a la NI.

Limite de ip’s publicas

Solo hay que recordar que en azure el limite de ip’s publicas por region por default es de 20 ya sean estáticas o dinámicas.

Aquí hemos agregado una ip privada extra sin embargo no hemos puesto una ip publica eso se puede configurar habilitando public ip address como la imagen siguiente.

Ahora entramos a la maquina por cualquiera de las ip’s publicas.

regner@test:~$ sudo -i
root@test:~#  vi /etc/netplan/60-static.yaml

#estamos creando un documento en ubuntu 18+ para indicarle a la maquina que esta cuenta con dos o más ip's de esta manera agregamos el siguiente script.
network:
    version: 2
    ethernets:
        eth0:
            addresses:
                - 10.0.0.5/24

:wq -> para guardar y cerrar

Importante remplazar la ip con la que quieres atachar, y ejecutar netplan.

netplan try
#Warning: Stopping systemd-networkd.service, but it can still be activated #by:
#  systemd-networkd.socket
#Do you want to keep these settings? -> yes


Press ENTER before the timeout to accept the new configuration
netplan apply
ip addr list eth0
Antes de agregar la nueva Ip.
roroot@test:/etc/netplan# ip addr list eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:0d:3a:a4:41:05 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.5/24 brd 10.0.0.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet 10.0.0.6/24 brd 10.0.0.255 scope global secondary eth0
       valid_lft forever preferred_lft forever
    inet 10.0.0.4/24 brd 10.0.0.255 scope global secondary eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::20d:3aff:fea4:4105/64 scope link
       valid_lft forever preferred_lft forever

Con esto ya podremos atachar la ip privada que esta ligada a la publica para poder hacer una referencia distinta por ip.

Suponiendo que este es la master de un cluster de kubernetes podriamos ejecutar un kubectl patch (-f FILENAME | TYPE NAME) -p PATCH de esta manera podríamos tener dns, distintos para aplicaciones o namespaces diferentes.