Crear restricciones

En esta página, se muestra cómo definir las restricciones del controlador de políticas.

El controlador de políticas te permite aplicar una política para un clúster de Kubernetes mediante la definición de uno o más objetos de restricción. Después de que se instala una restricción, las solicitudes al servidor de la API se verifican en la restricción y se rechazan si no cumplen con ella. Los recursos preexistentes que no cumplan con esta se informarán en el tiempo de auditoría.

Cada restricción está respaldada por una plantilla de restricciones que define el esquema y la lógica de la restricción. Las plantillas de restricciones se pueden obtener de Google y de terceros, o bien puedes escribirlas por tu cuenta. Para obtener más información sobre cómo crear plantillas nuevas, consulta Escribe una plantilla de restricciones.

Antes de comenzar

Usa la biblioteca de plantillas de restricciones

Cuando defines una restricción, debes especificar la plantilla de restricciones que extiende. De forma predeterminada, se instala una biblioteca común de plantillas de restricciones desarrollada por Google, por lo que muchas organizaciones no necesitan crear plantillas de restricción personalizadas directamente en Rego. Las plantillas de restricciones proporcionadas por Google tienen la etiqueta configmanagement.gke.io/configmanagement.

Para enumerar las restricciones, usa el siguiente comando:

kubectl get constrainttemplates \
    -l="configmanagement.gke.io/configmanagement=config-management"

Para describir una plantilla de restricciones y verificar los parámetros que requiere, usa el siguiente comando:

kubectl describe constrainttemplate CONSTRAINT_TEMPLATE_NAME

También puedes ver todas las plantillas de restricciones en la biblioteca.

Define una restricción

Debes usar YAML para definir una restricción, y no necesitas entender ni escribir Rego. En cambio, una restricción invoca una plantilla de restricciones y le proporciona parámetros específicos de la restricción.

Si usas un repositorio estructurado, te recomendamos crear las restricciones en el directorio cluster/.

Las restricciones tienen los siguientes campos:

  • El kind en minúsculas coincide con el nombre de una plantilla de restricciones.
  • El campo metadata.name es el nombre de la restricción.
  • El campo match define a qué objetos se aplica la restricción. Todas las condiciones especificadas deben coincidir antes de que un objeto esté dentro del alcance de una restricción. Las condiciones match se definen mediante los siguientes subcampos:
    • kinds son los tipos de recursos a los que se aplica la restricción, que se determinan mediante dos campos: apiGroups es una lista de los grupos de la API de Kubernetes que coincidirán y kinds es una lista de los tipos que coincidirán. Mediante "*", se realizan coincidencias con todo. Si al menos una entrada apiGroup y una entrada kind coinciden, se cumple la condición kinds.
    • namespaces es una lista de nombres de los espacios de nombres a los que puede pertenecer el objeto. El objeto debe pertenecer al menos a uno de estos espacios de nombres. Los recursos del espacio de nombres se tratan como si pertenecieran a sí mismos.
    • excludedNamespaces es una lista de espacios de nombres a los que el objeto no puede pertenecer.
    • labelSelector es un selector de etiquetas de Kubernetes con el que el objeto debe cumplir.
    • namespaceSelector es un selector de etiquetas en el espacio de nombres al que pertenece el objeto. Si el espacio de nombres no cumple con el objeto, no coincidirá. Los recursos del espacio de nombres se tratan como si pertenecieran a sí mismos.
  • El campo parameters define los argumentos para la restricción, en función de lo que espera la plantilla de restricciones.

La siguiente restricción, llamada ns-must-have-geo, invoca una plantilla de restricciones llamada K8sRequiredLabels, que se incluye en la biblioteca de plantillas de restricciones proporcionada por Google. La restricción define los parámetros que la plantilla de restricciones usa para evaluar si los espacios de nombres tienen la etiqueta geo establecida en algún valor.

# ns-must-have-geo.yaml

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
  name: ns-must-have-geo
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Namespace"]
  parameters:
    labels:
      - key: "geo"

Para crear la restricción, usa kubectl apply -f:

kubectl apply -f ns-must-have-geo.yaml

Audita una restricción

Si la restricción se configura y se instala de forma adecuada, su campo status.byPod[].enforced se configura como true, ya sea que la restricción esté configurada para aplicar la restricción o solo probarla.

Las restricciones se aplican de forma predeterminada y el incumplimiento de una restricción impide una operación de clúster determinada. Puedes establecer la spec.enforcementAction de una restricción en dryrun para informar los incumplimientos en el campo status.violations sin impedir la operación.

Para obtener más información sobre cómo auditar, consulta Audita mediante el uso de restricciones.

Advertencias durante la sincronización de restricciones

Ten en cuenta las siguientes advertencias cuando sincronices restricciones.

Coherencia eventual

Puedes asignar restricciones al repositorio y limitar sus efectos mediante ClusterSelectors o NamespaceSelectors. Debido a que la sincronización es eventualmente coherente, ten en cuenta las siguientes advertencias:

  • Si una operación de clúster desencadena una restricción cuyo NamespaceSelector hace referencia a un espacio de nombres que no se haya sincronizado, la restricción se aplicará y se evitará la operación. En otras palabras, un espacio de nombres faltante “se cerrará en falla”.
  • Si cambias las etiquetas de un espacio de nombres, puede que la memoria caché contenga datos desactualizados por un tiempo breve.

Minimiza la necesidad de cambiar el nombre de un espacio de nombres o sus etiquetas, y prueba las restricciones que afectan a un espacio de nombres con un cambio de nombre o de etiquetas para garantizar que funcionen como se espera.

Configura el controlador de políticas para restricciones referenciales

Antes de poder habilitar restricciones referenciales, debes crear una configuración que le indique al controlador de políticas qué tipos de objetos debe observar, como los espacios de nombres.

Guarda el siguiente manifiesto YAML en un archivo y aplícalo con kubectl. El manifiesto configura el controlador de políticas para que supervise los espacios de nombres y los ingresos. Crea una entrada con group, version y kind en spec.sync.syncOnly, con los valores de cada tipo de objeto que deseas ver.

apiVersion: config.gatekeeper.sh/v1alpha1
kind: Config
metadata:
  name: config
  namespace: "gatekeeper-system"
spec:
  sync:
    syncOnly:
      - group: ""
        version: "v1"
        kind: "Namespace"
      - group: "extensions"
        version: "v1beta1"
        kind: "Ingress"

Habilita las restricciones referenciales

Una restricción referencial hace referencia a otro objeto en su definición. Por ejemplo, podrías crear una restricción que requiera que los objetos de entrada en un clúster tengan nombres de host únicos. La restricción es referencial si tu plantilla de restricciones contiene la string data.inventory en su Rego.

Las restricciones referenciales están inhabilitadas de forma predeterminada en el controlador de políticas. Solo se garantiza que las restricciones de referencia sean eventualmente coherentes, y esto crea riesgos:

  • En un servidor de API sobrecargado, el contenido de la memoria caché del controlador de políticas puede volverse obsoleto, lo que causaría una restricción referencial para "abrirse con errores", lo que significa que la acción de aplicación forzosa parece estar funcionando cuando no lo está. Por ejemplo, puedes crear entradas con nombres de host duplicados demasiado rápido como para permitir que el controlador de admisión detecte los duplicados.

  • El orden en el que se instalan las restricciones y el orden en el que se actualiza la memoria caché son aleatorios.

Si comprendes estos riesgos y aún deseas habilitar la compatibilidad con las restricciones referenciales, establece policyController.referentialRulesEnabled en true en el objeto del operador:

apiVersion: configmanagement.gke.io/v1
kind: ConfigManagement
metadata:
  name: config-management
  namespace: config-management-system
spec:
  clusterName: my-cluster
  channel: dev
  policyController:
    enabled: true
    referentialRulesEnabled: true

Enumera todas las restricciones

Para enumerar todas las restricciones instaladas en un clúster, usa el siguiente comando:

kubectl get constraint

Quita una restricción

Si deseas encontrar todas las restricciones que usan una plantilla de restricciones, usa el siguiente comando para enumerar todos los objetos con el mismo kind que metadata.name de la plantilla de restricciones:

kubectl get CONSTRAINT_TEMPLATE_NAME

Para quitar una restricción, especifica su kind y su name:

kubectl delete CONSTRAINT_TEMPLATE_NAME CONSTRAINT_NAME

Si deseas borrar la plantilla de restricciones que usaba la restricción, toma nota del kind de la restricción.

Cuando quitas una restricción, deja de aplicarse tan pronto como el servidor de API la marca como eliminada.

Quita todas las plantillas de restricciones

Establece spec.policyController.templateLibraryInstalled en false. Esto evita que el operador vuelva a instalar la biblioteca de forma automática.

Para quitar todas las plantillas de restricciones y todas las restricciones, usa el siguiente comando:

kubectl delete constrainttemplate --all

Restaura la biblioteca de plantillas de restricciones

Si inhabilitaste la biblioteca de plantillas de restricciones o desinstalaste todas las plantillas de restricciones, puedes restaurarla si configuras spec.policyController.templateLibraryInstalled como true en la configuración del operador.

Soluciona problemas

No se pudo crear una plantilla de restricción

Si ves un error que menciona un disallowed ref, confirma que habilitaste las restricciones referenciales. Por ejemplo, si usas data.inventory en una plantilla de restricción sin habilitar primero las restricciones referenciales, el error es similar al siguiente:

admission webhook "validation.gatekeeper.sh" denied the request: check refs failed on module {templates["admission.k8s.gatekeeper.sh"]["MyTemplate"]}: disallowed ref data.inventory...

¿Qué sigue?