Como criar restrições

Esta página mostra como definir restrições do Policy Controller.

O Policy Controller permite aplicar uma política a um cluster do Kubernetes definindo um ou mais objetos de restrição. Depois que uma restrição é aplicada, as solicitações ao servidor de API são verificadas em relação à restrição e são rejeitadas se não estiverem em conformidade. Recursos preexistentes que não sejam compatíveis são relatados no momento da auditoria.

Cada restrição é baseada em um modelo que define o esquema e a lógica da restrição. Os modelos de restrição podem ser provenientes do Google e de terceiros ou criados por você. Saiba mais sobre como criar novos modelos em Como escrever um modelo de restrição.

Antes de começar

Como usar a biblioteca de modelos de restrição

Ao definir uma restrição, você especifica o modelo de restrição que ela estende. Uma biblioteca de modelos de restrição comuns desenvolvida pelo Google está instalada por padrão, e muitas organizações não precisam criar modelos de restrição personalizados diretamente no Rego. Os modelos de restrição fornecidos pelo Google têm o rótulo configmanagement.gke.io/configmanagement.

Para listar restrições, use o seguinte comando:

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

Para descrever um modelo de restrição e verificar os parâmetros necessários, use o seguinte comando:

kubectl describe constrainttemplate CONSTRAINT_TEMPLATE_NAME

Também é possível visualizar todos os modelos de restrição da biblioteca.

Como definir uma restrição

Defina uma restrição usando o YAML, não sendo necessário entender ou escrever o Rego. Em vez disso, uma restrição chama um modelo e envia-o com parâmetros específicos à restrição.

Se você estiver usando um repositório estruturado, recomendamos que crie as restrições no diretório cluster/.

As restrições têm os seguintes campos:

  • O kind em minúsculas corresponde ao nome de um modelo de restrição.
  • O metadata.name é o nome da restrição.
  • O campo match define a quais objetos a restrição se aplica. Todas as condições especificadas precisam ser correspondidas antes que um objeto esteja no escopo de uma restrição. As condições match são definidas pelos seguintes subcampos:
    • kinds são os tipos de recursos a que a restrição se aplica, determinados por dois campos: apiGroups é uma lista de grupos de APIs do Kubernetes que serão correspondentes, e kinds é uma lista de tipos que serão correspondentes. "*" corresponde a tudo. Se pelo menos um apiGroup e uma entrada kind forem correspondentes, a condição kinds será atendida.
    • scope aceita *, cluster ou namespace, que determina se os recursos com escopo de cluster e/ou com escopo de namespace são selecionados (o padrão é *).
    • namespaces é uma lista de nomes de namespace a que o objeto pode pertencer. O objeto precisa pertencer a pelo menos um desses namespaces. Os recursos de namespace são tratados como se pertencessem a eles mesmos.
    • excludedNamespaces é uma lista de namespaces a que o objeto não pode pertencer.
    • labelSelector é um seletor de rótulo do Kubernetes a que o objeto precisa atender.
    • namespaceSelector é um seletor de rótulo no namespace a que o objeto pertence. Se o namespace não atender ao objeto, ele não corresponderá. Os recursos de namespace são tratados como se pertencessem a eles mesmos.
  • O campo parameters define os argumentos para a restrição, com base no que o modelo de restrição espera.

A restrição a seguir, chamada ns-must-have-geo, invoca um modelo de restrição chamado K8sRequiredLabels, incluído na biblioteca de modelos de restrição fornecida pelo Google. A restrição define parâmetros que o modelo de restrição usa para avaliar se os namespaces têm o rótulo geo definido com algum 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 criar a restrição, use kubectl apply -f:

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

Como fazer auditoria de uma restrição

Se a restrição tiver sido configurada e instalada corretamente, o campo status.byPod[].enforced dela estará definido como true, esteja ela configurada para impor ou apenas testar a restrição.

As restrições são impostas por padrão, e a violação de uma restrição impede uma determinada operação de cluster. É possível definir spec.enforcementAction de uma restrição como dryrun para relatar violações no campo status.violations sem impedir a operação.

Saiba mais sobre auditoria em Como fazer auditoria usando restrições.

Advertências ao sincronizar restrições

Lembre-se das seguintes advertências ao sincronizar restrições.

Consistência eventual

É possível confirmar restrições no repositório Git e limitar os efeitos delas usando ClusterSelectors ou NamespaceSelectors. Como a sincronização tem consistência posterior, lembre-se das seguintes advertências:

  • Se uma operação de cluster acionar uma restrição em que o NamespaceSelector se referir a um namespace que não foi sincronizado, a restrição será imposta e a operação será impedida. Em outras palavras, um namespace ausente "falha ao fechar".
  • Se você alterar os rótulos de um namespace, o cache poderá conter dados desatualizados por um breve período.

Minimize a necessidade de renomear um namespace ou alterar os respectivos rótulos e teste as restrições que afetam um namespace com novo nome ou rótulo para garantir que funcionem conforme esperado.

Configurar o Policy Controller com restrições referenciais

Antes de ativar as restrições referenciais, é necessário criar um Config que informe ao Policy Controller quais tipos de objetos precisam ser observados, como os namespaces.

Salve o seguinte manifesto YAML em um arquivo e aplique-o com kubectl. O manifesto configura o Policy Controller para ficar atento a namespaces e entradas. Crie uma entrada com group, version e kind em spec.sync.syncOnly, com os valores para cada tipo de objeto que você quer observar.

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"

Como ativar restrições referenciais

Uma restrição referencial refere-se a outro objeto na definição. Por exemplo, é possível criar uma restrição que exija que os objetos da entrada em um cluster tenham nomes de host exclusivos. A restrição será referencial se o modelo de restrição contiver a string data.inventory no Rego.

Por padrão, as restrições referenciais estão desativadas no Policy Controller. As restrições referenciais são garantidas somente como consistências posteriores, e isso provoca riscos:

  • Em um servidor de API sobrecarregado, o conteúdo do cache do Policy Controller pode ficar desatualizado, provocando uma restrição referencial de "falha ao abrir". Isso significa que a ação de imposição parece estar funcionando, quando não está. Por exemplo, é possível criar entradas com nomes de host duplicados rápido demais para que o controlador de admissão consiga detectar as cópias.

  • As ordens em que as restrições são instaladas e em que o cache é atualizado são aleatórias.

Se você entende esses riscos e ainda quer ativar o suporte para restrições referenciais, é possível ativar restrições referenciais no Console do Google Cloud. Para saber mais, consulte Como instalar o Policy Controller.

Também é possível definir policyController.referentialRulesEnabled como true no arquivo config-management.yaml:

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

Como listar todas as restrições

Para listar todas as restrições instaladas em um cluster, use o seguinte comando:

kubectl get constraint

Como remover uma restrição

Para encontrar todas as restrições que usam um modelo de restrição, use o seguinte comando para listar todos os objetos com o mesmo kind que o metadata.name do modelo de restrição:

kubectl get CONSTRAINT_TEMPLATE_NAME

Para remover uma restrição, especifique kind e name:

kubectl delete CONSTRAINT_TEMPLATE_NAME CONSTRAINT_NAME

Se você quiser excluir o modelo de restrição que a restrição estava usando, anote o kind da restrição.

Quando você remove uma restrição, ela deixa de ser imposta assim que o servidor de API marca a restrição como excluída.

Como remover todos os modelos de restrição

Defina spec.policyController.templateLibraryInstalled como false. Isso impede que o Anthos Config Management reinstale automaticamente a biblioteca.

Para remover todos os modelos de restrição e todas as restrições, use o seguinte comando:

kubectl delete constrainttemplate --all

Como restaurar a biblioteca de modelos de restrição

Se você desativou a biblioteca de modelos de restrição ou desinstalou todos os modelos de restrição, será possível restaurá-la definindo spec.policyController.templateLibraryInstalled como true na configuração do Anthos Config Management.

Solução de problemas

Erro ao criar um modelo de restrição

Se você receber um erro que menciona um disallowed ref, confira se você ativou as restrições referenciais. Por exemplo, se você usar data.inventory em um modelo de restrição sem ativar restrições referenciais primeiro, o erro será semelhante ao seguinte:

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

A seguir