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

Nesta página, você verá 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 extra do nó.

Como ativar o GKE Sandbox

É possível ativar o GKE Sandbox em um cluster novo ou atual.

Antes de começar

Antes de começar, veja se você realizou as seguintes tarefas:

Defina configurações gcloud padrão usando um dos métodos a seguir:

  • Use gcloud init se você quiser ser orientado sobre como definir padrões.
  • Use gcloud config para definir individualmente a região, a zona e o ID do projeto.

Como usar o gcloud init

  1. Execute gcloud init e siga as instruções:

    gcloud init

    Se você estiver usando SSH em um servidor remoto, utilize a sinalização --console-only para impedir que o comando inicie um navegador:

    gcloud init --console-only
  2. Siga as instruções para autorizar gcloud a usar sua conta do Google Cloud.
  3. Crie uma nova configuração ou selecione uma atual.
  4. Escolha um projeto do Google Cloud.
  5. Escolha uma zona padrão do Compute Engine.

Como usar o gcloud config

  • Defina o ID do projeto padrão:
    gcloud config set project project-id
  • Se você estiver trabalhando com clusters zonais, defina a zona do Compute padrão:
    gcloud config set compute/zone compute-zone
  • Se você estiver trabalhando com clusters regionais, defina a região do Compute padrão:
    gcloud config set compute/region compute-region
  • Atualize gcloud para a versão mais recente:
    gcloud components update
  • O GKE Sandbox exige o GKE v1.12.7-gke.17 ou superior, ou v1.13.5-gke.15 ou superior, para o mestre do cluster e os nós.
  • Certifique-se de que o comando gcloud seja da versão 243.0.0 ou superior.

Em um novo cluster

Para ativar o GKE Sandbox, configure um pool de nós. O pool de nós padrão, que é o primeiro que você criou com seu cluster, não pode usar o GKE Sandbox. Para ativar o GKE Sandbox durante a criação do cluster, é necessário adicionar um segundo pool de nós durante esse processo.

Console

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

  1. Acesse o menu do Google Kubernetes Engine no Console do Cloud.

    Acessar o menu do Google Kubernetes Engine

  2. Clique em Criar cluster.

  3. Escolha o cluster padrão ou um modelo apropriado para a carga de trabalho.

  4. Opcional, mas recomendado: ative o Stackdriver Logging e o Stackdriver Monitoring para que as mensagens do gVisor sejam registradas.

  5. Clique em Adicionar pool de nós.

  6. Configure o pool de nós de acordo com seus requisitos. Clique em Mais opções do pool de nós para acessá-los. Defina estas configurações:

    • Para a versão do nó, selecione v1.12.6-gke.8 ou superior.
    • Para a imagem do nó, selecione Container-Optimized OS com Containerd (cos_containerd) (Beta).
    • Clique em Ativar o sandbox com o gVisor.
    • Se os nós no pool usarem mais de uma vCPU, clique em Adicionar rótulo. Defina a chave como cloud.google.com/gke-smt-disabled e o valor como true. Em seguida, siga as instruções para desativar o Hyper-Threading no boletim de segurança.

    Defina outras configurações do pool de nós conforme necessário.

  7. Salve as configurações do pool de nós e continue configurando o cluster.

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 enquanto você cria um novo cluster usando o comando gcloud. Em vez disso, crie seu cluster normalmente. É opcional, mas recomendável, ativar o Stackdriver Logging e o Stackdriver Monitoring adicionando a sinalização --enable-stackdriver-kubernetes. As mensagens do gVisor são registradas.

Em seguida, use o comando gcloud container node-pools create e defina a sinalização --sandbox como type=gvisor. Substitua os valores entre colchetes pelos seus e lembre-se de especificar uma versão de nó de v1.12.6-gke.8 ou superior.

gcloud container node-pools create [NODE_POOL_NAME] \
      --cluster=[CLUSTER_NAME] \
      --node-version=[NODE_VERSION] \
      --image-type=cos_containerd \
      --sandbox type=gvisor \
      --enable-autoupgrade
    

A RuntimeClass do gvisor é instanciada durante a criação do nó antes de qualquer carga de trabalho ser programada no nó. É possível verificar a existência de RuntimeClass do gvisor usando o comando a seguir:

    kubectl get runtimeclasses
    
    NAME     AGE
    gvisor   19s
    

Em um cluster atual

É possível ativar o GKE Sandbox em um cluster atual adicionando um novo pool de nós e ativando o recurso para esse pool ou modificando um pool de nós não padrão atual.

Console

  1. Acesse o menu do Google Kubernetes Engine no Console do Cloud.

    Acessar o menu do Google Kubernetes Engine

  2. Clique no botão de edição do cluster, que tem a forma de um lápis.

  3. Se necessário, adicione outro pool de nós clicando em Adicionar pool de nós. Para editar um pool de nós atual, clique no botão "Editar" do pool de nós. Não ative o Sandbox com o gVisor no pool de nós padrão.

  4. Ative o Sandbox com o gVisor e clique em Concluir.

  5. Se necessário, faça outras alterações de configuração no cluster e clique em Salvar.

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] \
      --image-type=cos_containerd \
      --sandbox type=gvisor \
      --enable-autoupgrade
    

Para ativar o GKE Sandbox em um pool de nós atual, use um comando como o seguinte. Não ative --sandbox type=gvisor no pool de nós padrão.

 gcloud container node-pools update [NODE_POOL_NAME] \
      --sandbox type=gvisor
    

A RuntimeClass do gvisor é instanciada durante a criação do nó antes de qualquer carga de trabalho ser programada no nó. É possível verificar a existência de RuntimeClass do gvisor usando o comando a seguir:

    kubectl get runtimeclasses
    
    NAME     AGE
    gvisor   19s
    

Opcional: ativar o Stackdriver Logging e o Stackdriver Monitoring

É opcional, mas recomendável, ativar o Stackdriver Logging e o Stackdriver Monitoring no cluster para que as mensagens do gVisor sejam registradas. Você precisa usar o Console do Google Cloud para ativar esses recursos em um cluster atual.

  1. Acesse o menu do Google Kubernetes Engine no Console do Cloud.

    Acessar o menu do Google Kubernetes Engine

  2. Clique no botão de edição do cluster, que tem a forma de um lápis.

  3. Ative o Stackdriver Logging e o Stackdriver Monitoring.

  4. Se necessário, faça outras alterações de configuração no cluster e clique em Salvar.

Como trabalhar com o GKE Sandbox

Como executar um aplicativo em um sandbox

Para forçar a execução de um objeto Deployment em um nó com o GKE Sandbox ativado, defina spec.template.spec.runtimeClassName como gvisor, conforme mostrado por este manifesto para esse objeto:

# 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
    

Para criar o Deployment, use o comando kubectl create:

kubectl create -f httpd.yaml
    

O pod é implantado em um nó em um pool de nós com o GKE Sandbox ativado. Para verificar isso, use o comando kubectl get pods para encontrar o nó em que o pod está implantado:

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

Encontre o nome do pod na saída e execute o seguinte comando para verificar seu valor para RuntimeClass:

kubectl get pods [NAME-OF-POD] -o jsonpath='{.spec.runtimeClassName}'
    
    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}'
    
    [NAME-OF-POD]: 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

Depois de ativar o GKE Sandbox em um pool de nós, é possível executar aplicativos confiáveis usando tolerâncias e taints de nós, sem precisar usar sandbox. 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 os de sandbox exigirem acesso aos serviços do Google Cloud, use a Identidade da carga de trabalho.

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

labels:
      sandbox.gke.io: gvisor
    
taints:
    - effect: NoSchedule
      key: sandbox.gke.io
      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 como 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ó acima 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 acima.

# 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}'
    
    httpd-db5899bc9-dk7lk: gvisor
    httpd-no-sandbox-5bf87996c6-cfmmd:
    

O Deployment httpd criado anteriormente está sendo executado em um sandbox, porque sua runtimeClass é gvisor. O Deployment httpd-no-sandbox não tem valor para runtimeClass. Por isso, ele não está sendo executado em um sandbox.

Em seguida, verifique se o Deployment 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 declaração de que os metadados estão protegidos dos nós que podem executar pods no sandbox, é possível fazer um teste:

  1. Crie um Deployment 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 o objeto seja executado 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://metadata.google.internal/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 saída 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

No momento, não é possível atualizar um pool de nós para desativar o GKE Sandbox. Para desativar o GKE Sandbox em um pool de nós atual, é possível realizar uma das seguintes ações:

  • Exclua os pods que estavam previamente em sandbox. Caso contrário, após a desativação do GKE Sandbox, esses pods serão executados como normais se nenhum nó disponível estiver ativado no GKE Sandbox. Em seguida, exclua o pool de nós em que o GKE Sandbox foi ativado. Ou
  • Redimensione o pool de nós para zero nós . Ou
  • Recrie os pods sem especificar um valor para RuntimeClassName.

A seguir