Google Distributed Cloud (GDC) air-gapped proporciona un balanceador de cargas de capa 4 (L4) administrado integrado, pero muchas aplicaciones empresariales requieren capacidades avanzadas de capa 7 (L7), como el enrutamiento basado en el host, la administración centralizada de TLS y la división compleja del tráfico. Históricamente, esto se logra con la API de Ingress, que ahora se considera una función congelada en la comunidad de Kubernetes.
Esta arquitectura de referencia proporciona una solución de balanceo de cargas de capa 7 autoadministrada. Cuando implementan el popular controlador de código abierto NGINX Gateway Fabric en un clúster estándar de GDC, los clientes pueden enrutar sin problemas el tráfico de L7 a entornos híbridos. Esta arquitectura usa la finalización de TLS (HTTPRoute) para enrutar el tráfico según la indicación de nombre del servidor (SNI) a los pods y las aplicaciones alojadas en contenedores integrados en máquinas virtuales externas.
Arquitectura

Los componentes clave de la solución incluyen lo siguiente:
- Cliente: Es una entidad que inicia solicitudes HTTPS para interactuar con las aplicaciones.
- Clúster estándar de GDC: GDC proporciona una forma integrada de crear clústeres de Kubernetes Vanilla. En esta solución, el clúster alojará el LB de L7 y sus controladores, junto con las cargas de trabajo y el servicio sin interfaz gráfica para las VMs externas.
- Balanceador de cargas de L4 de GDC: Es el balanceador de cargas de L4 integrado que actúa como punto de entrada y distribuye el tráfico TCP/443 directamente a los pods de Kubernetes que ejecutan los controladores de puerta de enlace.
- Controladores de puerta de enlace: Son operadores de NGINX que se ejecutan en el clúster estándar.
Supervisan los recursos de la API de Gateway (como
GatewayyHTTPRoute) y actualizan de forma dinámica los proxies subyacentes. Se usará Nginx Gateway Fabric para la solución. - Puerta de enlace (con HTTPRoute): Son recursos estandarizados de Kubernetes que definen el puerto de escucha físico (443) y las reglas de enrutamiento de host basadas en SNI con finalización de TLS.
- Carga de trabajo en contenedores (pods): Es una implementación estándar de Kubernetes expuesta de forma interna con un
Servicenormal de Kubernetes. - Carga de trabajo basada en VM (externa): Es una carga de trabajo alojada en una VM externa en la red del proyecto, expuesta al proxy con un
Servicede Kubernetes sin interfaz gráfica y un extremo personalizado que contiene la IP directa de la VM. - Registro de Harbor: Es un registro de contenedores privado que se usa para almacenar y entregar las imágenes de proxy y de aplicación en el entorno aislado.
En el clúster estándar, creas cuatro espacios de nombres:
El espacio de nombres
nginx-gatewayque aloja los recursos de Nginx Gateway Fabric:
El espacio de nombres
load-balancerque aloja los recursosGateway:
El espacio de nombres
vm-appaloja la IP de VM externavm-app, un servicio sin interfaz gráfica, unEndpointSliceque apunta a la IP externa y unHTTPRoutepara laGateway:
El espacio de nombres
hello-appaloja laDeployment, unService, unHTTPRoutey unaGatewaypara la carga de trabajo del contenedor de demostración:
Antes de comenzar
Antes de implementar esta solución, asegúrate de cumplir con los siguientes requisitos previos:
- Software necesario: helm, docker, kubectl
Acceso a la CLI y configuración local: Descarga la CLI de gdcloud desde la consola de GDC y configura tu entorno de forma local.
export USER_NAME="USER_NAME" export PROJECT_ID="PROJECT_ID" export ZONE="ZONE" export ORG_NAME="ORG_NAME" export GDCH_URL="GDC_URL" gdcloud components install gdcloud-k8s-auth-plugin gdcloud config set core/organization_console_url \ https://console.$ORG_NAME.$ZONE.$GDC_URL gdcloud config set core/zone $ZONE gdcloud config set core/project ${PROJECT_ID} gdcloud auth login # use --login-config-cert option in case of TLS errorConfiguración del proyecto: Crea un proyecto en tu entorno aislado de GDC para alojar los recursos.
gdcloud projects create $PROJECT_IDRoles de IAM: Otorga a tu usuario los roles de Administrador de clúster y Administrador de clúster estándar para administrar los recursos de Kubernetes, y el rol de Administrador de instancias de Harbor para enviar imágenes.
# Grant standard cluster and cluster admin roles gdcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member="user:${USER_NAME}" \ --role=cluster-admin gdcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member="user:${USER_NAME}" \ --role=standard-cluster-admin # Grant Harbor instance admin role gdcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member="user:${USER_NAME}" \ --role=harbor-instance-admin
Crea un clúster estándar
En esta sección, se te guiará a través del proceso de configuración de un clúster estándar de Kubernetes en tu entorno GDC aislado. Un clúster estándar proporciona una base flexible y sólida para implementar varias cargas de trabajo, incluido el controlador de puerta de enlace de Nginx y tus aplicaciones personalizadas. Los siguientes pasos garantizarán que tu clúster esté configurado correctamente y sea accesible para las implementaciones posteriores.
Para identificar los tipos de imágenes de máquina virtual disponibles, ejecuta lo siguiente:
gdcloud compute machine-types listSelecciona un tipo de máquina adecuado para los nodos de trabajador del clúster. Para este instructivo, se recomienda un tipo de máquina con al menos 4 CPU virtuales.
export MACHINE_TYPE="MACHINE_TYPE"Obtén el kubeconfig del servidor de la API de administración y establece un alias:
export CLUSTER_NAME="CLUSTER_NAME" KUBECONFIG=kubeconfig-admin.yaml gdcloud clusters \ get-credentials ${ORG_NAME}-admin alias km="kubectl --kubeconfig kubeconfig-admin.yaml"Crea un clúster estándar con 2 nodos de trabajador:
km create -f - <<EOF apiVersion: cluster.gdc.goog/v1 kind: Cluster metadata: name: ${CLUSTER_NAME} namespace: ${PROJECT_ID} spec: nodePools: - machineTypeName: ${MACHINE_TYPE} nodeCount: 2 name: ${CLUSTER_NAME}-node-pool EOFPara obtener más detalles sobre las opciones disponibles, consulta la documentación.
La creación de clústeres estándar puede tardar hasta 60 minutos en completarse. Para verificar el estado, usa el siguiente comando:
km get clusters/${CLUSTER_NAME} \ -n ${PROJECT_ID} \ --watchUna vez que el clúster esté listo, el resultado debería mostrar un estado de Running, como este:
NAME STATE K8S VERSION my-cluster Running 1.30.12-gke.300Cuando el clúster esté listo, recupera sus credenciales:
KUBECONFIG=kubeconfig-${CLUSTER_NAME}.yaml gdcloud clusters \ get-credentials ${CLUSTER_NAME} \ --standard \ --project ${PROJECT_ID} \ --zone ${ZONE}Crea un alias para que los comandos
kubectlsean más concisos en el resto de esta guía. Este alias se usará para interactuar con el clúster estándar:alias kk="kubectl --kubeconfig kubeconfig-${CLUSTER_NAME}.yaml"Crea espacios de nombres para el controlador, la app en contenedores de demostración "hello-app" y la app de demo basada en VM:
kk create namespace load-balancer kk create namespace hello-app kk create namespace vm-app
Crea e integra el registro de Harbor
Harbor es un registro de imágenes de contenedor con compatibilidad integrada en GDC air-gapped. En esta sección, se te guiará a través de los pasos para integrar un registro de Harbor con tu clúster estándar, incluida la configuración de credenciales y secretos para permitir la extracción y el envío seguros de imágenes.
- Crea una instancia de Harbor en tu proyecto.
- Crea un proyecto de Harbor en tu instancia de Harbor.
Establece las variables de entorno:
export HARBOR_INSTANCE_NAME="HARBOR_INSTANCE_NAME" export HARBOR_INSTANCE_URL="HARBOR_INSTANCE_URL" export HARBOR_PROJECT="HARBOR_INSTANCE_PROJECT" export IMAGE_PULL_SECRET_NAME="harbor-secret"Accede a la instancia de Harbor con una cuenta de robot:
docker --config=./docker login ${HARBOR_INSTANCE_URL}Crea los secretos en el clúster estándar:
kk create secret docker-registry ${IMAGE_PULL_SECRET_NAME} \ --from-file=.dockerconfigjson=./docker/config.json \ -n load-balancer kk create secret docker-registry ${IMAGE_PULL_SECRET_NAME} \ --from-file=.dockerconfigjson=./docker/config.json \ -n hello-app
Implementa una app en contenedores de demostración
En esta sección, se detalla la implementación de una aplicación en contenedores de demostración (hello-app) dentro de tu clúster de Kubernetes de GDC aislado. Crearás los recursos necesarios de implementación y servicio de Kubernetes para ejecutar hello-app y exponerlo de forma interna dentro del clúster, lo que lo preparará para el acceso con el balanceador de cargas de L7.
Sube una imagen de muestra para la app en contenedores de demostración a Harbor:
docker pull gcr.io/google-samples/hello-app:1.0 \ --platform linux/amd64 docker tag gcr.io/google-samples/hello-app:1.0 \ ${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/hello-app:1.0 docker --config=./docker push \ ${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/hello-app:1.0Implementa el siguiente manifiesto en el clúster estándar:
cat << EOF > hello-app.yaml apiVersion: apps/v1 kind: Deployment metadata: name: hello-app namespace: hello-app spec: replicas: 2 selector: matchLabels: app: hello-app template: metadata: labels: app: hello-app spec: containers: - name: hello-server image: ${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/hello-app:1.0 ports: - containerPort: 8080 imagePullSecrets: - name: ${IMAGE_PULL_SECRET_NAME} --- apiVersion: v1 kind: Service metadata: name: hello-app namespace: hello-app spec: type: ClusterIP selector: app: hello-app ports: - protocol: TCP port: 80 targetPort: 8080 EOF kk apply -f hello-app.yaml
Luego, verifica que la implementación y el servicio estén allí:
kk get svc,deploy -n hello-app
Implementa app de demo en una VM
En esta sección, se detalla la implementación de una aplicación de demostración dentro de una máquina virtual (VM) fuera de tu clúster de Kubernetes. Si configuras un servidor HTTP en una VM, simularás una aplicación externa que el balanceador de cargas puede exponer, lo que demuestra su capacidad para administrar el tráfico a los recursos dentro y fuera del clúster.
Primero, crea una VM para la app de demo.
- Abre la consola de GDC en tu navegador web.
- Selecciona el mismo proyecto en el que creaste tu clúster estándar de Kubernetes.
- Abre el menú y, luego, haz clic en Máquinas virtuales.
- Haz clic en Crear instancia.
- Asigna el nombre
vm-workloada la VM. Una imagen de 2 CPU virtuales es suficiente para el ejemplo. - Para la imagen del disco de arranque, selecciona una distribución de Ubuntu 22.04, que viene con Python preinstalado.
- Haz clic en Crear.
- Espera unos minutos hasta que la VM esté lista.
- Establece una conexión SSH a la VM:
- En la consola de GDC, haz clic en la VM.
- Haz clic en Conectar con SSH.
Después de conectarte a la consola de SSH, ejecuta lo siguiente:
mkdir ~/simple-server
cd ~/simple-server
echo 'Welcome to my VM!' > index.html
python3 -m http.server --bind 0.0.0.0 8080 &
Para enrutar el tráfico a una VM, crea un servicio sin interfaz gráfica (sin selectores). Esto se asignará de forma manual a la dirección IP interna de la VM con un recurso EndpointSlice.
kk apply -f - <<EOF
apiVersion: v1
kind: Service
metadata:
name: vm-app-svc
namespace: vm-app
spec:
ports:
- protocol: TCP
port: 443
targetPort: 443
EOF
Para obtener la dirección IP de la VM vm-workload, ejecuta lo siguiente:
gdcloud compute instances list --project ${PROJECT_ID} \
| grep workload-vm | awk '{print $3}'
El resultado será la dirección IP de la VM que se necesitará para configurar el recurso EndpointSlice.
Crea el recurso EndpointSlice que se conectará al servicio sin selector de la app de VM y dirigirá la IP de la VM a la que se debe enrutar el tráfico.
apiVersion: discovery.k8s.io/v1
kind: EndpointSlice
metadata:
name: vm-app-endpoints
namespace: vm-app
labels:
kubernetes.io/service-name: vm-app-svc
addressType: IPv4
ports:
- port: 8080
endpoints:
- addresses:
- "VM_IP"
conditions:
ready: true
Crea certificados autofirmados
En esta sección, se te guiará a través del proceso de generación de certificados TLS autofirmados para tus aplicaciones. En esta guía, se usan certificados autofirmados por conveniencia, pero en entornos de producción, debes usar certificados de nivel de producción , como se describe en Opcional: Usa certificados listos para producción. Estos certificados son fundamentales para habilitar la finalización de HTTPS en la puerta de enlace de Nginx, lo que garantiza la comunicación encriptada entre los clientes y el balanceador de cargas para las cargas de trabajo en contenedores y basadas en VM.
Crea un certificado para la app en contenedores:
openssl req -x509 -newkey rsa:2048 -nodes \ -keyout tls-containerized.key \ -out tls-containerized.crt \ -subj "/CN=k8s-app.example.com" \ -days 365 kk create secret tls tls-containerized \ --namespace load-balancer \ --key tls-containerized.key \ --cert tls-containerized.crt kk create secret tls tls-containerized \ --namespace hello-app \ --key tls-containerized.key \ --cert tls-containerized.crtCrea un certificado para la app de VM:
openssl req -x509 -newkey rsa:2048 -nodes \ -keyout tls-vm.key \ -out tls-vm.crt \ -subj "/CN=vm-app.example.com" \ -days 365 kk create secret tls tls-vm \ --namespace load-balancer \ --key tls-vm.key \ --cert tls-vm.crt kk create secret tls tls-vm \ --namespace vm-app \ --key tls-vm.key \ --cert tls-vm.crt
Implementa NGINX
En esta sección, se describen los pasos para implementar el controlador de puerta de enlace de Nginx, incluida la instalación de las definiciones de recursos personalizados (CRD) de la API de Gateway, la configuración de Nginx Gateway Fabric con Helm y la verificación de la instalación en tu clúster estándar. Esto prepara la infraestructura para el enrutamiento avanzado de capa 7.
Instala las CRD de la API de puerta de enlace
La API de Gateway requiere que se instalen definiciones de recursos personalizados (CRD) en el clúster antes de implementar el controlador. Usaremos las definiciones de recursos personalizados (CRD) experimentales oficiales del proyecto de la API de Gateway (para esta guía, se usa la versión 1.2.0).
Instala las CRD experimentales:
kk apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.0/experimental-install.yamlPara verificar que las CRD se hayan instalado correctamente, ejecuta
kk get crd gateways.gateway.networking.k8s.io.
Instala NGINX Gateway Fabric
Implementa el controlador de NGINX Gateway Fabric con Helm. Este controlador observará los recursos de la API de Gateway y configurará NGINX para controlar el tráfico.
Establece la etiqueta de imagen de NGINX:
helm template nfg oci://ghcr.io/nginx/charts/nginx-gateway-fabric | grep "image:" # get the tag of the nginx-gateway-fabric (in following case 2.4.2) export NGINX_TAG="2.4.2"Extrae las imágenes de NGINX Gateway Fabric y NGINX y, luego, envíalas a tu registro de Harbor:
docker pull ghcr.io/nginx/nginx-gateway-fabric:${NGINX_TAG} docker tag ghcr.io/nginx/nginx-gateway-fabric:${NGINX_TAG} \ ${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/nginx-gateway-fabric:${NGINX_TAG} docker --config=./docker push \ ${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/nginx-gateway-fabric:${NGINX_TAG} docker pull nginx:1.27.3 docker tag nginx:1.27.3 \ ${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/nginx:1.27.3 docker --config=./docker push \ ${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/nginx:1.27.3Crea el espacio de nombres
nginx-gatewayy agrega el secreto de extracción de imágenes de Harbor:kk create namespace nginx-gateway kk create secret docker-registry ${IMAGE_PULL_SECRET_NAME} \ --from-file=.dockerconfigjson=./docker/config.json \ -n nginx-gatewayImplementa NGINX Gateway Fabric con Helm, que apunta a las imágenes de tu registro de Harbor:
KUBECONFIG=kubeconfig-${CLUSTER_NAME}.yaml helm upgrade --install ngf \ oci://ghcr.io/nginx/charts/nginx-gateway-fabric \ --create-namespace -n nginx-gateway \ --set nginxGateway.image.tag="${NGINX_TAG}" \ --set nginxGateway.image.repository="${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/nginx-gateway-fabric" \ --set nginx.image.repository="${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/nginx" \ --set nginxGateway.serviceAccount.imagePullSecret="${IMAGE_PULL_SECRET_NAME}" \ --set nginx.imagePullSecret="${IMAGE_PULL_SECRET_NAME}"La implementación de Kubernetes extrae imágenes de Harbor de forma segura con el secreto proporcionado (
${IMAGE_PULL_SECRET_NAME}), que contiene las credenciales de la cuenta de robot de Harbor.Verifica que se acepten los recursos
GatewayClass:kk get gatewayclassDeberías ver
nginxen la lista conACCEPTED = True.
Crea la instancia de puerta de enlace
Define la instancia lógica del balanceador de cargas que escucha en el puerto 443. La configuraremos para el modo Terminate, lo que significa que la puerta de enlace realizará la finalización de TLS y desencriptará el tráfico antes de pasarlo.
Crea y aplica gateway.yaml:
cat << EOF > gateway.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: my-gateway
namespace: load-balancer
spec:
gatewayClassName: nginx
listeners:
- name: https-k8s-workload
hostname: "k8s-app.example.com"
port: 443
protocol: HTTPS
allowedRoutes:
namespaces:
from: All
tls:
mode: Terminate
certificateRefs:
- kind: Secret
name: tls-containerized
- name: https-vm-workload
hostname: "vm-app.example.com"
port: 443
protocol: HTTPS
allowedRoutes:
namespaces:
from: All
tls:
mode: Terminate
certificateRefs:
- kind: Secret
name: tls-vm
EOF
kk apply -f gateway.yaml
Para verificar que la puerta de enlace se haya implementado correctamente, comprueba si PROGRAMMED es True:
kk get gateway my-gateway --n load-balancer
Verifica que se haya implementado un balanceador de cargas de L4 de GDC administrado como un servicio junto con la puerta de enlace.
kk get services -n load-balancer
Comprueba que el servicio de Nginx esté creado y configurado. El resultado debería verse de la siguiente manera:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-gateway-nginx LoadBalancer 10.252.19.148 10.200.32.43 443:30649/TCP 45h
Define la lógica de enrutamiento de L7 (HTTPRoute)
Vincula HTTPRoutes a tu puerta de enlace para definir cómo se debe distribuir el tráfico según el nombre de host solicitado (SNI).
Crea y aplica routing.yaml:
cat << EOF > routing.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: k8s-http-route
namespace: hello-app
spec:
parentRefs:
- name: my-gateway
namespace: load-balancer
hostnames:
- "k8s-app.example.com"
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: hello-app
namespace: hello-app
port: 80
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: vm-http-route
namespace: vm-app
spec:
parentRefs:
- name: my-gateway
namespace: load-balancer
hostnames:
- "vm-app.example.com"
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: vm-app-svc
namespace: vm-app
port: 443
EOF
kk apply -f routing.yaml
Recupera la IP del balanceador de cargas
Ejecuta el comando para obtener la IP del balanceador de cargas de Nginx.
kk get services/my-gateway-nginx \
-n load-balancer \
-o jsonpath='{.status.loadBalancer.ingress[0].ip}'
Esto será necesario cuando se verifique el acceso a las apps. Se hará referencia a esto como LOAD_BALANCER_IP.
Crear una VM de cliente
Sigue los pasos para crear una VM de cliente.
- Abre la consola de GDC en tu navegador web.
- Abre el menú y, luego, haz clic en Máquinas virtuales.
- Haz clic en Crear instancia.
- Crea una VM llamada
client, selecciona un tipo de máquina pequeño y selecciona Rocky Linux o Ubuntu, que vienen concurlpreinstalado. - Haz clic en Crear.
- Espera unos minutos hasta que la VM esté lista.
- Cuando la VM esté lista, establece una conexión SSH a ella:
- En la consola de GDC, haz clic en la VM.
- Haz clic en Conectar con SSH.
Verifica el acceso y el enrutamiento
Para probar el enrutamiento, ejecuta comandos curl desde tu VM de cliente. Puedes conectarte a ambas aplicaciones con sus nombres de host definidos con la dirección IP del balanceador de cargas.
Si pasas la marca --resolve en curl, puedes forzar que los nombres de dominio se resuelvan en la dirección IP del balanceador de cargas de L4 de GDC air-gapped.
Ten en cuenta que pasamos la marca -k para confiar en los certificados autofirmados.
Prueba la app en contenedores de Kubernetes:
curl -k --resolve k8s-app.example.com:443:$LOAD_BALANCER_IP https://k8s-app.example.com -v
Prueba la app de VM externa:
curl -k --resolve vm-app.example.com:443:$LOAD_BALANCER_IP https://vm-app.example.com -v
Si se configura correctamente, el controlador de puerta de enlace actuará sin problemas como terminador de TLS y pasará el tráfico al destino.
Opcional: Usa certificados listos para producción
En esta sección, se explica cómo aprovechar el servicio de CA de GDC aislado para crear una autoridad de certificación raíz privada, emitir certificados firmados para tus cargas de trabajo y actualizar de forma segura tu clúster estándar de GDC aislado y las VMs de cliente.
En esta sección, se describe cómo usar el servicio de CA
aislado de GDC para crear una autoridad certificadora (CA) raíz privada y emitir certificados válidos para tus aplicaciones. Si instalas esta CA raíz en tu VM de cliente, puedes verificar que la finalización de TLS funcione sin problemas con certificados de confianza, sin necesidad de omitir las advertencias de SSL (por ejemplo, con curl -k).
Otorga los permisos necesarios y obtén las credenciales
Para administrar el servicio de CA y emitir certificados, tu usuario necesita los roles de IAM adecuados en el proyecto.
Otorga los roles
certificate-authority-service-adminycertificate-requester:gdcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member=user:${USER_NAME} \ --role=certificate-authority-service-admin gdcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member=user:${USER_NAME} \ --role=certificate-requesterObtén las credenciales del servidor de la API de administración:
gdcloud clusters get-credentials ${ORG_NAME}-admin
Crea una AC raíz:
Crearás una autoridad certificadora en el servidor de la API de administración dentro del espacio de nombres de tu proyecto.
Aplica el recurso
CertificateAuthority:km apply -f - <<EOF apiVersion: pki.security.gdc.goog/v1 kind: CertificateAuthority metadata: name: my-root-ca namespace: ${PROJECT_ID} spec: caProfile: commonName: "My Root CA" duration: 87600h # 10 years keyAlgorithm: RSA_2048 maxChainLength: 1 caType: ROOT keyLocation: HSM rotationPolicy: cronTime: 0 0 1 1 * EOFkm -n ${PROJECT_ID} get \ certificateauthority.pki.security.gdc.goog/my-root-ca -ojson \ | jq -r ' .status.conditions[] | select( .type as $id | "Ready" | index($id)) .status'
Emite e implementa certificados
Cuando la CA esté lista, solicitarás certificados para la app en contenedores y la app basada en VM. Estas solicitudes se realizan en el servidor de la API de administración, y las claves resultantes se deben mover a tu clúster estándar.
Crea solicitudes para ambos dominios:
km apply -f - <<EOF
apiVersion: pki.security.gdc.goog/v1
kind: CertificateRequest
metadata:
name: tls-containerized-req
namespace: ${PROJECT_ID}
spec:
certificateAuthorityRef:
name: my-root-ca
namespace: ${PROJECT_ID}
certificateConfig:
subjectConfig:
commonName: "k8s-app.example.com"
dnsNames:
- "k8s-app.example.com"
signedCertificateSecret: tls-containerized-signed
---
apiVersion: pki.security.gdc.goog/v1
kind: CertificateRequest
metadata:
name: tls-vm-req
namespace: ${PROJECT_ID}
spec:
certificateAuthorityRef:
name: my-root-ca
namespace: ${PROJECT_ID}
certificateConfig:
subjectConfig:
commonName: "vm-app.example.com"
dnsNames:
- "vm-app.example.com"
signedCertificateSecret: tls-vm-signed
EOF
Espera unos instantes a que se emitan los certificados. Puedes verificar que estén listos cuando la condición Ready sea True:
km get certificaterequests -n ${PROJECT_ID}
Actualiza el clúster estándar
Si seguiste las secciones anteriores de esta guía, tienes secretos autofirmados en tu clúster estándar. Debes borrarlos antes de crear las versiones nuevas y firmadas:
kk delete secret tls-containerized -n load-balancer
kk delete secret tls-vm -n load-balancer
kk delete secret tls-containerized -n hello-app
kk delete secret tls-vm -n vm-app
Ahora, extrae los certificados firmados del servidor de la API de administración y crea los secretos nuevos en el clúster estándar.
km get secret -n ${PROJECT_ID} tls-containerized-signed \
-o jsonpath='{.data.tls\.crt}' \
| base64 -d > tls-containerized.crt
km get secret -n ${PROJECT_ID} tls-containerized-signed \
-o jsonpath='{.data.tls\.key}' \
| base64 -d > tls-containerized.key
kk create secret tls tls-containerized \
--namespace load-balancer \
--key tls-containerized.key \
--cert tls-containerized.crt
kk create secret tls tls-containerized \
--namespace hello-app \
--key tls-containerized.key \
--cert tls-containerized.crt
km get secret -n ${PROJECT_ID} tls-vm-signed \
-o jsonpath='{.data.tls\.crt}' \
| base64 -d > tls-vm.crt
km get secret -n ${PROJECT_ID} tls-vm-signed \
-o jsonpath='{.data.tls\.key}' \
| base64 -d > tls-vm.key
kk create secret tls tls-vm \
--namespace load-balancer \
--key tls-vm.key \
--cert tls-vm.crt
kk create secret tls tls-vm \
--namespace vm-app \
--key tls-vm.key \
--cert tls-vm.crt
Los balanceadores de cargas obtendrán y actualizarán automáticamente los secretos nuevos.
Configura la confianza del cliente
Para verificar la configuración, debes indicarle a tu VM de cliente que confíe en tu nueva CA raíz.
Extrae el certificado de la AC raíz a un archivo:
km get secret -n ${PROJECT_ID} my-root-ca-secret \
-o jsonpath='{.data.tls\.crt}' \
| base64 -d > my-root-ca.crt
Transfiere el certificado a tu VM de cliente. (Puedes copiar el contenido de my-root-ca.crt y pegarlo en un archivo en la VM de cliente).
En la VM de cliente, actualiza el almacén de confianza.
Si la VM client es Ubuntu:
sudo cp my-root-ca.crt /usr/local/share/ca-certificates/
sudo chmod 644 /usr/local/share/ca-certificates/my-root-ca.crt
sudo update-ca-certificates
Si la VM client es Rocky Linux:
sudo cp my-root-ca.crt /etc/pki/ca-trust/source/anchors/
sudo update-ca-trust
Verifica el acceso
Ahora puedes acceder a tus aplicaciones con curl sin la marca -k. La conexión será completamente confiable.
Prueba la app en contenedores de Kubernetes:
curl -v --resolve k8s-app.example.com:443:LOAD_BALANDER_IP https://k8s-app.example.com
Prueba la app de VM:
curl -v --resolve vm.example.com:443:LOAD_BALANDER_IP https://vm-app.example.com
Si la operación se realiza correctamente, verás el resultado de la aplicación de inmediato sin ninguna advertencia de certificado SSL.