Como aumentar a proteção do isolamento da carga de trabalho com o GKE Sandbox

Nesta página, descrevemos como usar o GKE Sandbox para proteger o kernel do host nos nós quando os contêineres no pod executam código desconhecido ou não confiável, ou quando precisam de isolamento adicional do nó.

Disponibilidade do GKE Sandbox

O GKE Sandbox está pronto para uso nos clusters do Autopilot que executam as versões 1.27.4-gke.800 e posteriores do GKE. Para começar a implantar cargas de trabalho do Autopilot em um sandbox, pule para Como trabalhar com o GKE Sandbox.

Para usar o GKE Sandbox em clusters GKE Standard novos ou atuais, é necessário ativar manualmente o GKE Sandbox no cluster.

Antes de começar

Antes de começar, verifique se você realizou as tarefas a seguir:

  • Ativar a API Google Kubernetes Engine.
  • Ativar a API Google Kubernetes Engine
  • Se você quiser usar a Google Cloud CLI para essa tarefa, instale e, em seguida, inicialize a CLI gcloud. Se você instalou a CLI gcloud anteriormente, instale a versão mais recente executando gcloud components update.

Ativar o GKE Sandbox em um novo cluster Standard

O pool de nós padrão, criado quando você cria um cluster, não pode usar o GKE Sandbox se for o único pool de nós no cluster, porque as cargas de trabalho do sistema gerenciadas pelo GKE precisam ser executadas separadamente das cargas de trabalho não confiáveis executadas em sandbox. Para ativar o GKE Sandbox durante a criação do cluster, é preciso adicionar pelo menos um pool de nós adicional ao cluster.

Console

Para visualizar os clusters, acesse o menu do Google Kubernetes Engine no console do Google Cloud.

  1. Acesse a página Google Kubernetes Engine no console do Google Cloud.

    Acessar o Google Kubernetes Engine

  2. Clique em Criar.

  3. Opcional, mas recomendado: no menu de navegação, em Cluster, clique em Recursos e marque as caixas de seleção a seguir para que o gVisor são registradas:

    • Cloud Logging
    • Cloud Monitoring
    • Serviço gerenciado para o Prometheus
  4. Clique em Adicionar pool de nós.

  5. No painel de navegação, em Pools de nós, expanda o novo pool de nós e clique em Nós.

  6. Defina as configurações a seguir para o pool de nós:

    1. Na lista suspensa Tipo de imagem, selecione Container-Optimized OS com Containerd (cos_containerd). Esse é o único tipo de imagem compatível com o GKE Sandbox.
    2. Em Configuração da máquina, selecione uma Série e um Tipo de máquina.

  7. No painel de navegação, abaixo do nome do pool de nós que você está configurando, clique em Segurança e marque a caixa de seleção Ativar sandbox com o gVisor.

  8. Continue configurando os pools de nós e de cluster como quiser.

  9. Clique em Criar.

gcloud

O GKE Sandbox não pode ser ativado para o pool de nós padrão e não é possível criar outros pools de nós ao mesmo tempo que você cria um novo cluster usando o comando gcloud. Em vez disso, crie seu cluster normalmente. Embora seja opcional, é recomendável ativar o Logging e o Monitoring para que as mensagens do gVisor sejam registradas.

Em seguida, use o comando gcloud container node-pools create e defina a sinalização -- sandbox como type=gvisor. O tipo de imagem do nó precisa ser cos_containerd para o GKE Sandbox.

gcloud container node-pools create NODE_POOL_NAME \
  --cluster=CLUSTER_NAME \
  --node-version=NODE_VERSION \
  --machine-type=MACHINE_TYPE \
  --image-type=cos_containerd \
  --sandbox type=gvisor

Substitua as seguintes variáveis:

  • NODE_POOL_NAME: o nome do novo pool de nós.
  • CLUSTER_NAME: o nome do cluster.
  • NODE_VERSION: a versão a ser usada no pool de nós.
  • MACHINE_TYPE: o tipo de máquina a ser usado para os nós. O GKE Sandbox não é compatível com os tipos de máquina e2-micro, e2-small e e2-medium.

Ativar o GKE Sandbox em um cluster Standard atual

É possível ativar o GKE Sandbox em um cluster Standard atual ao adicionar um novo pool de nós e ativar o recurso para esse novo pool.

Console

Para criar um novo pool de nós com o GKE Sandbox ativado:

  1. Acesse a página Google Kubernetes Engine no console do Google Cloud.

    Acessar o Google Kubernetes Engine

  2. Clique no nome do cluster que você quer modificar.

  3. Clique em Adicionar pool de nós.

  4. Configure a página Detalhes do pool de nós conforme selecionado.

  5. No painel de navegação, clique em Nós e defina as seguintes configurações:

    1. Na lista suspensa Tipo de imagem, selecione Container-Optimized OS com Containerd (cos_containerd). Esse é o único tipo de imagem compatível com o GKE Sandbox.
    2. Em Configuração da máquina, selecione uma Série e um Tipo de máquina.

  6. No painel de navegação, clique em Segurança e marque a caixa de seleção Ativar sandbox com o gVisor.

  7. Clique em Criar.

gcloud

Para criar um novo pool de nós com o GKE Sandbox ativado, use um comando como este:

gcloud container node-pools create NODE_POOL_NAME \
  --cluster=CLUSTER_NAME \
  --machine-type=MACHINE_TYPE \
  --image-type=cos_containerd \
  --sandbox type=gvisor

O tipo de imagem do nó precisa ser cos_containerd para o GKE Sandbox.

Opcional: ativar o monitoramento e a geração de registros

É opcional, mas recomendável, ativar o Stackdriver Logging e o Stackdriver Monitoring no cluster para que as mensagens do gVisor sejam registradas. Esses serviços são ativados por padrão para novos clusters.

Você precisa usar o Console do Google Cloud para ativar esses recursos em um cluster atual.

  1. Acesse a página Google Kubernetes Engine no console do Google Cloud.

    Acessar o Google Kubernetes Engine

  2. Clique no nome do cluster que você quer modificar.

  3. Em Recursos, no campo Cloud Logging, clique em Editar Cloud Logging.

  4. Marque a caixa de seleção Ativar o Cloud Logging.

  5. Clique em Salvar alterações.

  6. Repita as mesmas etapas nos campos Cloud Monitoring e Managed Service para Prometheus se quiser ativar esses recursos.

Usar o GKE Sandbox no Autopilot e no Standard

Nos clusters do Autopilot e nos clusters Standard com o GKE Sandbox ativado, você solicita um ambiente de sandbox para um pod especificando a RuntimeClass gvisor na especificação do pod.

Para clusters do Autopilot, verifique se você está executando o GKE versão 1.26.0-gke.2500 ou posterior.

Como executar um aplicativo em um sandbox

Para que uma implantação seja executada em um nó com o GKE Sandbox ativado, defina spec.template.spec.runtimeClassName como gvisor, conforme mostrado no seguinte exemplo:

# httpd.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpd
  labels:
    app: httpd
spec:
  replicas: 1
  selector:
    matchLabels:
      app: httpd
  template:
    metadata:
      labels:
        app: httpd
    spec:
      runtimeClassName: gvisor
      containers:
      - name: httpd
        image: httpd

Crie a implantação:

kubectl apply -f httpd.yaml

O pod é implantado em um nó com o GKE Sandbox ativado. Para verificar a implantação, encontre o nó em que o pod está implantado:

kubectl get pods

O resultado será assim:

NAME                    READY   STATUS    RESTARTS   AGE
httpd-db5899bc9-dk7lk   1/1     Running   0          24s

Na saída, encontre o nome do pod e verifique o valor de RuntimeClass:

kubectl get pods POD_NAME -o jsonpath='{.spec.runtimeClassName}'

A resposta é gvisor.

Como alternativa, é possível listar a RuntimeClass de cada pod e procurar aqueles em que ela está definida como gvisor:

kubectl get pods -o jsonpath=$'{range .items[*]}{.metadata.name}: {.spec.runtimeClassName}\n{end}'

A saída é esta:

POD_NAME: gvisor

Esse método para verificar se o pod está sendo executado em um sandbox é confiável, porque não depende de dados no próprio sandbox. Qualquer item do sandbox que seja reportado não é confiável, porque pode estar com erros ou ser malicioso.

Como executar um pod normal junto com pods no sandbox

As etapas nesta seção se aplicam às cargas de trabalho do modo Standard. Não é preciso executar pods regulares com os pods do sandbox no modo do Autopilot, porque o modelo de preços do Autopilot elimina a necessidade de otimizar manualmente o número de pods programados nos nós.

Depois de ativar o GKE Sandbox em um pool de nós, é possível executar aplicativos confiáveis nesses nós sem usar um sandbox, com tolerâncias e taints de nó. Esses pods são chamados de “pods normais” para diferenciá-los dos pods em sandbox.

Os pods regulares, assim como os pods de sandbox, são impedidos de acessar outros serviços do Google Cloud ou metadados de cluster. Essa prevenção faz parte da configuração do nó. Se os pods regulares ou no sandbox exigirem acesso aos serviços do Google Cloud, use a federação de identidade da carga de trabalho do GKE.

O GKE Sandbox adiciona o seguinte rótulo e taint aos nós que podem executar pods no sandbox:

labels:
  sandbox.gke.io/runtime: gvisor
taints:
- effect: NoSchedule
  key: sandbox.gke.io/runtime
  value: gvisor

Além das configurações de afinidade e tolerância do nó no manifesto do pod, o GKE Sandbox aplica a seguinte afinidade e tolerância a todos os pods com RuntimeClass definida no gvisor:

affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
      - matchExpressions:
        - key: sandbox.gke.io/runtime
          operator: In
          values:
          - gvisor
tolerations:
  - effect: NoSchedule
    key: sandbox.gke.io/runtime
    operator: Equal
    value: gvisor

Para programar um pod normal em um nó com o GKE Sandbox ativado, aplique manualmente a afinidade e a tolerância do nó descritas anteriormente no manifesto do pod.

  • Se seu pod puder ser executado em nós com o GKE Sandbox ativado, adicione a tolerância.
  • Se seu pod precisar ser executado em nós com o GKE Sandbox ativado, adicione a afinidade e a tolerância do nó.

Por exemplo, o manifesto a seguir modifica o manifesto usado em Como executar um aplicativo em um sandbox para que ele seja executado como um pod normal em um nó com pods do sandbox removendo a runtimeClass e adicionando a tolerância e o taint descritos anteriormente.

# httpd-no-sandbox.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpd-no-sandbox
  labels:
    app: httpd
spec:
  replicas: 1
  selector:
    matchLabels:
      app: httpd
  template:
    metadata:
      labels:
        app: httpd
    spec:
      containers:
      - name: httpd
        image: httpd
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: sandbox.gke.io/runtime
                operator: In
                values:
                - gvisor
      tolerations:
        - effect: NoSchedule
          key: sandbox.gke.io/runtime
          operator: Equal
          value: gvisor

Primeiro, verifique se o Deployment não está sendo executado em um sandbox:

kubectl get pods -o jsonpath=$'{range .items[*]}{.metadata.name}: {.spec.runtimeClassName}\n{end}'

A resposta é semelhante a:

httpd-db5899bc9-dk7lk: gvisor
httpd-no-sandbox-5bf87996c6-cfmmd:

A implantação httpd criada anteriormente está sendo executada em um sandbox, porque sua runtimeClass é gvisor. A implantação httpd-no-sandbox não tem valor para runtimeClass. Por isso, ela não está sendo executada em um sandbox.

Em seguida, verifique se a implantação fora do sandbox está em execução em um nó com o GKE Sandbox executando o seguinte comando:

kubectl get pod -o jsonpath=$'{range .items[*]}{.metadata.name}: {.spec.nodeName}\n{end}'

O nome do pool de nós é incorporado ao valor de nodeName. Verifique se o pod está sendo executado em um nó em um pool de nós com o GKE Sandbox ativado.

Como verificar a proteção de metadados

Para validar a afirmação de que os metadados estão protegidos dos nós que podem executar pods no sandbox, é possível fazer um teste:

  1. Crie uma implantação em sandbox a partir do seguinte manifesto, usando kubectl apply -f. Ele usa a imagem fedora, que inclui o comando curl. O pod executa o comando /bin/sleep para garantir que a implantação seja executada por 10.000 segundos.

    # sandbox-metadata-test.yaml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: fedora
      labels:
        app: fedora
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: fedora
      template:
        metadata:
          labels:
            app: fedora
        spec:
          runtimeClassName: gvisor
          containers:
          - name: fedora
            image: fedora
            command: ["/bin/sleep","10000"]
    
  2. Consiga o nome do pod usando kubectl get pods e use kubectl exec para se conectar ao pod de forma interativa.

    kubectl exec -it POD_NAME /bin/sh
    

    Você está conectado a um contêiner em execução no pod, em uma sessão /bin/sh.

  3. Na sessão interativa, tente acessar um URL que retorne metadados de cluster:

    curl -s "http://169.254.169.254/computeMetadata/v1/instance/attributes/kube-env" -H "Metadata-Flavor: Google"
    

    O comando trava e, por fim, expira, porque os pacotes são descartados silenciosamente.

  4. Pressione Ctrl+C para encerrar o comando curl e digite exit para se desconectar do pod.

  5. Remova a linha RuntimeClass do manifesto YAML e reimplante o pod usando kubectl apply -f FILENAME. O pod no sandbox é encerrado e recriado em um nó sem o GKE Sandbox.

  6. Consiga o novo nome do pod, conecte-se a ele usando kubectl exec e execute o comando curl novamente. Dessa vez, os resultados são retornados. Este exemplo de resultado está truncado.

    ALLOCATE_NODE_CIDRS: "true"
    API_SERVER_TEST_LOG_LEVEL: --v=3
    AUTOSCALER_ENV_VARS: kube_reserved=cpu=60m,memory=960Mi,ephemeral-storage=41Gi;...
    ...
    

    Digite exit para se desconectar do pod.

  7. Remova a implantação:

    kubectl delete deployment fedora
    

Como desativar o GKE Sandbox

Não é possível desativar o GKE Sandbox em clusters Autopilot do GKE ou em pools de nós GKE Standard. Se você quiser parar de usar o GKE Sandbox, exclua o pool de nós.

A seguir