Bảo vệ tài nguyên: Khóa & ngăn xóa
Vì sao cần Resource Protection
Xóa hoặc sửa nhầm là một trong các nguyên nhân lớn gây sự cố production:
Kịch bản 1: Engineer vô tình xóa database production
Kết quả: Mất dữ liệu, downtime, vi phạm quy định
Kịch bản 2: Script terraform destroy bị lỗi
Kết quả: Hạ tầng quan trọng bị phá hủy
Kịch bản 3: Kẻ xấu có quyền chỉnh sửa
Kết quả: Phá hoại dịch vụ
Kịch bản 4: Service account quá nhiều quyền
Kết quả: Lỗi tự động hóa lan rộngCác cơ chế bảo vệ tài nguyên của GCP:
- Resource locks (billing accounts, projects)
- Deletion protection (cài đặt riêng cho từng resource)
- Soft-delete windows (projects, backups)
- Audit logging (theo dõi ai xóa cái gì)
- IAM controls (hạn chế ai được xóa)
Bảo vệ ở cấp Project
Delete Protection
Projects có cơ chế soft-delete tích hợp sẵn:
T+0: gcloud projects delete my-project
→ Trạng thái: DELETE_REQUESTED
→ Project vẫn tồn tại, vẫn hiển thị, vẫn có thể dùng
T+0 đến T+30 ngày: Cửa sổ soft-delete
→ Có thể undelete project
→ Vẫn tính vào quota project
→ Billing dừng
T+30 ngày: Xóa vĩnh viễn
→ Project biến mất hoàn toàn
→ Có thể tái sử dụng Project ID (sau 30 ngày)
→ Quota được giải phóngƯu điểm:
- Có thể phục hồi nếu xóa nhầm
- Có 30 ngày để khôi phục
- Không mất dữ liệu vĩnh viễn nếu phát hiện sớm
Khôi phục project đã xóa:
bash
# Liệt kê project đã xóa
gcloud projects list --filter="lifecycleState:DELETE_REQUESTED"
# Khôi phục project đã xóa
gcloud projects undelete my-project
# Khôi phục với parent mới (nếu di chuyển folder)
gcloud projects move my-project \
--folder-id=NEW_FOLDER_IDQuota project khi xóa
Project đã xóa vẫn tính vào quota trong thời gian ân hạn:
Quota organization: 10 projects
Tình huống:
- Project 1-9: Active
- Project 10: Active
- Quota: 10/10 (đạt giới hạn)
Xóa Project 10:
- T+0 đến T+30d: Project 10 ở soft-delete (vẫn tính)
- Không thể tạo Project 11 → sẽ thành 11/10
- Phải đợi 30 ngày HOẶC khôi phục rồi xóa đúng cách
Giải pháp: Xóa và đợi 30 ngày trước khi tính lại quotaBảo vệ ở cấp Resource
Các resource khác nhau có cơ chế bảo vệ khác nhau:
Cloud Storage Buckets
bash
# Versioning: cho phép khôi phục object
gsutil versioning set on gs://my-bucket
# Bảo vệ xóa: ngăn xóa bucket
gsutil retention set 1w gs://my-bucket # giữ 1 tuần
# Lifecycle policies: tự động xóa phiên bản cũ
gsutil lifecycle set policy.json gs://my-bucketPersistent Disks (Compute Engine)
bash
# Tạo snapshot trước khi xóa disk
gcloud compute disks snapshot my-disk \
--snapshot-names=my-disk-backup
# Snapshot có thể khôi phục disk nếu cần (phục hồi dữ liệu)Cloud SQL Databases
bash
# Backup tự động: bật mặc định
gcloud sql instances patch my-instance \
--backup-start-time=03:00 \
--retained-backups-count=7
# Point-in-time recovery: khôi phục về bất kỳ thời điểm nào
gcloud sql backups restore BACKUP_ID \
--backup-instance=my-instance
# Quan trọng: mặc định backup retention là 7 ngày
# Nếu xóa ngay sau khi lịch backup chưa chạy, có thể không có backupBigQuery Datasets
bash
# Thời gian hết hạn mặc định của table: giúp tránh mất dữ liệu do nhầm
bq update \
--default_table_expiration=7776000 \ # 90 ngày
project_id:dataset_id
# Nhưng có thể bị ghi đè ở cấp table/job
# Khuyến nghị: bỏ default expiration cho dataset quan trọngBảo vệ dựa trên IAM
Ngăn xóa qua IAM
bash
# Không cho service account xóa resource
gcloud iam deny-policies create deny-deletions \
--location=projects/PROJECT_ID \
--rules='
deny {
permissions: [
"compute.instances.delete",
"compute.disks.delete",
"storage.buckets.delete",
"sqladmin.instances.delete"
]
principals: ["principalSet://goog/public:all"]
deny_rule {
deny_condition {
expression: "resource.matchTag(\"environment\", \"production\")"
}
}
}
'Kiểm soát truy cập theo role
bash
# Giới hạn quyền xóa cho role cụ thể
# Tạo custom role: Có thể quản lý nhưng không thể xóa
gcloud iam roles create projects/PROJECT_ID/roles/resourceManager \
--title="Resource Manager" \
--description="Có thể tạo/cập nhật nhưng không thể xóa resource" \
--permissions=\
compute.instances.create,\
compute.instances.get,\
compute.instances.setMetadata
# Gán role thay vì Owner/Editor
gcloud projects add-iam-policy-binding PROJECT_ID \
--member=group:developers@company.com \
--role=projects/PROJECT_ID/roles/resourceManagerAudit logging cho thao tác xóa
Theo dõi ai đã xóa gì
bash
# Truy vấn audit logs cho các thao tác xóa
gcloud logging read \
'protoPayload.methodName="compute.instances.delete" AND severity=WARNING' \
--limit=20 \
--format=json
# Lọc theo resource và thời gian
gcloud logging read \
'protoPayload.resourceName="projects/my-project/zones/us-central1-a/instances/my-vm" AND
protoPayload.methodName="compute.instances.delete"' \
--format=jsonCảnh báo khi có xóa
python
from google.cloud import monitoring_v3
def create_deletion_alert(project_id):
"""Cảnh báo khi resource production bị xóa"""
client = monitoring_v3.AlertPolicyServiceClient()
# Điều kiện: bất kỳ thao tác delete nào trên resource prod
condition = monitoring_v3.AlertPolicy.Condition(
display_name="Production resource deleted",
condition_threshold=monitoring_v3.AlertPolicy.Condition.MetricThreshold(
filter='''
resource.type="gce_instance"
AND metric.type="logging.googleapis.com/user/resource_deletion"
AND resource.labels.environment="production"
''',
comparison=monitoring_v3.ComparisonType.COMPARISON_GT,
threshold_value=0,
duration={"seconds": 60}
)
)
# Tạo alert
policy = monitoring_v3.AlertPolicy(
display_name="Production resource deletion alert",
conditions=[condition],
notification_channels=[create_notification_channel()]
)
client.create_alert_policy(
name=f"projects/{project_id}",
alert_policy=policy
)Chiến lược backup
Quy tắc 3-2-1
Với dữ liệu quan trọng:
- 3 bản sao: Bản gốc + 2 bản backup
- 2 loại media khác nhau: Disk + Cloud Storage
- 1 bản offsite: region/project khácpython
def backup_critical_data(source_disk):
"""Triển khai backup 3-2-1 cho dữ liệu quan trọng"""
# Bản sao 1: Snapshot (định dạng disk)
snapshot1 = create_snapshot(source_disk, name="backup-snapshot-1")
# Bản sao 2: Snapshot ở region khác
snapshot2 = create_snapshot_in_region(
source_disk,
name="backup-snapshot-2",
region="us-east1" # Region khác
)
# Bản sao 3: Export sang Cloud Storage (offsite)
export_snapshot_to_storage(
snapshot1,
bucket="gs://backups-project",
path="backups/critical-data/"
)
return {
"snapshots": [snapshot1.name, snapshot2.name],
"storage_export": "gs://backups-project/backups/critical-data/"
}Backup bất biến
bash
# Cloud Storage bucket với Object Lock
gsutil bucket-lock set gs://backups-immutable
# Lúc này object không thể bị xóa/sửa
# Ngay cả admin cũng không thể gỡ cho đến khi hết retentionKiểm thử Disaster Recovery
python
def dr_test():
"""Kiểm thử DR định kỳ: tạo resource từ backup"""
import time
# Tạo project test
test_project = create_project(f"dr-test-{int(time.time())}")
try:
# Khôi phục từ backup
restore_from_snapshot(
snapshot="snapshots/critical-data-backup",
destination_project=test_project
)
# Xác thực dữ liệu khôi phục
assert validate_data_integrity(test_project)
print("✓ DR test passed")
finally:
# Dọn dẹp project test (sau thời gian retention)
schedule_project_deletion(test_project, delay_days=7)Bảo vệ khi destroy bằng Terraform
hcl
# Ngăn terraform destroy vô tình
resource "google_compute_instance" "production" {
name = "production-vm"
# Thêm lifecycle rule để ngăn destruction
lifecycle {
prevent_destroy = true
}
}
# Cách khác: yêu cầu phê duyệt
resource "null_resource" "approval_gate" {
triggers = {
production_vm = google_compute_instance.production.id
}
provisioner "local-exec" {
command = "echo 'Require manual approval before destroy'; exit 1"
when = destroy
}
}
# Muốn thực sự destroy phải bỏ prevent_destroy
terraform destroy -auto-approve # Sẽ thất bại nếu prevent_destroy=trueQuy trình khôi phục
bash
#!/bin/bash
# recover-deleted-project.sh
PROJECT_ID=$1
# Bước 1: Kiểm tra project có ở soft-delete không
STATUS=$(gcloud projects describe $PROJECT_ID --format='value(lifecycleState)')
if [ "$STATUS" == "DELETE_REQUESTED" ]; then
echo "✓ Project đang ở trạng thái soft-delete"
# Bước 2: Undelete project
gcloud projects undelete $PROJECT_ID
echo "✓ Project đã được khôi phục"
# Bước 3: Xác minh resources
RESOURCE_COUNT=$(gcloud compute instances list \
--project=$PROJECT_ID --format=json | jq 'length')
echo "✓ Tìm thấy $RESOURCE_COUNT instances"
# Bước 4: Bật lại services
gcloud services enable compute.googleapis.com \
--project=$PROJECT_ID
echo "✓ Khôi phục hoàn tất"
else
echo "✗ Project không ở soft-delete (không thể khôi phục)"
exit 1
fiCác anti-pattern cần tránh
| Anti-pattern | Vấn đề | Giải pháp |
|---|---|---|
| Không có backup | Mất dữ liệu là vĩnh viễn | Triển khai backup 3-2-1 |
| Service account quá quyền | Có thể xóa mọi thứ | Giới hạn IAM theo least privilege |
| Không audit logging | Không truy vết được ai xóa | Bật audit logging |
| Terraform destroy không có bảo vệ | Phá hủy nhầm | Thêm bảo vệ lifecycle |
| Không cảnh báo khi xóa | Lỗi âm thầm | Giám sát audit log xóa |
| Backup trong cùng project | Backup bị xóa cùng project | Backup sang project khác |