En esta página, se muestra cómo mutar recursos mediante el controlador de políticas. Esto sirve para configurar valores predeterminados. Por ejemplo, es posible que desees insertar una etiqueta para todos los recursos en un espacio de nombres específico o que el imagePullPolicy
de un Pod se establezca de forma predeterminada en Always
si aún no está configurado.
Habilita la mutación
Console
Para habilitar la mutación, completa los siguientes pasos:
- En la consola de Google Cloud , ve a la página Política de GKE Enterprise en la sección Administración de postura.
- En la pestaña Configuración, en la tabla del clúster, selecciona Editar edit en la columna Editar configuración.
- Expande el menú Editar configuración de Policy Controller.
- Selecciona la casilla de verificación Habilitar webhook de mutación.
- Selecciona Guardar cambios.
Policy Controller de gcloud
Para habilitar la mutación, ejecuta el siguiente comando:
gcloud container fleet policycontroller update \
--memberships=MEMBERSHIP_NAME \
--mutation
Reemplaza MEMBERSHIP_NAME
por el nombre de membresía del clúster registrado para habilitar la mutación. Puedes especificar varias membresías separadas por comas.
gcloud ConfigManagement
Se debe habilitar la mutación mediante la configuración de spec.policyController.mutation.enabled
en true
en el recurso config-management
:
apiVersion: configmanagement.gke.io/v1
kind: ConfigManagement
metadata:
name: config-management
spec:
policyController:
enabled: true
mutation:
enabled: true
Si usas el comando de la CLI de gcloud, debes usar la versión alfa para habilitar la mutación como se muestra en el siguiente ejemplo:
# apply-spec.yaml
applySpecVersion: 1
spec:
policyController:
enabled: true
mutationEnabled: true
Después de crear el archivo apply-spec.yaml
, ejecuta el siguiente comando para aplicar la configuración:
gcloud alpha container fleet config-management apply \
--membership=MEMBERSHIP_NAME \
--config=CONFIG_YAML_PATH \
--project=PROJECT_ID
Reemplaza lo siguiente:
MEMBERSHIP_NAME
: El nombre de la membresía del clúster registrado que tiene la configuración del controlador de políticas que deseas usarCONFIG_YAML_PATH
: Es la ruta de acceso al archivoapply-spec.yaml
PROJECT_ID
: El ID de tu proyecto
Definiciones
- mutator: un recurso de Kubernetes que ayuda a configurar el comportamiento de mutación del controlador de políticas
- system: Una disposición de varios mutadores
Ejemplo de mutación
En el siguiente ejemplo, se muestra un mutador que establece el imagePullPolicy
para todos los contenedores en todos los Pods en Always
:
# set-image-pull-policy.yaml
apiVersion: mutations.gatekeeper.sh/v1alpha1
kind: Assign
metadata:
name: always-pull-image
spec:
applyTo:
- groups: [""]
kinds: ["Pod"]
versions: ["v1"]
location: "spec.containers[name: *].imagePullPolicy"
parameters:
assign:
value: "Always"
En este ejemplo, hay los campos de metadatos estándar de Kubernetes (apiVersion
, kind
, metadata.name
), pero spec
es el lugar en el que se configura el comportamiento del mutador.
spec.applyTo
vincula el mutador a los recursos especificados. Debido a que cambiamos campos específicos en un objeto, definimos implícitamente el esquema de ese objeto. Por ejemplo, el mutador actual no tendría sentido si se aplicara a un recurso Namespace
. Debido a esto, este campo es obligatorio para que el controlador de políticas sepa para qué esquemas es relevante este mutador.
Los GroupVersionKinds
que faltan de esta lista no se mutan.
spec.location
nos dice qué campo modificar. En este caso, usamos un glob (*
) para indicar que queremos modificar todas las entradas de la lista de contenedores. Ten en cuenta que los únicos tipos de listas que el campo location
puede desviar son listas de tipos de mapa y se debe especificar el campo de clave para el mapa. Las listas de tipos de mapas son una construcción de Kubernetes. Encontrarás más detalles al respecto en la documentación de Kubernetes.
spec.parameters.assign.value
es el valor que se asignará a location
.
Este campo no tiene tipo y puede tomar cualquier valor, aunque ten en cuenta que Kubernetes aún valida la solicitud después de la mutación, por lo que insertar valores con un esquema incorrecto para el objeto que se modifica da como resultado el rechazo de la solicitud.
Usa mutadores para Jobs
Si configuras un objeto Job o CronJob, debes especificar la versión y el grupo por separado como se muestra en el ejemplo siguiente:
applyTo:
- groups: ["batch"]
kind: ["Job"]
versions: ["v1"]
Cuando usas un mutador para Jobs, los Jobs existentes no mutan, a menos que se modifiquen. La modificación de un objeto Job activa una solicitud al webhook de mutación y hace que mute.
Flujo de ejecución
Quizás el concepto más importante para comprender sobre los webhooks de mutación de Kubernetes es su política de revocación, porque el resultado de un mutador puede cambiar el comportamiento de otro mutador. Por ejemplo, si agregas un contenedor de archivo adicional nuevo, un mutador que establece la política de extracción de imágenes para todos los contenedores ahora tiene un contenedor nuevo que puede mutar.
En la práctica, esto significa que cualquier webhook de mutación del controlador de políticas de solicitudes podría llamarse más de una vez.
Para reducir la latencia, el controlador de políticas se vuelve a invocar a sí mismo para evitar solicitudes HTTP adicionales. Esto significa que la política de inserción de archivo adicional y de extracción de imagen tienen el resultado esperado.
La rutina de mutación del controlador de políticas continuará revocándose hasta que el recurso “converge”, lo que significa que las iteraciones adicionales no tengan más efectos.
Sintaxis de la ubicación
La sintaxis de la ubicación usa el descriptor de acceso de puntos (.
) para desviar campos. En el caso de listas con clave, los usuarios pueden hacer referencia a objetos individuales en una lista con la sintaxis [<key>: <value>]
o a todos los objetos en la lista con [<key>: *]
.
Los valores y los campos se pueden entrecomillar entre comillas simples ('
) o dobles ("
). Esto es necesario cuando tienen caracteres especiales, como puntos o espacios.
En los valores entre comillas, se pueden marcar los caracteres especiales con el prefijo \
. "Use \" to escape and \\\" to escape"
se convierte en Use " to escape and \" to escape
.
Estos son algunos ejemplos del recurso v1/Pod
:
spec.priority
referenciasspec.priority
spec.containers[name: "foo"].volumeMounts[mountPath: "/my/mount"].readOnly
hace referencia al camporeadOnly
de la activación/my/mount
del contenedorfoo
.spec.containers[name: *].volumeMounts[mountPath: "/my/mount"].readOnly
hace referencia al camporeadOnly
de la activación/my/mount
de todos los contenedores.
Si haces referencia a una ubicación que no existe en la actualidad en un recurso, esa ubicación se crea de forma predeterminada. Este comportamiento se puede configurar mediante pruebas de ruta de acceso.
Pruebas de ruta de acceso
¿Cómo podemos realizar la configuración predeterminada, en la que evitamos modificar un valor que ya existe? Tal vez queremos configurar /secure-mount
en solo lectura para todos los contenedores, pero no queremos crear un /secure-mount
si aún no existe uno. Podemos realizar cualquiera de estas acciones a través de pruebas de ruta.
En este ejemplo, se evita mutar imagePullPolicy
si ya está configurado:
# set-image-pull-policy.yaml
apiVersion: mutations.gatekeeper.sh/v1alpha1
kind: Assign
metadata:
name: always-pull-image
spec:
applyTo:
- groups: [""]
kinds: ["Pod"]
versions: ["v1"]
location: "spec.containers[name: *].imagePullPolicy"
parameters:
assign:
value: "Always"
pathTests:
- subPath: "spec.containers[name: *].imagePullPolicy"
condition: "MustNotExist"
Este es otro ejemplo que evita crear un contenedor sidecar
vacío si aún no existe:
# set-image-pull-policy.yaml
apiVersion: mutations.gatekeeper.sh/v1alpha1
kind: Assign
metadata:
name: always-pull-image
spec:
applyTo:
- groups: [""]
kinds: ["Pod"]
versions: ["v1"]
location: 'spec.containers[name: "sidecar"].imagePullPolicy'
parameters:
assign:
value: "Always"
pathTests:
- subPath: 'spec.containers[name: "sidecar"]'
condition: "MustExist"
Se pueden especificar varias pruebas de ruta de acceso, si es necesario.
subPath
debe ser un prefijo de (o igual a) location
.
Los únicos valores válidos para condition
son MustExist
y MustNotExist
.
Coincidencia
Los mutadores también permiten la coincidencia mediante el uso de los mismos criterios que las restricciones.
Mutadores
En la actualidad, existen dos tipos de mutadores: Assign
y AssignMetadata
.
Asignar
Assign
puede cambiar cualquier valor fuera del campo metadata
de un recurso.
Debido a que todos GroupVersionKinds
tienen un esquema único, deben estar vinculados a un conjunto de GroupVersionKinds
en particular.
Tiene el siguiente esquema:
apiVersion: mutations.gatekeeper.sh/v1alpha1
kind: Assign
metadata:
name: always-pull-image
spec:
applyTo:
- groups: [""]
kinds: ["Pod"]
versions: ["v1"]
match:
kinds: # redundant because of `applyTo`, but left in for consistency
- apiGroups: ["*"]
kinds: ["*"]
namespaces: ["my-namespace"]
scope: "Namespaced" # or "Cluster"
excludedNamespaces: ["some-other-ns"]
labelSelector:
matchLabels:
mutate: "yes"
matchExpressions:
- key: "my-label"
operator: "In" # or, "NotIn", "Exists", or "DoesNotExist"
values: ["my-value"]
namespaceSelector:
matchLabels:
mutate: "yes"
matchExpressions:
- key: "my-label"
operator: "In" # or, "NotIn", "Exists", or "DoesNotExist"
values: ["my-value"]
location: "spec.containers[name: *].imagePullPolicy"
parameters:
pathTests:
- subPath: 'spec.containers[name: "sidecar"]' # must be a prefix of `location`
condition: "MustExist" # or "MustNotExist"
- subPath: "spec.containers[name: *].imagePullPolicy"
condition: "MustNotExist"
assign:
value: "Always" # any type can go here, not just a string
AssignMetadata
AssignMetadata
puede agregar nuevas etiquetas de metadatos. No puede cambiar el valor de las etiquetas de metadatos existentes. De lo contrario, podría escribirse un sistema de mutadores que se repetiría de forma indefinida, lo que provocaría que se agotara el tiempo de espera de las solicitudes.
Debido a que todos los recursos comparten el mismo esquema metadata
, no es necesario especificar a qué recurso se aplica un AssignMetadata
.
Además, debido a que AssignMetadata
no puede hacer tanto, su esquema es un poco más simple.
apiVersion: mutations.gatekeeper.sh/v1alpha1
kind: AssignMetadata
metadata:
name: set-team-name
spec:
match:
kinds:
- apiGroups: ["*"]
kinds: ["*"]
namespaces: ["my-namespace"]
scope: "Namespaced" # or "Cluster"
excludedNamespaces: ["some-other-ns"]
labelSelector:
matchLabels:
mutate: "yes"
matchExpressions:
- key: "my-label"
operator: "In" # or, "NotIn", "Exists", or "DoesNotExist"
values: ["my-value"]
namespaceSelector:
matchLabels:
mutate: "yes"
matchExpressions:
- key: "my-label"
operator: "In" # or, "NotIn", "Exists", or "DoesNotExist"
values: ["my-value"]
location: "metadata.labels.team" # must start with `metadata.labels`
parameters:
assign:
value: "Always" # any type can go here, not just a string
Prácticas recomendadas
Advertencias de Kubernetes
En la documentación de Kubernetes, se enumeran algunas consideraciones importantes sobre el uso de los webhooks de mutación. Debido a que el controlador de políticas funciona como un webhook de admisión de Kubernetes, ese consejo se aplica aquí.
La sintaxis de mutación del controlador de políticas está diseñada para facilitar el cumplimiento de problemas operativos en torno a los webhooks de mutación, incluida la idempotencia.
Escribe mutadores
Atomicidad
Se recomienda que cada mutador sea lo suficientemente autosuficiente como sea posible. Debido a que Kubernetes tiene coherencia eventual, un mutador no debería confiar en que un segundo mutador se haya reconocido para que haga su trabajo de forma correcta. Por ejemplo, cuando agregas un archivo adicional, agrégalo completo, no lo construyas a través de varios mutadores.
Validación
Si hay una condición que deseas aplicar, es una buena idea que el mutador tenga una restricción coincidente. Esto ayuda a garantizar que se rechacen las solicitudes de incumplimiento y se detecten los incumplimientos preexistentes en la auditoría.
Recuperación de emergencia
La mutación se implementa como un webhook de mutación de Kubernetes. Se puede detener de la misma manera que el webhook de validación, pero el recurso relevante es un MutatingWebhookConfiguration
llamado gatekeeper-mutating-webhook-configuration
.
¿Qué sigue?
- Para obtener explicaciones y ejemplos de mutaciones de Gatekeeper, consulta la documentación de código abierto.