Halaman ini menunjukkan cara memecahkan masalah akun layanan Google Kubernetes Engine (GKE).
Memberikan peran yang diperlukan untuk GKE ke akun layanan node
Akun layanan IAM yang digunakan node GKE Anda
harus memiliki semua izin yang disertakan dalam
peran IAM Kubernetes Engine Default Node Service Account
(roles/container.defaultNodeServiceAccount
). Jika akun layanan node GKE tidak memiliki satu atau beberapa izin ini, GKE tidak dapat melakukan tugas sistem seperti berikut:
- Mengirim log sistem dan aplikasi dari node ke Cloud Logging.
- Mengirim metrik sistem dan aplikasi dari node ke Cloud Monitoring.
- Operasikan profil performa Horizontal Pod Autoscaler.
Akun layanan node mungkin tidak memiliki izin tertentu yang diperlukan karena alasan seperti berikut:
- Organisasi menerapkan
batasan kebijakan organisasi
iam.automaticIamGrantsForDefaultServiceAccounts
, yang mencegah Google Cloud secara otomatis memberikan peran IAM ke akun layanan IAM default. - Peran IAM yang Anda berikan ke akun layanan node kustom tidak mencakup semua izin yang diperlukan yang disertakan dalam peran
roles/container.defaultNodeServiceAccount
.
Jika akun layanan node Anda tidak memiliki izin yang diperlukan GKE, Anda mungkin melihat error dan pemberitahuan seperti berikut:
- Di Google Cloud konsol, di halaman Kubernetes clusters, pesan error Grant critical permissions akan muncul di kolom Notifications untuk cluster tertentu.
Di konsol Google Cloud , pada halaman detail cluster untuk cluster tertentu, pesan error berikut akan muncul:
Grant roles/container.defaultNodeServiceAccount role to Node service account to allow for non-degraded operations.
Di Cloud Audit Logs, log Aktivitas Admin untuk Google Cloud API seperti
monitoring.googleapis.com
memiliki nilai berikut jika izin yang sesuai untuk mengakses API tersebut tidak ada di akun layanan node:- Tingkat keseriusan:
ERROR
- Pesan:
Permission denied (or the resource may not exist)
- Tingkat keseriusan:
Log untuk node tertentu tidak ada di Cloud Logging dan log Pod untuk agen logging di node tersebut menampilkan error
401
. Untuk mendapatkan log Pod ini, jalankan perintah berikut:[[ $(kubectl logs -l k8s-app=fluentbit-gke -n kube-system -c fluentbit-gke | grep -cw "Received 401") -gt 0 ]] && echo "true" || echo "false"
Jika outputnya adalah
true
, berarti beban kerja sistem mengalami error401
, yang menunjukkan kurangnya izin.
Untuk mengatasi masalah ini, berikan peran Akun Layanan Node Default Kubernetes Engine (roles/container.defaultNodeServiceAccount
) di project ke akun layanan yang menyebabkan error. Pilih salah satu opsi berikut:
console
Untuk menemukan nama akun layanan yang digunakan node Anda, lakukan hal berikut:
Buka halaman Cluster Kubernetes:
Dalam daftar cluster, klik nama cluster yang ingin diperiksa.
Temukan nama akun layanan node. Anda akan memerlukan nama ini nanti.
- Untuk cluster mode Autopilot, di bagian Security, temukan kolom Service account.
- Untuk cluster mode Standard, lakukan hal berikut:
- Klik tab Nodes.
- Di tabel Node pool, klik nama node pool. Halaman Detail node pool akan terbuka.
- Di bagian Keamanan, temukan kolom Service account.
Jika nilai di kolom Service account adalah
default
, node Anda akan menggunakan akun layanan default Compute Engine. Jika nilai di kolom ini bukandefault
, node Anda menggunakan akun layanan kustom.
Untuk memberikan peran Kubernetes Engine Default Node Service Account
ke akun layanan, lakukan hal berikut:
Buka halaman Sambutan:
Di kolom Project number, klik
Copy to clipboard.Buka halaman IAM:
Klik
Berikan akses.Di kolom New principals, tentukan nama akun layanan node Anda. Jika node Anda menggunakan akun layanan Compute Engine default, tentukan nilai berikut:
PROJECT_NUMBER-compute@developer.gserviceaccount.com
Ganti
PROJECT_NUMBER
dengan nomor project yang Anda salin.Di menu Select a role, pilih peran Kubernetes Engine Default Node Service Account.
Klik Simpan.
Untuk memverifikasi bahwa peran telah diberikan, lakukan hal berikut:
- Di halaman IAM, klik tab Lihat menurut peran.
- Luaskan bagian Kubernetes Engine Default Node Service Account. Daftar akun utama yang memiliki peran ini akan ditampilkan.
- Temukan akun layanan node Anda dalam daftar akun utama.
gcloud
Temukan nama akun layanan yang digunakan node Anda:
- Untuk cluster mode Autopilot, jalankan perintah berikut:
gcloud container clusters describe CLUSTER_NAME \ --location=LOCATION \ --flatten=autoscaling.autoprovisioningNodePoolDefaults.serviceAccount
- Untuk cluster mode Standar, jalankan perintah berikut:
gcloud container clusters describe CLUSTER_NAME \ --location=LOCATION \ --format="table(nodePools.name,nodePools.config.serviceAccount)"
Jika outputnya adalah
default
, node Anda akan menggunakan akun layanan default Compute Engine. Jika outputnya bukandefault
, node Anda menggunakan akun layanan kustom.Temukan Google Cloud nomor project Anda:
gcloud projects describe PROJECT_ID \ --format="value(projectNumber)"
Ganti
PROJECT_ID
dengan project ID Anda.Outputnya mirip dengan hal berikut ini:
12345678901
Berikan peran
roles/container.defaultNodeServiceAccount
ke akun layanan:gcloud projects add-iam-policy-binding PROJECT_ID \ --member="SERVICE_ACCOUNT_NAME" \ --role="roles/container.defaultNodeServiceAccount"
Ganti
SERVICE_ACCOUNT_NAME
dengan nama akun layanan yang Anda temukan di langkah sebelumnya. Jika node Anda menggunakan akun layanan default Compute Engine, tentukan nilai berikut:serviceAccount:PROJECT_NUMBER-compute@developer.gserviceaccount.com
Ganti
PROJECT_NUMBER
dengan nomor project dari langkah sebelumnya.Pastikan bahwa peran berhasil diberikan:
gcloud projects get-iam-policy PROJECT_ID \ --flatten="bindings[].members" --filter=bindings.role:roles/container.defaultNodeServiceAccount \ --format='value(bindings.members)'
Output-nya adalah nama akun layanan Anda.
Mengidentifikasi akun layanan node yang tidak memiliki izin yang diperlukan
Bagian berikut menjelaskan cara mengidentifikasi akun layanan node yang tidak memiliki izin yang diperlukan untuk GKE.
Mengidentifikasi cluster yang memiliki akun layanan node dengan izin yang tidak ada
Gunakan rekomendasi GKE dari subjenis rekomendasi NODE_SA_MISSING_PERMISSIONS
untuk
mengidentifikasi cluster Autopilot dan Standard yang memiliki akun layanan node
tanpa izin. Pemberi Rekomendasi hanya mengidentifikasi
cluster yang dibuat pada atau setelah 1 Januari 2024. Untuk menemukan dan memperbaiki
izin yang tidak ada menggunakan Rekomendasi, lakukan hal berikut:
Temukan rekomendasi aktif dalam project Anda untuk subjenis perekomendasikan
NODE_SA_MISSING_PERMISSIONS
:gcloud recommender recommendations list \ --recommender=google.container.DiagnosisRecommender \ --location LOCATION \ --project PROJECT_ID \ --format yaml \ --filter="recommenderSubtype:NODE_SA_MISSING_PERMISSIONS"
Ganti kode berikut:
LOCATION
: lokasi untuk menemukan rekomendasi.PROJECT_ID
: Google Cloud Project ID Anda.
Output-nya mirip dengan berikut ini, yang menunjukkan bahwa cluster memiliki akun layanan node dengan izin yang tidak ada:
associatedInsights: # lines omitted for clarity recommenderSubtype: NODE_SA_MISSING_PERMISSIONS stateInfo: state: ACTIVE targetResources: - //container.googleapis.com/projects/12345678901/locations/us-central1/clusters/cluster-1
Mungkin diperlukan waktu hingga 24 jam agar rekomendasi muncul. Untuk petunjuk mendetail, lihat melihat insight dan rekomendasi.
Untuk setiap cluster yang ada dalam output langkah sebelumnya, temukan akun layanan node terkait dan berikan peran yang diperlukan ke akun layanan tersebut. Untuk mengetahui detailnya, lihat petunjuk di bagian Memberikan peran yang diperlukan untuk GKE ke akun layanan node.
Setelah Anda memberikan peran yang diperlukan ke akun layanan node yang diidentifikasi, rekomendasi tersebut mungkin tetap ada hingga 24 jam, kecuali jika Anda menutupnya secara manual.
Mengidentifikasi semua akun layanan node yang tidak memiliki izin
Anda dapat menjalankan skrip yang menelusuri node pool di cluster Standard dan Autopilot project untuk menemukan akun layanan node yang tidak memiliki izin yang diperlukan untuk GKE. Skrip ini menggunakan gcloud CLI dan utilitas jq
. Untuk melihat skrip, luaskan bagian berikut:
Melihat skrip
#!/bin/bash
# Set your project ID
project_id=PROJECT_ID
project_number=$(gcloud projects describe "$project_id" --format="value(projectNumber)")
declare -a all_service_accounts
declare -a sa_missing_permissions
# Function to check if a service account has a specific permission
# $1: project_id
# $2: service_account
# $3: permission
service_account_has_permission() {
local project_id="$1"
local service_account="$2"
local permission="$3"
local roles=$(gcloud projects get-iam-policy "$project_id" \
--flatten="bindings[].members" \
--format="table[no-heading](bindings.role)" \
--filter="bindings.members:\"$service_account\"")
for role in $roles; do
if role_has_permission "$role" "$permission"; then
echo "Yes" # Has permission
return
fi
done
echo "No" # Does not have permission
}
# Function to check if a role has the specific permission
# $1: role
# $2: permission
role_has_permission() {
local role="$1"
local permission="$2"
gcloud iam roles describe "$role" --format="json" | \
jq -r ".includedPermissions" | \
grep -q "$permission"
}
# Function to add $1 into the service account array all_service_accounts
# $1: service account
add_service_account() {
local service_account="$1"
all_service_accounts+=( ${service_account} )
}
# Function to add service accounts into the global array all_service_accounts for a Standard GKE cluster
# $1: project_id
# $2: location
# $3: cluster_name
add_service_accounts_for_standard() {
local project_id="$1"
local cluster_location="$2"
local cluster_name="$3"
while read nodepool; do
nodepool_name=$(echo "$nodepool" | awk '{print $1}')
if [[ "$nodepool_name" == "" ]]; then
# skip the empty line which is from running `gcloud container node-pools list` in GCP console
continue
fi
while read nodepool_details; do
service_account=$(echo "$nodepool_details" | awk '{print $1}')
if [[ "$service_account" == "default" ]]; then
service_account="${project_number}-compute@developer.gserviceaccount.com"
fi
if [[ -n "$service_account" ]]; then
printf "%-60s| %-40s| %-40s| %-10s| %-20s\n" $service_account $project_id $cluster_name $cluster_location $nodepool_name
add_service_account "${service_account}"
else
echo "cannot find service account for node pool $project_id\t$cluster_name\t$cluster_location\t$nodepool_details"
fi
done <<< "$(gcloud container node-pools describe "$nodepool_name" --cluster "$cluster_name" --zone "$cluster_location" --project "$project_id" --format="table[no-heading](config.serviceAccount)")"
done <<< "$(gcloud container node-pools list --cluster "$cluster_name" --zone "$cluster_location" --project "$project_id" --format="table[no-heading](name)")"
}
# Function to add service accounts into the global array all_service_accounts for an Autopilot GKE cluster
# Autopilot cluster only has one node service account.
# $1: project_id
# $2: location
# $3: cluster_name
add_service_account_for_autopilot(){
local project_id="$1"
local cluster_location="$2"
local cluster_name="$3"
while read service_account; do
if [[ "$service_account" == "default" ]]; then
service_account="${project_number}-compute@developer.gserviceaccount.com"
fi
if [[ -n "$service_account" ]]; then
printf "%-60s| %-40s| %-40s| %-10s| %-20s\n" $service_account $project_id $cluster_name $cluster_location $nodepool_name
add_service_account "${service_account}"
else
echo "cannot find service account" for cluster "$project_id\t$cluster_name\t$cluster_location\t"
fi
done <<< "$(gcloud container clusters describe "$cluster_name" --location "$cluster_location" --project "$project_id" --format="table[no-heading](autoscaling.autoprovisioningNodePoolDefaults.serviceAccount)")"
}
# Function to check whether the cluster is an Autopilot cluster or not
# $1: project_id
# $2: location
# $3: cluster_name
is_autopilot_cluster() {
local project_id="$1"
local cluster_location="$2"
local cluster_name="$3"
autopilot=$(gcloud container clusters describe "$cluster_name" --location "$cluster_location" --format="table[no-heading](autopilot.enabled)")
echo "$autopilot"
}
echo "--- 1. List all service accounts in all GKE node pools"
printf "%-60s| %-40s| %-40s| %-10s| %-20s\n" "service_account" "project_id" "cluster_name" "cluster_location" "nodepool_name"
while read cluster; do
cluster_name=$(echo "$cluster" | awk '{print $1}')
cluster_location=$(echo "$cluster" | awk '{print $2}')
# how to find a cluster is a Standard cluster or an Autopilot cluster
autopilot=$(is_autopilot_cluster "$project_id" "$cluster_location" "$cluster_name")
if [[ "$autopilot" == "True" ]]; then
add_service_account_for_autopilot "$project_id" "$cluster_location" "$cluster_name"
else
add_service_accounts_for_standard "$project_id" "$cluster_location" "$cluster_name"
fi
done <<< "$(gcloud container clusters list --project "$project_id" --format="value(name,location)")"
echo "--- 2. Check if service accounts have permissions"
unique_service_accounts=($(echo "${all_service_accounts[@]}" | tr ' ' '\n' | sort -u | tr '\n' ' '))
echo "Service accounts: ${unique_service_accounts[@]}"
printf "%-60s| %-40s| %-40s| %-20s\n" "service_account" "has_logging_permission" "has_monitoring_permission" "has_performance_hpa_metric_write_permission"
for sa in "${unique_service_accounts[@]}"; do
logging_permission=$(service_account_has_permission "$project_id" "$sa" "logging.logEntries.create")
time_series_create_permission=$(service_account_has_permission "$project_id" "$sa" "monitoring.timeSeries.create")
metric_descriptors_create_permission=$(service_account_has_permission "$project_id" "$sa" "monitoring.metricDescriptors.create")
if [[ "$time_series_create_permission" == "No" || "$metric_descriptors_create_permission" == "No" ]]; then
monitoring_permission="No"
else
monitoring_permission="Yes"
fi
performance_hpa_metric_write_permission=$(service_account_has_permission "$project_id" "$sa" "autoscaling.sites.writeMetrics")
printf "%-60s| %-40s| %-40s| %-20s\n" $sa $logging_permission $monitoring_permission $performance_hpa_metric_write_permission
if [[ "$logging_permission" == "No" || "$monitoring_permission" == "No" || "$performance_hpa_metric_write_permission" == "No" ]]; then
sa_missing_permissions+=( ${sa} )
fi
done
echo "--- 3. List all service accounts that don't have the above permissions"
if [[ "${#sa_missing_permissions[@]}" -gt 0 ]]; then
printf "Grant roles/container.defaultNodeServiceAccount to the following service accounts: %s\n" "${sa_missing_permissions[@]}"
else
echo "All service accounts have the above permissions"
fi
Skrip ini berlaku untuk semua cluster GKE dalam project Anda.
Setelah Anda mengidentifikasi nama akun layanan yang tidak memiliki izin, berikan peran yang diperlukan. Untuk mengetahui detailnya, lihat petunjuk di bagian Memberikan peran yang diperlukan untuk GKE ke akun layanan node.
Memulihkan akun layanan default ke project Google Cloud Anda
Akun layanan default GKE, container-engine-robot
, dapat
tidak terikat dari project secara tidak sengaja. Peran Agen Layanan Kubernetes Engine (roles/container.serviceAgent
) adalah peran Identity and Access Management (IAM) yang memberikan izin kepada akun layanan untuk mengelola resource cluster. Jika Anda menghapus binding peran ini dari akun layanan, akun layanan default akan terlepas dari project, sehingga Anda tidak dapat men-deploy aplikasi dan melakukan operasi cluster lainnya.
Untuk melihat apakah akun layanan dihapus dari project Anda, Anda dapat menggunakan konsol Google Cloud atau Google Cloud CLI.
Konsol
Di konsol Google Cloud , buka halaman IAM & Admin.
gcloud
Jalankan perintah berikut:
gcloud projects get-iam-policy PROJECT_ID
Ganti
PROJECT_ID
dengan project ID Anda.
Jika dasbor atau perintah tidak menampilkan container-engine-robot
di antara akun layanan Anda, peran tidak terikat.
Untuk memulihkan binding peran Agen Layanan Kubernetes Engine
(roles/container.serviceAgent
), jalankan perintah berikut:
PROJECT_NUMBER=$(gcloud projects describe "PROJECT_ID" \
--format 'get(projectNumber)') \
gcloud projects add-iam-policy-binding PROJECT_ID \
--member "serviceAccount:service-${PROJECT_NUMBER?}@container-engine-robot.iam.gserviceaccount.com" \
--role roles/container.serviceAgent
Pastikan bahwa penetapan peran dipulihkan:
gcloud projects get-iam-policy $PROJECT_ID
Jika Anda melihat nama akun layanan beserta peran container.serviceAgent
, artinya binding peran telah dipulihkan. Contoh:
- members:
- serviceAccount:service-1234567890@container-engine-robot.iam.gserviceaccount.com
role: roles/container.serviceAgent
Mengaktifkan akun layanan default Compute Engine
Akun layanan yang digunakan untuk node pool biasanya adalah akun layanan default Compute Engine. Jika akun layanan default ini dinonaktifkan, node Anda mungkin gagal didaftarkan ke cluster.
Untuk melihat apakah akun layanan dinonaktifkan di project Anda, Anda dapat menggunakanGoogle Cloud console atau gcloud CLI.
Konsol
Di konsol Google Cloud , buka halaman IAM & Admin.
gcloud
- Jalankan perintah berikut:
gcloud iam service-accounts list --filter="NAME~'compute' AND disabled=true"
Jika akun layanan dinonaktifkan, jalankan perintah berikut untuk mengaktifkan akun layanan:
gcloud iam service-accounts enable PROJECT_ID-compute@developer.gserviceaccount.com
Ganti PROJECT_ID
dengan project ID Anda.
Untuk mengetahui informasi selengkapnya, lihat Memecahkan masalah pendaftaran node.
Error 400/403: Izin edit untuk akun tidak ada
Jika akun layanan dihapus, Anda mungkin melihat error izin edit yang hilang. Untuk mempelajari cara memecahkan masalah error ini, lihat Error 400/403: Izin edit untuk akun tidak ada.
Langkah berikutnya
Jika Anda tidak dapat menemukan solusi untuk masalah Anda dalam dokumentasi, lihat Mendapatkan dukungan untuk mendapatkan bantuan lebih lanjut, termasuk saran tentang topik berikut:
- Membuka kasus dukungan dengan menghubungi Layanan Pelanggan Cloud.
- Mendapatkan dukungan dari komunitas dengan mengajukan pertanyaan di
StackOverflow
dan menggunakan tag
google-kubernetes-engine
untuk menelusuri masalah yang serupa. Anda juga dapat bergabung ke#kubernetes-engine
channel Slack untuk mendapatkan dukungan komunitas lebih lanjut. - Membuka bug atau permintaan fitur menggunakan issue tracker publik.