Coherence. Crear un nodo de tipo proxy con Coherence Operator.

En una entrada anterior desplegamos un cluster de Oracle Coherence en OKE con Coherence Operator. En esta entrada añadiremos un punto de entrada para clientes remotos usando Coherence*Extend.

Coherence*Extend permite que clientes que no forman parte del cluster se conecten a través de un ProxyService. En Kubernetes esto encaja muy bien con un servicio interno ClusterIP para pruebas o consumo dentro del cluster, y con un LoadBalancer de OKE cuando necesitamos exponerlo fuera.

La arquitectura del ejemplo será la siguiente:

  • Un despliegue Coherence para miembros de almacenamiento.
  • Un despliegue Coherence separado para miembros proxy, con storageEnabled: false.
  • Un puerto extend escuchando en 20000.
  • Acceso local mediante kubectl port-forward.
  • Exposición opcional mediante un Service LoadBalancer.

Separar storage y proxy no es obligatorio, pero suele ser más limpio: puedes escalar proxies sin tocar el número de miembros de almacenamiento.

Configuración de caché para los miembros storage

Primero mantenemos una configuración de almacenamiento sencilla en storage-cache-config.xml:

<?xml version="1.0"?>
<cache-config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xmlns="http://xmlns.oracle.com/coherence/coherence-cache-config"
              xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-cache-config coherence-cache-config.xsd">

  <caching-scheme-mapping>
    <cache-mapping>
      <cache-name>test*</cache-name>
      <scheme-name>distributed</scheme-name>
    </cache-mapping>
  </caching-scheme-mapping>

  <caching-schemes>
    <distributed-scheme>
      <scheme-name>distributed</scheme-name>
      <service-name>DistributedCache</service-name>
      <backing-map-scheme>
        <local-scheme/>
      </backing-map-scheme>
      <autostart>true</autostart>
    </distributed-scheme>
  </caching-schemes>
</cache-config>

Configuración del proxy Extend

Creamos ahora proxy-cache-config.xml. La parte importante es el proxy-scheme, que escucha en 0.0.0.0 para que Kubernetes pueda enrutar tráfico al contenedor.

<?xml version="1.0"?>
<cache-config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xmlns="http://xmlns.oracle.com/coherence/coherence-cache-config"
              xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-cache-config coherence-cache-config.xsd">

  <caching-scheme-mapping>
    <cache-mapping>
      <cache-name>test*</cache-name>
      <scheme-name>distributed</scheme-name>
    </cache-mapping>
  </caching-scheme-mapping>

  <caching-schemes>
    <distributed-scheme>
      <scheme-name>distributed</scheme-name>
      <service-name>DistributedCache</service-name>
      <backing-map-scheme>
        <local-scheme/>
      </backing-map-scheme>
      <autostart>true</autostart>
    </distributed-scheme>

    <proxy-scheme>
      <service-name>ExtendTcpProxyService</service-name>
      <acceptor-config>
        <tcp-acceptor>
          <local-address>
            <address system-property="coherence.extend.address">0.0.0.0</address>
            <port system-property="coherence.extend.port">20000</port>
          </local-address>
        </tcp-acceptor>
      </acceptor-config>
      <load-balancer>client</load-balancer>
      <autostart>true</autostart>
    </proxy-scheme>
  </caching-schemes>
</cache-config>

La imagen de aplicación debe incluir ambos ficheros:

files/
  conf/
    storage-cache-config.xml
    proxy-cache-config.xml
  lib/
    ...tus jars si los necesitas...

Construimos una nueva versión y la publicamos en OCIR:

docker build -t coherence-demo:1.0.1 .

docker tag coherence-demo:1.0.1 \
  fra.ocir.io/<ocir-namespace>/coherence-demo:1.0.1

docker push fra.ocir.io/<ocir-namespace>/coherence-demo:1.0.1

Desplegar miembros de almacenamiento

coherence-storage.yaml:

apiVersion: coherence.oracle.com/v1
kind: Coherence
metadata:
  name: coherence-storage
  namespace: coherencetest
spec:
  replicas: 3

  image: fra.ocir.io/<ocir-namespace>/coherence-demo:1.0.1
  imagePullSecrets:
    - name: ocirsecret

  jvm:
    memory:
      heapSize: 2g

  coherence:
    cacheConfig: storage-cache-config.xml
    storageEnabled: true

Aplicamos:

kubectl apply -f coherence-storage.yaml
kubectl -n coherencetest get pods

Desplegar miembros proxy

Creamos otro recurso Coherence para el tier de proxy.

coherence-proxy.yaml:

apiVersion: coherence.oracle.com/v1
kind: Coherence
metadata:
  name: coherence-proxy
  namespace: coherencetest
spec:
  replicas: 2

  image: fra.ocir.io/<ocir-namespace>/coherence-demo:1.0.1
  imagePullSecrets:
    - name: ocirsecret

  ports:
    - name: extend
      port: 20000

  coherence:
    cacheConfig: proxy-cache-config.xml
    storageEnabled: false
    wka:
      deployment: coherence-storage

El campo wka.deployment indica al tier de proxy que debe descubrir el cluster de storage a través del despliegue coherence-storage.

Aplicamos:

kubectl apply -f coherence-proxy.yaml
kubectl -n coherencetest get pods
kubectl -n coherencetest get svc

El Operator debe crear un servicio para el puerto extend, normalmente con un nombre parecido a:

coherence-proxy-extend

Compruébalo con:

kubectl -n coherencetest get svc | grep extend

Probar con port-forward

Antes de publicar nada fuera del cluster, probamos localmente:

kubectl -n coherencetest port-forward svc/coherence-proxy-extend 20000:20000

En el cliente Extend usamos 127.0.0.1:20000. Ejemplo de client-cache-config.xml:

<?xml version="1.0"?>
<cache-config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xmlns="http://xmlns.oracle.com/coherence/coherence-cache-config"
              xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-cache-config coherence-cache-config.xsd">

  <caching-scheme-mapping>
    <cache-mapping>
      <cache-name>test*</cache-name>
      <scheme-name>remote</scheme-name>
    </cache-mapping>
  </caching-scheme-mapping>

  <caching-schemes>
    <remote-cache-scheme>
      <scheme-name>remote</scheme-name>
      <service-name>ExtendTcpCacheService</service-name>
      <initiator-config>
        <tcp-initiator>
          <remote-addresses>
            <socket-address>
              <address system-property="proxy.address">127.0.0.1</address>
              <port system-property="proxy.port">20000</port>
            </socket-address>
          </remote-addresses>
        </tcp-initiator>
      </initiator-config>
    </remote-cache-scheme>
  </caching-schemes>
</cache-config>

Prueba conceptual con la consola o con un cliente Java:

Map (?): cache test1
Map (test1): put mykey myvalue
Map (test1): get mykey
myvalue
Map (test1): bye

Exponer el proxy fuera del cluster

Para consumo interno desde otros pods, no necesitas LoadBalancer. Puedes usar el DNS interno:

coherence-proxy-extend.coherencetest.svc.cluster.local:20000

Si necesitas acceder desde fuera de OKE, crea un Service de tipo LoadBalancer. Antes de definir el selector, mira las etiquetas reales de los pods:

kubectl -n coherencetest get pods \
  -l coherence.oracle.com/deployment=coherence-proxy \
  --show-labels

Un ejemplo de Service externo sería:

apiVersion: v1
kind: Service
metadata:
  name: coherence-proxy-extend-lb
  namespace: coherencetest
  annotations:
    oci.oraclecloud.com/load-balancer-type: "nlb"
spec:
  type: LoadBalancer
  selector:
    coherence.oracle.com/deployment: coherence-proxy
  ports:
    - name: extend
      protocol: TCP
      port: 20000
      targetPort: 20000
  loadBalancerSourceRanges:
    - 203.0.113.0/24

Aplicamos:

kubectl apply -f coherence-proxy-extend-lb.yaml
kubectl -n coherencetest get svc coherence-proxy-extend-lb

Cuando OKE asigne IP pública, veremos algo similar a:

NAME                         TYPE           EXTERNAL-IP      PORT(S)
coherence-proxy-extend-lb    LoadBalancer   131.141.250.155  20000/TCP

Entonces el cliente puede usar:

-Dproxy.address=131.141.250.155 -Dproxy.port=20000

Seguridad: no publiques Extend sin controles

Publicar un proxy Extend en Internet sin controles no es una buena idea. Antes de hacerlo en producción, revisa como mínimo:

  • Usar un load balancer privado y entrar por VPN, FastConnect o bastión.
  • Restringir rangos de origen con loadBalancerSourceRanges, NSGs o security lists.
  • Activar TLS en el proxy y en los clientes.
  • Definir autenticación y autorización si aplica en tu arquitectura.
  • Usar Network Policies para limitar qué pods pueden hablar con el proxy.
  • Monitorizar conexiones, errores y latencia del proxy.
  • Escalar proxies de forma independiente del tier de storage.

Escalado del proxy

El tier de proxy se escala igual que cualquier recurso Coherence:

kubectl -n coherencetest scale coherence/coherence-proxy --replicas=3

Comprueba que el Service reparte tráfico hacia los nuevos pods:

kubectl -n coherencetest get endpoints coherence-proxy-extend

Limpieza

kubectl -n coherencetest delete svc coherence-proxy-extend-lb
kubectl -n coherencetest delete coherence coherence-proxy
kubectl -n coherencetest delete coherence coherence-storage

Conclusión

Un proxy Coherence*Extend permite que clientes externos al cluster consuman cachés de Coherence sin convertirse en miembros del cluster. En Kubernetes, una forma clara de organizarlo es separar los miembros de storage y los miembros proxy, exponiendo el puerto Extend solo donde sea necesario.

El patrón de trabajo queda así:

  • Mantener los miembros de storage separados de los proxies.
  • Exponer el puerto Extend con spec.ports.
  • Probar primero con kubectl port-forward.
  • Usar LoadBalancer solo cuando haya una necesidad real.
  • No abrir el proxy a Internet sin TLS, filtrado de origen y controles de red.

Enlaces útiles

 

Read More

1 Comment

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *