Isolar cargas de trabalho em pools de nós dedicados
Nesta página, mostramos como reduzir o risco de ataques de escalonamento de privilégios no seu cluster configurando o GKE no Azure para programar suas cargas de trabalho em um pool de nós separado e dedicado, longe de cargas de trabalho gerenciadas com privilégios.
Visão geral
Os clusters do GKE no Azure usam cargas de trabalho privilegiadas que gerenciamos para ativar funcionalidades e recursos específicos do cluster, como coleta de métricas. Essas cargas de trabalho recebem permissões especiais para serem executadas corretamente no cluster.
As cargas de trabalho que você implanta nos nós podem ser comprometidas por uma entidade maliciosa. A execução dessas cargas de trabalho junto com cargas de trabalho de sistema privilegiados significa que um invasor que sai de um contêiner comprometido pode usar as credenciais da carga de trabalho privilegiada no nó para transferir privilégios no seu cluster.
Como evitar rompimentos de contêiner
Sua defesa principal deve ser os aplicativos. O GKE no Azure tem vários recursos que podem ser usados para aumentar a proteção dos seus clusters e pods. Na maioria dos casos, é altamente recomendável usar o Policy Controller e os recursos de segurança do kernel para aumentar a proteção das suas cargas de trabalho. Para mais recomendações de segurança, consulte a Visão geral de segurança.
Como evitar ataques de escalonamento de privilégios
Se você quiser uma camada extra de isolamento, além de outras medidas de aumento da proteção, use taints de nó e afinidade de nós para programar as cargas de trabalho em um pool de nós dedicado.
Um taint de nó informa ao GKE no Azure para evitar a programação de cargas de trabalho sem uma tolerância correspondente (como o GKE em cargas de trabalho gerenciadas pelo Azure) nesses nós. A afinidade do nó em suas próprias cargas de trabalho instrui o GKE no Azure a programar seus pods nos nós dedicados.
Limitações do isolamento de nós
- Os invasores ainda podem iniciar ataques de negação de serviço (DoS) no nó comprometido.
- Os nós comprometidos ainda podem ler muitos recursos, incluindo todos os pods e namespaces no cluster.
- Os nós comprometidos podem acessar Secrets e credenciais usadas por todos os pods em execução nesse nó.
- O uso de um pool de nós separado para isolar suas cargas de trabalho pode afetar a eficiência de custos, o escalonamento automático e a utilização de recursos.
- Os nós comprometidos ainda podem ignorar as políticas de saída de rede.
- Algumas cargas de trabalho gerenciadas do GKE no Azure precisam ser executadas em todos os nós do cluster e são configuradas para tolerar todos os taints.
- Se você implantar DaemonSets que tenham permissões elevadas e possam tolerar qualquer taint, esses pods poderão ser um caminho para o escalonamento de privilégios de um nó comprometido.
Como funciona o isolamento de nós
Para implementar o isolamento de nós para as cargas de trabalho, faça isto:
- Atribua um taint e um identificador a um pool de nós para as cargas de trabalho.
- Atualize as cargas de trabalho com a tolerância e a regra de afinidade de nó correspondente.
Este guia pressupõe que você começará com um pool de nós no cluster. O uso da afinidade de nó, além dos taints de nó, não é obrigatório, mas isso é recomendável porque você se beneficia de um maior controle sobre a programação.
Antes de começar
Para executar as etapas desta página, primeiro conclua o seguinte:
- Crie um cluster.
- Crie um pool de nós.
Escolha um nome para o taint e o rótulo do nó que você quer usar para os pools de nós dedicados. Neste exemplo, usamos
workloadType=untrusted
.
Atribuir um taint e um identificador a um pool de nós para as cargas de trabalho
Crie um novo pool de nós para as cargas de trabalho e atribua um taint e um identificador de nó. Quando você atribui um taint ou um identificador no nível do pool de nós, todos os novos nós, como aqueles criados pelo escalonamento automático, recebem automaticamente os taints e identificadores especificados.
Também é possível adicionar taints e identificadores de nós a pools de nós que já existem. Se você usar o efeito NoExecute
, o GKE no Azure removerá todos os pods em execução nos nós que não tiverem uma tolerância para o novo taint.
Para adicionar um taint e um identificador a um novo pool 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:
POOL_NAME
: o nome do novo pool de nós para as cargas de trabalho.CLUSTER_NAME
: o nome do cluster do GKE no Azure.TAINT_KEY=TAINT_VALUE
: um par de chave-valor associado a umTAINT_EFFECT
de programação. Por exemplo,workloadType=untrusted
.TAINT_EFFECT
: um dos seguintes valores de efeito:NoSchedule
,PreferNoSchedule
ouNoExecute
.NoExecute
oferece uma garantia de remoção melhor do queNoSchedule
.LABEL_KEY
=LABEL_VALUE
: pares de chave-valor para os rótulos de nó, que correspondem aos seletores especificados nos manifestos das cargas de trabalhos.
Adicionar uma tolerância e uma regra de afinidade de nó às cargas de trabalho
Depois que você atribui um taint ao pool de nós dedicado, nenhuma carga de trabalho poderá ser programada nele, a menos que tenha uma tolerância correspondente ao taint adicionado. Adicione a tolerância à especificação das cargas de trabalho para permitir que esses pods sejam programados no pool de nós com taint.
Se você rotulou o pool de nós dedicado, também é possível adicionar uma regra de afinidade de nó para instruir o GKE no Azure a programar apenas suas cargas de trabalho nesse pool de nós.
O exemplo a seguir adiciona uma tolerância ao taint workloadType=untrusted:NoExecute
e uma regra de afinidade de nó para o identificador 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:
TAINT_KEY
: a chave do taint que você aplicou ao pool de nós dedicado.TAINT_VALUE
: o valor do taint que você aplicou ao pool de nós dedicado.LABEL_KEY
: a chave do rótulo do nó que você aplicou ao pool de nós dedicado.LABEL_VALUE
: o valor do rótulo do nó que você aplicou ao pool de nós dedicado.
Quando você atualiza sua implantação com kubectl apply
, o GKE no Azure
recria os pods afetados. A regra de afinidade de nó força os pods no pool de nós dedicado que você criou. A tolerância permite que apenas esses pods sejam posicionados nos nós.
Verificar se a separação funciona
Para verificar se a programação funciona corretamente, execute o comando a seguir e verifique se as cargas de trabalho estão no pool de nós dedicado:
kubectl get pods -o=wide
Conselhos e práticas recomendadas
Após configurar o isolamento de nós, recomendamos que você faça isto:
- Adicione o taint
components.gke.io/gke-managed-components
para restringir pools de nós específicos ao GKE em cargas de trabalho gerenciadas pelo Azure. A adição desse taint impede que seus próprios pods sejam programados nesses nós, melhorando o isolamento. - Ao criar novos pools de nós, impeça que a maioria das cargas de trabalho do GKE gerenciadas pelo Azure seja executada nesses nós adicionando seu próprio taint a esses pools.
- Sempre que você implantar novas cargas de trabalho no cluster, como ao instalar ferramentas de terceiros, faça a auditoria das permissões exigidas pelos pods. Sempre que possível, evite implantar cargas de trabalho que usam permissões elevadas para nós compartilhados.