Halaman ini menunjukkan cara memecahkan masalah terkait akun layanan Google Kubernetes Engine (GKE).
Memberikan peran yang diperlukan untuk GKE ke akun layanan node
Akun layanan IAM yang digunakan oleh 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 menjalankan tugas sistem seperti berikut:
- Mengirim log sistem dan aplikasi dari node ke Cloud Logging.
- Mengirim metrik sistem dan aplikasi dari node ke Cloud Monitoring.
- Mengoperasikan 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 Trusted Cloud memberikan peran IAM secara otomatis kepada 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 akan melihat error dan pemberitahuan seperti berikut:
- Di konsol Trusted Cloud , pada halaman Kubernetes clusters, pesan error Grant critical permissions muncul di kolom Notifications untuk cluster tertentu.
Di konsol Trusted 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 API seperti Trusted Cloud
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
, maka 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 kepada 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:
Di daftar cluster, klik nama cluster yang ingin Anda periksa.
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 Node pool details akan terbuka.
- Di bagian Security, 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 Selamat Datang:
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.s3ns-system.iam.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.
- Perluas 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 Standard, jalankan perintah berikut:
gcloud container clusters describe CLUSTER_NAME \ --location=LOCATION \ --format="table(nodePools.name,nodePools.config.serviceAccount)"
Jika outputnya adalah
default
, node Anda menggunakan akun layanan default Compute Engine. Jika outputnya bukandefault
, node Anda menggunakan akun layanan kustom.Temukan nomor project Trusted Cloud 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.s3ns-system.iam.gserviceaccount.com
Ganti
PROJECT_NUMBER
dengan nomor project dari langkah sebelumnya.Verifikasi bahwa peran berhasil diberikan:
gcloud projects get-iam-policy PROJECT_ID \ --flatten="bindings[].members" --filter=bindings.role:roles/container.defaultNodeServiceAccount \ --format='value(bindings.members)'
Outputnya adalah nama akun layanan Anda.
Mengidentifikasi cluster yang memiliki akun layanan node dengan izin yang tidak ada
Gunakan rekomendasi GKE dari NODE_SA_MISSING_PERMISSIONS
subjenis pemberi rekomendasi untuk
mengidentifikasi cluster Autopilot dan Standard yang memiliki akun layanan
node dengan izin yang tidak ada. Pemberi Rekomendasi hanya mengidentifikasi cluster yang dibuat pada atau setelah 1 Januari 2024. Untuk menemukan dan memperbaiki izin yang tidak ada menggunakan Recommender, lakukan hal berikut:
Temukan rekomendasi aktif di project Anda untuk subjenis pemberi rekomendasi
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
: ID project Trusted Cloud Anda.
Outputnya 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 mendapatkan petunjuk mendetail, lihat artikel 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 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 mungkin tetap ada hingga 24 jam kecuali jika Anda menutupnya secara manual.
Mengidentifikasi semua akun layanan node dengan izin yang tidak ada
Anda dapat menjalankan skrip yang menelusuri node pool di cluster Standard
dan Autopilot project Anda 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.s3ns-system.iam.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.s3ns-system.iam.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 kepada akun layanan tersebut. Untuk mengetahui detailnya, lihat petunjuk di bagian Memberikan peran yang diperlukan untuk GKE kepada akun layanan node.
Memulihkan akun layanan default ke Trusted Cloud project Anda
Akun layanan default GKE, container-engine-robot
, dapat
secara tidak sengaja menjadi tidak terikat dari project. Peran Agen Layanan Kubernetes Engine
(roles/container.serviceAgent
) adalah peran Identity and Access Management (IAM)
yang memberi akun layanan izin 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 Trusted Cloud atau Google Cloud CLI.
Konsol
Di konsol Trusted 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 tersebut 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.s3ns-system.iam.gserviceaccount.com" \
--role roles/container.serviceAgent
Konfirmasi bahwa pengikatan peran telah 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.s3ns-system.iam.gserviceaccount.com
role: roles/container.serviceAgent
Aktifkan 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 menggunakan konsolTrusted Cloud atau gcloud CLI.
Konsol
Di konsol Trusted 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:
Temukan nomor project Trusted Cloud Anda:
gcloud projects describe PROJECT_ID \ --format="value(projectNumber)"
Ganti
PROJECT_ID
dengan project ID Anda.Outputnya mirip dengan hal berikut ini:
12345678901
Aktifkan akun layanan:
gcloud iam service-accounts enable PROJECT_NUMBER-compute@developer.s3ns-system.iam.gserviceaccount.com
Ganti
PROJECT_NUMBER
dengan nomor project Anda dari output langkah sebelumnya.
Untuk mengetahui informasi selengkapnya, lihat Memecahkan masalah pendaftaran node.
Error 400/403: Izin edit untuk akun tidak ada
Jika akun layanan Anda dihapus, Anda mungkin melihat kesalahan izin edit tidak ada. 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 serupa. Anda juga dapat bergabung ke#kubernetes-engine
channel Slack untuk mendapatkan dukungan komunitas lainnya. - Membuka bug atau permintaan fitur menggunakan issue tracker publik.