TetriNET para Kubernetes y AKS

Este año también tuvimos servidor de TetriNET en la Global Azure Bootcamp 2018, pero en esta ocasión, ¡corre sobre AKS!

TetriNET para Kubernetes y AKS

En la edición 2017 de la Global Azure Bootcamp servidor hospedó en Azure un servidor de TetriNET dockerizado disponible para todo el que quisiera conectarse.

Este año vamos a mantenerlo pero con una vuelta de tuerca adicional: estará hospedado en Azure Kubernetes Service. Con el contendor del servidor ya desarrollado, la adaptación a AKS ha sido trivial y meramente basada en construir las declaraciones YAML necesarias para Kubernetes. Aún así creo que es lo suficientemente relevante para mencionarlo en un artículo.

Para este propósito he creado dos YAML, uno que crea el Service y el Secret donde irán las password de administrador del servicio y un segundo con el Deployment.

El motivo de esta división es que, como vamos a ver, el tipo del Service es LoadBalancer, ya que AKS se encargará de gestionarlo. La creación del balanceador de carga y sus reglas le lleva a Azure unos pocos minutos y nuestro Deployment se quejará amargamente y dará error si su Service no está en funcionamiento previamente. A diferencia de las plantillas JSON de ARM, no parece que haya forma de especificar dependencias dentro de un mismo YAML de Kubernetes, por lo que no queda más remedio que dividir la implementación en dos archivos y lanzarlos secuencialmente tras un tiempo prudencial. Agradeceré que me dejéis ideas y/o comentarios a este respecto.

Antes de continuar, os recuerdo que vamos usar la imagen Docker que ya construimos para la Global Azure Bootcamp 2017.

tetrinetx-aks-1.yaml

Lo primero es definir el Service, que será la IP estable y conocida mediante la cual nos podremos conectar a nuestro servidor. Una vez más, los Pods que se encuentran bajo un Deployment son susceptibles de cambiar dinámicamente y su red agnóstica a nosotros.

apiVersion: v1
kind: Service
metadata:
  name: tetrinetx
  labels:
    app: tetrinetx
spec:
  ports:
    - name: http
      protocol: TCP
      port: 80
    - name: tetrinet
      protocol: TCP
      port: 31457
    - name: tetrispec
      protocol: TCP
      port: 31458
  selector:
    app: tetrinetx
  type: LoadBalancer
  loadBalancerIP: 52.174.54.111
  clusterIP: 10.0.1.1 # Default range: 10.0.0.0/16
---
apiVersion: v1
kind: Secret
metadata:
  name: tetrinetx
  labels:
    app: tetrinetx
type: Opaque
data:
  op-pwd: cDRzc3cwcmQK # p4ssw0rd in base64
  spec-pwd: cDRzc3cwcmQK # p4ssw0rd in base64

Ningun misterio aquí: definimos los labels del selector y los puertos disponbiles para la conexión. Como siempre, ClusterIP será la IP interna estable de nuestro servidor, mientras que loadBalancerIP será la pública del Azure Load Balancer, atributo que por cierto es opcional, siendo este un matiz importante.

Si la definición especificamos type como LoadBalancer, pero no definimos loadBalancerIP, el servicio se creará con una IP aleatoria que Azure le asigne al balanceador de carga.

En cambio, si hemos definido loadBalancerIP, Azure nos asignará dicha IP siempre que el recurso de Public IP que la contenga haya sido creado previamente y se encuentre en el mismo grupo de recursos que el cluster de AKS. Así que no, no podemos pedirle a Azure la dirección IP pública que queramos.

En cuanto al Secret sólo mencionar que las contraseñas se especifican en base64.

tetrinetx-aks-2.yaml

Ahora hacemos la definicion del Deployment, que quedaría tal que así:

apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2, before 1.8.0 use apps/v1beta1
kind: Deployment
metadata:
  name: tetrinetx
  labels:
    app: tetrinetx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: tetrinetx
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: tetrinetx
    spec:
      hostname: tetrinet
      subdomain: azurebootcamp
      containers:
      - image: cmilanf/tetrinetx
        imagePullPolicy: Always
        name: tetrinetx
        env:
        - name: OP_PASSWORD
          valueFrom:
            secretKeyRef:
              name: tetrinetx
              key: op-pwd
        - name: SPEC_PASSWORD
          valueFrom:
            secretKeyRef:
              name: tetrinetx
              key: spec-pwd
        ports:
        - containerPort: 80
          name: http
        - containerPort: 31457
          name: tetrinetx
        - containerPort: 31458
          name: tetrispec

Notas sobre esta declaración:

  • Tetrinetx nunca se diseñó para escalar, así que el número de réplicas por defecto es 1. ¿Significa esto que no podemos escalarlo a -por ejemplo- 200 instancias? Para nada, desde luego que podemos, pero serán totalmente independientes y los jugadores acabarán en una u otra sin control alguno; algo que no es muy deseable.
  • Bajo spec tenemos la plantilla de definición del Pod que se va a crear a partir de este Deployment.
  • Las líneas 19 y 20 son para la especificación de un hostname, que era un requisito de Tetrinetx que ya teníamos que afrontar desplegándolo en bruto mediante Docker.
  • La línea 22 indica la imagen Docker que vamos a utilizar en los Pods y como no estamos especificando nada especial, por defecto buscará en el repositorio público oficial de Docker, es decir descargará esta imagen.
  • La línea 23 especifica que siempre iremos al repositorio pertinente a descargar la imagen ante una reimplementación del Pod. Es muy útil para testing y desarrollo, pero se debe manejar con cuidado en entornos productivos, en especial si nuestras imágenes son grandes.
  • Especificamos variables y puertos, al igual que ya hacíamos con Docker.

Resultado

Es el siguiente:

C:\>kubectl get secrets -l app=tetrinetx
NAME        TYPE      DATA      AGE
tetrinetx   Opaque    2         9d

C:\>kubectl get service -o wide -l app=tetrinetx
NAME        TYPE           CLUSTER-IP   EXTERNAL-IP     PORT(S)                                        AGE       SELECTOR
tetrinetx   LoadBalancer   10.0.1.1     52.174.xxx.xxx   80:31888/TCP,31457:31255/TCP,31458:30115/TCP   9d        app=tetrinetx

C:\>kubectl get deployment -o wide -l app=tetrinetx
NAME        DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE       CONTAINERS   IMAGES              SELECTOR
tetrinetx   1         1         1            1           9d        tetrinetx    cmilanf/tetrinetx   app=tetrinetx

C:\>kubectl get pods -o wide -l app=tetrinetx
NAME                         READY     STATUS    RESTARTS   AGE       IP            NODE
tetrinetx-8559b876c7-8x9d7   1/1       Running   0          9d        10.244.xxx.xxx   aks-nodepool1-393643750-0

Podemos dirigirnos a http://tetrinet.azurebootcamp.es o http://tetrinet.calnus.com, descargar nuestro cliente y apuntarlo a tetrinet.azurebootcamp.es o tetrinet.calnus.com.

tetrinetaks

Happy tetrit!

Related Article