Isole as suas cargas de trabalho em node pools dedicados

Este documento explica como melhorar a segurança e a gestão do seu cluster do Kubernetes isolando as cargas de trabalho de contentores em pools de nós dedicados no Google Distributed Cloud (GDC) com isolamento de ar. Isolar as cargas de trabalho dá-lhe maior controlo sobre os seus pods e reduz o risco de ataques de elevação de privilégios no seu cluster do Kubernetes. Para mais informações sobre as vantagens e as limitações dos conjuntos de nós dedicados, consulte a vista geral do isolamento de nós.

Existem vários fluxos de trabalho envolvidos no isolamento das cargas de trabalho de contentores, que incluem o seguinte:

  • Contamine e etiquete um node pool: aplique uma contaminação e uma etiqueta a um node pool para que repila pods do node pool, a menos que estejam especificamente etiquetados para serem executados aí.

  • Adicione uma tolerância e uma regra de afinidade de nós: aplique tolerâncias e regras aos seus pods para forçá-los a serem executados apenas no conjunto de nós designado.

  • Verifique se a separação funciona: confirme se os conjuntos de nós contaminados estão apenas a executar os pods que etiquetou para serem executados aí.

Estes fluxos de trabalho destinam-se a públicos como os administradores de TI no grupo de administradores da plataforma, que são responsáveis pela gestão dos conjuntos de nós de um cluster do Kubernetes, e os programadores de aplicações no grupo de operadores de aplicações, que são responsáveis pela gestão das cargas de trabalho de contentores. Para mais informações, consulte a documentação sobre públicos-alvo para GDC com isolamento de ar.

Antes de começar

Antes de começar, certifique-se de que realizou as seguintes tarefas:

  • Escolha um nome específico para a restrição de nós e a etiqueta de nós que quer usar para os conjuntos de nós dedicados. Por exemplo, workloadType=untrusted.

  • Se necessário, peça ao administrador de IAM da organização para lhe conceder a função de programador de clusters de utilizadores (user-cluster-developer), que não está associada a um espaço de nomes.

Contamine e etiquete um novo conjunto de nós

Quando aplica uma restrição ou uma etiqueta a um novo conjunto de nós, todos os nós, incluindo os nós adicionados posteriormente, recebem automaticamente as restrições e as etiquetas especificadas.

Para adicionar uma restrição e uma etiqueta a um novo conjunto de nós, conclua os seguintes passos:

  1. Edite a secção nodePools do recurso personalizado Cluster diretamente quando criar o node pool:

    nodePools:
      # Several lines of code are omitted here.
      - machineTypeName: n2-standard-2-gdc
        name: nodepool-1
        nodeCount: 3
        taints:
        - key: "TAINT_KEY"
          value: "TAINT_VALUE"
          effect: "TAINT_EFFECT"
        labels:
          LABEL_KEY: LABEL_VALUE
    

    Substitua o seguinte:

    • TAINT_KEY: a parte da chave de contaminação do par de chave-valor associado a uma TAINT_EFFECT de agendamento. Por exemplo, workloadType.
    • TAINT_VALUE: a parte do valor de contaminação do par chave-valor associado a uma programação TAINT_EFFECT. Por exemplo, untrusted.
    • TAINT_EFFECT: um dos seguintes valores de efeito:
      • NoSchedule: os agrupamentos que não toleram esta contaminação não são agendados no nó; os agrupamentos existentes não são removidos do nó.
      • PreferNoSchedule: o Kubernetes evita agendar pods que não toleram esta contaminação no nó.
      • NoExecute: o pod é removido do nó se já estiver a ser executado no nó e não é agendado para o nó se ainda não estiver a ser executado no nó.
    • LABEL_KEY: LABEL_VALUE: os pares de chaves-valores para as etiquetas dos nós, que correspondem aos seletores que especificar nos manifestos da carga de trabalho.
  2. Aplique o recurso Cluster para criar o novo node pool:

    kubectl apply -f cluster.yaml --kubeconfig MANAGEMENT_API_SERVER
    

    Substitua MANAGEMENT_API_SERVER pelo caminho kubeconfig do servidor de API zonal onde o cluster Kubernetes está alojado. Se ainda não gerou um ficheiro kubeconfig para o servidor da API na zona segmentada, consulte Recursos do servidor da API de gestão zonal para mais informações.

Aplique uma restrição e etiquete um conjunto de nós existente

Para aplicar uma restrição ou uma etiqueta a um conjunto de nós existente, tem de aplicar as alterações a cada nó existente. Não pode atualizar dinamicamente as configurações do conjunto de nós.

Para adicionar uma restrição e uma etiqueta a um conjunto de nós existente, conclua os seguintes passos:

  1. Liste os nós no node pool dedicado:

    kubectl get node --kubeconfig KUBERNETES_CLUSTER_KUBECONFIG \
        -l baremetal.cluster.gke.io/node-pool=NODE_POOL_NAME
    

    Substitua as seguintes variáveis:

    • KUBERNETES_CLUSTER_KUBECONFIG: o caminho do kubeconfig para o cluster do Kubernetes.
    • NODE_POOL_NAME: o nome do seu node pool dedicado.

    Tome nota do ID de cada nó de todos os nós no conjunto de nós a partir do resultado.

  2. Para cada nó no conjunto de nós, aplique as manchas:

    kubectl taint nodes NODE_ID \
        TAINT_KEY=TAINT_VALUE:TAINT_EFFECT \
        --kubeconfig KUBERNETES_CLUSTER_KUBECONFIG
    

    Substitua as seguintes variáveis:

    • NODE_ID: o ID do nó trabalhador no conjunto de nós dedicado.
    • 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: os agrupamentos que não toleram esta contaminação não são agendados no nó; os agrupamentos existentes não são removidos do nó.
      • PreferNoSchedule: o Kubernetes evita agendar pods que não toleram esta contaminação no nó.
      • NoExecute: o pod é removido do nó se já estiver a ser executado no nó e não é agendado para o nó se ainda não estiver a ser executado no nó.
    • KUBERNETES_CLUSTER_KUBECONFIG: o caminho do kubeconfig para o cluster do Kubernetes.
  3. Para cada nó no conjunto de nós, aplique as etiquetas que correspondem aos seletores que vai definir nas cargas de trabalho de contentores:

    kubectl label NODE_ID \
        LABEL_KEY:LABEL_VALUE \
        --kubeconfig KUBERNETES_CLUSTER_KUBECONFIG
    

    Substitua as seguintes variáveis:

    • NODE_ID: o ID do nó trabalhador no conjunto de nós dedicado.
    • LABEL_KEY:LABEL_VALUE: os pares de chaves-valores para as etiquetas dos nós, que correspondem aos seletores que especifica nos manifestos da carga de trabalho.
    • KUBERNETES_CLUSTER_KUBECONFIG: o caminho do kubeconfig para o cluster do Kubernetes.

Adicione uma tolerância e uma regra de afinidade de nós

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 pool de nós dedicado, também pode adicionar uma regra de afinidade de nós para indicar ao GDC que agende as suas cargas de trabalho apenas nesse pool de nós.

Para configurar a carga de trabalho do contentor para ser executada no conjunto de nós dedicado, conclua os seguintes passos:

  1. Adicione as secções seguintes à secção .spec.template.spec do ficheiro de manifesto da carga de trabalho do contentor, como um recurso personalizado Deployment:

      # Several lines of code are omitted here.
        spec:
          template:
            spec:
              tolerations:
              - key: TAINT_KEY
                operator: Equal
                value: TAINT_VALUE
                effect: TAINT_EFFECT
              affinity:
                nodeAffinity:
                  requiredDuringSchedulingIgnoredDuringExecution:
                    nodeSelectorTerms:
                    - matchExpressions:
                      - key: LABEL_KEY
                        operator: In
                        values:
                        - "LABEL_VALUE"
            # Several lines of code are omitted here.
    

    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 conjunto de nós dedicado.
    • TAINT_EFFECT: um dos seguintes valores de efeito:
      • NoSchedule: os agrupamentos que não toleram esta contaminação não são agendados no nó; os agrupamentos existentes não são removidos do nó.
      • PreferNoSchedule: o Kubernetes evita agendar pods que não toleram esta contaminação no nó.
      • NoExecute: o pod é removido do nó se já estiver a ser executado no nó e não é agendado para o nó se ainda não estiver a ser executado no nó.
    • LABEL_KEY: a chave da etiqueta do nó que aplicou ao seu conjunto de nós dedicado.
    • LABEL_VALUE: o valor da etiqueta do nó que aplicou ao seu conjunto de nós dedicado.

    Por exemplo, o recurso Deployment seguinte adiciona uma tolerância para a falha de funcionamento 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: workloadType
            operator: Equal
            value: untrusted
            effect: NoExecute
          affinity:
            nodeAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
                nodeSelectorTerms:
                - matchExpressions:
                  - key: workloadType
                    operator: In
                    values:
                    - "untrusted"
          containers:
          - name: my-app
            image: harbor-1.org-1.zone1.google.gdc.test/harborproject/my-app
            ports:
            - containerPort: 80
          imagePullSecrets:
          - name: SECRET
    
  2. Atualize a carga de trabalho do contentor:

    kubectl apply -f deployment.yaml -n NAMESPACE \
        --kubeconfig KUBERNETES_CLUSTER_KUBECONFIG
    

    Substitua as seguintes variáveis:

    • NAMESPACE: o espaço de nomes do projeto da sua carga de trabalho do contentor.
    • KUBERNETES_CLUSTER_KUBECONFIG: o caminho do kubeconfig para o cluster do Kubernetes.

O GDC recria os agrupamentos 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

Verifique se os pods que designou estão a ser executados no conjunto de nós etiquetado.

  • Liste os pods no espaço de nomes indicado:

    kubectl get pods -o=wide -n NAMESPACE \
        --kubeconfig KUBERNETES_CLUSTER_KUBECONFIG
    

    Substitua as seguintes variáveis:

    • NAMESPACE: o espaço de nomes do projeto da sua carga de trabalho do contentor.
    • KUBERNETES_CLUSTER_KUBECONFIG: o caminho do kubeconfig para o cluster do Kubernetes.

    O resultado tem um aspeto semelhante ao seguinte:

    pod/kube-abc-12tyuj
    pod/kube-abc-39oplef
    pod/kube-abc-95rzkap
    

    Confirme que as suas cargas de trabalho estão a ser executadas no conjunto de nós dedicado.

O que se segue?