Isole cargas de trabalho em node pools dedicados

Esta página mostra como reduzir o risco de ataques de escalada de privilégios no seu cluster configurando o GKE no Azure para agendar as suas cargas de trabalho num conjunto de nós dedicado separado das cargas de trabalho geridas privilegiadas.

Vista geral

Os clusters do GKE on Azure usam cargas de trabalho privilegiadas que gerimos para ativar funcionalidades e funcionalidades específicas do cluster, como a recolha de métricas. Estas cargas de trabalho recebem autorizações especiais para serem executadas corretamente no cluster.

As cargas de trabalho que implementa nos seus nós podem ser potencialmente comprometidas por uma entidade maliciosa. A execução destas cargas de trabalho juntamente com cargas de trabalho de sistema privilegiadas significa que um atacante que saia de um contentor comprometido pode usar as credenciais da carga de trabalho privilegiada no nó para aumentar os privilégios no seu cluster.

Prevenção de fugas de contentores

A sua defesa principal deve ser as suas aplicações. O GKE no Azure tem várias funcionalidades que pode usar para proteger os seus clusters e pods. Na maioria dos casos, recomendamos vivamente a utilização do Policy Controller e das funcionalidades de segurança do kernel para proteger as suas cargas de trabalho. Para mais recomendações de segurança, consulte a vista geral da segurança.

Evitar ataques de escalamento de privilégios

Se quiser uma camada adicional de isolamento para além de outras medidas de reforço, pode usar contaminações de nós e afinidade de nós para agendar as suas cargas de trabalho num conjunto de nós dedicado.

Uma restrição de nó indica ao GKE no Azure que deve evitar agendar cargas de trabalho sem uma tolerância correspondente (como cargas de trabalho geridas pelo GKE no Azure) nesses nós. A afinidade de nós nas suas próprias cargas de trabalho indica ao GKE no Azure que agende os seus pods nos nós dedicados.

Limitações do isolamento de nós

  • Os atacantes continuam a poder iniciar ataques de negação de serviço (DoS) a partir do nó comprometido.
  • Os nós comprometidos ainda podem ler muitos recursos, incluindo todos os pods e namespaces no cluster.
  • Os nós comprometidos podem aceder a segredos e credenciais usados por todos os pods em execução nesse nó.
  • A utilização de um node pool separado para isolar as cargas de trabalho pode afetar a eficiência de custos, o dimensionamento automático e a utilização de recursos.
  • Os nós comprometidos podem continuar a ignorar as políticas de rede de saída.
  • Algumas cargas de trabalho geridas pelo GKE on Azure têm de ser executadas em todos os nós do cluster e estão configuradas para tolerar todas as manchas.
  • Se implementar DaemonSets com autorizações elevadas e que possam tolerar qualquer contaminação, esses pods podem ser uma via para a escalada de privilégios a partir de um nó comprometido.

Como funciona o isolamento de nós

Para implementar o isolamento de nós para as suas cargas de trabalho, tem de fazer o seguinte:

  1. Contamine e etiquete um conjunto de nós para as suas cargas de trabalho.
  2. Atualize as suas cargas de trabalho com a regra de tolerância e afinidade de nós correspondente.

Este guia pressupõe que começa com um node pool no seu cluster. A utilização da afinidade de nós, além das restrições de nós, não é obrigatória, mas recomendamos que o faça porque beneficia de um maior controlo sobre o agendamento.

Antes de começar

Para realizar os passos nesta página, conclua primeiro o seguinte:

Contamine e etiquete um conjunto de nós para as suas cargas de trabalho

Crie um novo node pool para as suas cargas de trabalho e aplique uma restrição de nó e uma etiqueta de nó. Quando aplica uma restrição ou uma etiqueta ao nível do conjunto de nós, todos os novos nós, como os criados pelo dimensionamento automático, recebem automaticamente as restrições e as etiquetas especificadas.

Também pode adicionar taints de nós e etiquetas de nós a pools de nós existentes. Se usar o efeito NoExecute, o GKE no Azure despeja todos os pods em execução nesses nós que não tenham uma tolerância para a nova mancha.

Para adicionar uma restrição e uma etiqueta a um novo conjunto de nós, execute o seguinte comando:

gcloud container azure node-pools create POOL_NAME \
    --cluster CLUSTER_NAME \
    --node-taints TAINT_KEY=TAINT_VALUE:TAINT_EFFECT \
    --node-labels LABEL_KEY=LABEL_VALUE

Substitua o seguinte:

  • POOL_NAME: o nome do novo conjunto de nós para as suas cargas de trabalho.
  • CLUSTER_NAME: o nome do seu cluster do GKE no Azure.
  • TAINT_KEY=TAINT_VALUE: um par de chave-valor associado a uma programação TAINT_EFFECT. Por exemplo, workloadType=untrusted.
  • TAINT_EFFECT: um dos seguintes valores de efeito: NoSchedule, PreferNoSchedule ou NoExecute. NoExecute oferece uma garantia de despejo melhor do que NoSchedule.
  • LABEL_KEY=LABEL_VALUE: pares de chaves-valores para as etiquetas dos nós, que correspondem aos seletores que especifica nos manifestos da carga de trabalho.

Adicione uma tolerância e uma regra de afinidade de nós às suas cargas de trabalho

Depois de contaminar o pool de nós dedicado, nenhuma carga de trabalho pode ser agendada no mesmo, a menos que tenha uma tolerância correspondente à contaminação que adicionou. Adicione a tolerância à especificação das suas cargas de trabalho para permitir que esses pods sejam agendados no seu conjunto de nós contaminado.

Se etiquetou o conjunto de nós dedicado, também pode adicionar uma regra de afinidade de nós para indicar ao GKE no Azure que agende apenas as suas cargas de trabalho nesse conjunto de nós.

O exemplo seguinte adiciona uma tolerância para a restrição workloadType=untrusted:NoExecute e uma regra de afinidade de nós para a etiqueta de nó workloadType=untrusted.

kind: Deployment
apiVersion: apps/v1
metadata:
  name: my-app
  namespace: default
  labels:
    app: my-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      tolerations:
      - key: TAINT_KEY
        operator: Equal
        value: TAINT_VALUE
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: LABEL_KEY
                operator: In
                values:
                - "LABEL_VALUE"
      containers:
      - name: sleep
        image: ubuntu
        command: ["/bin/sleep", "inf"]

Substitua o seguinte:

  • TAINT_KEY: a chave de contaminação que aplicou ao seu conjunto de nós dedicado.
  • TAINT_VALUE: o valor de contaminação que aplicou ao seu grupo de nós dedicado.
  • LABEL_KEY: a chave da etiqueta do nó que aplicou ao seu node pool dedicado.
  • LABEL_VALUE: o valor da etiqueta do nó que aplicou ao seu node pool dedicado.

Quando atualiza a sua implementação com kubectl apply, o GKE no Azure recria os pods afetados. A regra de afinidade de nós força os pods para o node pool dedicado que criou. A tolerância permite que apenas esses pods sejam colocados nos nós.

Verifique se a separação funciona

Para verificar se o agendamento funciona corretamente, execute o seguinte comando e verifique se as suas cargas de trabalho estão no conjunto de nós dedicado:

kubectl get pods -o=wide

Recomendações e práticas recomendadas

Depois de configurar o isolamento de nós, recomendamos que faça o seguinte:

  • Restrinja pools de nós específicos a cargas de trabalho geridas pelo GKE on Azure apenas adicionando a contaminação components.gke.io/gke-managed-components. A adição desta mancha impede que os seus próprios pods sejam agendados nesses nós, o que melhora o isolamento.
  • Ao criar novos pools de nós, impeça que a maioria das cargas de trabalho geridas pelo GKE on Azure sejam executadas nesses nós adicionando a sua própria mancha a esses pools de nós.
  • Sempre que implementar novas cargas de trabalho no cluster, como quando instala ferramentas de terceiros, audite as autorizações que os pods requerem. Sempre que possível, evite implementar cargas de trabalho que usem autorizações elevadas em nós partilhados.

O que se segue?