Flushing Akun Master
Panduan ini dipakai pemegang satu akun master untuk membersihkan ketiga project kelompoknya setelah satu batch selesai, lalu membuktikan bahwa tidak ada lagi biaya yang tertagih.
Bacaan ini untuk instruktur dan asisten instruktur. Empat pemegang akun master menjalankan prosedur yang sama pada akunnya masing-masing; tidak ada prosedur terpisah per akun, supaya satu perbaikan perintah tidak berhenti di satu berkas.
Hasil akhir yang dituju bukan “tidak ada resource”, melainkan tidak ada biaya. Dua hal berbeda, dan selisihnya justru yang paling sering menagih: alamat IP statis yang tidak dipakai dan disk yang tertinggal setelah VM-nya hilang.
1. Yang dibersihkan dan yang tidak
Section titled “1. Yang dibersihkan dan yang tidak”Satu akun master mengelola tiga project. Flushing dijalankan per batch, bukan setelah semua batch selesai.
| Dibersihkan setelah batch | Dipertahankan antar batch |
|---|---|
| Mesin virtual (VM) | Project dan tautan Billing Account |
| Disk, snapshot, dan custom image | API yang sudah diaktifkan |
| Alamat IP statis | Firewall allow-webgis-http dan allow-webgis-iap-ssh |
Image di Artifact Registry dan registry lama gcr.io |
Artifact Registry katalog-images |
| Bucket Cloud Storage | Service Account default Compute Engine |
| Trigger dan GitHub connection Cloud Build | Budget alert |
| Service Account deployment peserta | Label batch dan billing-code |
| Uptime check, alert policy, notification channel | |
| IAM binding sembilan role peserta |
Yang di kolom kanan tidak boleh dihapus. Peserta batch berikutnya mengandalkan keempatnya sudah ada; menghapus Artifact Registry berarti peserta berikutnya harus membuatnya ulang, dan itu bertentangan dengan panduan yang mereka pegang.
Bila seluruh batch sudah selesai dan akun master tidak akan dipakai lagi, jalur kedua ada pada bagian 10.
2. Kenapa per batch, bukan setelah semua batch
Section titled “2. Kenapa per batch, bukan setelah semua batch”Alasan utamanya bukan kerapian.
Kuota alamat IPv4 publik berbatas empat per project per region, jadi project yang masih menahan VM batch pertama tidak punya slot untuk batch kedua. Batas itu dijelaskan pada panduan batch peserta bagian 6.2.
Alamat IP statis ditagih saat menganggur. Alamat yang sudah di-reserve tetapi tidak terpasang ke instance apa pun tetap masuk tagihan. Ini biaya yang paling sering bertahan setelah seseorang mengira pekerjaannya selesai.
Disk tetap ditagih walaupun VM di-stop. Yang berhenti hanya biaya compute. Stop bukan delete.
3. Siapa yang menjalankan
Section titled “3. Siapa yang menjalankan”| Peran | Tugas |
|---|---|
| Pemegang akun master | Menjalankan seluruh prosedur pada akunnya sendiri |
| Koordinator | Mengumpulkan bukti biaya nol dari keempat akun |
| Peserta | Tidak mengerjakan apa pun di sini |
Peserta tidak menjalankan langkah apa pun pada dokumen ini. Semua resource peserta dihapus oleh pemegang akun master.
4. Urutan kerja
Section titled “4. Urutan kerja”Duabelas langkah, dengan empat tanda aman untuk lanjut. Jangan melompati tanda.
Langkah 1: Kunci variabel dan identitas
Section titled “Langkah 1: Kunci variabel dan identitas”REGION="asia-southeast2"ZONE="asia-southeast2-b"BATCH="batch-1"
PROJECT_IDS=( "geoportal-kelompok-a-xxxxx" "geoportal-kelompok-b-xxxxx" "geoportal-kelompok-c-xxxxx")
gcloud auth listecho "Akun di atas harus akun master untuk akun ini. Kalau bukan, hentikan sekarang."Langkah 2: Inventaris sebelum menghapus
Section titled “Langkah 2: Inventaris sebelum menghapus”Jangan menghapus sebelum daftarnya dilihat. Perintah ini tidak mengubah apa pun.
for PROJECT_ID in "${PROJECT_IDS[@]}"; do echo "================ $PROJECT_ID"
echo "-- VM" gcloud compute instances list --project="$PROJECT_ID"
echo "-- disk" gcloud compute disks list --project="$PROJECT_ID"
echo "-- snapshot" gcloud compute snapshots list --project="$PROJECT_ID"
echo "-- custom image" gcloud compute images list --project="$PROJECT_ID" --no-standard-images
echo "-- alamat IP" gcloud compute addresses list --project="$PROJECT_ID"
echo "-- Artifact Registry" gcloud artifacts repositories list --project="$PROJECT_ID" --location="$REGION"
echo "-- bucket" gcloud storage buckets list --project="$PROJECT_ID"
echo "-- trigger dan connection" gcloud builds triggers list --project="$PROJECT_ID" --region="$REGION" gcloud builds connections list --project="$PROJECT_ID" --region="$REGION"
echo "-- Service Account" gcloud iam service-accounts list --project="$PROJECT_ID"
echo "-- Secret Manager" gcloud secrets list --project="$PROJECT_ID"
echo "-- uptime check dan alert" gcloud monitoring uptime list-configs --project="$PROJECT_ID" gcloud alpha monitoring policies list --project="$PROJECT_ID" --format="value(displayName)" gcloud alpha monitoring channels list --project="$PROJECT_ID" --format="value(displayName)"doneCatat setiap nama yang muncul. Dua hal yang harus diperhatikan pada keluaran ini:
- VM yang masih menyala tetap menagih biaya selama proses pembongkaran berjalan.
- Alamat IP berstatus
RESERVEDdengan kolomuserskosong adalah biaya menganggur. Ini yang paling sering tertinggal.
Aman untuk lanjut bila daftar sudah tercatat dan kamu sudah tahu resource mana milik batch yang sedang dibongkar.
Langkah 3: Stop seluruh VM
Section titled “Langkah 3: Stop seluruh VM”Langkah ini menghentikan biaya terbesar lebih dahulu, sehingga sisa proses bisa dikerjakan tanpa terburu-buru.
for PROJECT_ID in "${PROJECT_IDS[@]}"; do gcloud compute instances list \ --project="$PROJECT_ID" \ --format="value(name,zone)" | while IFS=$'\t' read -r NAME VM_ZONE; do echo "Stop $NAME di $VM_ZONE ($PROJECT_ID)" gcloud compute instances stop "$NAME" \ --zone="$VM_ZONE" \ --project="$PROJECT_ID" \ --quiet donedonePerintah ini mengambil zone dari keluaran instances list, bukan dari variabel $ZONE. Alasannya
praktis: satu project boleh berisi VM di region berbeda, dan zone yang salah akan menghasilkan
not found yang mudah disalahartikan sebagai “VM-nya sudah tidak ada”.
Aman untuk lanjut bila
gcloud compute instances listuntuk ketiga project hanya menampilkan statusTERMINATED, atau tidak menampilkan apa pun.
Langkah 4: Hapus VM beserta disk-nya
Section titled “Langkah 4: Hapus VM beserta disk-nya”Urutannya mengikat: VM harus hilang sebelum disknya, karena disk tidak dapat dihapus saat masih terpasang.
for PROJECT_ID in "${PROJECT_IDS[@]}"; do gcloud compute instances list \ --project="$PROJECT_ID" \ --format="value(name,zone)" | while IFS=$'\t' read -r NAME VM_ZONE; do echo "Hapus $NAME di $VM_ZONE ($PROJECT_ID)" gcloud compute instances delete "$NAME" \ --zone="$VM_ZONE" \ --delete-disks=all \ --project="$PROJECT_ID" \ --quiet donedone--delete-disks=all menghapus boot disk sekaligus. Tanpa flag itu, disknya tertinggal dan tetap
ditagih.
Langkah 5: Hapus alamat IP statis
Section titled “Langkah 5: Hapus alamat IP statis”for PROJECT_ID in "${PROJECT_IDS[@]}"; do gcloud compute addresses list \ --project="$PROJECT_ID" \ --format="value(name,region)" | while IFS=$'\t' read -r NAME ADDRESS_REGION; do echo "Hapus alamat $NAME di $ADDRESS_REGION ($PROJECT_ID)" gcloud compute addresses delete "$NAME" \ --region="$ADDRESS_REGION" \ --project="$PROJECT_ID" \ --quiet donedoneLangkah 6: Hapus disk, snapshot, dan image yang tertinggal
Section titled “Langkah 6: Hapus disk, snapshot, dan image yang tertinggal”for PROJECT_ID in "${PROJECT_IDS[@]}"; do gcloud compute disks list \ --project="$PROJECT_ID" \ --format="value(name,zone)" | while IFS=$'\t' read -r NAME DISK_ZONE; do echo "Hapus disk $NAME di $DISK_ZONE ($PROJECT_ID)" gcloud compute disks delete "$NAME" \ --zone="$DISK_ZONE" --project="$PROJECT_ID" --quiet done
gcloud compute snapshots list \ --project="$PROJECT_ID" \ --format="value(name)" | while read -r SNAPSHOT; do echo "Hapus snapshot $SNAPSHOT ($PROJECT_ID)" gcloud compute snapshots delete "$SNAPSHOT" \ --project="$PROJECT_ID" --quiet done
gcloud compute images list \ --project="$PROJECT_ID" --no-standard-images \ --format="value(name)" | while read -r IMAGE; do echo "Hapus image $IMAGE ($PROJECT_ID)" gcloud compute images delete "$IMAGE" \ --project="$PROJECT_ID" --quiet donedoneAman untuk lanjut bila tidak ada satu pun disk, snapshot, atau custom image yang masih terpasang pada VM yang hidup. Langkah 7 sampai 11 belum menyentuh compute, jadi daftar
instancesdanaddressessudah menjadi bukti bahwa resource berbayar terbesar sudah lepas. Pemeriksaan kosong yang menyeluruh dilakukan sekali di langkah 12, setelah kesebelas langkah sebelumnya selesai.
Langkah 7: Bersihkan artifact
Section titled “Langkah 7: Bersihkan artifact”Artifact Registry ditagih per GB-bulan, dan image Next.js beserta seluruh tag lamanya bisa menumpuk jauh melebihi 0,5 GB jatah gratis.
Yang dibersihkan hanya isinya, bukan repository-nya.
for PROJECT_ID in "${PROJECT_IDS[@]}"; do REPO="${REGION}-docker.pkg.dev/${PROJECT_ID}/katalog-images" echo "== $PROJECT_ID"
# Daftar lebih dahulu, supaya jumlahnya terlihat sebelum dihapus. gcloud artifacts docker images list "$REPO" \ --include-tags \ --format="table(image,digest,tags)"
# Satu paket mewakili satu image beserta seluruh tag dan digest-nya. gcloud artifacts packages list \ --repository=katalog-images \ --location="$REGION" \ --project="$PROJECT_ID" \ --format="value(name)" | while read -r PAKET; do echo "Hapus paket $PAKET" gcloud artifacts packages delete "$PAKET" \ --repository=katalog-images \ --location="$REGION" \ --project="$PROJECT_ID" \ --quiet donedoneMenghapus paket lebih ringkas daripada menghapus image satu per satu. Satu paket memuat seluruh tag dan digest di dalamnya, sehingga tidak ada tag lama yang tertinggal untuk ditagih.
Registry lama gcr.io menyimpan image di bucket Cloud Storage, bukan di Artifact Registry.
Kalau project ini pernah memakainya, isinya tidak akan terlihat pada perintah di atas:
for PROJECT_ID in "${PROJECT_IDS[@]}"; do gcloud storage ls --project="$PROJECT_ID" "gs://artifacts.${PROJECT_ID}.appspot.com/**" 2>/dev/null \ && echo "Bucket gcr.io masih berisi objek di $PROJECT_ID" \ || echo "Tidak ada bucket gcr.io di $PROJECT_ID"doneLangkah 8: Hapus bucket Cloud Storage
Section titled “Langkah 8: Hapus bucket Cloud Storage”Cloud Build dapat menulis log atau artifact ke bucket. Periksa, lalu hapus isinya, bukan bucketnya, karena beberapa bucket dibuat otomatis oleh layanan GCP dan akan dibuat ulang.
for PROJECT_ID in "${PROJECT_IDS[@]}"; do echo "== $PROJECT_ID" gcloud storage buckets list --project="$PROJECT_ID" \ --format="table(name,location,storageClass)"doneHapus hanya bucket yang isinya berkas batch ini:
PROJECT_ID="geoportal-kelompok-a-xxxxx"BUCKET="gs://nama-bucket-yang-dikonfirmasi"
gcloud storage ls "$BUCKET/**"gcloud storage rm --recursive "$BUCKET/**"Langkah 9: Bersihkan Cloud Build
Section titled “Langkah 9: Bersihkan Cloud Build”Trigger dihapus lebih dahulu daripada connection. Connection yang masih dipakai trigger akan menolak dihapus.
for PROJECT_ID in "${PROJECT_IDS[@]}"; do echo "== $PROJECT_ID"
gcloud builds triggers list \ --project="$PROJECT_ID" --region="$REGION" --format="value(name)" | while read -r TRIGGER; do gcloud builds triggers delete "$TRIGGER" \ --project="$PROJECT_ID" --region="$REGION" --quiet done
gcloud builds connections list \ --project="$PROJECT_ID" --region="$REGION" --format="value(name)" | while read -r CONNECTION; do gcloud builds connections delete "$CONNECTION" \ --project="$PROJECT_ID" --region="$REGION" --quiet donedoneLangkah 10: Hapus Service Account deployment
Section titled “Langkah 10: Hapus Service Account deployment”Service Account default Compute Engine jangan dihapus. Ia dibuat otomatis dan dipakai ulang oleh batch berikutnya.
for PROJECT_ID in "${PROJECT_IDS[@]}"; do echo "== $PROJECT_ID" gcloud iam service-accounts list \ --project="$PROJECT_ID" \ --format="value(email)"doneHapus setiap Service Account yang berawalan cb-deployer- milik batch ini:
PROJECT_ID="geoportal-kelompok-a-xxxxx"
gcloud iam service-accounts list \ --project="$PROJECT_ID" \ --filter="email:cb-deployer-" \ --format="value(email)" |while read -r SA; do gcloud iam service-accounts delete "$SA" \ --project="$PROJECT_ID" --quietdoneAman untuk lanjut bila Service Account yang tersisa hanya milik bawaan layanan GCP:
*-asisten01@example.com,service-*@gcp-sa-*.iam.gserviceaccount.com, danservice-*@cloudbuild.gserviceaccount.com.
Langkah 11: Bersihkan pemantauan dan cabut IAM peserta
Section titled “Langkah 11: Bersihkan pemantauan dan cabut IAM peserta”Resource pemantauan hidup di dalam project, bukan di dalam VM. Menghapus VM tidak menghapusnya.
for PROJECT_ID in "${PROJECT_IDS[@]}"; do echo "== $PROJECT_ID"
gcloud monitoring uptime list-configs \ --project="$PROJECT_ID" --format="value(name)" | while read -r CHECK; do gcloud monitoring uptime delete "$CHECK" --project="$PROJECT_ID" --quiet done
gcloud alpha monitoring policies list \ --project="$PROJECT_ID" --format="value(name)" | while read -r POLICY; do gcloud alpha monitoring policies delete "$POLICY" --project="$PROJECT_ID" --quiet done
gcloud alpha monitoring channels list \ --project="$PROJECT_ID" --format="value(name)" | while read -r CHANNEL; do gcloud alpha monitoring channels delete "$CHANNEL" --project="$PROJECT_ID" --quiet donedoneCabut sembilan role dari setiap email peserta. Isi ROLES dengan blok pada
panduan batch peserta bagian 5.1, karena blok itu sumber tunggal
daftar role. Daftar itu tidak disalin ulang di sini supaya keduanya tidak bisa berbeda.
# ROLES diisi dari panduan batch peserta bagian 5.1.
for PROJECT_ID in "${PROJECT_IDS[@]}"; do echo "== $PROJECT_ID"
gcloud projects get-iam-policy "$PROJECT_ID" \ --flatten="bindings[].members" \ --filter="bindings.members~user:@" \ --format="value(bindings.members)" | while read -r MEMBER; do for ROLE in "${ROLES[@]}"; do gcloud projects remove-iam-policy-binding "$PROJECT_ID" \ --member="$MEMBER" \ --role="$ROLE" \ --condition=None \ --quiet || true done donedone|| true dipakai di sini, berbeda dari waktu pemasangan. Alasannya: pada pencabutan, “binding
tidak ditemukan” adalah hasil yang diinginkan, bukan kegagalan. Pada pemasangan, error apa pun
harus menghentikan proses.
Verifikasi bahwa tidak ada lagi user selain akun master:
for PROJECT_ID in "${PROJECT_IDS[@]}"; do echo "== $PROJECT_ID" gcloud projects get-iam-policy "$PROJECT_ID" \ --flatten="bindings[].members" \ --filter="bindings.members~user:@" \ --format="table(bindings.role, bindings.members)"doneLangkah 12: Bukti biaya nol
Section titled “Langkah 12: Bukti biaya nol”Langkah ini yang menutup pekerjaan, dan ia tidak dapat dikerjakan pada hari yang sama dengan langkah 1 sampai 11.
Bagian A, bukti hari itu, dari terminal. Tidak ada resource tertagih yang tersisa:
for PROJECT_ID in "${PROJECT_IDS[@]}"; do echo "================ $PROJECT_ID" gcloud compute instances list --project="$PROJECT_ID" --format="value(name)" gcloud compute disks list --project="$PROJECT_ID" --format="value(name)" gcloud compute addresses list --project="$PROJECT_ID" --format="value(name,status,users)" gcloud compute snapshots list --project="$PROJECT_ID" --format="value(name)" gcloud artifacts docker images list \ "${REGION}-docker.pkg.dev/${PROJECT_ID}/katalog-images" \ --include-tags --format="value(image)" gcloud storage buckets list --project="$PROJECT_ID" --format="value(name)"doneSeluruh perintah itu harus menghasilkan keluaran kosong. Dua pengecualian: bucket bawaan layanan dengan isi kosong boleh tetap ada, dan resource yang sengaja ditahan untuk peserta yang masih bekerja (bagian 7) tentu masih muncul. Selain kedua itu, satu nama pun yang tercetak berarti masih ada yang ditagih.
Bagian B, bukti di Console, dari Billing. Untuk setiap Billing Account:
- Billing → Reports. Pilih rentang waktu sejak batch dimulai, kelompokkan per project. Periksa bahwa biaya berhenti bertambah sejak tanggal pembongkaran.
- Billing → Cost table. Periksa bahwa tidak ada SKU yang masih bergerak, terutama
External IP ChargedanStorage PD Capacity. Kedua SKU inilah yang bertahan setelah VM dihapus bila langkah 5 dan 6 terlewat. - Billing → Credits. Periksa sisa kredit. Kredit trial berkurang oleh pemakaian yang sudah terjadi dan tidak kembali setelah resource dihapus.
- Billing → Budgets & alerts. Periksa budget masih menunjuk project yang benar.
Bagian C, bukti tunggu. Billing Reports punya jeda beberapa jam sampai beberapa hari sebelum pemakaian terakhir muncul. Karena itu:
Tanggal pembongkaran: ____Periksa ulang pada: ____ (24 sampai 48 jam setelahnya)Hasil periksa ulang: ____Isi tabel ini untuk keempat akun master, lalu serahkan ke koordinator. Tanpa bagian C, kamu menutup pekerjaan dengan keyakinan yang belum terbukti. Kalimat yang berlaku sejak panduan lama tetap benar: mematikan billing menghentikan tagihan baru, tetapi tidak membatalkan tagihan yang sudah berjalan.
5. Tanda aman untuk lanjut
Section titled “5. Tanda aman untuk lanjut”| Setelah langkah | Yang harus benar |
|---|---|
| 3 | Tidak ada VM berstatus RUNNING di ketiga project |
| 6 | instances list, disks list, dan addresses list kosong |
| 10 | Service Account yang tersisa hanya milik bawaan layanan GCP |
| 12 | Billing Reports menunjukkan biaya berhenti bertambah, dan periksa ulang 24–48 jam kemudian sudah terisi |
6. Biaya yang paling sering tertinggal
Section titled “6. Biaya yang paling sering tertinggal”Empat hal ini berulang di setiap pembongkaran, dan keempatnya bukan compute:
| Yang tertinggal | Kenapa ditagih | Langkah pencegahnya |
|---|---|---|
| Alamat IP statis tanpa instance | Ditagih saat menganggur | 5 |
Disk setelah VM dihapus tanpa --delete-disks=all |
Ditagih per GB-bulan | 4 dan 6 |
| Snapshot dan custom image | Ditagih per GB-bulan | 6 |
| Tag image lama di Artifact Registry | Ditagih per GB-bulan, dan tag lama menumpuk | 7 |
7. Kalau ada peserta yang masih butuh VM-nya
Section titled “7. Kalau ada peserta yang masih butuh VM-nya”Jangan tunda seluruh pembongkaran karena satu orang. Pisahkan:
- Bersihkan resource batch ini saja, dengan daftar nama yang sudah dicatat pada langkah 2. Jangan memakai perintah yang menghapus “semua yang ada” di project.
- Sisakan VM dan alamat IP orang itu, dan catat di manifest dengan status
DITAHAN. - Ulangi langkah 3 sampai 11 untuk sisanya setelah orang itu selesai.
Yang tidak boleh dilakukan: membiarkan seluruh project utuh karena satu peserta. Empat alamat IP publik yang tertahan berarti project itu tidak dapat menampung peserta batch berikutnya.
8. Pencabutan akses setelah seluruh batch selesai
Section titled “8. Pencabutan akses setelah seluruh batch selesai”Kalau akun master tidak akan dipakai lagi, dua hal berikut masih tersisa setelah langkah 12:
- Budget alert. Hapus budget project dan budget Billing Account.
- Akses Billing Account. Cabut
roles/billing.admindari pemegang akun master bila ia bukan pemilik Billing Account.
Kalau yang kamu butuhkan hanya membebaskan slot billing untuk batch berikutnya, bukan
menutup akun, jangan jalankan bagian ini. Yang dibutuhkan cuma melepas tautan satu project, dan
caranya ada di panduan batch peserta bagian 2.1. Ingat bahwa
unlink mematikan seluruh isi project itu.
9. Yang tidak pernah masuk tagihan ini
Section titled “9. Yang tidak pernah masuk tagihan ini”Dua hal ini sering ditanyakan saat melihat daftar bongkar, dan keduanya bukan milik GCP:
| Yang tetap hidup | Ditagih? |
|---|---|
| Database Supabase milik setiap peserta | Tidak. Akun peserta sendiri, di luar GCP. |
| Fork repository GitHub milik setiap peserta | Tidak. Source code, tanpa biaya. |
Sertifikat Let’s Encrypt pada VM yang dihapus mati bersama VM-nya dan tidak perlu dicabut.
10. Bila seluruh batch selesai dan akun master tidak dipakai lagi
Section titled “10. Bila seluruh batch selesai dan akun master tidak dipakai lagi”Jalur ini hanya untuk akun master yang benar-benar selesai, bukan untuk jeda antar batch.
PROJECT_ID="geoportal-kelompok-a-xxxxx"
gcloud billing projects unlink "$PROJECT_ID"gcloud projects delete "$PROJECT_ID"Ulangi untuk ketiga project. Penghapusan project bersifat sementara selama 30 hari; selama masa itu project dapat dipulihkan, tetapi seluruh resource di dalamnya sudah tidak berjalan dan tidak ditagih.
Kalau pekerjaan satu project saja perlu dibongkar tanpa menyentuh dua lainnya, urutan per langkahnya ada di panduan setup project bagian 13.
11. Checklist penutup per akun
Section titled “11. Checklist penutup per akun”- Tidak ada VM berstatus
RUNNING. - Tidak ada disk, snapshot, atau custom image yang tersisa.
- Tidak ada alamat IP statis yang tersisa.
- Artifact Registry kosong, dan bucket gcr.io kosong.
- Trigger dan connection Cloud Build sudah hilang.
- Hanya Service Account bawaan layanan yang tersisa.
- Uptime check, alert policy, dan notification channel sudah hilang.
- IAM binding peserta sudah dicabut, hanya akun master yang tersisa.
- Billing Reports menunjukkan biaya berhenti bertambah.
- Periksa ulang 24–48 jam kemudian sudah diisi dan hasilnya bersih untuk keempat akun.