Multi-tenancy tra progetti per Knative serving

Questa guida illustra la procedura di configurazione di 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 il servizio Knative è che un team di sviluppatori di applicazioni utilizzi il proprio progetto Google Cloud per eseguire il deployment e gestire i servizi in esecuzione in cluster GKE diversi nei progettiGoogle Cloud di altri team. Questa funzionalità, chiamata multi-tenancy, ti consente, in qualità di operatore della piattaforma, di personalizzare l'accesso dei team di sviluppo solo ai loro servizi in esecuzione nei vari ambienti della tua organizzazione (ad esempio, produzione e staging).

Knative serving supporta in modo specifico il multitenancy per le aziende. Questo tipo di multitenancy consente a un cluster Google Cloud project di consentire l'accesso a risorse specifiche del proprio cluster GKE. Il progetto Google Cloud a cui è stato concesso l'accesso al progetto Google Cloud è il tenant Google Cloud . I tenant del progetto Google Cloud possono utilizzare il servizio Knative per accedere, gestire e possedere i servizi e le risorse per i quali è stato concesso l'accesso.

A livello concettuale, la configurazione del multitenancy aziendale con il servizio Knative prevede quattro passaggi:

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

Prima di iniziare

L'operatore della piattaforma responsabile della configurazione del multitenancy 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 locali sia per il progetto del cluster Google Cloud sia per il progetto del tenant Google Cloud :

  1. Sostituisci YOUR_CLUSTER_PROJECT_ID con l'ID del progetto Google Cloud e poi esegui il seguente comando:

    export CLUSTER_PROJECT_ID=YOUR_CLUSTER_PROJECT_ID
    
  2. Sostituisci YOUR_TENANT_PROJECT_ID con l'ID del tenant Google Cloud e poi esegui il seguente comando:

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

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

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

Verifica delle autorizzazioni IAM

Esegui i seguenti comandi testIamPermissions per verificare di disporre delle autorizzazioni IAM necessarie per accedere alle risorse nel progetto Google Cloud e nei progetti tenant Google Cloud .

Esegui il seguente comando per convalidare le 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 del cluster Google Cloud :

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

Esegui il seguente comando per convalidare le autorizzazioni in ogni progetto Google Cloud :

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 :

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

Utilizzare un gruppo Google e Identity and Access Management per configurare l'accesso del tenant

Utilizza 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 contenente tutti gli utenti del progetto del tuo tenant Google Cloud . Per ulteriori informazioni sull'utilizzo di un gruppo di sicurezza, consulta Utilizzare 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 dei cluster Kubernetes

Esegui i seguenti comandi per consentire ai tenant di ottenere le credenziali per il cluster. I tenant non potranno leggere o manipolare le risorse sul cluster GKE.

Documentazione di 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"

Monitoring Viewer

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

Riferimento ai ruoli di monitoraggio

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

Mappatura di ogni progetto tenant Google Cloud al progetto cluster Google Cloud

Utilizzi i valori delle impostazioni delle risorse per mappare i progetti tenant Google Cloud a un progetto cluster Google Cloud .

L'impostazione della risorsa può essere configurata per ogni singolo progetto Google Cloud o puoi essere impostata a qualsiasi livello della gerarchia delle cartelle. È più facile impostarlo a livello di singola cartella del tenant, ma è più flessibile a livello di progetto di ogni tenant. Dopo la configurazione, ogni volta che gli utenti esplorano l'interfaccia utente di Knative Serving, vedranno anche i propri servizi nel progetto del cluster Google Cloud . Ciò non modifica le autorizzazioni IAM nel progetto Google Cloud o nei cluster GKE, ma si tratta solo di una mappatura da un progetto (o una cartella) del tenant a un progetto Google Cloud .

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

    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 il seguente 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 della risorsa in una cartella Google Cloud principale, se tutte le cartelle dei progetti Google Cloud e Google Cloud secondarie utilizzano lo stesso valore.

Progetti tenant

Imposta il valore dell'impostazione della risorsa per ogni progetto Google Cloud :

  1. Ottieni il name del tenant Google Cloud 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 di valori delle impostazioni delle risorse per definire la mappatura dal progetto Google Cloud al progetto Google Cloud . In questo file è possibile definire più ID progetto Google Cloud di cluster e aggiungerli a un singolo progetto Google Cloud .
    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 del tenant:
    gcloud resource-settings set-value cloudrun-multiTenancy --value-file value-file.json --project $TENANT_PROJECT_ID

Cartelle del tenant

Imposta il valore dell'impostazione della risorsa per una cartella del tenant principale per impostare quel valore su tutti i progetti e le cartelle del tenant figlio Google Cloud :

  1. Ottieni il number della cartella del tenant e impostalo su una variabile di ambiente locale:
    export TENANT_FOLDER_NUMBER=$TENANT_FOLDER_NUMBER
  2. Crea un file del valore dell'impostazione della risorsa per definire la mappatura dalla cartella del tenant al progetto Google Cloud del cluster. In questo file è possibile definire più ID progetto Google Cloud di cluster e aggiungerli a una singola cartella del 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 della risorsa nella cartella del tenant:
    gcloud resource-settings set-value cloudrun-multiTenancy --value-file value-file.json --folder $TENANT_FOLDER_NUMBER

Configurazione dei bucket e dei sink dei log per instradare i dati di log

Per ogni tenant, crei un bucket di log, un sink e le autorizzazioni per instradare i dati dei log del progetto Google Cloud al progetto Google Cloud del tenant. Nei passaggi seguenti, tutti i log del nome spazio nel progetto Google Cloud del cluster vengono inoltrati al bucket. Consulta l'insieme di seguito per informazioni dettagliate su come limitare i log condivisi.

Crea le seguenti variabili di ambiente locali:

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

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

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

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

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 i seguenti comandi per aggiungere l'autorizzazione dall'account di servizio di 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 del tenant con controllo dell'accesso basato sui ruoli (RBAC)

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

Crea ruoli cluster

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

Ruoli UI

Questo ruolo consente agli utenti di eseguire query su tutti gli spazi dei nomi. Questo è necessario per trovare gli spazi dei nomi a cui 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. Questo passaggio è necessario per elencare i servizi nell'interfaccia utente di Knative serving.

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

Crea ruoli cluster

È necessaria una sola di queste autorizzazioni. La prima autorizzazione consente ai tenant di manipolare qualsiasi risorsa nel loro spazio dei nomi. La seconda autorizzazione consente di creare un insieme più limitato di 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 propri 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 del tenant e assegna le autorizzazioni.

Tieni presente che questa operazione presuppone che tu abbia eseguito 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

Possibilità di visualizzare tutti gli spazi dei nomi

Per eseguire query sul cluster GKE, tutti i tenant devono avere la possibilità di elencare gli spazi dei nomi. Al momento non esiste un auth can-i che restituisce gli spazi dei nomi per i quali è possibile un'azione. L'unico workaround è elencare gli spazi dei nomi e poi eseguire query su ogni spazio dei nomi singolarmente.

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

Per prima cosa, 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à per il 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

Puoi verificare di aver configurato correttamente il multitenancy aziendale aprendo il progetto tenant Google Cloud in Knative Serving ed eseguendo il deployment di un servizio in un cluster GKE.

Vai a Knative serving

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

Riferimento multi-tenancy