Servicio NodePort Dinámico IPF

Descripción general

IPF Dynamic nodePort es un Kubernetes servicio que asigna dinámicamente un nodePort para contenedores a través de un initContainer. Consiste en dos componentes: un creador y un observador.

El creador es responsable de crear el servicio y asignar el nodePort, escribiendo la configuración en un archivo que puede ser incluido en Akka aplicaciones.

Archivo generado por el creador
IPF_NODEPORT = %v
IPF_MANAGEMENTPORT = %v
IPF_NODENAME = %s
akka.remote.artery.canonical.port = ${IPF_NODEPORT}
akka.remote.artery.canonical.hostname = ${IPF_NODENAME}
akka.management.http.hostname = ${IPF_NODENAME}
akka.management.http.port = ${IPF_MANAGEMENTPORT}

El observador monitorea el state de los pods y servicios, asegurando que el servicio dedicado se limpie adecuadamente cuando su pod correspondiente sea eliminado.

Despliegue

RBAC

Para que el nodoPort dinámico de IPF funcione correctamente, requiere especificaciones. Kubernetes permisos. Estos permisos se definen en el directorio examples/permissions, que contiene tanto permisos basados en ClusterRole como en Role.

Los permisos RBAC deben ser implementados antes de desplegar los componentes de creador y observador; de lo contrario, las aplicaciones no funcionarán correctamente.

Ejemplo de permisos para el espacio de nombres predeterminado
apiVersion: v1
kind: ServiceAccount
metadata:
  name: ipf-dynamic-nodeport-service
  namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: ipf-dynamic-nodeport-service
  namespace: default
rules:
  - apiGroups: [""]
    resources: ["services"]
    verbs: ["get", "list", "watch", "delete", "create"]
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "list", "watch", "patch"]
  - apiGroups: [""]
    resources: ["configmaps"]
    verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: ipf-dynamic-nodeport-service
  namespace: default
subjects:
  - kind: ServiceAccount
    name: ipf-dynamic-nodeport-service
    namespace: default
roleRef:
  kind: Role
  name: ipf-dynamic-nodeport-service
  apiGroup: rbac.authorization.k8s.io

Creador

El componente creador está diseñado para ser implementado como un contenedor de inicialización junto con el IPF application.

Expondrá automáticamente un pod a través de un nodePort asignado dinámicamente mediante un Kubernetes servicio.

Debe configurarlo con una plantilla de servicio que se utilizará para crear el servicio.

Ejemplo de ConfigMap para el creador del servicio nodeport
apiVersion: v1
kind: ConfigMap
metadata:
  name: ipf-dynamic-nodeport-service-creator
data:
  default.yaml: |
    apiVersion: v1
    kind: Service
    metadata:
      name: {{.PodName}}
      labels:
        creator: ipf-dynamic-nodeport-service-creator
        app: {{.PodName}}
    spec:
      externalTrafficPolicy: Local
      internalTrafficPolicy: Local
      publishNotReadyAddresses: true
      type: NodePort
      selector:
        ipfPodName: {{.PodName}}
      ports:
        - name: akka-management
          port: 8558
          targetPort: 8558
          protocol: TCP
          nodePort: 0
        - name: akka-artery
          port: 55001
          targetPort: 55001
          protocol: TCP
          nodePort: 0

Los valores predeterminados deberían ser suficientes para la mayoría de los casos de uso, pero usted puede customize la configuración según sea necesario. Por ejemplo, puede agregar nuevos servicios que requieran un nodePort asignado dinámicamente o cambiar el nombre del servicio de destino.

Claves en el ejemplo que contienen el valor '{{. PodName}}' se utilizan para generar el adecuado mapping entre el pod y el servicio; por lo tanto, no deben ser cambiados.

El último paso es desplegar el creador como un contenedor de inicialización en su IPF application.

Será necesario un volumen compartido para escribir el archivo de configuración que puede ser utilizado por el IPF application, y una sección en la especificación del pod para agregar un contenedor de inicialización que ejecutará el creador.

El volumen compartido puede ser montado en el directorio /tmp, y puede ser un tipo de volumen 'emptyDir' con un tamaño límite de 1 MB, ya que el archivo escrito es muy pequeño.

Por defecto, el creador escribirá el archivo de configuración en el directorio /tmp; sin embargo, puede ajustar esto a cualquier ruta que desee utilizando un interruptor de aplicación.

      initContainers:
        - name: service-creator
          image:ipf-dynamic-nodeport-service-creator:latest
          volumeMounts:
            - name: shared
              mountPath: /tmp
..
      volumes:
        - name: shared
          emptyDir: {}

Esto creará un archivo /tmp/nodeport.conf que puede ser incluido dinámicamente por un IPF application al agregar incluir /nodeport/nodeport.conf al principio de la application.conf archivo (ajustando la ruta del archivo a la ubicación de montaje según sea necesario).

Ejemplo completo de la IPF application con el contenedor init del creador
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: ipf-example-discovery-mongodb
  labels:
    app: ipf-example-discovery-mongodb
    product: ipfv2
data:
  application.conf: |
    include "file:///nodeport/nodeport.conf"
    ipf.mongodb.url = "mongodb://ipf-mongo:27017/ipf"
    akka.cluster.seed-nodes = []
    akka {
      extensions = ["akka.management.cluster.bootstrap.ClusterBootstrap"]
      discovery {
        method = akka-mongodb
        akka-mongodb.uri = ${ipf.mongodb.url}
      }
      management {
        cluster.bootstrap {
          contact-point.filter-on-fallback-port=false
        }
      }
    }
    akka.management.http.bind-port = 8558
    akka.remote.artery.bind-port = 55001
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ipf-example
  labels:
    product: ipfv2
spec:
  replicas: 1
  selector:
    matchLabels:
      product: ipfv2
  template:
    metadata:
      labels:
        product: ipfv2
    spec:
      serviceAccountName: ipf-dynamic-nodeport-service
      imagePullSecrets:
        - name: registrysecret
      initContainers:
        - name: service-creator
          image: ipf-dynamic-nodeport-service-creator:latest
          imagePullPolicy: Never
          command:
            [
              "/ipf-dynamic-nodeport-service-creator",
              "--output",
              "/nodeport/nodeport.conf",
            ]
          volumeMounts:
            - mountPath: /nodeport
              name: cache-volume
      containers:
        - name: ipf
          image: iconsolutions/example-discovery-mongodb:latest
          ports:
            - containerPort: 8558
            - containerPort: 55001
          volumeMounts:
            - mountPath: /nodeport
              name: cache-volume
            - name: application-config
              mountPath: /example-project-app/conf/application.conf
              subPath: application.conf
      volumes:
        - name: cache-volume
          emptyDir: {}
        - name: application-config
          configMap:
            name: ipf-example-discovery-mongodb

Observador

El componente observador monitorea los pods eliminados que tienen la etiqueta product=ipfv2. Cuando tal un event se detecta, el observador intentará automáticamente limpiar el servicio correspondiente, que comparte el mismo nombre que el pod eliminado.

Además, el observador se ejecuta a intervalos fijos (cada 5 minutos) para buscar posibles omisiones.events Este escaneo de fondo tiene como objetivo todos los servicios etiquetados con creator=ipf-dynamic-nodeport-service-creator.

Este servicio puede ser implementado como una implementación independiente en el clúster, y no se requiere ninguna configuración adicional.

Ejemplo de implementación para el servicio watcher de nodeport
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ipf-dynamic-nodeport-service-watcher
  labels:
    product: ipfv2
spec:
  replicas: 1
  selector:
    matchLabels:
      product: ipfv2
  template:
    metadata:
      labels:
        product: ipfv2
    spec:
      serviceAccountName: ipf-dynamic-nodeport-service
      containers:
        - name: service-watcher
          image: ipf-dynamic-nodeport-service-watcher:latest
          imagePullPolicy: Never

Configuración

Orden de Prioridad (Precedencia de Fuentes de Configuración)

Los valores de configuración se aplican en el siguiente orden de prioridad:

  1. Banderas de CLI (por ejemplo, --namespace, --scan-interval)

  2. Variables de Entorno (por ejemplo, NAMESPACE, SCAN_INTERVAL)

  3. Archivo de configuración (config.yaml)

  4. Valores predeterminados (por ejemplo, "predeterminado" para el espacio de nombres, 5m para el intervalo de escaneo)

Ubicaciones y prioridades de los archivos de búsqueda de configuración

Creador

  1. /etc/ipf-dynamic-nodeport-service-creator/

  2. $HOME/.config/ipf-dynamic-nodeport-service-creator .

Observador

  1. /etc/ipf-dynamic-nodeport-service-watcher/

  2. $HOME/.config/ipf-dynamic-nodeport-service-watcher .

Opciones de configuración

Observador

Para configurar el observador, cree un archivo de configuración.yaml archivo:

namespace: my-namespace
scan-interval: 2m

Alternativamente, establezca las siguientes variables de entorno:

NAMESPACE=my-namespace
SCAN-INTERVAL: 2m

El tiempo puede ser especificado como:

  • 1 (segundos)

  • 1s (segundos)

  • 1m (minuto)

  • 1h (hora)

Creador

Para configurar el creador, cree un archivo de configuración.yaml archivo:

pod: test-pod
output: /nodeport/nodeport.conf
configmapkey: default.yaml
akka-artery-management-port-name: akka-artery
akka-management-port-name: akka-management

Alternativamente, puede establecer las siguientes variables de entorno:

POD=test-pod
OUTPUT=/nodeport/nodeport.conf
CONFIGMAPKEY=default.yaml
AKKA-ARTERY-MANAGEMENT-PORT-NAME=akka-artery
AKKA-MANAGEMENT-PORT-NAME=akka-management