Kubernetes en varios continentes: k3s y k8s en alta disponibilidad entre centros de datos de todo el mundo

Publicado el 16 min de lectura

Kubernetes repartido entre EE. UU., Europa y Asia, en el que se puede permitir la caída de un continente entero: por qué etcd no tolera las largas distancias, un clúster k3s por región, GitOps con Flux, failover con Geo-DNS, los datos entre regiones y las diferencias con kubeadm.

Kubernetes es el estándar cuando las aplicaciones tienen que ser tolerantes a fallos y escalar de forma automática. Sin embargo, la idea más obvia de extender un único clúster de Kubernetes sobre servidores en EE. UU., Europa y Asia fracasa por un detalle: etcd, la base de datos en la que Kubernetes guarda todo su estado. Este artículo muestra cómo funciona aun así Kubernetes en varios continentes, y de tal forma que se puede permitir la caída de un continente entero: con un clúster por región, un despliegue común con GitOps y un Geo-DNS que envía a los usuarios a la región sana más cercana.

Montamos la arquitectura con k3s, la distribución de Kubernetes ligera y totalmente certificada que se instala en minutos, y al final mostramos qué cambia con un Kubernetes clásico instalado con kubeadm. Los fundamentos de disponibilidad, quórum y failover entre varias ubicaciones se explican en detalle en el artículo Docker Swarm en tres continentes; aquí tratamos lo que es distinto en Kubernetes.

¿Un clúster para todos los continentes o un clúster por región?

Para Kubernetes en varios continentes, la arquitectura correcta es un clúster por región, no un único clúster que abarque todos los continentes. Cada clúster funciona por su cuenta, todos se despliegan desde el mismo repositorio Git y un Geo-DNS con health checks reparte a los usuarios. Si falla una región, las demás toman el relevo sin que haya que consensuar un estado de clúster común a través del océano.

Por qué etcd no tolera las largas distancias

Kubernetes guarda en etcd todo su estado, cada configuración y cada cambio. etcd es un almacén clave-valor con consenso Raft, y cada escritura necesita la confirmación de la mayoría de todos sus miembros. Por defecto, etcd trabaja con un heartbeat de 100 milisegundos y un tiempo de espera de elección de un segundo; entre Europa, Norteamérica y Asia, la latencia de los paquetes es de 80 a 250 milisegundos. Se pueden aumentar esos tiempos, pero entonces cada escritura en el clúster se vuelve lenta, desde la planificación de un pod hasta el guardado de un Secret. La documentación de k3s es clara en este punto: el etcd integrado no se admite en clústeres repartidos entre varias redes, y todos los servidores deben estar en la misma ubicación. El propio Kubernetes también está pensado para que un clúster abarque varias zonas dentro de una región, no varios continentes.

Comparativa de los tres patrones

PatrónCómo funcionaValoración
Un clúster que abarca todos los continentesPlano de control y etcd repartidos entre varios continentesNo recomendado: escrituras lentas, etcd inestable y, en k3s con etcd integrado, no se admite
Plano de control en una región, workers en todo el mundoServidores en una ubicación, agents en otros continentesTécnicamente funciona, pero si cae la región del plano de control, ya no se puede volver a planificar nada en ningún lugar del mundo
Un clúster por regiónTres clústeres independientes, desplegados en conjunto con GitOps y con un Geo-DNS delanteRecomendado: cada región sobrevive a la caída de las demás y los fallos quedan limitados a una sola región

El enfoque «un clúster por región» tiene una segunda ventaja que a menudo se subestima: un fallo en el plano de control, un cambio erróneo en el clúster o una actualización que sale mal afecta siempre a una sola región. Los usuarios de las demás regiones no notan nada.

¿k3s o k8s?

Ambos son Kubernetes de verdad, con la misma API, los mismos manifiestos y las mismas herramientas. La diferencia está en la estructura y en el esfuerzo:

Característicak3sk8s con kubeadm
InstalaciónUn comando, un binarioConfigurar por separado el runtime de contenedores, kubeadm, kubelet y el plugin de red
Recursos para un nodo servidorAl menos 2 núcleos y 2 GB de RAMBastante más, según los componentes
Incluido de serieControlador de Ingress (Traefik), red (Flannel), aprovisionador de almacenamiento, balanceador de carga para serviciosSolo el núcleo; todo lo demás lo eliges tú
Alta disponibilidadetcd integrado con tres servidoresTres nodos del plano de control con un balanceador de carga delante de la API
Adecuado paraLa mayoría de las aplicaciones, equipos pequeños, un solo nodo por regiónEquipos que quieren decidir cada componente por sí mismos

Para la arquitectura de un clúster por región recomendamos k3s: operar tres clústeres solo resulta cómodo si cada uno de ellos es sencillo. Si ya tienes experiencia con kubeadm, puedes adoptar la arquitectura sin cambios; la sección sobre kubeadm, más abajo, muestra las diferencias.

La arquitectura: tres regiones, tres clústeres, un único punto de entrada

ComponenteFunciónQué caída cubre
Un clúster k3s por regiónEjecuta la aplicación cerca de los usuariosCaída de una región entera
Tres servidores por región (fase de ampliación)Mantiene etcd y el plano de control en alta disponibilidad dentro de la regiónCaída de servidores concretos dentro de una región
Repositorio Git y Flux en cada clústerCada clúster obtiene por sí mismo su estado deseado desde GitNingún servidor de despliegue central como punto de fallo
Ingress con certificados mediante el desafío DNSRecibe las peticiones de los usuariosLos certificados funcionan con independencia de la conmutación de DNS
Geo-DNS con health checksEnvía a los usuarios a la región sana más cercanaRegiones inaccesibles
Almacenamiento replicado de datos y copias de seguridadMantiene los datos en varias regionesPérdida de datos si cae una región

Punto de partida y ampliación

El punto de partida son tres servidores, uno en EE. UU., otro en Europa y otro en Asia, cada uno como clúster independiente de un solo nodo. Si falla un servidor, cae su región, y el Geo-DNS envía a sus usuarios a la región vecina. Esta fase ya está diseñada para soportar la caída de un continente entero. En la ampliación, cada región recibe tres servidores en la misma ubicación; así, cada región sobrevive también por sí sola a la caída de un servidor, sin que haya que redirigir a los usuarios.

Qué ubicaciones de KernelHost son adecuadas

KernelHost opera servidores en el centro de datos maincubes de Frankfurt am Main y ofrece servidores virtuales en otras ubicaciones de Europa, Norteamérica y Asia-Pacífico, entre ellas tres ubicaciones en EE. UU., Canadá, Londres, Estrasburgo, Varsovia, Helsinki, Singapur, Japón, Sídney y Mumbai. La lista completa está en la página Ubicaciones de servidores. El ejemplo de este artículo usa Frankfurt am Main para Europa, la costa este de EE. UU. para Norteamérica y Singapur para Asia.

Guía: Kubernetes con k3s en tres regiones

El ejemplo usa tres servidores con Debian 12 o 13: k3s-eu, k3s-us y k3s-asia. Las direcciones públicas proceden de la red de documentación 203.0.113.0/24 y el dominio es example.com. Sustituye ambos por tus propios valores.

Paso 1: aprovisionar servidores en tres regiones

Contrata tres servidores en tres regiones, con al menos 2 vCPU y 4 GB de RAM, para que además de k3s también quepa tu aplicación. Aplica el endurecimiento básico de la lista de comprobación para servidores root nuevos y asigna nombres de host descriptivos. etcd se beneficia notablemente de unos SSD rápidos, y el almacenamiento NVMe de los servidores de KernelHost cumple ese requisito.

Paso 2: instalar k3s

En cada uno de los tres servidores instalas k3s con un solo comando. Con ello, cada servidor se convierte en un clúster de Kubernetes completo con un nodo:

curl -sfL https://get.k3s.io | sh -
kubectl get nodes

Al cabo de un minuto aproximadamente, kubectl get nodes muestra el nodo como Ready. Vienen incluidos Traefik como controlador de Ingress, Flannel como red y un aprovisionador para volúmenes locales.

Paso 3: ampliar a tres servidores por región

Si quieres que una región sea también de alta disponibilidad por sí misma, coloca tres servidores en la misma ubicación. El primer servidor inicia el etcd integrado y los otros dos se unen con un token común. etcd exige un número impar de servidores; con tres servidores, la región aguanta la caída de uno de ellos:

curl -sfL https://get.k3s.io | K3S_TOKEN=TOKEN_SECRETO sh -s - server \
    --cluster-init \
    --tls-san=api.eu.example.com
curl -sfL https://get.k3s.io | K3S_TOKEN=TOKEN_SECRETO sh -s - server \
    --server https://203.0.113.21:6443 \
    --tls-san=api.eu.example.com

Todos los servidores de una región necesitan los mismos ajustes de rangos de red y de funciones. Entre ellos tienen que estar abiertos los puertos 2379 a 2380/TCP para etcd, 6443/TCP para la API, 10250/TCP para el Kubelet y 8472/UDP para la red de Flannel; hacia fuera permanecen bloqueados. El token es un secreto: quien lo conozca puede añadir sus propios servidores al clúster.

Paso 4: configurar el acceso a los tres clústeres

k3s guarda los datos de acceso en /etc/rancher/k3s/k3s.yaml. Copia el archivo de cada clúster a tu equipo de trabajo, sustituye en él 127.0.0.1 por la dirección del servidor y nombra los contextos según la región:

kubectl config rename-context default eu
kubectl config use-context eu
kubectl --context us get nodes

La API en el puerto 6443 es el acceso más potente al clúster. Permite ese acceso en el firewall solo desde tu propia dirección o desde una VPN, nunca para todo internet. El archivo k3s.yaml contiene un certificado de administrador y hay que guardarlo con el mismo cuidado que una contraseña de root.

Paso 5: GitOps con Flux en cada clúster

Para que las tres regiones operen la misma aplicación en la misma versión, el estado deseado reside en un repositorio Git, y en cada clúster se ejecuta Flux, que establece ese estado de forma autónoma. Es decir, cada clúster obtiene su configuración por sí mismo; no existe ningún servidor de despliegue central que pueda fallar. Una estructura de repositorio que ha dado buenos resultados:

apps/
  web/            manifiestos comunes de la aplicación
clusters/
  eu/             ajustes y versión para Europa
  us/             ajustes y versión para Norteamérica
  asia/           ajustes y versión para Asia
flux bootstrap git --url=ssh://git@git.example.com/infra/fleet.git --branch=main --path=clusters/eu

El mismo comando lo ejecutas con --path=clusters/us y --path=clusters/asia en el contexto correspondiente. Como cada región tiene su propio directorio, puedes desplegar una versión nueva primero en una región y solo después en las demás.

Paso 6: describir la aplicación para que tolere fallos

Dentro de una región, tres cosas hacen que la aplicación sobreviva a los mantenimientos y a las caídas de servidores: varias réplicas repartidas entre distintos nodos, sondas que detectan los pods en mal estado y un presupuesto de interrupciones que impide que un mantenimiento retire todos los pods a la vez:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      topologySpreadConstraints:
        - maxSkew: 1
          topologyKey: kubernetes.io/hostname
          whenUnsatisfiable: ScheduleAnyway
          labelSelector:
            matchLabels:
              app: web
      containers:
        - name: web
          image: registry.example.com/web:1.0
          ports:
            - containerPort: 8080
          readinessProbe:
            httpGet:
              path: /health
              port: 8080
            periodSeconds: 5
          livenessProbe:
            httpGet:
              path: /health
              port: 8080
            periodSeconds: 10
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: web
spec:
  minAvailable: 1
  selector:
    matchLabels:
      app: web

La sonda de readiness saca a un pod del tráfico mientras no responde, y la sonda de liveness lo reinicia si se queda colgado. En un clúster de un solo nodo, el reparto entre varios nodos todavía no tiene efecto; se activa automáticamente en cuanto la región tiene tres servidores.

Paso 7: Ingress y certificados

De la entrada se encarga el Traefik incluido. Como las tres regiones sirven el mismo dominio, obtienes los certificados TLS con cert-manager mediante el desafío DNS: funciona en todas las regiones, independientemente de adónde apunte en ese momento el registro DNS. El desafío HTTP, en cambio, falla en todas las regiones a las que el registro no apunta en ese momento. Si trabajas sin Ingress de Kubernetes, encontrarás los fundamentos en el artículo Configurar nginx como reverse proxy.

Paso 8: configurar Geo-DNS con failover

Un servicio DNS con enrutamiento geográfico y health checks envía a los usuarios de Europa a Frankfurt am Main, a los de América a la costa este de EE. UU. y a los de Asia a Singapur, y comprueba a intervalos de 30 a 60 segundos si responde la entrada de cada región. Si falla una región, deja de devolver su dirección. Fija el TTL de los registros en 60 segundos; así, un cambio suele completarse en uno o dos minutos. Si quieres gestionar los registros desde el propio clúster, puedes usar external-dns.

Paso 9: desplegar región por región y probar la caída

Una versión nueva la introduces primero en el directorio de una región, observas esa región durante unos minutos y después aplicas la versión a las demás. Así, un fallo que ninguna comprobación detecte llega como mucho a una región. La caída de una región la ensayas deteniendo k3s en su servidor, y compruebas a la vez si el Geo-DNS retira la región de sus respuestas y si la región vecina asume la carga:

systemctl stop k3s
systemctl start k3s

En una región con tres servidores, ensayas además el mantenimiento de un único servidor. kubectl drain traslada los pods respetando el presupuesto de interrupciones del paso 6, y kubectl uncordon vuelve a poner el servidor en servicio:

kubectl drain k3s-eu-2 --ignore-daemonsets --delete-emptydir-data
kubectl uncordon k3s-eu-2

Datos entre regiones

Kubernetes reparte pods, no datos. Un PersistentVolume del aprovisionador incluido reside en un único nodo, y entre los clústeres no existe de serie ningún almacenamiento de datos común. Por eso, para todo lo que maneja datos vale lo mismo que en cualquier clúster repartido entre varias ubicaciones:

  • Las bases de datos se encargan ellas mismas de su replicación. Un esquema probado es una instancia primaria en una región con réplicas en las demás; los operadores de bases de datos como CloudNativePG para PostgreSQL admiten esas réplicas también entre clústeres distintos. Entre continentes, la replicación es asíncrona, y en caso de incidente pueden faltar los últimos segundos de escrituras. Para escribir sin pérdidas en todo el mundo existen bases de datos multirregión como CockroachDB o YugabyteDB.
  • Los archivos y las subidas deben guardarse en un almacenamiento de objetos compatible con S3, con replicación a una segunda región.
  • Las sesiones se guardan en una base de datos o una caché replicadas, o bien la aplicación usa tokens firmados.
  • Las copias de seguridad siguen siendo obligatorias, porque la replicación distribuye los errores igual que los datos buenos. Para los objetos y volúmenes de Kubernetes es adecuado Velero; para los fundamentos, consulta la estrategia de backup para servidores.

Kubernetes con kubeadm en lugar de k3s

Con kubeadm, la arquitectura sigue siendo la misma: un clúster por región, GitOps, Geo-DNS. Lo que cambia es cómo se monta cada clúster. En todos los nodos instalas un runtime de contenedores como containerd, además de kubeadm, kubelet y kubectl; delante de la API de la región colocas un balanceador de carga o una dirección virtual, por ejemplo con kube-vip, e inicializas el primer nodo del plano de control:

kubeadm init --control-plane-endpoint "api.eu.example.com:6443" --upload-certs

La salida contiene dos comandos de unión: uno con --control-plane --certificate-key para los otros dos nodos del plano de control y otro para los workers. Después instalas un plugin de red como Calico o Cilium y un controlador de Ingress, que k3s ya trae incluido. El esfuerzo adicional merece la pena si necesitas elegir componentes concretos de forma deliberada o mantenerte muy cerca de la versión upstream.

Por qué KernelHost para Kubernetes en varios continentes

RequisitoPor qué importaEn KernelHost
Ubicaciones en varios continentesUn clúster por región necesita servidores en cada regiónFrankfurt am Main más ubicaciones en Europa, Norteamérica y Asia-Pacífico, todo con un mismo proveedor
Tráfico ilimitadoLas descargas de imágenes, la replicación de bases de datos y las copias de seguridad generan tráfico de forma continuaVPS con tráfico ilimitado sin límite de volumen
Almacenamiento rápidoetcd es sensible a los discos lentosSSD NVMe en RAID
Protección DDoSCada Ingress es accesible públicamenteIncluida en todas las ubicaciones; en la ubicación principal de Frankfurt am Main, con 3,2 Tbps de filtrado Arbor en tiempo real, sin null-routing
Acceso root completok3s, el firewall y los ajustes del kernel requieren control totalEn todos los servidores root KVM y servidores dedicados
Sin compromiso contractualLos nodos y los clústeres de prueba vienen y vanPrePaid, sin permanencia mínima, sin cuota de alta
AutomatizaciónLos nodos nuevos deben poder crearse mediante scriptsContratación y control a través de la KernelHost API

Encontrarás una visión general de todos los planes cloud y una comparativa de costes con los grandes proveedores cloud en la página Alquilar un servidor cloud.

Errores frecuentes y cómo evitarlos

  • etcd extendido entre continentes. La consecuencia son escrituras lentas y elecciones inestables, y en k3s con etcd integrado no se admite. Solución: un clúster por región.
  • Dos servidores en una región. etcd necesita una mayoría, y dos servidores no aguantan ninguna caída. Solución: uno o tres.
  • API abierta a todo internet. El puerto 6443 es la llave maestra del clúster. Solución: solo desde tu propia dirección o por VPN.
  • Servidor de despliegue central. Si falla, ya no se puede desplegar nada. Solución: Flux en cada clúster, que se abastece por sí mismo desde Git.
  • Actualización en todas las regiones a la vez. Un fallo afecta entonces a todos los usuarios. Solución: región por región, mediante los directorios del repositorio.
  • Certificados mediante el desafío HTTP. En las regiones a las que el registro DNS no apunta en ese momento, la renovación falla. Solución: desafío DNS.
  • Base de datos en un volumen local sin replicación. Si falla el nodo, los datos no están accesibles. Solución: replicación mediante un operador de bases de datos.
  • Sin sondas ni presupuesto de interrupciones. Los pods en mal estado siguen recibiendo tráfico, y los mantenimientos dejan fuera de servicio todos los pods a la vez. Solución: sondas de readiness y liveness más un PodDisruptionBudget.

En resumen

  • Para Kubernetes en varios continentes lo correcto es un clúster por región; un único clúster que abarque todos los continentes fracasa por la latencia de etcd.
  • El punto de partida son tres servidores, uno en EE. UU., otro en Europa y otro en Asia; ya esta fase sobrevive a la caída de un continente entero.
  • En la ampliación, cada región recibe tres servidores en la misma ubicación, y entonces cada región sobrevive también a la caída de servidores concretos.
  • Flux en cada clúster despliega la aplicación desde el mismo repositorio Git, región por región.
  • Un Geo-DNS con health checks y un TTL corto envía a los usuarios a la región sana más cercana, y los certificados se obtienen mediante el desafío DNS.
  • Kubernetes reparte pods, no datos: las bases de datos necesitan su propia replicación y las copias de seguridad siguen siendo obligatorias.
  • Para esta arquitectura, k3s suele ser mejor opción que kubeadm, porque tres clústeres sencillos son más fáciles de operar que tres complejos.

Preguntas frecuentes

¿Puede un clúster de Kubernetes abarcar varios continentes?
Técnicamente se puede repartir el plano de control, pero no es recomendable. Kubernetes guarda su estado en etcd, y cada escritura necesita la confirmación de una mayoría de todos los miembros de etcd. Entre continentes hay de 80 a 250 milisegundos de latencia, y etcd trabaja por defecto con un heartbeat de 100 milisegundos. Según la documentación de k3s, el etcd integrado no se admite en redes distribuidas. Lo correcto es un clúster por región.
¿Cómo se monta Kubernetes en alta disponibilidad en varias regiones?
Con un clúster propio por región, por ejemplo un clúster k3s en EE. UU., otro en Europa y otro en Asia. Todos los clústeres se despliegan con GitOps desde el mismo repositorio Git, por ejemplo con Flux en cada clúster, y un Geo-DNS con health checks envía a los usuarios a la región sana más cercana. Si falla una región, las demás toman el relevo sin que haya que consensuar un estado común a través del océano.
¿Qué diferencia hay entre k3s y k8s?
Ambos son Kubernetes completo, con la misma API y los mismos manifiestos. k3s es una distribución ligera y certificada en un único binario que se instala con un comando e incluye controlador de Ingress, red y aprovisionador de almacenamiento; un servidor necesita al menos 2 núcleos y 2 GB de RAM. Un clúster k8s con kubeadm se monta a partir de componentes individuales, ofrece más libertad de elección y exige más esfuerzo.
¿Cuántos servidores necesita un clúster k3s de alta disponibilidad?
Tres nodos servidor con etcd integrado, en la misma ubicación. etcd necesita una mayoría, así que tres servidores aguantan la caída de uno. Dos servidores no aportan nada, porque la caída de cualquiera de los dos hace perder la mayoría. Para Kubernetes en varios continentes, al principio bastan tres clústeres de un solo nodo, uno por región, porque el Geo-DNS absorbe la caída de una región entera.
¿Qué puertos necesita k3s?
La API de Kubernetes y el supervisor de k3s usan el puerto 6443/TCP, el Kubelet el 10250/TCP y la red de Flannel el 8472/UDP con VXLAN o el 51820/UDP con WireGuard. Con varios servidores y etcd integrado se añaden los puertos 2379 a 2380/TCP entre los servidores. Ninguno de estos puertos debe quedar abierto a internet; la API solo la permites desde tu propia dirección o por VPN.
¿Cómo se despliegan aplicaciones en varios clústeres de Kubernetes?
Con GitOps: el estado deseado de todos los clústeres está en un repositorio Git, y en cada clúster se ejecuta una herramienta como Flux que establece ese estado de forma autónoma. Cada región tiene su propio directorio, de modo que una versión nueva se puede desplegar primero en una región y, tras un periodo de observación, en las demás. Así no hay ningún servidor de despliegue central que pueda fallar.
¿Cómo funciona el failover entre las regiones de Kubernetes?
Mediante un servicio DNS con enrutamiento geográfico y health checks. Envía a los usuarios a la región más cercana y comprueba a intervalos de 30 a 60 segundos si su Ingress responde. Si falla una región, deja de devolver su dirección y dirige a los usuarios a la región sana más cercana. Con un TTL de 60 segundos, el cambio suele completarse en uno o dos minutos.
¿Cómo se conservan los datos si cae una región?
Kubernetes reparte pods, no datos. Por eso las bases de datos se encargan ellas mismas de su replicación, por ejemplo PostgreSQL con el operador CloudNativePG, que mantiene réplicas también entre clústeres distintos. Entre continentes, la replicación es asíncrona, y en caso de incidente pueden faltar los últimos segundos de escrituras. Los archivos deben guardarse en un almacenamiento de objetos replicado, y las copias de seguridad periódicas, por ejemplo con Velero, siguen siendo obligatorias.
¿Kubernetes o Docker Swarm para varios continentes?
Docker Swarm se puede extender como un único clúster sobre tres continentes y es bastante más sencillo de operar. Kubernetes ofrece más automatización y un ecosistema más amplio, pero entre continentes se opera como un clúster por región y se unifica con GitOps. Para equipos pequeños con aplicaciones manejables, Swarm suele ser la opción pragmática; para plataformas complejas, Kubernetes.
¿Qué ubicaciones de KernelHost son adecuadas para Kubernetes en varios continentes?
KernelHost ofrece servidores en Frankfurt am Main y en otras ubicaciones de Europa, Norteamérica y Asia-Pacífico, entre ellas tres ubicaciones en EE. UU., Canadá, Londres, Estrasburgo, Varsovia, Helsinki, Singapur, Japón, Sídney y Mumbai. Una combinación probada es Frankfurt am Main, la costa este de EE. UU. y Singapur, con uno o tres servidores por región en la misma ubicación.
¿Cuánto cuesta Kubernetes en tres continentes?
En la fase inicial, tres servidores, uno por región, y en la ampliación, nueve, además de un servicio DNS con health checks. k3s en sí es gratuito. Como la replicación, las copias de seguridad y las descargas de imágenes generan tráfico de forma continua, los planes con tráfico ilimitado son decisivos. En KernelHost, los VPS con tráfico ilimitado funcionan sin límite de volumen, PrePaid, sin permanencia mínima y sin cuota de alta, de modo que los clústeres se pueden ampliar o reducir según las necesidades.

Kubernetes k3s k8s kubeadm Alta disponibilidad Multirregión GitOps Flux Geo-DNS Cloud