Implemente la gobernanza en su clúster de Kubernetes

Cuando trabaja con Kubernetes, se convierte lentamente en su templo de producción. Invierte tiempo y recursos para desarrollarlo y potenciarlo y, naturalmente, comienza a buscar formas de controlar al usuario final de Kubernetes en su organización.

Conozca al Guardián de la OPA. Este artículo le mostrará cómo usarlo para crear y aplicar políticas y gobernanza para sus clústeres de Kubernetes para que los recursos que aplique cumplan con esa política.

Índice

    ¿Por qué utilizar OPA Gatekeeper?

    OPA Gatekeeper le ofrece dos habilidades críticas:

    • Vea lo que el usuario final puede hacer en el clúster
    • Aplicar políticas de negocio en el clúster

    Sin embargo, el verdadero poder de Gatekeeper es su efecto en las organizaciones. Gatekeeper ayuda a reducir la dependencia entre los administradores de DevOps y los propios desarrolladores. La aplicación de las políticas de su organización se puede automatizar, lo que libera a los ingenieros de DevOps de la preocupación de que los desarrolladores cometan errores. También brinda a los desarrolladores comentarios instantáneos sobre lo que salió mal y lo que necesitan cambiar.

    OPA Gatekeeper, un subproyecto de Open Policy Agent, está diseñado específicamente para implementar OPA en un clúster de Kubernetes. (Dato curioso: el proyecto es una colaboración entre Google, Microsoft, Red Hat y Styra). Este artículo requiere una comprensión básica de Kubernetes y OPA, por lo que si ya está familiarizado con OPA, no dude en omitir esta parte y continuar. a. siguiente.

    ¿Qué es la oferta pública de adquisición?

    La oferta pública de adquisición es como un súper motor. Puede escribir todas sus políticas en él, luego ejecutarlo con cada entrada para verificar si viola alguna política y, de ser así, cómo.

    La idea principal detrás de la adquisición es la capacidad de desvincular la lógica de la formulación de políticas del uso de la aplicación de políticas.

    Supongamos que estamos trabajando en una arquitectura multiservicio. Es posible que sea necesario tomar decisiones de política, por ejemplo, cuando el microservicio recibe una solicitud de API (como una autorización). Esa lógica se basa en reglas establecidas en su organización, por lo que en este caso puede descargar y unificar toda su lógica de toma de decisiones en un servicio dedicado: OPA.

    Cómo utilizar la OPA:

    1. Integrar con OPA: Si sus servicios están escritos en Go, puede integrar OPA como un paquete dentro de su proyecto. De lo contrario, puede implementar OPA como un demonio a nivel de host.
    2. Escriba y archive sus pólizas: Para definir sus políticas en la oferta pública de adquisición, debe escribirlas Rego y enviarlos a la oferta pública de adquisición. De esta forma, cada vez que utilice OPA para la aplicación de políticas, OPA consulta la entrada con respecto a estas políticas.
    3. Solicitar evaluación de póliza: Cuando la aplicación necesite tomar una decisión de política, enviará una solicitud de consulta API utilizando JSON, que contiene todos los datos solicitados a través de HTTP.

    Si quieres saber más sobre OPA y cómo usarlo y aprender más sobre sus capacidades, te recomiendo que sigas leyendo La documentación de la oferta pública de adquisición.

    Webhook de admisión de Kubernetes

    Antes de profundizar en cómo funciona Gatekeeper bajo el capó, primero debemos conocer los webhooks de admisión de Kubernetes.

    Cuando llega una solicitud a la API de Kubernetes, pasa por una serie de pasos antes de ejecutarse.

    1. La solicitud es autenticada y autorizada.
    2. La solicitud es procesada por una lista de colecciones de webhooks de Kubernetes especiales llamadas que pueden mutar, modificar y validar objetos en la solicitud.
    3. La solicitud se guarda en etcd para ser ejecutada.

    Los controladores de admisión de Kubernetes son middleware de clúster. Ellos controlan lo que puede suceder en el clúster. Los controladores de admisión manejan implementaciones que consumen muchos recursos, hacen cumplir las políticas de seguridad de los módulos e incluso bloquean la implementación de imágenes vulnerables.

    Debajo del capó de un controlador de admisión hay una colección de devoluciones de llamadas HTTP predefinidas (por ejemplo, webhooks), que interceptan la API de Kubernetes y procesan las solicitudes después de que se autentican y autorizan.

    Hay dos tipos de controladores de admisión:

    • MutatingAdmissionWebhook
    • ValidatingAdmissionWebhook

    Los controladores de admisión se invocan primero porque su trabajo es aplicar valores predeterminados personalizados y, si es necesario, modificar los objetos enviados al servidor API. Una vez que se completan todos los cambios y se valida el objeto de entrada, se invocan los controladores de admisión y pueden rechazar las solicitudes para aplicar políticas personalizadas. Tenga en cuenta que algunos controladores están validando la mutación. Si alguno de ellos rechaza la solicitud, la solicitud fallará.

    Es potente, gratuito y es posible que ya lo estés usando

    Varios controladores de admisión están preconfigurados y probablemente ya los use. LimitRanger, por ejemplo, es un webhook de admisión que evita que los pods se ejecuten si el clúster no tiene recursos. Para leer más sobre MutatingAdmissionWebhook, para ver "Sumérgete en Kubernetes MutatingAdmissionWebhooks"en el blog de IBM Cloud.

    Control de admisión dinámico

    Quizás se pregunte por qué los controladores de admisión se implementan con webhooks. Aquí es donde brilla el controlador de admisión y donde entra en juego.

    Los webhooks brindan a los desarrolladores la libertad y flexibilidad para personalizar la lógica de admisión para acciones como Crear, Actualizar o Eliminar en cualquier recurso. Esto es extremadamente útil, ya que casi todas las organizaciones necesitarán agregar/modificar sus políticas y mejores prácticas.

    Los problemas clave surgen de la forma en que operan los controladores de admisión. Cambiar los controladores de admisión requiere volver a compilarlos Kube-apiserver, y solo se puede habilitar cuando el apiserver Está activado. La implementación de controladores de admisión con webhooks permite a los administradores crear webhooks personalizados y agregar webhooks de admisión mutantes o de validación a la cadena de webhooks de admisión sin volver a compilarlos. El Kuberneti apiserver ejecuta webhooks registrados, que son interfaces estándar.

    Para leer más sobre el control de admisión dinámico, recomiendo el Documentos K8.

    Cómo funciona OPA Gatekeeper

    Gatekeeper actúa como un puente entre el servidor API de Kubernetes y la OPA. En la práctica, esto significa que Gatekeeper verifica cada solicitud que llega al clúster para ver si viola alguna de las políticas predefinidas. Si es así, apiserver lo rechazará.

    Bajo el capó, Gatekeeper se integra con Kubernetes mediante la API de control de admisión dinámica y se instala como personalizable ValidatingAdmission webhook. Una vez instalado, el apiserver lo activa cada vez que se crea, actualiza o elimina un recurso en el clúster.

    Como Gatekeeper opera a través de OPA, todas las políticas deben estar escritas en Rego. Afortunadamente, Kubernetes cubre esto usando el marco de restricciones OPA.

    Una restricción es un CRD que representa la política que queremos aplicar sobre un tipo específico de recurso. Cuando el ValidatingAdmission se invoca el controlador, el webhook de Gatekeeper evalúa todas las restricciones y envía la solicitud de OPA junto con la política para aplicarla. Todas las restricciones se evalúan como lógicas y, si no se cumple una restricción, se rechaza toda la solicitud.

    Cómo usar OPA Gatekeeper: un escenario simple

    Suponga que desea aplicar un recurso sin una etiqueta de propietario.

    Primero, instale Gatekeeper en su clúster:

    kubectl apply -f
    https://raw.githubusercontent.com/open-policy-agent/gatekeeper
    /release-3.4/deploy/gatekeeper.yaml

    Puedes probarlo ejecutando el siguiente comando:

    kubectl get pods --all-namespaces

    Si todo funciona bien, debería ver un pod en ejecución llamado gatekeeper-controller-managerunder gatekeeper-systemnamespace.

    Aplica el ConstraintTemplate que requerirá la presencia de todas las etiquetas descritas por la restricción:

    apiVersion: templates.gatekeeper.sh/v1beta1
    kind
    : ConstraintTemplate
    metadata
    :
      name
    : k8srequiredlabels
    spec
    :
      crd
    :
        spec
    :
          names
    :
            kind
    : K8sRequiredLabels
          validation
    :
           # Schema for the `parameters` field
            openAPIV3Schema
    :
              properties
    :
                labels
    :
                  type
    : array
                  items
    : string
      targets
    :
        - target
    : admission.k8s.gatekeeper.sh
          rego
    : |
           package k8srequiredlabels
            violation[{"msg": msg, "details": {"missing_labels": missing}}] {
              provided := {label | input.review.object.metadata.labels[label]}
              required := {label | label := input.parameters.labels[_]}
              missing := required - provided
              count(missing) > 0
              msg := sprintf("you must provide labels: %v", [missing])
            }

    Aplicar la restricción de que el K8sRequiredLabel que creó antes del alcance del espacio de nombres, por lo que se obligará a cada espacio de nombres a tener una etiqueta de propietario:

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

    Auditoría

    Como me gusta decir, el clúster es su templo de producción, por lo que desea un monitoreo continuo para detectar la corrección de configuraciones erróneas preexistentes. Aquí es donde entra la auditoría.

    Cuando se invoca el webhook de Gatekeeper, almacena los resultados de la auditoría como violaciones en el campo de estado de la restricción relevante. Por ejemplo:

    apiVersion: constraints.gatekeeper.sh/v1beta1
    kind
    : K8sRequiredLabels
    metadata
    :
      name
    : ns-must-have-owner
    spec
    :
      match
    :
        kinds
    :
          - apiGroups
    : [""]
            kinds
    : ["Namespace"]
      parameters
    :
        labels
    : ["owner"]
    status
    :
      auditTimestamp
    : "2019-08-06T01:46:13Z"
      byPod
    :
      - enforced
    : true
        id
    : gatekeeper-controller-manager-0
      violations
    :
      - enforcementAction
    : deny
        kind
    : Namespace
        message
    : 'you must provide labels: {"hr"}'
        name
    : default
      - enforcementAction
    : deny
        kind
    : Namespace
        message
    : 'you must provide labels: {"hr"}'
        name
    : gatekeeper-system
      - enforcementAction
    : deny
        kind
    : Namespace
        message
    : 'you must provide labels: {"hr"}'
        name
    : kube-public
      - enforcementAction
    : deny
        kind
    : Namespace
        message
    : 'you must provide labels: {"hr"}'
        name
    : kube-system

    Tal vez desee crear una política que requiera que todos los nombres de host entrantes sean únicos. En este caso, querrá utilizar la función de comprobación. Sin embargo, la restricción que impone un nombre de host de entrada único debe tener acceso a todas las entradas que no sean el objeto que se está evaluando. Esta situación requiere la replicación de datos en OPA.

    Un escenario sencillo

    De forma predeterminada, un control no requiere replicación, pero hay dos formas de configurar manualmente la replicación de datos:

    1. Utilice el mecanismo de caché OPA: pon la bandera audit-from-cache a true, que usará la caché OPA como fuente de verdad para todas las consultas de control. Cualquier objeto primero debe almacenarse en caché antes de que pueda verificarse si hay violaciones de restricciones.
    2. Usar un Kubernetes config recurso: Crear un config recurso y defina los recursos a los que desea replicar en OPA syncOnly. No te preocupes, actualiza syncOnly debería actualizar dinámicamente todos los objetos sincronizados.

    Por ejemplo, la siguiente configuración replica todos los espacios de nombres y recursos de pod en OPA:

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

    funcionamiento en seco

    Puede ir aún más lejos y probar las restricciones antes de agregarlas y aplicarlas. Aquí es donde entra en juego la función de ejecución en seco.

    El simulacro ofrece la misma funcionalidad que la auditoría, lo que le permite distribuir restricciones y ver todas las infracciones de restricciones informadas en el estado sin realizar cambios reales. Para configurar una restricción para el modo de ejecución en seco, todo lo que necesita hacer es usar el enforcementAction: dryrun etiqueta en la especificación de la restricción. Por defecto, enforcementAction se establece en "denegar", ya que el comportamiento predeterminado es denegar las solicitudes de admisión con cualquier infracción.

    Por ejemplo:

    apiVersion: constraints.gatekeeper.sh/v1beta1
    kind
    : K8sRequiredLabels
    metadata
    :
      name
    : ns-must-have-owner
    spec
    :
      match
    :
        kinds
    :
          - apiGroups
    : [""]
            kinds
    : ["Namespace"]
      parameters
    :
        labels
    : ["owner"]
    status
    :
      auditTimestamp
    : "2019-08-06T01:46:13Z"
      byPod
    :
      - enforced
    : true
        id
    : gatekeeper-controller-manager-0
      violations
    :
      - enforcementAction
    : dryrun
        kind
    : Namespace
        message
    : 'you must provide labels: {"hr"}'
        name
    : default
      - enforcementAction
    : deny
        kind
    : Namespace
        message
    : 'you must provide labels: {"hr"}'
        name
    : gatekeeper-system
      - enforcementAction
    : deny
        kind
    : Namespace
        message
    : 'you must provide labels: {"hr"}'
        name
    : kube-public
      - enforcementAction
    : deny
        kind
    : Namespace
        message
    : 'you must provide labels: {"hr"}'
        name
    : kube-system

    Piensa en grande

    Ahora que su producción está sana y salva, me gustaría detenerme un segundo y hacerle una pregunta: ¿En qué se diferencia Gatekeeper de las pruebas unitarias? Personalmente, cuando escuché por primera vez sobre Gatekeeper, no pude entender, después de todo, idealmente, ¿no pasa todo por el mismo conducto?

    Como desarrollador, pensar en las políticas de Kubernetes como pruebas unitarias tenía tanto sentido que me pregunté cuál es la diferencia entre mi código y los recursos de Kubernetes.

    Entra Datree.

    Datree es una solución de interfaz de línea de comandos (CLI) que le permite probar políticas en archivos YAML. La CLI viene con políticas integradas para todas las mejores prácticas de Kubernetes y una solución de administración centralizada para todas las políticas que cree. Ejecute Datree en el CI o como enlace de confirmación previa y utilícelo como lo haría con una biblioteca de prueba local. Es un proyecto de código abierto, por lo que es gratis. Puedes encontrar el proyecto en GitHub y obtén toda la información sobre El sitio de Datree.

    Le animo a que revise nuestro código y nos envíe sus comentarios para que pueda adaptarse mejor a su producción.

    Resumen

    A mi modo de ver, el hecho de que Kubernetes le permita implementar un pod con acceso al espacio de nombres de la red del host, por ejemplo, no significa que sea una buena idea.

    Cuando adopta Kubernetes, también está cambiando la cultura de su organización. DevOps no es algo que sucede de la noche a la mañana; es un proceso y es importante saber gestionarlo, especialmente en términos de escala.

    Espero que esto lo inspire a comenzar a pensar en sus políticas y cómo aplicarlas dentro de su organización.


    Este artículo apareció originalmente en blog de datree y se vuelve a publicar con permiso.

    Artículos de interés

    Subir