Faça o arranque automático dos nós do GKE com DaemonSets


Este tutorial mostra como personalizar os nós de um cluster do Google Kubernetes Engine (GKE) usando DaemonSets. Um DaemonSet garante que todos os nós (ou os selecionados) executam uma cópia de um Pod. Esta abordagem permite-lhe usar as mesmas ferramentas para orquestrar as suas cargas de trabalho que usa para modificar os seus nós do GKE.

Se as ferramentas e os sistemas que usa para inicializar os clusters forem diferentes das ferramentas e dos sistemas que usa para executar as cargas de trabalho, aumenta o esforço necessário para gerir o seu ambiente. Por exemplo, se usar uma ferramenta de gestão de configuração para inicializar os nós do cluster, está a confiar num procedimento que está fora do ambiente de tempo de execução onde o resto das suas cargas de trabalho é executado.

O objetivo deste tutorial é ajudar os administradores de sistemas, os engenheiros de sistemas ou os operadores de infraestrutura a simplificar a inicialização de clusters do Kubernetes.

Antes de ler esta página, certifique-se de que conhece:

Neste tutorial, vai aprender a usar etiquetas e seletores do Kubernetes para escolher o procedimento de inicialização a executar com base nas etiquetas que são aplicadas a um nó. Nestes passos, implementa um DaemonSet para ser executado apenas em nós com a etiqueta default-init aplicada. No entanto, para demonstrar a flexibilidade deste mecanismo, pode criar outro conjunto de nós e aplicar a etiqueta alternative-init aos nós neste novo conjunto. No cluster, pode implementar outro DaemonSet configurado para ser executado apenas em nós com a etiqueta alternative-init.

Além disso, pode executar vários procedimentos de inicialização em cada nó e não apenas um. Pode tirar partido deste mecanismo para estruturar melhor os seus procedimentos de inicialização, separando claramente as preocupações de cada um.

Neste tutorial, como exemplo, o procedimento de inicialização executa as seguintes ações em cada nó etiquetado com a etiqueta default-init:

  1. Anexa um disco adicional ao nó.
  2. Instala um conjunto de pacotes e bibliotecas através do gestor de pacotes do sistema operativo do nó.
  3. Carrega um conjunto de módulos do kernel do Linux.

Objetivos

Neste tutorial, faz o seguinte:

  • Aprovisione e configure um cluster do GKE.
  • Prepare um descritor DaemonSet para inicializar os nós no cluster.
  • Implemente o DaemonSet no cluster.
  • Verifique se os nós do cluster foram inicializados.

Custos

Neste documento, usa os seguintes componentes faturáveis do Google Cloud:

Para gerar uma estimativa de custos com base na sua utilização projetada, use a calculadora de preços.

Os novos Google Cloud utilizadores podem ser elegíveis para uma avaliação gratuita.

Quando terminar as tarefas descritas neste documento, pode evitar a faturação contínua eliminando os recursos que criou. Para mais informações, consulte o artigo Limpe.

Antes de começar

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  3. Verify that billing is enabled for your Google Cloud project.

  4. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  5. Verify that billing is enabled for your Google Cloud project.

Inicialize o ambiente

Nesta secção, faz o seguinte:

  1. Ative as APIs Cloud necessárias.
  2. Aprovisione uma conta de serviço com privilégios limitados para os nós no cluster do GKE.
  3. Prepare o cluster do GKE.
  4. Conceda ao utilizador privilégios de administração do cluster.

Ative as APIs Cloud

  1. Abra o Cloud Shell.

    ABRIR Cloud Shell

  2. Selecione o Google Cloud projeto:

    gcloud config set project project-id
    

    Substitua project-id pelo ID do Google Cloud projeto que criou ou selecionou para este tutorial.

  3. Ative a API Google Kubernetes Engine:

    gcloud services enable container.googleapis.com
    

Aprovisione uma conta de serviço para gerir clusters do GKE

Nesta secção, cria uma conta de serviço associada aos nós no cluster. Neste tutorial, os nós do GKE usam esta conta de serviço em vez da conta de serviço predefinida. Como prática recomendada, conceda à conta de serviço apenas as funções e as autorizações de acesso necessárias para executar a aplicação.

As funções necessárias para a conta de serviço são as seguintes:

  • Função de visualizador de monitorização (roles/monitoring.viewer). Esta função concede acesso só de leitura à consola e à API Cloud Monitoring.
  • Função de escritor de métricas de monitorização (roles/monitoring.metricWriter). Esta função permite escrever dados de monitorização.
  • Função Logs Writer (roles/logging.logWriter). Esta função concede autorizações suficientes para escrever registos.
  • Função de utilizador da conta de serviço (roles/iam.serviceAccountUser). Esta função dá acesso a contas de serviço num projeto. Neste tutorial, o procedimento de inicialização representa a conta de serviço para executar operações privilegiadas.
  • Função de administrador de computação (roles/compute.admin). Esta função oferece controlo total de todos os recursos do Compute Engine. Neste tutorial, a conta de serviço precisa desta função para anexar discos adicionais aos nós do cluster.

Para aprovisionar uma conta de serviço, siga estes passos:

  1. No Cloud Shell, inicialize uma variável de ambiente que armazena o nome da conta de serviço:

    GKE_SERVICE_ACCOUNT_NAME=ds-init-tutorial-gke
    
  2. Crie uma conta de serviço:

    gcloud iam service-accounts create "$GKE_SERVICE_ACCOUNT_NAME" \
      --display-name="$GKE_SERVICE_ACCOUNT_NAME"
    
  3. Inicialize uma variável de ambiente que armazena o nome da conta de email da conta de serviço:

    GKE_SERVICE_ACCOUNT_EMAIL="$(gcloud iam service-accounts list \
        --format='value(email)' \
        --filter=displayName:"$GKE_SERVICE_ACCOUNT_NAME")"
    
  4. Associe as funções de gestão de identidade e de acesso (IAM) à conta de serviço:

    gcloud projects add-iam-policy-binding \
        "$(gcloud config get-value project 2> /dev/null)" \
        --member serviceAccount:"$GKE_SERVICE_ACCOUNT_EMAIL" \
        --role roles/compute.admin
    gcloud projects add-iam-policy-binding \
        "$(gcloud config get-value project 2> /dev/null)" \
        --member serviceAccount:"$GKE_SERVICE_ACCOUNT_EMAIL" \
        --role roles/monitoring.viewer
    gcloud projects add-iam-policy-binding \
        "$(gcloud config get-value project 2> /dev/null)" \
        --member serviceAccount:"$GKE_SERVICE_ACCOUNT_EMAIL" \
        --role roles/monitoring.metricWriter
    gcloud projects add-iam-policy-binding \
        "$(gcloud config get-value project 2> /dev/null)" \
        --member serviceAccount:"$GKE_SERVICE_ACCOUNT_EMAIL" \
        --role roles/logging.logWriter
    gcloud projects add-iam-policy-binding \
        "$(gcloud config get-value project 2> /dev/null)" \
        --member serviceAccount:"$GKE_SERVICE_ACCOUNT_EMAIL" \
        --role roles/iam.serviceAccountUser
    

Prepare o cluster do GKE

Nesta secção, inicia o cluster do GKE, concede autorizações e conclui a configuração do cluster.

Para este tutorial, um cluster com um número relativamente baixo de nós pequenos de propósito geral é suficiente para demonstrar o conceito deste tutorial. Cria um cluster com um node pool (o predefinido). Em seguida, etiqueta todos os nós no conjunto de nós predefinido com a etiqueta default-init.

  • No Cloud Shell, crie e inicie um cluster do GKE regional:

    gcloud container clusters create ds-init-tutorial \
        --enable-ip-alias \
        --image-type=ubuntu_containerd \
        --machine-type=n1-standard-2 \
        --metadata disable-legacy-endpoints=true \
        --node-labels=app=default-init \
        --node-locations us-central1-a,us-central1-b,us-central1-c \
        --no-enable-basic-auth \
        --no-issue-client-certificate \
        --num-nodes=1 \
        --location us-central1 \
        --service-account="$GKE_SERVICE_ACCOUNT_EMAIL"
    

Implemente o DaemonSet

Nesta secção, faz o seguinte:

  1. Crie o ConfigMap que armazena o procedimento de inicialização.
  2. Implemente o DaemonSet que agenda e executa o procedimento de inicialização.

O DaemonSet faz o seguinte:

  1. Configura um volume que disponibiliza o conteúdo do ConfigMap aos contentores que o DaemonSet processa.
  2. Configura os volumes para áreas privilegiadas do sistema de ficheiros do nó do cluster subjacente. Estas áreas permitem que os contentores que o DaemonSet agenda interajam diretamente com o nó que os executa.
  3. Agenda e executa um contentor init que executa o procedimento de inicialização e, em seguida, é terminado após a conclusão.
  4. Agenda e executa um contentor que permanece inativo e não consome recursos.

O contentor inativo garante que um nó é inicializado apenas uma vez. Os DaemonSets são concebidos para que todos os nós elegíveis executem uma cópia de um Pod. Se usar um contentor normal, esse contentor executa o procedimento de inicialização e, em seguida, é terminado após a conclusão. Por predefinição, o DaemonSet reagenda o pod. Para evitar o "reagendamento contínuo", o DaemonSet executa primeiro o procedimento de inicialização num contentor init e, em seguida, deixa um contentor em execução.

O procedimento de inicialização seguinte contém operações privilegiadas e não privilegiadas. Ao usar o chroot, pode executar comandos como se os estivesse a executar diretamente no nó e não apenas dentro de um contentor.

# Copyright 2019 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: entrypoint
  labels:
    app: default-init
data:
  entrypoint.sh: |
    #!/usr/bin/env bash

    set -euo pipefail

    DEBIAN_FRONTEND=noninteractive
    ROOT_MOUNT_DIR="${ROOT_MOUNT_DIR:-/root}"

    echo "Installing dependencies"
    apt-get update
    apt-get install -y apt-transport-https curl gnupg lsb-release

    echo "Installing gcloud SDK"
    export CLOUD_SDK_REPO="cloud-sdk-$(lsb_release -c -s)"
    echo "deb https://packages.cloud.google.com/apt $CLOUD_SDK_REPO main" | tee -a /etc/apt/sources.list.d/google-cloud-sdk.list
    curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
    apt-get update
    apt-get install -y google-cloud-sdk

    echo "Getting node metadata"
    NODE_NAME="$(curl -sS http://metadata.google.internal/computeMetadata/v1/instance/name -H 'Metadata-Flavor: Google')"
    ZONE="$(curl -sS http://metadata.google.internal/computeMetadata/v1/instance/zone -H 'Metadata-Flavor: Google' | awk -F  "/" '{print $4}')"

    echo "Setting up disks"
    DISK_NAME="$NODE_NAME-additional"

    if ! gcloud compute disks list --filter="name:$DISK_NAME" | grep "$DISK_NAME" > /dev/null; then
        echo "Creating $DISK_NAME"
        gcloud compute disks create "$DISK_NAME" --size=1024 --zone="$ZONE"
    else
        echo "$DISK_NAME already exists"
    fi

    if ! gcloud compute instances describe "$NODE_NAME" --zone "$ZONE" --format '(disks[].source)' | grep "$DISK_NAME" > /dev/null; then
        echo "Attaching $DISK_NAME to $NODE_NAME"
        gcloud compute instances attach-disk "$NODE_NAME" --device-name=sdb --disk "$DISK_NAME" --zone "$ZONE"
    else
        echo "$DISK_NAME is already attached to $NODE_NAME"
    fi

    # We use chroot to run the following commands in the host root (mounted as the /root volume in the container)
    echo "Installing nano"
    chroot "${ROOT_MOUNT_DIR}" apt-get update
    chroot "${ROOT_MOUNT_DIR}" apt-get install -y nano

    echo "Loading Kernel modules"
    # Load the bridge kernel module as an example
    chroot "${ROOT_MOUNT_DIR}" modprobe bridge
...

Recomendamos que reveja cuidadosamente cada procedimento de inicialização, uma vez que o procedimento pode alterar o estado dos nós do cluster. Apenas um pequeno grupo de indivíduos deve ter o direito de modificar esses procedimentos, porque esses procedimentos podem afetar significativamente a disponibilidade e a segurança dos seus clusters.

Para implementar o ConfigMap e o DaemonSet, faça o seguinte:

  1. No Cloud Shell, altere o diretório de trabalho para o diretório $HOME:

    cd "$HOME"
    
  2. Clone o repositório Git que contém os scripts e os ficheiros de manifesto para implementar e configurar o procedimento de inicialização:

    git clone https://github.com/GoogleCloudPlatform/solutions-gke-init-daemonsets-tutorial
    
  3. Altere o diretório de trabalho para o diretório do repositório recém-clonado:

    cd "$HOME"/solutions-gke-init-daemonsets-tutorial
    
  4. Crie um ConfigMap para conter o script de inicialização do nó:

    kubectl apply -f cm-entrypoint.yaml
    
  5. Implemente o DaemonSet:

    kubectl apply -f daemon-set.yaml
    
  6. Verifique se a inicialização do nó está concluída:

    kubectl get ds --watch
    

    Aguarde até que o DaemonSet seja comunicado como pronto e atualizado, conforme indicado por um resultado semelhante ao seguinte:

    NAME              DESIRED   CURRENT   READY     UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
    node-initializer   3         3         3         3            3          <none>  2h
    

Valide e verifique o procedimento de inicialização

Depois de cada nó do cluster marcado com a etiqueta default-init executar o procedimento de inicialização, pode verificar os resultados.

Para cada nó, o procedimento de validação verifica o seguinte:

  1. Foi anexado um disco adicional e está pronto a ser usado.
  2. Os pacotes e as bibliotecas instalados do gestor de pacotes do sistema operativo do nó.
  3. Os módulos do kernel são carregados.

Execute o procedimento de validação:

  • No Cloud Shell, execute o script de validação:

    kubectl get nodes -o=jsonpath='{range .items[?(@.metadata.labels.app=="default-init")]}{.metadata.name}{" "}{.metadata.labels.failure-domain\.beta\.kubernetes\.io/zone}{"\n"}{end}' | while IFS= read -r line ; do ./verify-init.sh $line < /dev/null; done
    

    Aguarde que o script seja executado e verifique se cada nó foi corretamente inicializado, conforme indicado por um resultado semelhante ao seguinte:

    Verifying gke-ds-init-tutorial-default-pool-5464b7e3-nzjm (us-central1-c) configuration
    Disk configured successfully on gke-ds-init-tutorial-default-pool-5464b7e3-nzjm (us-central1-c)
    Packages installed successfully in gke-ds-init-tutorial-default-pool-5464b7e3-nzjm (us-central1-c)
    Kernel modules loaded successfully on gke-ds-init-tutorial-default-pool-5464b7e3-nzjm (us-central1-c)
    Verifying gke-ds-init-tutorial-default-pool-65baf745-0gwt (us-central1-a) configuration
    Disk configured successfully on gke-ds-init-tutorial-default-pool-65baf745-0gwt (us-central1-a)
    Packages installed successfully in gke-ds-init-tutorial-default-pool-65baf745-0gwt (us-central1-a)
    Kernel modules loaded successfully on gke-ds-init-tutorial-default-pool-65baf745-0gwt (us-central1-a)
    Verifying gke-ds-init-tutorial-default-pool-6b125c50-3xvl (us-central1-b) configuration
    Disk configured successfully on gke-ds-init-tutorial-default-pool-6b125c50-3xvl (us-central1-b)
    Packages installed successfully in gke-ds-init-tutorial-default-pool-6b125c50-3xvl (us-central1-b)
    Kernel modules loaded successfully on gke-ds-init-tutorial-default-pool-6b125c50-3xvl (us-central1-b)
    

Limpar

Para evitar incorrer em custos na sua Google Cloud conta pelos recursos usados neste tutorial, pode eliminar o projeto que criou para este tutorial. Se criou um projeto dedicado a este tutorial, pode eliminá-lo na totalidade. Se usou um projeto existente, mas não quer eliminá-lo, siga os passos abaixo para limpar o projeto.

Limpe o projeto

Para limpar um projeto sem o eliminar, tem de remover os recursos que criou neste tutorial.

  1. No Cloud Shell, elimine o cluster do GKE:

    gcloud container clusters delete ds-init-tutorial --quiet --location us-central1
    
  2. Elimine os discos adicionais que criou como parte deste procedimento de inicialização de exemplo:

    gcloud compute disks list --filter="name:additional" --format="csv[no-heading](name,zone)" | while IFS= read -r line ; do DISK_NAME="$(echo $line | cut -d',' -f1)"; ZONE="$(echo $line | cut -d',' -f2)"; gcloud compute disks delete "$DISK_NAME" --quiet --zone "$ZONE" < /dev/null; done
    
  3. Elimine a conta de serviço:

    gcloud iam service-accounts delete "$GKE_SERVICE_ACCOUNT_EMAIL" --quiet
    
  4. Elimine o diretório do repositório clonado:

    rm -rf "$HOME"/solutions-gke-init-daemonsets-tutorial
    

Elimine o projeto

A forma mais fácil de eliminar a faturação é eliminar o projeto que criou para o tutorial.

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

O que se segue?