Skip to content

Kubewarden

Kubewarden es un motor de políticas de Kubernetes. Su objetivo es ser el motor de políticas universal para Kubernetes.

  • Puede reutilizar políticas de otros motores de políticas sin tener que reescribirlas.
  • Puede escribir sus propias políticas en cualquier lenguaje de programación que genere archivos binarios de WebAssembly, reutilizando sus bibliotecas y herramientas de lenguaje.
  • Puede ejecutar políticas tanto fuera del clúster como como parte de sus procesos de CI/CD.
  • Kubewarden también proporciona un escáner de auditoría para comprobar de forma activa y continua el cumplimiento de las políticas a lo largo del tiempo.

Kubewarden es un proyecto CNCF Sandbox, creado originalmente por SUSE Rancher .

Componentes de Kubewarden

Se compone de varios tipos de recursos y componentes que trabajan juntos para proporcionar una gestión avanzada y segura de políticas en Kubernetes. ClusterAdmissionPolicy y AdmissionPolicy definen las políticas a diferentes niveles, PolicyServer evalúa y ejecuta estas políticas, y el kubewarden-controller coordina y asegura el funcionamiento adecuado de todo el sistema.

Recursos ClusterAdmissionPolicy: Estos recursos definen cómo se implementan las políticas para los clústeres de Kubernetes. Cada ClusterAdmissionPolicy especifica una política que se aplica a nivel de clúster, proporcionando una forma centralizada de gestionar las reglas de seguridad y comportamiento que deben seguir los recursos dentro del clúster.

Recursos PolicyServer: Representan una implementación de un PolicyServer de Kubewarden. Los PolicyServer son responsables de cargar y evaluar las políticas definidas por el administrador. Estas políticas se ejecutan en el contexto del PolicyServer, que actúa como un entorno seguro y aislado para la evaluación de las políticas.

Recursos AdmissionPolicy: Definen políticas específicas para un namespace determinado. Mientras que ClusterAdmissionPolicy aplica políticas a nivel de clúster, AdmissionPolicy permite definir y aplicar políticas específicas dentro de un namespace, proporcionando un control más granular sobre los recursos y las reglas dentro de ese ámbito.

Implementación de un kubewarden-controller: Este controlador monitorea los recursos ClusterAdmissionPolicy y AdmissionPolicy, e interactúa con los componentes del PolicyServer de Kubewarden. El kubewarden-controller asegura que las políticas se carguen y apliquen correctamente, gestionando la comunicación entre Kubernetes y los servidores de políticas de Kubewarden.

Un listado de políticas las puede encontrar en el siguiente enlace: ArtifactHub

Instalación en Rancher Kubernetes Engine

  1. Ingresar como usuario administrador al cluster de Kubernetes con el siguiente comando:
    export KUBECONFIG=/home/student/rke2_conn/cluster1/cluster1_kubeconfig.yaml
    
  2. Instalar Kubewarden stack usando helm charts de la siguiente forma: Primero se deben agregar los repositorios de los helm charts desde el servidor bastion
    helm repo add kubewarden https://charts.kubewarden.io
    
    helm repo update kubewarden
    
  3. Instalar los CRDS
    helm install --wait -n kubewarden --create-namespace kubewarden-crds kubewarden/kubewarden-crds
    
  4. Instalar kubewarden-controller:
    helm install --wait -n kubewarden kubewarden-controller kubewarden/kubewarden-controller
    
  5. Instalar kubewarden-defaults, que creará un recurso de PolicyServer llamado default. También puede instalar un conjunto de políticas recomendadas para proteger su clúster aplicando algunas de las mejores prácticas conocidas.
    helm install --wait -n kubewarden kubewarden-defaults kubewarden/kubewarden-defaults
    

Ejemplo: Implementando una Politica para prevenir crear recursos en el sistema sin definición de recursos de computo.

El siguiente ejemplo aplicará una Politica que restringe la creación de Pods sin recursos definidos. Esto ayuda a mantener la capacidad del cluster controlada.

  1. Ingresar como usuario administrador al cluster de Kubernetes con el siguiente comando:
    export KUBECONFIG=/home/student/rke2_conn/cluster1/cluster1_kubeconfig.yaml
    
  2. Crearemos un namespace con el nombre test-kw-policy1.

    kubectl create ns test-kw-policy1
    

  3. Usaremos el siguiente comando para crear la política de tipo AdmissionPolicy llamada container-resources-policy, en el nuevo namespace test-kw-policy1. Necesitamos evitar la creación de pods sin recursos (requests,limits) definidos o dentro de los valore permitidos por esta política.

    Puede obtener información acerca de la política en este enlace.

    Recurso Parámetro Valor
    Memoria defaultRequest 128M
    defaultLimit 256M
    maxLimit 2G
    CPU defaultRequest 100m
    defaultLimit 150m
    maxLimit 500m
    kubectl apply -f - <<EOF
    apiVersion: policies.kubewarden.io/v1
    kind: AdmissionPolicy
    metadata:
      name: container-resources-policy
      namespace: test-kw-policy1
    spec:
      module: registry://ghcr.io/kravciak/policies/container-resources:latest
      rules:
      - apiGroups: [""]
        apiVersions: ["v1"]
        resources: ["pods"]
        operations:
        - CREATE
        - UPDATE
      mutating: false
      settings:
        memory:
          defaultRequest: 128M
          defaultLimit: 256M
          maxLimit: 2G
        cpu:
          defaultRequest: 100m
          defaultLimit: 150m
          maxLimit: 500m
    EOF
    
  4. Cuando el recurso AdmissionPolicy se crea, el estado se establece en pending y forzará una implementación del en PolicyServer. En nuestro ejemplo, es el PolicyServer llamado default. Puede monitorear el lanzamiento ejecutando el siguiente comando:

    watch kubectl get admissionpolicy.policies -n test-kw-policy1
    

  5. Crearemos la definición de un pod en un archivo llamado simple-pod.yaml.

    kubectl run simple-pod --image=docker.io/redis:latest\
     -n test-kw-policy1 -o yaml --dry-run=client > simple-pod.yaml
    

  6. Consultamos la definición del recurso.

    cat simple-pod.yaml
    
    Salida ejemplo:
    apiVersion: v1
    kind: Pod
    metadata:
      creationTimestamp: null
      labels:
        run: simple-pod
      name: simple-pod
      namespace: test-kw-policy1
    spec:
      containers:
      - image: docker.io/redis:latest
        name: simple-pod
        resources: {}
      dnsPolicy: ClusterFirst
      restartPolicy: Always
    status: {}
    
    Note que por defecto no cuenta con recursos definidos.

  7. Trate de aplicar el cambio en el cluster.

    kubectl apply -f simple-pod.yaml
    
    Deberá fallar con el siguiente mensaje:
    Error from server: error when creating "simple-pod.yaml": admission 
    webhook "namespaced-test-kw-policy1-container-resources-policy.
    kubewarden.admission" denied the request: Request rejected by 
    policy namespaced-test-kw-policy1-container-resources-policy. The 
    policy attempted to mutate the request, but it is currently 
    configured to not allow mutations
    
    Lo que indica que no tiene recuros definidos y no se forza a modificar el recurso para asigarne valores por defecto.

  8. Modicaremos el recurso para incluir la definición de los recursos de la siguiente manera:

    apiVersion: v1
    kind: Pod
    metadata:
      creationTimestamp: null
      labels:
        run: simple-pod
      name: simple-pod
      namespace: test-kw-policy1
    spec:
      containers:
      - image: docker.io/redis:latest
        name: simple-pod
        resources:
          requests:
            cpu: 100m
            memory: 100M
          limits:
            cpu: 150m
            memory: 8G
      dnsPolicy: ClusterFirst
      restartPolicy: Always
    status: {}
    
    Note que hemos definido como valor máximo de memoria 8G.

  9. Trate de aplicar el cambio en el cluster.

    kubectl apply -f simple-pod.yaml
    
    Deberá fallar con el siguiente mensaje:
    Error from server: error when creating "simple-pod.yaml": admission 
    webhook "namespaced-test-kw-policy1-container-resources-policy.
    kubewarden.admission" denied the request: memory limit '8G' exceeds 
    the max allowed value '2G'
    

  10. Modifique la definición de recursos y ajuste los parámetros de resources.limits.memory a 1G.

    apiVersion: v1
    kind: Pod
    metadata:
      creationTimestamp: null
      labels:
        run: simple-pod
      name: simple-pod
      namespace: test-kw-policy1
    spec:
      containers:
      - image: docker.io/redis:latest
        name: simple-pod
        resources:
          requests:
            cpu: 100m
            memory: 100M
          limits:
            cpu: 150m
            memory: 1G
      dnsPolicy: ClusterFirst
      restartPolicy: Always
    status: {}
    

  11. Trate de aplicar el cambio en el cluster.

    kubectl apply -f simple-pod.yaml
    
    El comando deberá ser exitoso y se creará el pod en el namespace deseado.

Ejemplo: Modificación de una Politica para ajustar los recursos de un pod en su definición de recursos de computo.

El siguiente ejemplo aplicará una Politica que modificar la creación de Pods sin recursos definidos y coloca los valores predeterminados. Esto ayuda a mantener la capacidad del cluster controlada.

  1. Modifique la politica creada previamete.

    kubectl apply -f - <<EOF
    apiVersion: policies.kubewarden.io/v1
    kind: AdmissionPolicy
    metadata:
      name: container-resources-policy
      namespace: test-kw-policy1
    spec:
      module: registry://ghcr.io/kravciak/policies/container-resources:latest
      rules:
      - apiGroups: [""]
        apiVersions: ["v1"]
        resources: ["pods"]
        operations:
        - CREATE
        - UPDATE
      mutating: true
      settings:
        memory:
          defaultRequest: 128M
          defaultLimit: 256M
          maxLimit: 2G
        cpu:
          defaultRequest: 100m
          defaultLimit: 150m
          maxLimit: 500m
    EOF
    
    Note el cambio en mutating, esto permitirá que el recurso sea modificado en tiempo de ejecución con los valores de la política.

  2. Puede monitorear el lanzamiento ejecutando el siguiente comando:

    watch kubectl get admissionpolicy.policies -n test-kw-policy1
    
    Espere a que esta activa.

  3. Crearemos la definición de un pod en un archivo llamado simple-pod2.yaml.

    kubectl run simple-pod2 --image=docker.io/redis:latest\
     -n test-kw-policy1 -o yaml --dry-run=client > simple-pod2.yaml
    

  4. Consultamos la definición del recurso.

    cat simple-pod2.yaml
    
    Salida ejemplo:
    apiVersion: v1
    kind: Pod
    metadata:
      creationTimestamp: null
      labels:
        run: simple-pod
      name: simple-pod
      namespace: test-kw-policy1
    spec:
      containers:
      - image: docker.io/redis:latest
        name: simple-pod
        resources: {}
      dnsPolicy: ClusterFirst
      restartPolicy: Always
    status: {}
    
    Note que por defecto no cuenta con recursos definidos.

  5. Trate de aplicar el cambio en el cluster.

    kubectl apply -f simple-pod2.yaml
    
    Deberá set exitoso.
    pod/simple-pod2 created
    

  6. Inspeccione el pod en ejecución.

    kubectl get -o yaml pod/simple-pod2 -n test-kw-policy1 |yq .spec.containers[0].resources
    
    Salida ejemplo:
    limits:
      cpu: 150m
      memory: 256M
    requests:
      cpu: 100m
      memory: 128M
    
    Note que se ha modificado en tiempo de ejecución con los valores definidos en la política.

    Recurso Parámetro Valor
    Memoria defaultRequest 128M
    defaultLimit 256M
    CPU defaultRequest 100m
    defaultLimit 150m

Ejemplo: Implementando una Politica Nivel de Cluster

El siguiente ejemplo aplicará una Politica que restringe la creación de Pods con securityContext privileged, la configuración securityContext: privileged: true en un POD proporciona a los contenedores permisos extendidos en el host, lo que puede ser necesario para ciertas aplicaciones pero conlleva riesgos significativos de seguridad.

⚠ NO DEBE DEJAR ESTA POLITICA ACTIVA EN ESTE CLUSTER, ASEGURESE DE ELIMINAR LOS RECURSOS EN LA SECCION "Limpieza del ambiente" AL FINALIZAR

  1. Usaremos el siguiente comando para crear la política pod-privileged. Necesitamos evitar la creación de contenedores privilegiados dentro de nuestro clúster de Kubernetes aplicando esta política.
    kubectl apply -f - <<EOF
    apiVersion: policies.kubewarden.io/v1
    kind: ClusterAdmissionPolicy
    metadata:
      name: privileged-pods
    spec:
      module: registry://ghcr.io/kubewarden/policies/pod-privileged:v0.2.2
      rules:
      - apiGroups: [""]
        apiVersions: ["v1"]
        resources: ["pods"]
        operations:
        - CREATE
        - UPDATE
      mutating: false
    EOF
    
    Esto produce el siguiente resultado:
    clusteradmissionpolicy.policies.kubewarden.io/privileged-pods created
    
  2. Cuando el recurso ClusterAdmissionPolicy se crea, el estado se establece en pending y forzará una implementación del objetivo PolicyServer. En nuestro ejemplo, es el PolicyServer llamado default. Puede monitorear el lanzamiento ejecutando el siguiente comando:
    kubectl get clusteradmissionpolicy.policies.kubewarden.io/privileged-pods
    
    Y se debe mostrarse en estado active para comenzar a funcionar:
    [student@student-0-aio ~]$ kubectl get clusteradmissionpolicy.policies.kubewarden.io/privileged-pods
    NAME              POLICY SERVER   MUTATING   BACKGROUNDAUDIT   MODE      OBSERVED MODE   STATUS   AGE
    privileged-pods   default         false      true              protect   protect         active   103s
    
  3. Una vez que ClusterAdmissionPolicy esté activo, puede probar la política. Creemos un Pod con un Contenedor que no está en modo privileged:

    kubectl apply -f - <<EOF
    apiVersion: v1
    kind: Pod
    metadata:
      name: unprivileged-pod
    spec:
      containers:
        - name: nginx
          image: nginx:latest
    EOF
    
    Esto producirá el siguiente resultado:
    pod/unprivileged-pod created
    
    El Pod se creó exitosamente, con lo que comprobamos que contenedores que NO esten en modo privilegiado se crearan sin ningún inconveniente.

  4. Ahora, creemos un Pod con securityContext en privileged con valor true, la configuración securityContext: privileged: true proporciona a los contenedores permisos extendidos en el host, lo que puede ser necesario para ciertas aplicaciones pero conlleva riesgos significativos de seguridad.

    kubectl apply -f - <<EOF
    apiVersion: v1
    kind: Pod
    metadata:
      name: privileged-pod
    spec:
      containers:
        - name: nginx
          image: nginx:latest
          securityContext:
              privileged: true
    EOF
    
    La política ha denegado la creación del Pod y debería ver el siguiente mensaje:
    Error from server: error when creating "STDIN": admission webhook 
    "clusterwide-privileged-pods.kubewarden.admission" denied the 
    request: Privileged container is not allowed
    
    Lo anterior comprueba que la politica creada anteriormente esta funcionando correctamente, ya que NO permite crear contnedores en modo privileged

Limpieza del ambiente

  1. Puede eliminar los recursos creados desinstalando los helm charts de la siguiente manera::
    helm uninstall --namespace kubewarden kubewarden-defaults
    
    helm uninstall --namespace kubewarden kubewarden-controller
    
    helm uninstall --namespace kubewarden kubewarden-crds
    
    kubectl delete namespace kubewarden test-kw-policy1