Multitenancy tra progetti per Knative serving

Questa guida illustra come configurare Knative serving per consentire a uno o più progetti Google Cloud di eseguire e gestire i carichi di lavoro in esecuzione su un cluster GKE in un altro progetto Google Cloud.

Un modello operativo comune con Knative serving prevede che un team di sviluppatori di applicazioni utilizzi il proprio progetto Google Cloud per eseguire il deployment e gestire i servizi in esecuzione in diversi cluster GKE nei progetti Google Cloud di altri team. Questa funzionalità, chiamata multi-tenancy, consente agli operatori di piattaforma di personalizzare l'accesso dei team di sviluppo solo ai servizi in esecuzione nei vari ambienti della tua organizzazione (ad esempio, produzione o gestione temporanea).

Knative serving supporta nello specifico l'architettura multi-tenancy aziendale. Questo tipo di architettura multi-tenancy consente a un progetto Google Cloud su cluster di accedere a risorse specifiche del proprio cluster GKE. Il progetto Google Cloud a cui viene concesso l'accesso al progetto Google Cloud del cluster è il progetto Google Cloud tenant. I tenant del progetto Google Cloud del cluster possono utilizzare Knative serving per accedere, utilizzare e possedere i servizi e le risorse per i quali viene concesso loro l'accesso.

Concettualmente, sono previsti quattro passaggi per la configurazione dell'architettura multi-tenancy aziendale con Knative serving:

  1. Configura l'accesso dei tenant al progetto Google Cloud del cluster utilizzando un gruppo Google e Identity and Access Management.
  2. Mappa ogni progetto Google Cloud tenant al progetto Google Cloud del cluster.
  3. Instrada i dati di log del progetto Google Cloud del cluster ai progetti Google Cloud tenant utilizzando bucket di log e sink.
  4. Definisci le autorizzazioni del cluster per i tenant utilizzando controllo dell'accesso basato sui ruoli.

Prima di iniziare

L'operatore di piattaforma responsabile della configurazione dell'architettura multi-tenancy deve comprendere e soddisfare i seguenti requisiti:

Definisci le variabili di ambiente locali

Per semplificare i comandi utilizzati in questo processo, definisci le variabili di ambiente locale sia per il progetto Google Cloud del cluster che per il progetto Google Cloud tenant:

  1. Sostituisci YOUR_CLUSTER_PROJECT_ID con l'ID del progetto Google Cloud del cluster ed esegui questo comando:

    export CLUSTER_PROJECT_ID=YOUR_CLUSTER_PROJECT_ID
    
  2. Sostituisci YOUR_TENANT_PROJECT_ID con l'ID del progetto Google Cloud tenant ed esegui questo comando:

    export TENANT_PROJECT_ID=$YOUR_TENANT_PROJECT_ID
    
  3. Verifica le variabili di ambiente locali eseguendo questi comandi:

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

L'ID progetto Google Cloud del tuo cluster e l'ID progetto Google Cloud tenant vengono ora utilizzati in tutti i comandi seguenti in cui sono specificati $CLUSTER_PROJECT_ID e $TENANT_PROJECT_ID.

Verifica delle autorizzazioni IAM in corso...

Esegui questi comandi testIamPermissions per confermare di disporre delle autorizzazioni IAM necessarie per accedere alle risorse nel progetto Google Cloud del cluster e ai progetti Google Cloud tenant.

Esegui questo comando per convalidare le tue autorizzazioni nel progetto Google Cloud del 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

Risultati previsti per il progetto Google Cloud del cluster:

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

Esegui questo comando per convalidare le autorizzazioni su ciascun progetto Google Cloud tenant:

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

Risultati previsti per ogni progetto Google Cloud tenant:

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

Usa Google Gruppi e Identity and Access Management per configurare l'accesso dei tenant

Usa un gruppo Google per consentire ai tenant di accedere al cluster GKE. Le autorizzazioni IAM concedono ai tenant le autorizzazioni per ottenere le credenziali, ma non potranno fare nulla nel cluster finché il controllo dell'accesso basato sui ruoli di Kubernetes non verrà configurato in un passaggio successivo.

Devi creare un gruppo Google che contenga tutti gli utenti del progetto Google Cloud tenant. Per ulteriori informazioni sull'utilizzo di un gruppo di sicurezza, vedi Utilizzo di Google Gruppi per GKE.

Crea la seguente variabile di ambiente locale per il tuo gruppo Google:

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

Visualizzatore cluster Kubernetes

Esegui questi comandi per consentire ai tenant di ottenere le credenziali nel cluster. Ciò non consente ai tenant di leggere o manipolare risorse nel cluster GKE.

Riferimento IAM

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

Per limitare l'accesso a un cluster specifico, puoi utilizzare una condizione 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"

Visualizzatore Monitoring

Esegui questo comando per consentire ai tenant di leggere le metriche di monitoraggio.

Riferimento per i ruoli in Monitoring

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

Mappando ogni progetto Google Cloud tenant al progetto Google Cloud del cluster

Puoi utilizzare i valori dell'impostazione delle risorse per mappare i progetti Google Cloud tenant a un progetto Google Cloud del cluster.

L'impostazione delle risorse può essere configurata per ogni singolo progetto Google Cloud tenant oppure a qualsiasi livello della gerarchia delle cartelle. L'impostazione è più semplice a livello di cartella del singolo tenant, ma è più flessibile a livello di progetto tenant. Al termine della configurazione, ogni volta che i tenant esplorano la UI di Knative serving, vedranno anche i propri servizi nel progetto Google Cloud del cluster. Questa operazione non modifica le autorizzazioni IAM nel progetto Google Cloud del cluster o nei cluster GKE; si tratta solo di una mappatura da un progetto (o cartella) tenant a un progetto Google Cloud per il cluster.

  1. Abilita l'API resourcesettings nel progetto Google Cloud tenant.

    gcloud services enable resourcesettings.googleapis.com \
      --project=$TENANT_PROJECT_ID
    
  2. Aggiungi i privilegi di amministratore dell'organizzazione (roles/resourcesettings.admin) al tuo ID utente eseguendo questo comando:

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

    Sostituisci YOUR_ORGANIZATION_ID con l'ID della tua organizzazione e YOUR_ADMIN_MEMBER_ID con il tuo ID utente, ad esempio user:my-email@my-domain.com.

  3. Scegli uno dei seguenti metodi per definire la mappatura.

    Puoi impostare il valore dell'impostazione delle risorse su una cartella Google Cloud padre se tutti i progetti Google Cloud secondari e le cartelle Google Cloud utilizzano lo stesso valore.

Progetti tenant

Imposta il valore dell'impostazione delle risorse per ogni progetto Google Cloud tenant:

  1. Ottieni name del progetto Google Cloud tenant e impostalo su una variabile di ambiente locale:
    export TENANT_PROJECT_NUMBER=$(gcloud projects describe $TENANT_PROJECT_ID --format="value(projectNumber)")
  2. Crea un file dei valori delle impostazioni delle risorse per definire la mappatura dal progetto Google Cloud tenant al progetto Google Cloud del cluster. In questo file è possibile definire più ID progetto Google Cloud del cluster e aggiungerli a un progetto Google Cloud con singolo tenant.
    cat > value-file.json << EOF
    {
    "name": "projects/$TENANT_PROJECT_NUMBER/settings/cloudrun-multiTenancy/value",
    "value": {
      "stringSetValue": {
        "values": [ "projects/$CLUSTER_PROJECT_ID" ]
      }
    }
    }
    EOF
    
  3. Esegui il deployment delle impostazioni delle risorse nel progetto Google Cloud tenant:
    gcloud resource-settings set-value cloudrun-multiTenancy --value-file value-file.json --project $TENANT_PROJECT_ID

Cartelle tenant

Imposta il valore dell'impostazione delle risorse per una cartella tenant padre per impostare il valore su tutti i progetti e le cartelle Google Cloud del tenant figlio:

  1. Ottieni il valore number della cartella tenant e impostalo su una variabile di ambiente locale:
    export TENANT_FOLDER_NUMBER=$TENANT_FOLDER_NUMBER
    
  2. Crea un file dei valori delle impostazioni delle risorse per definire la mappatura dalla cartella tenant al progetto Google Cloud del cluster. In questo file è possibile definire più ID progetto Google Cloud del cluster e aggiungerli a una cartella con un singolo tenant.
    cat > value-file.json << EOF
    {
    "name": "folders/$TENANT_FOLDER_NUMBER/settings/cloudrun-multiTenancy/value",
    "value": {
      "stringSetValue": {
        "values": [ "projects/$CLUSTER_PROJECT_ID" ]
      }
    }
    }
    EOF
    
  3. Esegui il deployment delle impostazioni delle risorse nella cartella tenant:
    gcloud resource-settings set-value cloudrun-multiTenancy --value-file value-file.json --folder $TENANT_FOLDER_NUMBER

Configurazione dei bucket e dei sink di log per il routing dei dati di log

Per ogni tenant, puoi creare un bucket di log, un sink e le autorizzazioni per instradare i dati di log del progetto Google Cloud del cluster al progetto Google Cloud tenant. Nei passaggi seguenti, tutti i log dello spazio dei nomi nel progetto Google Cloud del cluster vengono instradati al bucket. Consulta l'insieme riportato di seguito per i dettagli su come limitare i log condivisi.

Crea le seguenti variabili di ambiente locale:

  • Specifica lo spazio dei nomi del cluster GKE a cui accedono i tenant.
  • Il nome del sink. Per semplificare questo passaggio, il nome è una combinazione delle variabili di ambiente locale del progetto Google Cloud e del progetto Google Cloud tenant che hai creato in precedenza. Puoi modificare questo valore.
export NAMESPACE=$NAMESPACE
export SINK_NAME=$CLUSTER_PROJECT_ID-$TENANT_PROJECT_ID

Esegui questo comando per creare il bucket di log nel progetto tenant. Tieni presente che il nome del bucket di log deve essere l'ID del progetto Google Cloud del cluster e non può essere modificato o modificato.

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

Esegui questo comando per creare il sink dallo spazio dei nomi specificato nel progetto Google Cloud del cluster al bucket del progetto Google Cloud tenant. Tieni presente che puoi restringere l'ambito dei log, ad esempio per condividere solo singoli cluster GKE o risorse Knative serving specifiche definendo ulteriori valori di log-filter.

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

Esegui questi comandi per aggiungere l'autorizzazione dall'account di servizio del sink di log al bucket che hai creato.

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"

Configurazione delle autorizzazioni dei tenant con il controllo dell'accesso basato sui ruoli (RBAC, Role-Based Access Control)

In precedenza hai utilizzato Google Gruppi e IAM per configurare le autorizzazioni e consentire ai tenant di accedere al progetto Google Cloud del cluster GKE. Per consentire ai tenant di accedere alle risorse all'interno del cluster GKE, devi definire le autorizzazioni con Kubernetes RBAC.

Creazione di ruoli nei cluster

Dopo aver definito e creato i ruoli del cluster seguenti, puoi continuare a utilizzarli in futuro per aggiungere tutti i tenant successivi del progetto Google Cloud del cluster.

Ruoli UI

Questo ruolo consente ai tenant di eseguire query su tutti gli spazi dei nomi. Questa operazione è necessaria per trovare gli spazi dei nomi che gli utenti hanno accesso per creare servizi /sdk/gcloud/reference/logging/sinks/create.

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

Questo ruolo consente ai tenant di visualizzare i servizi Knative serving. Questa operazione è necessaria per elencare i servizi nella UI di Knative serving.

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

Creazione di ruoli nei cluster

È richiesta solo una di queste autorizzazioni. La prima autorizzazione consente ai tenant di manipolare qualsiasi risorsa nel loro spazio dei nomi. La seconda autorizzazione consente a un insieme più limitato di creare solo servizi Knative serving.

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

Se l'autorizzazione kubernetes-developer è troppo permissiva, quanto segue consente ai tenant di creare servizi Knative nei loro spazi dei nomi e di visualizzare le altre risorse 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

Crea lo spazio dei nomi tenant e assegna le autorizzazioni.

Tieni presente che questo presuppone che tu abbia configurato la configurazione utilizzando Google Gruppi per GKE. Questa operazione è necessaria per ogni tenant.

export TENANT_GROUP=tenant-a@company.com

TENANT_GROUP deve far parte di SECURITY_GROUP

Può visualizzare tutti gli spazi dei nomi

Per eseguire query sul cluster GKE, la maggior parte di tutti i tenant ha la possibilità di elencare gli spazi dei nomi. Al momento non esiste un'autenticazione can-i che restituisce spazi dei nomi per i quali è possibile un'azione. L'unica soluzione consiste nell'elencare gli spazi dei nomi ed eseguire una query su ogni spazio dei nomi individualmente.

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

Possibilità di elencare i servizi Knative serving

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

Possibilità di manipolare le risorse nello spazio dei nomi

Innanzitutto, crea lo spazio dei nomi:

kubectl create namespace $NAMESPACE

Se utilizzi il ruolo kubernetes-developer:

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

Se utilizzi il ruolo knative-developer:

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

Aggiungi la possibilità al tenant di accedere all'indirizzo IP esterno

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

Verifica

Per verificare di aver configurato correttamente la multitenancy aziendale, apri il progetto Google Cloud tenant in Knative serving ed esegui il deployment di un servizio in un cluster GKE.

Vai a Knative serving

Complimenti, il tenant può ora interagire con i servizi e le risorse all'interno dello spazio dei nomi del cluster GKE a cui è stato concesso l'accesso.

Riferimento multi-tenancy