Crea una implementación con encriptación TLS en Kubernetes

Spanner Omni usa TLS 1.3 para encriptar los datos que fluyen entre el cliente y el servidor, y entre los servidores de Spanner Omni. Spanner Omni proporciona mTLS para mejorar la seguridad, en la que ambas partes establecen la autenticidad de la otra antes de intercambiar datos. Si usas la encriptación, tus servidores deben comunicarse a través de mTLS. Puedes elegir si tu cliente y servidor también usan mTLS.

Antes de comenzar

Asegúrate de cumplir con los siguientes requisitos:

  • Crea un clúster de Kubernetes. La configuración admite Google Kubernetes Engine (GKE) y Amazon Elastic Kubernetes Service (Amazon EKS). Es posible que debas personalizar la configuración para que funcione en otros entornos.

  • Asegúrate de que el clúster de Kubernetes pueda acceder al artefacto de Artifact Registry que aloja el contenedor de Spanner Omni.

  • Instala y configura la herramienta de línea de comandos de kubectl y Helm.

  • Si configuras el entorno de Kubernetes en máquinas de la plataforma de virtualización de vSphere, inhabilita la virtualización del contador de marca de tiempo (TSC) agregando monitor_control.virtual_rdtsc = FALSE al archivo de configuración .vmx de la máquina virtual. Esto garantiza que TrueTime funcione correctamente.

  • Verifica que tu entorno cumpla con los requisitos del sistema de Spanner Omni.

Paso 1: Genera los certificados

Debes crear tres conjuntos de certificados:

  • Certificados de API: Ayudan a proteger el servidor de la API de Spanner Omni.

  • Certificados de servidor: Ayudan a proteger la comunicación entre servidores.

  • Certificados de cliente: Los usuarios finales o las aplicaciones los usan para establecer su identidad y confianza con los servidores de Spanner Omni.

Una autoridad certificadora (AC) emite estos certificados. Spanner Omni proporciona herramientas para crear una AC autofirmada y los tres tipos de certificados.

Realiza los siguientes pasos en una de tus máquinas. En los pasos, se supone que el espacio de nombres es spanner-ns. Cámbialo por el espacio de nombres que quieras usar en tu implementación.

Puedes crear estos certificados en tu estación de trabajo con la CLI de Spanner Omni.

1. Crea una autoridad certificadora (AC)

Una autoridad certificadora (AC) emite todos los certificados. Es posible que tu organización tenga una CA central o que puedas usar una CA pública. Si bien puedes usar la misma AC para todos los certificados, los certificados de API y los certificados de cliente deben usar la misma AC.

Spanner Omni te permite crear una CA privada.

./google/spanner/bin/spanner certificates create-ca --ca-certificate-directory=certs

El comando create-ca genera el certificado de la AC en el directorio certs. Puedes copiar este certificado para usarlo como la AC de los certificados de la API o crear una AC diferente. Asegúrate de usar la AC correcta cuando crees certificados.

cp certs/ca.crt certs/ca-api.crt

El directorio $HOME/.spanner/private-keys contiene la clave privada de la AC. Es fundamental crear una copia de seguridad de este directorio y protegerlo. Los usuarios con acceso a la clave privada pueden firmar certificados arbitrarios en los que confían los clientes que confían en la AC autofirmada. De manera opcional, puedes crear una CA adicional (o usar una CA de confianza externa) para los certificados de la API. En este documento, se usa la misma CA para todos los tipos de certificados.

2. Genera certificados de servidor

Debes generar dos tipos de certificados de servidor:

  • Certificado de API: Usa este certificado para encriptar la comunicación de los sistemas que interactúan con la implementación.

  • Certificado del servidor de Spanner: Los servidores de Spanner Omni usan este certificado para encriptar la comunicación entre sí.

Esta configuración proporciona flexibilidad para administrar estos certificados. Por ejemplo, te permite usar la rotación de certificados.

Crea el certificado de servidor de Spanner

Para crear el certificado del servidor, ejecuta el siguiente comando:

# Comma-separate names of the Spanner servers; wildcards are supported.
SERVER_NAMES=*.pod.NAMESPACE
./google/spanner/bin/spanner certificates create-server --hostnames=${SERVER_NAMES} --ca-certificate-directory certs --output-directory certs

Este comando crea server.crt y server.key en el directorio certs.

Crea el certificado de la API

Para crear el certificado de la API, ejecuta el siguiente comando:

OMNI_ENDPOINT=spanner.NAMESPACE
./google/spanner/bin/spanner certificates create-server --filename-prefix=api --hostnames=${OMNI_ENDPOINT} --ca-certificate-directory certs --output-directory certs

Este comando crea api.crt y api.key en el directorio certs. Si es necesario, usa una CA de confianza externa para los certificados de la API.

3. Genera certificados de cliente

Puedes usar certificados de cliente para autenticar usuarios y aplicaciones. Los certificados de cliente habilitan la mTLS entre el cliente y el servidor. Puedes omitir este paso si no planeas usar mTLS.

La misma AC que firma el certificado de la API debe firmar los certificados de cliente, que también deben contener un nombre de usuario para la autorización. En este ejemplo, usa el usuario admin, que es el usuario predeterminado para cada base de datos nueva. Para obtener más información, consulta Autenticación y autorización en Spanner Omni.

USERNAME=admin
./google/spanner/bin/spanner certificates create-client $USERNAME --output-directory clientcerts --ca-certificate-directory certs

Este comando crea client.crt y client.key en el directorio clientcerts. Envía estos archivos a cualquier máquina que se conecte a la implementación.

Si planeas usar certificados de cliente con la biblioteca cliente de Java, debes generar la clave de certificado en formato PKCS#8. Usa el siguiente comando:

USERNAME=admin
./google/spanner/bin/spanner certificates create-client $USERNAME --output-directory clientcerts --ca-certificate-directory certs --generate-pkcs8-key

4. Genera el conjunto de claves de wrapper

Spanner Omni usa un conjunto de claves de wrapper de clave de encriptación de claves (KEK) activado en /spanner/kms/wrapper_key en cada Pod de servidor para encriptar las claves internas, como las claves de firma y encriptación de tokens.

Para generar un nuevo archivo de conjunto de claves de wrapper con spanner keys create-keyset, ejecuta el siguiente comando:

./google/spanner/bin/spanner keys create-keyset --output-file=kms/wrapper_key

De forma predeterminada, spanner keys create-keyset genera una clave AES256_GCM. Para generar un tipo de clave diferente, usa la marca --key-template con uno de los siguientes valores de tipo de clave: AES256_GCM, AES128_GCM, AES256_GCM_RAW, CHACHA20_POLY1305 o XCHACHA20_POLY1305.

Paso 2: Envía los certificados, el conjunto de claves de wrapper y la contraseña de administrador al clúster de Kubernetes

Ejecuta los siguientes comandos para crear el espacio de nombres y enviar los certificados, el conjunto de claves de wrapper y la contraseña de administrador a tu clúster de Kubernetes:

  1. Crea el espacio de nombres:

    kubectl create namespace NAMESPACE
    
  2. Envía los certificados TLS a un Secret:

    kubectl create secret generic tls-certs \
      --from-file=ca.crt="certs/ca.crt" \
      --from-file=ca-api.crt="certs/ca-api.crt" \
      --from-file=server.crt="certs/server.crt" \
      --from-file=server.key="certs/server.key" \
      --from-file=api.crt="certs/api.crt" \
      --from-file=api.key="certs/api.key" \
      -n NAMESPACE
    
  3. Envía el conjunto de claves de wrapper a un Secret (wrapper-key), que se activa en /spanner/kms en cada Pod del servidor:

    kubectl create secret generic wrapper-key \
      --from-file=wrapper_key="kms/wrapper_key" \
      -n NAMESPACE
    
  4. Crea un archivo de contraseña que contenga la contraseña del usuario admin predeterminado, con permisos restringidos (solo el propietario puede leerlo, permisos 600):

    printf '%s' 'PASSWORD' > admin_password.txt
    chmod 600 admin_password.txt
    

    La contraseña debe cumplir con los siguientes requisitos:

    • Debe tener entre 8 y 32 caracteres.
    • Al menos un carácter en mayúscula
    • Al menos un carácter en minúscula
    • Al menos un número
    • Al menos un carácter especial
  5. Crea un Secret para la contraseña de administrador:

    kubectl create secret generic spanner-admin-password \
      --from-file=password=admin_password.txt \
      -n NAMESPACE
    

Paso 3: Crea la implementación con encriptación TLS

Sigue estos pasos para crear tu implementación con encriptación TLS.

1. Prepara la configuración de Helm

Consulta Crea una configuración de gráfico de Helm y crea la configuración de implementación para tu entorno.

Para habilitar TLS y configurar la contraseña de administrador, establece los siguientes valores en la configuración del gráfico de Helm:

# Enables TLS
global:
  insecureMode: false

# Enables client certificate authentication (mTLS)
deployment:
  enableClientCertificateAuthentication: true
  # Name of the secret containing the administrator password
  adminPasswordSecret: spanner-admin-password

2. Crea la implementación:

Ejecute el siguiente comando para crear la implementación:

kubectl create ns monitoring

helm upgrade --install spanner-omni oci://us-docker.pkg.dev/spanner-omni/charts/spanner-omni \
  --version VERSION \
  --set global.platform=gke \
  --set global.insecureMode=false \
  --set deployment.enableClientCertificateAuthentication=true \
  --set deployment.adminPasswordSecret=spanner-admin-password \
  --namespace NAMESPACE \
  --set monitoring.enabled=true

El comando activa un trabajo de arranque. Puedes hacer un seguimiento del progreso mirando los registros de este trabajo:

kubectl logs -n NAMESPACE -l app.kubernetes.io/component=bootstrap -f

El resultado indica el progreso. Cuando se complete, verás un mensaje que indica "Deployment se creó correctamente".

3. Verifica el estado de los Pods

Ejecuta el siguiente comando para verificar el estado del Pod:

kubectl get pods --watch --namespace NAMESPACE

Todos los Pods están en el estado READY.

4. Actualiza el certificado y la implementación con los detalles del balanceador de cargas

Este paso es obligatorio si deseas que los clientes se conecten desde fuera del clúster de Kubernetes.

# Get the service details
kubectl get service spanner -n NAMESPACE

# The EXTERNAL-IP:PORT is the API or deployment endpoint for your deployment.
# Update the API certificate with these details.
OMNI_ENDPOINT=EXTERNAL_IP,spanner.NAMESPACE.svc
./google/spanner/bin/spanner certificates update \
    --certificate-file=certs/api.crt \
    --certificate-key-file=certs/api.key \
    --hostnames=${OMNI_ENDPOINT} \
    --ca-certificate-directory=certs

# Update the secrets in Kubernetes
kubectl patch secret tls-certs -n NAMESPACE -p "{\"data\":{\"api.crt\":\"$(base64 -w 0 certs/api.crt)\"}}"

Paso 4: Interactúa con Spanner Omni

Puedes interactuar con tu implementación de Spanner Omni desde cualquier VM con la CLI de Spanner Omni.

Si habilitaste mTLS para los clientes, usa las siguientes marcas con cada comando:

  • --client-certificate-directory=CLIENT_CERTIFICATE_DIRECTORY

  • --ca-certificate-file=API_CA_CERT_FILE_PATH

1. Accede a Spanner Omni (opcional)

Accede a Spanner Omni (este paso es opcional si usas certificados de cliente):

./google/spanner/bin/spanner auth login admin \
    --ca-certificate-file=certs/ca-api.crt \
    --deployment-endpoint=DEPLOYMENT_ENDPOINT

Cuando se te solicite, ingresa la contraseña configurada en admin_password.txt.

Successfully logged in as "admin"

2. Crea una base de datos

Ejecuta el siguiente comando para crear una base de datos:

./google/spanner/bin/spanner --deployment-endpoint=DEPLOYMENT_ENDPOINT databases create DATABASE_NAME --ca-certificate-file=certs/ca-api.crt --client-certificate-directory=clientcerts

3. Abre SQL Shell

Ejecuta el siguiente comando para abrir la shell:

./google/spanner/bin/spanner sql --database=DATABASE_NAME --deployment-endpoint=DEPLOYMENT_ENDPOINT --ca-certificate-file=certs/ca-api.crt --client-certificate-directory=clientcerts

4. Crea una tabla y agrega datos

Ejecuta los siguientes comandos de SQL:

spanner> CREATE TABLE names (nameId INT64 NOT NULL, name String(100)) PRIMARY KEY (nameId);
Query OK, 0 rows affected (4.62 sec)

spanner> INSERT names (nameId, name) VALUES (1, "Jack");
Query OK, 1 rows affected (0.18 sec)

5. Verifica la implementación

Para enumerar las bases de datos, ejecuta el siguiente comando:

./google/spanner/bin/spanner databases list --ca-certificate-file=certs/ca-api.crt --client-certificate-directory=clientcerts --deployment-endpoint=DEPLOYMENT_ENDPOINT

El resultado es similar al siguiente:

NOMBRE ESTADO VERSION_RETENTION_PERIOD EARLIEST_VERSION_TIME ENABLE_DROP_PROTECTION
DATABASE_NAME READY 1 h 2025-02-07T12:25:30Z falso

Para consultar los datos, ejecuta el siguiente comando:

./google/spanner/bin/spanner sql --database=DATABASE_NAME --ca-certificate-file=certs/ca-api.crt --client-certificate-directory=clientcerts --deployment-endpoint=DEPLOYMENT_ENDPOINT

Ejecuta los siguientes comandos de SQL:

SHOW TABLES;
SELECT * FROM names;

Como alternativa, puedes seguir las instrucciones que se indican en Usa PGAdapter con Spanner Omni para configurar PGAdapter y interactuar con herramientas como psql.

Paso 5: Supervisa la implementación

Si instalaste Spanner Omni con monitoring.enabled=true, Prometheus recopila las métricas. Puedes usar Grafana para visualizar estas métricas.

1. Obtén los detalles del servicio

Ejecuta los siguientes comandos para obtener los detalles del servicio:

# Prometheus service details. Default port is 9090.
kubectl get service prometheus-service -n monitoring

# Grafana service details. Default port is 3000.
kubectl get service grafana -n monitoring

¿Qué sigue?