Configura Google Cloud Armor

En esta página, se muestra cómo usar un recurso personalizado de BackendConfig para configurar Google Cloud Armor en Google Kubernetes Engine.

Descripción general

En un clúster de GKE, el balanceo de cargas de HTTP(S) controla el tráfico entrante, que es un componente de Cloud Load Balancing. Por lo general, el balanceador de cargas de HTTP(S) se configura con un controlador Ingress de GKE, que obtiene la información de configuración de un objeto Ingress de Kubernetes. El objeto Ingress se asocia a uno o más objetos de servicio. Cada objeto de servicio contiene datos de enrutamiento que se usan para direccionar una solicitud entrante a un pod o puerto específico.

A partir de la versión de Kubernetes 1.10.5-gke.3, tienes la posibilidad de agregar configuraciones al balanceador de cargas si vinculas un puerto de servicio a un recurso personalizado llamado BackendConfig.

El controlador del Ingress de GKE lee la información de configuración de BackendConfig y configura el balanceador de cargas según corresponda. Un BackendConfig tiene información de configuración específica de Cloud Load Balancing. Los recursos Ingress y servicio de Kubernetes no ofrecen una manera de configurar funciones específicas de los proveedores, como Google Cloud Armor. BackendConfig te permite establecer esa configuración.

A continuación, se detalla el panorama general de cómo configurar un BackendConfig en este ejercicio:

  1. Crea un BackendConfig.
  2. Crea un servicio y asocia uno de sus puertos al BackendConfig.
  3. Crea un Ingress y asócialo al par (servicio, puerto).

Antes de comenzar

Sigue estos pasos a fin de prepararte para esta tarea:

  • Asegúrate de haber habilitado la API de Google Kubernetes Engine.
  • Habilitar la API de Google Kubernetes Engine
  • Asegúrate de haber instalado el SDK de Cloud.
  • Establece tu ID del proyecto predeterminado:
    gcloud config set project [PROJECT_ID]
  • Si trabajas con clústeres zonales, establece tu zona de procesamiento predeterminada:
    gcloud config set compute/zone [COMPUTE_ZONE]
  • Si trabajas con clústeres regionales, establece tu región de procesamiento predeterminada:
    gcloud config set compute/region [COMPUTE_REGION]
  • Actualiza gcloud a la versión más reciente:
    gcloud components update

Crea un espacio de nombres

Crea un espacio de nombres de Kubernetes para los objetos en esta guía:

kubectl create namespace cloud-armor-how-to

Crea una implementación

En este manifiesto de implementación, se declara que quieres ejecutar dos réplicas de la aplicación web hello-app:

apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: cloud-armor-how-to
  name: my-deployment
spec:
  selector:
    matchLabels:
      app: hello-app
  replicas: 2
  template:
    metadata:
      labels:
        app: hello-app
    spec:
      containers:
      - name: hello-app-container
        image: gcr.io/google-samples/hello-app:1.0
        ports:
        - containerPort: 8080

Copia el manifiesto en un archivo llamado my-deployment.yaml y crea la implementación:

kubectl apply -f my-deployment.yaml

Crea una regla y una política de seguridad de Google Cloud Armor

Crea una política de seguridad de Google Cloud Armor:

gcloud beta compute security-policies create ca-how-to-security-policy \
    --description "policy for Google Cloud Armor how-to topic"

Crea una regla destinada a la política de seguridad; para ello, sigue estos pasos:

gcloud beta compute security-policies rules create 1000 \
    --security-policy ca-how-to-security-policy \
    --description "Deny traffic from 192.0.2.0/24." \
    --src-ip-ranges "192.0.2.0/24" \
    --action "deny-404"

Observa la política de seguridad:

gcloud beta compute security-policies describe ca-how-to-security-policy

Resultado:

...
kind: compute#securityPolicy
name: ca-how-to-security-policy
rules:
- action: deny(404)
  description: Deny traffic from 192.0.2.0/24.
  kind: compute#securityPolicyRule
  match:
    config:
      srcIpRanges:
      - 192.0.2.0/24
    versionedExpr: SRC_IPS_V1
  preview: false
  priority: 1000
  ...

Cómo crear un BackendConfig

A continuación, se detalla un manifiesto para un BackendConfig. El manifiesto especifica una política de seguridad:

apiVersion: cloud.google.com/v1beta1
kind: BackendConfig
metadata:
  namespace: cloud-armor-how-to
  name: my-backend-config
spec:
  securityPolicy:
    name: "ca-how-to-security-policy"

Copia el manifiesto en un archivo denominado my-backend-config.yaml y crea el BackendConfig:

kubectl apply -f my-backend-config.yaml

Observa el BackendConfig:

kubectl get backendconfig my-backend-config --namespace cloud-armor-how-to --output yaml

El resultado muestra la política de seguridad especificada:

apiVersion: cloud.google.com/v1beta1
kind: BackendConfig
metadata:
  name: my-backend-config
  namespace: cloud-armor-how-to
  ...
spec:
  securityPolicy:
    name: ca-how-to-security-policy

Cómo crear un servicio

Aquí hay un manifiesto para un servicio:

apiVersion: v1
kind: Service
metadata:
  namespace: cloud-armor-how-to
  name: my-service
  labels:
    app: hello-app
  annotations:
    beta.cloud.google.com/backend-config: '{"ports": {"80":"my-backend-config"}}'
spec:
  type: NodePort
  selector:
    app: hello-app
  ports:
  - port: 80
    protocol: TCP
    targetPort: 8080

Guarda el manifiesto en un archivo denominado my-service.yaml y crea el servicio:

kubectl apply -f my-service.yaml

Observa el servicio:

kubectl get service my-service --namespace cloud-armor-how-to --output yaml

El resultado es similar al siguiente ejemplo:

apiVersion: v1
kind: Service
metadata:
  annotations:
    beta.cloud.google.com/backend-config: '{"ports": {"80":"my-backend-config"}}'
  labels:
    app: hello-app
  name: my-service
  namespace: cloud-armor-how-to
  ...
spec:
  clusterIP: 10.19.249.137
  externalTrafficPolicy: Cluster
  ports:
  - nodePort: 32629
    port: 80
    protocol: TCP
    targetPort: 8080
  selector:
    app: hello-app
  sessionAffinity: None
  type: NodePort
status:
  loadBalancer: {}

A los fines de este ejercicio, estos son los aspectos importantes que debes tener en cuenta sobre tu servicio:

  • El puerto 80 del servicio está asociado a una BackendConfig con el nombre my-backend-config. En la anotación beta.cloud.google.com/backend-config, se especifica lo siguiente.

  • El servicio tiene el tipo NodePort. Este es el tipo requerido para los servicios que se van a asociar a un Ingress.

  • Cualquier pod que tenga la etiqueta app: hello-app es miembro del servicio. Esto se especifica en el campo selector.

  • El tráfico dirigido al servicio en el puerto TCP 80 se enruta al puerto TCP 8080 en uno de los pods miembro. Esto se especifica en los campos port y targetPort.

Reserva una dirección IP externa estática

Reserva una dirección IP externa estática:

gcloud compute addresses create cloud-armor-how-to-address --global

Observa una dirección IP externa estática:

gcloud compute addresses list --filter "name=cloud-armor-how-to-address"

Resultado:

NAME                        REGION  ADDRESS        STATUS
cloud-armor-how-to-address          203.0.113.2    RESERVED

Cómo crear un Ingress

Este es un manifiesto para un Ingress:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  namespace: cloud-armor-how-to
  name: my-ingress
  annotations:
    kubernetes.io/ingress.global-static-ip-name: "cloud-armor-how-to-address"
spec:
  backend:
    serviceName: my-service
    servicePort: 80

Copia el manifiesto en un archivo con el nombre my-ingress.yaml y crea el Ingress:

kubectl create -f my-ingress.yaml

Espera unos minutos a que el controlador de Ingress de Kubernetes configure un balanceador de cargas de Cloud y, luego, observa el Ingress:

kubectl get ingress my-ingress --output yaml --namespace cloud-armor-how-to

Resultado:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-ingress
  namespace: cloud-armor-how-to
  ...
spec:
  backend:
    serviceName: my-service
    servicePort: 80
status:
  loadBalancer:
    ingress:
    - ip: 203.0.113.2

A los fines de este ejercicio, estas son las cuestiones importantes que debes tener en cuenta sobre tu Ingress:

  • La dirección IP para el tráfico entrante aparece en loadBalancer:ingress:.

  • El Ingress tiene una regla que se aplica a las solicitudes HTTP entrantes desde cualquier host. Esto se debe a que no existe un campo host en la regla. Por eso, de manera predeterminada, se aplica la regla a todos los hosts.

  • Todas las solicitudes entrantes se tratan de la misma manera, independientemente de la ruta de URL. Esto se especifica mediante el valor path /*.

  • Las solicitudes entrantes se enrutan a un pod miembro de my-service. En este ejercicio, los pods miembros tienen la etiqueta app: hello-app.

  • Las solicitudes se enrutan al pod en el puerto de destino especificado en my-service. En este ejercicio, el puerto de destino del pod es 8080.

Visualiza la app web

Espera unos minutos. Luego, en tu navegador ingresa tu dirección IP externa estática.

En la página se muestra la respuesta de la aplicación web hello-app que se está ejecutando en uno de los pods de tu implementación:

Hello, world!
Version: 1.0.0
Hostname: my-deployment-574ddbdf88-f9fbj

Usa curl para ver la aplicación web:

curl -v [STATIC_ADDRESS]

donde [STATIC_ADDRESS] es tu dirección IP externa estática.

El resultado es la respuesta de hello-app:

Hello, world!
Version: 1.0.0
Hostname: my-deployment-574ddbdf88-zpb94

Cómo desvincular la política de seguridad

Para desvincular la política de seguridad desde un Ingress, deja vacío el nombre de la política en BackendConfig. A continuación, se muestra un ejemplo de la desvinculación de una política de seguridad:

apiVersion: cloud.google.com/v1beta1
kind: BackendConfig
metadata:
  namespace: cloud-armor-how-to
  name: my-backend-config
spec:
  securityPolicy:
    name: ""

Limitaciones

Límite de cuota

Existe un límite estricto en la cantidad de reglas de Google Cloud Armor que puedes escribir mientras esta función está en la versión Beta. Este límite se quitará cuando la función esté disponible por completo.

Solo listas blanca y negra de IP

Google Cloud Armor solo admite listas blanca y negra de IP.

Solución de problemas

No se encontró el BackendConfig

Este error se muestra cuando un BackendConfig para un puerto de servicio se especifica en la anotación del servicio, pero no se pudo encontrar ese recurso BackendConfig. Esto puede ocurrir si no creaste el recurso BackendConfig en absoluto, lo creaste en el espacio de nombres equivocado o escribiste mal la referencia en la anotación del servicio.

kubectl get event
KIND    ... SOURCE
Ingress ... loadbalancer-controller

MESSAGE
Error during sync: error getting BackendConfig for port 80 on service "default/my-service":
no BackendConfig for service port exists

No se encontró la política de seguridad

Después de crear el objeto Ingress, si la política de seguridad no está asociada correctamente al servicio de balanceador de cargas, evalúa el evento de Kubernetes para ver si hay un error de configuración. Específicamente, si tu BackendConfig especifica una política inexistente, se emitirá un evento de advertencia periódicamente. Para solucionar este problema, asegúrate de especificar la política de seguridad correcta, por nombre, en tu BackendConfig.

kubectl get event
KIND    ... SOURCE
Ingress ... loadbalancer-controller

MESSAGE
Error during sync: The given security policy "my-policy" does not exist.

Limpieza

Luego de completar los ejercicios de esta página, sigue estos pasos para quitar los recursos y evitar cargos no deseados en tu cuenta:

Borra los objetos de Kubernetes que creaste para este ejercicio:

kubectl delete ingress my-ingress --namespace cloud-armor-how-to
kubectl delete service my-service --namespace cloud-armor-how-to
kubectl delete backendconfig my-backend-config --namespace cloud-armor-how-to
kubectl delete deployment my-deployment --namespace cloud-armor-how-to
kubectl delete namespace cloud-armor-how-to

Borra tu dirección IP externa estática:

gcloud compute addresses delete cloud-armor-how-to-address --global

Borra la política de seguridad:

gcloud beta compute security-policies delete ca-how-to-security-policy

Pasos siguientes

¿Te ha resultado útil esta página? Enviar comentarios:

Enviar comentarios sobre...

Documentación de Kubernetes Engine