Multitenancy entre projetos para o Knative serving

Este guia explica como configurar o Knative Serving para permitir que um ou mais Google Cloud projetos executem e geram as cargas de trabalho que estão a ser executadas num cluster do GKE num projeto Google Cloud diferente.

Um modelo de funcionamento comum com o Knative Serving é que uma equipa de programadores de aplicações use o respetivo Google Cloud projeto para implementar e gerir serviçosGoogle Cloud que estão a ser executados em clusters do GKE distintos nos projetos de outras equipas. Esta capacidade, denominada multi-tenancy, permite-lhe, como operador da plataforma, personalizar o acesso das suas equipas de desenvolvimento apenas aos respetivos serviços que estão a ser executados nos vários ambientes da sua organização (por exemplo, produção vs. preparação).

O Knative Serving suporta especificamente a multilocação empresarial. Este tipo de multi-tenancy permite que um projeto de cluster Google Cloud conceda acesso a recursos específicos do respetivo cluster do GKE. O Google Cloud projeto ao qual é concedido acesso ao projeto do cluster Google Cloud é o projeto do inquilino Google Cloud . Os inquilinos do projeto do cluster Google Cloud podem usar o Knative Serving para aceder, operar e possuir os serviços e os recursos aos quais lhes é concedido acesso.

Em termos conceptuais, existem quatro passos para configurar a multi-posse empresarial com o Knative serving:

  1. Configure o acesso do inquilino ao projeto do cluster Google Cloud usando um grupo Google e a gestão de identidades e acessos.
  2. Mapeie cada projeto Google Cloud cliente ao projeto Google Cloud cluster.
  3. Encaminhe os dados de registo do projeto do cluster para os projetos do inquilino através de contentores de registos e destinos. Google Cloud Google Cloud
  4. Defina autorizações de cluster para inquilinos através do controlo de acesso baseado em funções.

Antes de começar

O operador da plataforma responsável pela configuração da multi-posse tem de compreender e cumprir os seguintes requisitos:

Defina variáveis de ambiente local

Para simplificar os comandos usados neste processo, defina variáveis de ambiente locais para o projeto do cluster Google Cloud e o projeto do inquilino Google Cloud :

  1. Substitua YOUR_CLUSTER_PROJECT_ID pelo ID do projeto Google Cloud do cluster e, em seguida, execute o seguinte comando:

    export CLUSTER_PROJECT_ID=YOUR_CLUSTER_PROJECT_ID
    
  2. Substitua YOUR_TENANT_PROJECT_ID pelo ID do projeto do inquilino e, em seguida, execute o seguinte comando: Google Cloud

    export TENANT_PROJECT_ID=$YOUR_TENANT_PROJECT_ID
    
  3. Valide as variáveis de ambiente local executando os seguintes comandos:

    echo "cluster Google Cloud project is:" $CLUSTER_PROJECT_ID
    echo "tenant Google Cloud project is:" $TENANT_PROJECT_ID
    

O ID do projeto do cluster Google Cloud e o ID do projeto do inquilino Google Cloud são agora usados em todos os seguintes comandos onde $CLUSTER_PROJECT_ID e $TENANT_PROJECT_ID são especificados.

Validar as suas autorizações de IAM

Execute os seguintes comandos testIamPermissions para validar que tem as autorizações do IAM necessárias para aceder aos recursos no projeto Google Cloud do cluster, bem como nos projetos Google Cloud de inquilino.

Execute o seguinte comando para validar as suas autorizações no projeto Google Cloud do cluster:

curl -X POST \
  -H "Authorization: Bearer "$(gcloud auth application-default print-access-token) \
  --header "Content-Type: application/json" \
  --data '{"permissions":["logging.sinks.create", "logging.sinks.get", "resourcemanager.projects.setIamPolicy"]}' \
  https://cloudresourcemanager.googleapis.com/v1/projects/$CLUSTER_PROJECT_ID:testIamPermissions

Resultados esperados para o projeto Google Cloud :

{
  "permissions": [
    "logging.sinks.create",
    "logging.sinks.get",
    "resourcemanager.projects.setIamPolicy"
  ]
}

Execute o seguinte comando para validar as suas autorizações em cada projeto Google Cloud inquilino:

curl -X POST \
  -H "Authorization: Bearer "$(gcloud auth application-default print-access-token) \
  --header "Content-Type: application/json" \
  --data '{"permissions":["logging.buckets.create", "logging.buckets.get", "resourcemanager.projects.setIamPolicy", "resourcesettings.settingvalues.create", "serviceusage.services.enable"]}' \
  https://cloudresourcemanager.googleapis.com/v1/projects/$TENANT_PROJECT_ID:testIamPermissions

Resultados esperados para cada projeto Google Cloud de inquilino:

{
  "permissions": [
    "logging.buckets.create",
    "logging.buckets.get",
    "resourcemanager.projects.setIamPolicy",
    "resourcesettings.settingvalues.create",
    "serviceusage.services.enable",
  ]
}

Use um grupo Google e a gestão de identidade e de acesso para configurar o acesso do inquilino

Use um Grupo Google para permitir que os inquilinos acedam ao cluster do GKE. As autorizações de IAM dão aos inquilinos as autorizações para obter credenciais, mas não podem fazer nada no cluster até que o controlo de acesso baseado em funções do Kubernetes seja configurado num passo posterior.

Tem de criar um Grupo Google que contenha todos os utilizadores do projeto do seu inquilino. Google Cloud Para mais informações sobre a utilização de um grupo de segurança, consulte o artigo Usar o Google Groups para o GKE.

Crie a seguinte variável de ambiente local para o seu grupo Google:

export SECURITY_GROUP=gke-security-groups@company.com

Visualizador de clusters do Kubernetes

Execute os seguintes comandos para permitir que os inquilinos obtenham credenciais para o cluster. Isto não permite que os inquilinos leiam nem manipulem recursos no cluster do GKE.

Referência de IAM

gcloud projects add-iam-policy-binding $CLUSTER_PROJECT_ID \
   --member=group:$SECURITY_GROUP \
   --role='roles/container.clusterViewer' \
   --condition=None

Para restringir o acesso a um cluster específico, pode usar uma condição do IAM.

gcloud projects add-iam-policy-binding $CLUSTER_PROJECT_ID \
   --member=group:$SECURITY_GROUP \
   --role='roles/container.clusterViewer' \
   --condition="expression=resource.name == 'cluster-name',title=Restrict cluster access"

Visualizador de monitorização

Execute o seguinte comando para permitir que os inquilinos leiam as métricas de monitorização.

Referência das funções de monitorização

gcloud projects add-iam-policy-binding $CLUSTER_PROJECT_ID \
   --member=group:$SECURITY_GROUP \
   --role='roles/monitoring.viewer' \
   --condition=None

Mapear cada projeto Google Cloud cliente ao projeto Google Cloud cluster

Usa os valores de definição de recursos para mapear Google Cloud projetos de inquilinos para um projeto de Google Cloud cluster.

A definição do recurso pode ser configurada para cada projeto Google Cloud individual do inquilino ou pode ser definida em qualquer nível da hierarquia de pastas. É mais fácil definir esta opção ao nível da pasta de inquilino único, mas é mais flexível defini-la ao nível de cada projeto de inquilino. Após esta configuração, sempre que os inquilinos explorarem a IU de serviço do Knative, também veem os respetivos serviços no projeto do cluster Google Cloud . Isto não altera as autorizações da IAM no projeto Google Cloud do cluster nem nos clusters do GKE. É apenas um mapeamento de um projeto (ou uma pasta) de inquilino para um projeto Google Cloud do cluster.

  1. Ative a API resourcesettings no projeto Google Cloud do inquilino.

    gcloud services enable resourcesettings.googleapis.com \
      --project=$TENANT_PROJECT_ID
    
  2. Adicione os privilégios de administrador da organização (roles/resourcesettings.admin) ao seu ID de utilizador executando o seguinte comando:

    gcloud organizations add-iam-policy-binding YOUR_ORGANIZATION_ID \
      --member=YOUR_ADMIN_MEMBER_ID \
      --role='roles/resourcesettings.admin'
    

    Substitua YOUR_ORGANIZATION_ID pelo ID da sua organização e YOUR_ADMIN_MEMBER_ID pelo seu ID de utilizador, por exemplo user:my-email@my-domain.com.

  3. Escolha um dos seguintes métodos para definir o mapeamento.

    Pode definir o valor da definição do recurso numa Google Cloud pasta Google Cloud principal, se todos os projetos Google Cloud e pastas Google Cloud secundários usarem esse mesmo valor.

Projetos de inquilinos

Defina o valor da definição do recurso para cada projeto Google Cloud :

  1. Obtenha o name do projeto do inquilino Google Cloud e defina-o como uma variável de ambiente local:
    export TENANT_PROJECT_NUMBER=$(gcloud projects describe $TENANT_PROJECT_ID --format="value(projectNumber)")
  2. Crie um ficheiro de valor de definição de recursos para definir o mapeamento do projeto Google Cloud principal para o projeto Google Cloud do cluster. É possível definir vários IDs de projetos Google Cloud de clusters neste ficheiro e adicioná-los a um único projeto Google Cloud de inquilino.
    cat > value-file.json << EOF
    {
    "name": "projects/$TENANT_PROJECT_NUMBER/settings/cloudrun-multiTenancy/value",
    "value": {
      "stringSetValue": {
        "values": [ "projects/$CLUSTER_PROJECT_ID" ]
      }
    }
    }
    EOF
  3. Implemente as definições de recursos no projeto Google Cloud do inquilino:
    gcloud resource-settings set-value cloudrun-multiTenancy --value-file value-file.json --project $TENANT_PROJECT_ID

Pastas de inquilinos

Defina o valor da definição do recurso para uma pasta de inquilino principal para definir esse valor para todos os projetos e pastas de inquilino secundário Google Cloud :

  1. Obtenha o number da pasta do inquilino e defina-o como uma variável de ambiente local:
    export TENANT_FOLDER_NUMBER=$TENANT_FOLDER_NUMBER
  2. Crie um ficheiro de valor de definição de recursos para definir o mapeamento da pasta do inquilino para o projeto do cluster Google Cloud . É possível definir vários IDs de projetos Google Cloud de cluster neste ficheiro e adicioná-los a uma única pasta de inquilino.
    cat > value-file.json << EOF
    {
    "name": "folders/$TENANT_FOLDER_NUMBER/settings/cloudrun-multiTenancy/value",
    "value": {
      "stringSetValue": {
        "values": [ "projects/$CLUSTER_PROJECT_ID" ]
      }
    }
    }
    EOF
  3. Implemente as definições de recursos na pasta do inquilino:
    gcloud resource-settings set-value cloudrun-multiTenancy --value-file value-file.json --folder $TENANT_FOLDER_NUMBER

Configurar os contentores e os destinos de registos para encaminhar dados de registos

Para cada inquilino, cria um contentor de registos, um destino e as autorizações para encaminhar os dados de registo do projeto Google Cloud do cluster para o projeto Google Cloud do inquilino. Nos passos seguintes, todos os registos do espaço de nomes no projeto do cluster são encaminhados para o contentor. Google Cloud Consulte o conjunto abaixo para ver detalhes sobre como limitar os registos partilhados.

Crie as seguintes variáveis de ambiente local:

  • Especifique o espaço de nomes do cluster do GKE ao qual os seus inquilinos acedem.
  • O nome do destino. Para simplificar este passo, o nome é uma combinação das variáveis de ambiente local do projeto do cluster Google Cloud e do projeto do inquilino Google Cloud que criou anteriormente. Pode modificar este valor.
export NAMESPACE=$NAMESPACE
export SINK_NAME=$CLUSTER_PROJECT_ID-$TENANT_PROJECT_ID

Execute o seguinte comando para criar o contentor de registos no projeto de inquilino. Tenha em atenção que o nome do contentor de registos tem de ser o ID do projeto Google Cloud do cluster e não pode ser alterado nem modificado.

gcloud logging buckets \
   create $CLUSTER_PROJECT_ID \
   --location=global \
   --project=$TENANT_PROJECT_ID

Execute o seguinte comando para criar o coletor a partir do espaço de nomes especificado no projeto do cluster Google Cloud para o contentor do projeto do inquilino Google Cloud . Tenha em atenção que pode restringir o âmbito dos registos, por exemplo, para partilhar apenas um cluster do GKE individual ou recursos de serviço do Knative específicos, definindo valores log-filter adicionais.

gcloud logging sinks \
   create $SINK_NAME \
   logging.googleapis.com/projects/$TENANT_PROJECT_ID/locations/global/buckets/$CLUSTER_PROJECT_ID \
   --log-filter=resource.labels.namespace_name=$NAMESPACE \
   --project $CLUSTER_PROJECT_ID

Execute os seguintes comandos para adicionar a autorização da conta de serviço do destino de registo ao contentor que criou.

export SINK_SERVICE_ACCOUNT=$(gcloud logging sinks \
   describe $SINK_NAME \
   --project $CLUSTER_PROJECT_ID \
   --format="value(writerIdentity)")
gcloud projects add-iam-policy-binding $TENANT_PROJECT_ID \
   --member=$SINK_SERVICE_ACCOUNT \
   --role='roles/logging.bucketWriter' \
   --condition="expression=resource.name.endsWith\
   (\"locations/global/buckets/$CLUSTER_PROJECT_ID\"),\
   title=Log bucket writer from $CLUSTER_PROJECT_ID"

Configurar autorizações de inquilino com controlo de acesso baseado em funções (CABF)

Usou anteriormente os Grupos Google e o IAM para configurar as autorizações de modo a permitir que os inquilinos acedam ao projeto do cluster do GKE. Google Cloud Para permitir que os inquilinos acedam aos recursos no cluster do GKE, tem de definir autorizações com o RBAC do Kubernetes.

Crie funções de cluster

Depois de definir e criar as seguintes funções de cluster, pode continuar a usá-las no futuro para adicionar todos os inquilinos subsequentes do projeto do cluster Google Cloud .

Funções da IU

Esta função permite que os inquilinos consultem todos os espaços de nomes. Isto é necessário para saber a que espaços de nomes os utilizadores têm acesso para criar serviços /sdk/gcloud/reference/logging/sinks/create.

kubectl create clusterrole \
   namespace-lister \
   --verb=list \
   --resource=namespaces

Esta função permite que os inquilinos vejam os serviços de fornecimento do Knative. Isto é necessário para listar os serviços na IU do Knative Serving.

kubectl create clusterrole \
   ksvc-lister \
   --verb=list \
   --resource=services.serving.knative.dev

Crie funções de cluster

Apenas uma destas autorizações é necessária. A primeira autorização permite que os inquilinos manipulem qualquer recurso no respetivo espaço de nomes. A segunda autorização permite um conjunto mais limitado de apenas criar serviços Knative serving.

kubectl create clusterrole \
   kubernetes-developer \
   --verb="*" \
   --resource="*.*"

Se a autorização kubernetes-developer for demasiado permissiva, o seguinte permite que os inquilinos criem serviços Knative nos respetivos espaços de nomes e vejam os outros recursos Knative.

cat <<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: knative-developer
rules:
- apiGroups: ["serving.knative.dev"]
  resources: ["services"]
  verbs: ["*"]
- apiGroups: ["serving.knative.dev"]
  resources: ["*"]
  verbs: ["get", "list", "watch"]
EOF

Crie o espaço de nomes do inquilino e atribua autorizações.

Tenha em atenção que isto pressupõe que fez a configuração através do Grupos Google para GKE. Isto é necessário para cada inquilino.

export TENANT_GROUP=tenant-a@company.com

TENANT_GROUP tem de fazer parte de SECURITY_GROUP

Capacidade de ver todos os espaços de nomes

Para consultar o cluster do GKE, todos os inquilinos têm de ter a capacidade de listar espaços de nomes. Atualmente, não existe um auth can-i que devolva espaços de nomes para os quais é possível realizar uma ação. A única solução alternativa é listar os namespaces e, em seguida, consultar cada namespace individualmente.

kubectl create clusterrolebinding \
   all-namespace-listers \
   --clusterrole=namespace-lister \
   --group=$TENANT_GROUP

Capacidade de listar serviços de publicação Knative

kubectl create clusterrolebinding \
   all-ksvc-listers \
   --clusterrole=ksvc-lister \
   --group=$TENANT_GROUP

Capacidade de manipular recursos no espaço de nomes

Primeiro, crie o espaço de nomes:

kubectl create namespace $NAMESPACE

Se usar a função kubernetes-developer:

kubectl create rolebinding \
   kubernetes-developer \
   --namespace=$NAMESPACE \
   --clusterrole=kubernetes-developer \
   --group=$TENANT_GROUP

Se usar a função knative-developer:

kubectl create rolebinding \
   kubernetes-developer \
   --namespace=$NAMESPACE \
   --clusterrole=knative-developer \
   --group=$TENANT_GROUP

Adicionar capacidade para o inquilino aceder ao endereço IP externo

cat <<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: ingress-reader
rules:
- apiGroups: [""]
  resources: ["services"]
  verbs: ["get"]
EOF
kubectl create rolebinding \
   ingress-reader-$TENANT_GROUP \
   --namespace=istio-system \
   --clusterrole=ingress-reader \
   --group=$TENANT_GROUP

Validar

Pode verificar se configurou com êxito a multilocação empresarial abrindo o projeto do inquilino no Knative Serving e implementando um serviço num cluster do GKE. Google Cloud

Aceda ao Knative serving

Parabéns, o seu inquilino já pode interagir com os serviços e os recursos no espaço de nomes do cluster do GKE ao qual lhe foi concedido acesso.

Referência de multi-inquilino