Esta página mostra como modificar recursos usando o
Policy Controller. Isso é útil para
definir valores padrão. Por exemplo, convém injetar
um rótulo para todos os recursos em um namespace específico ou definir o padrão de imagePullPolicy
de um pod como Always
se ele ainda não estiver definido.
Ativar mutação
Console
Para ativar a mutação, siga estas etapas:
- No console do Google Cloud, acesse a página Política do GKE Enterprise na seção Gerenciamento de postura.
- Na guia Configurações, na tabela de clusters, selecione Editar edit na coluna Editar configuração.
- Expanda o menu Editar configuração do Policy Controller.
- Marque a caixa de seleção Ativar webhook de mutação.
- Selecione Salvar alterações.
Policy Controller da gcloud
Para ativar a mutação, execute o seguinte comando:
gcloud container fleet policycontroller update \
--memberships=MEMBERSHIP_NAME \
--mutation
Substitua MEMBERSHIP_NAME
pelo nome de assinatura do
cluster registrado para ativar a mutação. Você pode especificar várias
associações separadas por uma vírgula.
gcloud ConfigManagement
A mutação precisa estar ativada definindo spec.policyController.mutation.enabled
como true
no recurso config-management
:
apiVersion: configmanagement.gke.io/v1
kind: ConfigManagement
metadata:
name: config-management
spec:
policyController:
enabled: true
mutation:
enabled: true
Se você estiver usando o comando da CLI gcloud, use a versão Alfa para ativar a mutação, conforme mostrado no exemplo a seguir:
# apply-spec.yaml
applySpecVersion: 1
spec:
policyController:
enabled: true
mutationEnabled: true
Depois de criar o arquivo apply-spec.yaml
, execute o seguinte comando para
aplicar a configuração:
gcloud alpha container fleet config-management apply \
--membership=MEMBERSHIP_NAME \
--config=CONFIG_YAML_PATH \
--project=PROJECT_ID
Substitua:
MEMBERSHIP_NAME
: o nome da assinatura do cluster registrado que contém as configurações do Policy Controller que você quer usarCONFIG_YAML_PATH
: o caminho para o arquivoapply-spec.yaml
PROJECT_ID
: ID do projeto
Definições
- mutador: um recurso do Kubernetes que ajuda a configurar o comportamento de mutação do Policy Controller.
- sistema: uma organização de vários mutadores
Exemplo de mutação
O exemplo a seguir mostra um mutador que define imagePullPolicy
para todos os contêineres em todos os pods como 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"
Neste exemplo, há os campos de metadados padrão do Kubernetes
(apiVersion
, kind
, metadata.name
), mas spec
é onde o comportamento
do mutador está configurado.
spec.applyTo
vincula o mutador aos recursos especificados. Como estamos
alterando campos específicos em um objeto, estamos definindo implicitamente o esquema desse
objeto. Por exemplo, o mutador atual não faria sentido se fosse aplicado
a um recurso Namespace
. Por isso, esse campo é obrigatório para
que o Policy Controller saiba para quais esquemas esse mutador é relevante.
Os GroupVersionKinds
ausentes da lista não são alterados.
spec.location
informa qual campo modificar. Nesse caso, estamos
usando um glob (*
) para indicar que queremos modificar todas as
entradas na lista de contêineres. Os únicos tipos de lista que podem ser percorridos
pelo campo location
são as listas de tipo de mapa, e o campo de chave do
mapa precisa ser especificado. Listas do tipo mapa são uma construção do Kubernetes. Veja mais detalhes na
documentação do Kubernetes (em inglês).
spec.parameters.assign.value
é o valor a ser atribuído a location
.
Esse campo não tem tipo e pode receber qualquer valor. No entanto, o Kubernetes
ainda valida a solicitação após a mutação. Portanto, inserir valores com um esquema
incorreto para o objeto que está sendo modificado resulta na rejeição da solicitação.
Usar mutadores para jobs
Se estiver configurando um job ou um CronJob, especifique a versão e o grupo separadamente, como mostrado no exemplo a seguir:
applyTo:
- groups: ["batch"]
kind: ["Job"]
versions: ["v1"]
Quando você usa um mutador, os jobs atuais não vão ser alterados, a menos que sejam modificados. Modificar um job aciona um pedido para o webhook de mutação e faz com que ele seja transformado.
Fluxo de execução
Talvez o conceito mais importante para entender os webhooks de mutação do Kubernetes seja a política de reinvocação porque a saída de um mutador pode alterar o comportamento de outro mutador. Por exemplo, se você adicionar um novo contêiner de arquivo secundário, um mutador que define a política de extração de imagens para todos os contêineres agora terá um novo contêiner.
Na prática, o que isso significa é que, para qualquer solicitação, o webhook de mutação do controlador de políticas pode ser chamado mais de uma vez.
Para reduzir a latência, o Policy Controller é invocado novamente para evitar solicitações HTTP adicionais. Isso significa que a injeção de arquivo secundário e a política de extração de imagem têm o resultado esperado.
A rotina de mutação do Policy Controller continuará a ser invocada novamente até que o recurso convirja, e isso significa que outras iterações não terão mais efeito.
Sintaxe do local
A sintaxe do local usa o acessador de ponto (.
) para percorrer campos. No caso
de listas com chave, os usuários podem referenciar objetos individuais em uma lista usando a sintaxe
[<key>: <value>]
ou todos os objetos na lista usando [<key>: *]
.
Valores e campos podem ser colocados entre aspas simples ('
) ou duplas ("
). Isso é
necessário quando eles têm caracteres especiais, como pontos ou espaços.
Nos valores entre aspas, faça o escape de caracteres especiais usando
\
como prefixo. "Use \" to escape and \\\" to escape"
se transforma em Use " to escape and \" to escape
.
Alguns exemplos do recurso v1/Pod
:
spec.priority
referenciaspec.priority
spec.containers[name: "foo"].volumeMounts[mountPath: "/my/mount"].readOnly
faz referência ao camporeadOnly
da ativação/my/mount
do contêinerfoo
.spec.containers[name: *].volumeMounts[mountPath: "/my/mount"].readOnly
faz referência ao camporeadOnly
da montagem/my/mount
de todos os contêineres.
Se você se referir a um local que não existe atualmente em um recurso, esse local será criado por padrão. Esse comportamento pode ser configurado por meio de teste de caminho.
Teste de caminho
Como executar a padronização, em que evitamos modificar um valor que já
existe? Podemos querer definir /secure-mount
como somente leitura para todos os contêineres,
mas não criar um /secure-mount
se ainda não houver um. Podemos
fazer isso por meio de teste de caminho.
Veja um exemplo que evita a mutação de imagePullPolicy
se ele já estiver
definido:
# 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"
Veja a seguir outro exemplo que evita a criação de um contêiner sidecar
vazio se ele ainda não existir:
# 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"
Vários testes de caminho podem ser especificados, se necessário.
subPath
precisa ser um prefixo (ou igual a) location
.
Os únicos valores válidos para condition
são MustExist
e MustNotExist
.
Correspondência
Os mutadores também permitem a correspondência, usando os mesmos critérios de restrições.
Mutadores
Atualmente, há dois tipos de mutadores: Assign
e AssignMetadata
.
Atribuir
Assign
pode alterar qualquer valor fora do campo metadata
de um recurso.
Como todos os GroupVersionKinds
têm um esquema exclusivo, ele precisa estar vinculado a um conjunto
de GroupVersionKinds
específico.
Ele tem o seguinte 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
pode adicionar novos rótulos de metadados. Não é possível alterar o valor dos
rótulos de metadados atuais. Caso contrário, seria possível escrever um sistema
de mutadores que se repetiriam indefinidamente, fazendo com que as solicitações expirassem.
Como todos os recursos compartilham o mesmo esquema metadata
, não é necessário
especificar a que recurso um AssignMetadata
se aplica.
Além disso, como AssignMetadata
não tem permissão para fazer tanto, o esquema
é um pouco mais simples.
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áticas recomendadas
Advertências do Kubernetes
A documentação do Kubernetes lista algumas considerações importantes sobre como usar webhooks de mutação. Como o Policy Controller funciona como um webhook de admissão do Kubernetes, essa recomendação se aplica aqui.
A sintaxe de mutação do Policy Controller foi projetada para facilitar a conformidade com as preocupações operacionais relacionadas a webhooks de mutação, incluindo a idempotência.
Gravar mutadores
Atomicidade
A prática recomendada é tornar cada mutador o mais autossuficiente possível. Como o Kubernetes tem consistência posterior, um mutador não pode confiar em um segundo mutador para ser reconhecido para fazer o job corretamente. Por exemplo, ao adicionar um arquivo secundário, adicione-o por completo, não o crie de forma fragmentada usando vários mutadores.
Validação
Se você quiser aplicar uma condição, é recomendável que o mutador tenha uma restrição correspondente. Isso ajuda a garantir que solicitações de violação sejam rejeitadas e que violações preexistentes sejam detectadas na auditoria.
Recuperação de emergência
A mutação é implementada como um webhook de mutação do Kubernetes. Ele pode ser interrompido da
mesma forma que o webhook de validação,
mas o recurso relevante é um MutatingWebhookConfiguration
chamado gatekeeper-mutating-webhook-configuration
.
A seguir
- Para ver explicações e exemplos de mutação do Gatekeeper, consulte a documentação de código aberto.