Khám phá giải pháp sao lưu và khôi phục của Kubernetes thông qua một ví dụ cụ thể trên Google Kubernetes Engine (GKE).

Trước đây, vì chủ yếu làm việc trên các cài đặt Kubernetes nhỏ, tôi chưa bao giờ hiểu sự cần thiết của giải pháp sao lưu và khôi phục Kubernetes, đây là lý do:
- Chúng ta chỉ chạy stateless trong Kubernetes (có nghĩa là chúng ta không phải lo lắng về persistent volume)
- Các config và workload Kubernetes đã được quản lý tập trung.
Nhưng điều gì sẽ xảy ra nếu một hoặc cả hai điều này không đúng? Ví dụ: giả sử nhiều nhóm quản lý workload của họ trên một hoặc nhiều cluster Kubernetes, đôi lúc chúng ta cần backup và restore trên các cụm.
Bạn sẽ cần một giải pháp sao lưu và khôi phục Kubernetes; dự án Velero mã nguồn mở là một lựa chọn phổ biến.
Velero (trước đây là Heptio Ark) cung cấp cho bạn các công cụ để sao lưu và khôi phục tài nguyên cụm Kubernetes và workload của bạn. Bạn có thể chạy Velero với nhà cung cấp đám mây hoặc on-premise. Velero cho phép bạn:
– Sao lưu cluster của bạn và khôi phục trong trường hợp bị mất.
– Di chuyển tài nguyên cluster này sang các cluster khác.
– Nhân rộng cluster trên production của bạn sang các cụm development và testing.
Bài viết này sẽ hướng dẫn cài đặt và sử dụng cơ bản Velero trên một cụm GKE. Project Terraform được sử dụng trong bài viết này có sẵn tại đây để tải xuống .
Điều kiện tiên quyết
Nếu bạn muốn làm theo, bạn sẽ cần:
- Project Google Cloud Platform (GCP)
- Một OS; tốt nhất là macOS hoặc Linux (sử dụng Linux trong bài viết này)
- Google Cloud SDK , bao gồm gcloud CLI, được cài đặt trên máy local (tôi đã sử dụng phiên bản 316.0.0 )
- gcloud CLI được khởi tạo với dự án GCP
- Terraform CLI 0.13.5 hoặc phiên bản lớn hơn (tôi đã sử dụng phiên bản 0.13.5 )
- Velero CLI được cài đặt trên máy local (tôi đã sử dụng phiên bản 1.5)
Cài đặt một cụm GKE
Đầu tiên, bạn sẽ phải kích hoạt Kubernetes Engine API cho project GCP; phương pháp đơn giản nhất là điều hướng đến màn hình Kubernetes Engine cho dự án GCP trong Google Cloud Console.
Tạo một thư mục trống trên máy của bạn và tạo (và cập nhật) tệp sau trong đó; terraform.tfvars :
cluster_name = "" # lower case letters (2+) with optional dashes in between master_version = "" # from output of "gcloud container get-server-config" node_version = "" # from output of "gcloud container get-server-config" project = "" # from output of "gcloud config get-value project" region = "" # from https://cloud.google.com/compute/docs/regions-zones zones = [] # from https://cloud.google.com/compute/docs/regions-zones
Xin lưu ý : Để có đủ CPU để chạy workload trong ví dụ này, bạn sẽ cần ít nhất ba node, tức là ba zone. Trong cùng một thư mục, hãy tạo tệp sau; main.tf :
variable "cluster_name" {
type = string
validation {
condition = can(regex("^[a-z]+[-a-z]*[a-z]+$", var.cluster_name))
error_message = "The cluster_name value must be lower case letters (2+) with optional dashes in between."
}
}
variable "master_version" {
type = string
}
variable "node_version" {
type = string
}
variable "project" {
type = string
}
variable "region" {
type = string
}
variable "zones" {
type = list(string)
}
terraform {
required_providers {
google = {
source = "hashicorp/google"
version = "~> 3.45.0"
}
}
required_version = "~> 0.13.5"
}
provider "google" {
project = var.project
}
Chúng ta cũng tạo một tệp cluster.tf trong cùng một thư mục:
resource "google_container_cluster" "this" {
initial_node_count = 1
ip_allocation_policy {
cluster_ipv4_cidr_block = "172.16.0.0/12"
services_ipv4_cidr_block = "192.168.0.0/16"
}
location = var.region
master_auth {
client_certificate_config {
issue_client_certificate = false
}
password = ""
username = ""
}
min_master_version = var.master_version
name = var.cluster_name
node_locations = var.zones
remove_default_node_pool = true
workload_identity_config {
identity_namespace = "${var.project}.svc.id.goog"
}
}
resource "google_container_node_pool" "this" {
cluster = google_container_cluster.this.name
location = var.region
management {
auto_upgrade = false
}
name = var.cluster_name
node_config {
workload_metadata_config {
node_metadata = "GKE_METADATA_SERVER"
}
}
node_count = 1
upgrade_settings {
max_surge = 1
max_unavailable = 0
}
version = var.node_version
}
Những điều cần quan sát:
- Các đối số initial_node_count và remove_default_pool được sử dụng để xóa node pool mặc định ; cho phép chúng ta quản lý riêng resource node pool.
- Đối số ip_allocation_policy định cấu hình cụm VPC-gốc được đề xuất ; các khối CIDR riêng tư đã được chọn để không chồng lên nhau hoặc các khối trong VPC mặc định của GCP
- Đối số master_auth vô hiệu hóa bất kỳ xác thực nào ngoài xác thực OAuth
- Các workload_identity_config và workload_metadata_config đối số cho phép Workload Identity
- Các auto_upgrade và upgrade_settings đối số cho phép chúng ta nâng cấp kiểm soát bằng tay
Chúng ta khởi tạo dự án Terraform của mình bằng cách thực thi (trong thư mục):
terraform init
Chúng ta tạo một cụm GKE khu vực bằng cách thực thi (trong thư mục):
terraform apply
Chúng ta cài đặt phiên bản thích hợp của kubectl CLI bằng cách thực thi:
gcloud components install kubectl
Chúng ta xác thực cụm bằng cách thực thi (thay thế [REPLACE] bằng giá trị của cluster_name và vùng mà chúng ta đã chỉ định trước đó):
gcloud container clusters get-credentials [REPLACE] --region [REPLACE]
Chúng ta xác nhận rằng chúng ta có thể truy cập vào cụm GKE bằng cách thực hiện:
kubectl get nodes NAME STATUS ROLES AGE VERSION gke-my-cluster-my-cluster-fbbd62e6-373c Ready <none> 29m v1.17.12-gke.1504
Chuẩn bị cho Plugin GCP
Vì chúng ta đang sử dụng Google Cloud Platform (GCP) nên chúng ta sẽ sử dụng Google Cloud Storage (GCS) làm nơi lưu trữ cho Velero của chúng ta.
Velero hỗ trợ nhiều storage provider cho các hoạt động sao lưu và snapshot khác nhau. Velero có một hệ thống plugin cho phép mọi người thêm khả năng tương thích cho các nền tảng sao lưu và lưu trữ workload bổ sung mà không cần sửa đổi base code Velero.
Velero – Nhà cung cấp
Trước khi cài đặt Velero với plugin GCP, chúng ta cần chuẩn bị project GCP của mình như được mô tả trong Plugin dành cho Google Cloud Platform (GCP) ; về cơ bản là tạo một group GCS và cấp cho Velero quyền truy cập vào nó.
Tạo một tệp, velero.tf , trong thư mục:
locals {
clustername = replace(var.cluster_name, "-", "")
}
resource "google_storage_bucket" "this" {
force_destroy = true
location = var.region
name = "velero-${var.cluster_name}"
uniform_bucket_level_access = true
}
resource "google_service_account" "this" {
account_id = "velero-${var.cluster_name}"
display_name = "velero-${var.cluster_name}"
}
resource "google_project_iam_custom_role" "this" {
permissions = [
"compute.disks.get",
"compute.disks.create",
"compute.disks.createSnapshot",
"compute.snapshots.get",
"compute.snapshots.create",
"compute.snapshots.useReadOnly",
"compute.snapshots.delete",
"compute.zones.get"
]
role_id = "velero${local.clustername}"
title = "velero-${var.cluster_name}"
}
resource "google_project_iam_binding" "custom_role" {
role = "projects/${var.project}/roles/${google_project_iam_custom_role.this.role_id}"
members = [
"serviceAccount:${google_service_account.this.email}"
]
}
resource "google_project_iam_binding" "object_admin" {
role = "roles/storage.objectAdmin"
members = [
"serviceAccount:${google_service_account.this.email}"
]
condition {
expression = "resource.name.startsWith(\"projects/_/buckets/velero-${var.cluster_name}/objects/\")"
title = "bucket"
}
}
resource "google_service_account_iam_binding" "this" {
service_account_id = google_service_account.this.name
role = "roles/iam.workloadIdentityUser"
members = [
"serviceAccount:${var.project}.svc.id.goog[velero/velero]"
]
}
Những điều cần chú ý:
- Cấu hình Terraform này chỉ đơn giản là tự động hóa các bước thủ công được ghi chép lại; chúng ta đang sử dụng option Workload Identity
- Các local variable CLUSTERNAME được yêu cầu bởi vì role GCP IAM id không thể có dấu gạch ngang trong nó
Chúng ta tạo tài nguyên bằng cách thực thi (trong thư mục):
terraform apply
Cài đặt và khởi động Velero
Để cho phép nhiều quyền kiểm soát hơn đối với cài đặt Velero, chẳng hạn như gỡ cài đặt nó, chúng ta xuất tài nguyên Velero Kubernetes ra một tệp (xem các quan sát để biết các thay thế bên dưới) bằng cách thực hiện:
velero install \ --provider gcp \ --plugins velero/velero-plugin-for-gcp:v1.1.0 \ --bucket [REPLACE] \ --no-secret \ --sa-annotations iam.gke.io/gcp-service-account=[REPLACE]@[REPLACE].iam.gserviceaccount.com \ --backup-location-config serviceAccount=[REPLACE]@[REPLACE].iam.gserviceaccount.com \ --dry-run \ -o yaml \ > velero.yaml
Những điều cần chú ý:
- Các bucket lựa chọn là Velero- tiếp theo là giá trị của CLUSTER_NAME từ những gì chúng ta chỉ định trước
- Hai tùy chọn với service account có Velero- theo sau là giá trị của cluster_name trước ký hiệu “at”; sau ký hiệu “at”, chúng ta sử dụng project mà chúng ta đã chỉ định trước đó
Chúng ta cài đặt Velero bằng cách thực thi:
kubectl apply -f velero.yaml
Chúng ta có thể xác nhận rằng nó đang chạy bằng cách thực thi:
kubectl get all -n velero Output: NAME READY STATUS RESTARTS AGE pod/velero-757d655b4b-fsbrl 1/1 Running 0 5m47s NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/velero 1/1 1 1 5m48s NAME DESIRED CURRENT READY AGE replicaset.apps/velero-757d655b4b 1 1 1 5m48s
Ví dụ cơ bản
Để minh họa một ví dụ cơ bản về việc sử dụng Velero, chúng ta bắt đầu bằng cách tạo một namespace cách thực thi:
kubectl create ns nginx-example
Chúng ta tạo một deployment trong namespace này bằng cách thực thi:
kubectl create deployment nginx --image = nginx -n nginx-example
Chúng ta xác nhận rằng deployment này đang chạy bằng cách thực thi câu lện
kubectl get all -n nginx-example NAME READY STATUS RESTARTS AGE pod/nginx-86c57db685-487xf 1/1 Running 0 47s NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/nginx 1/1 1 1 47s NAME DESIRED CURRENT READY AGE replicaset.apps/nginx-86c57db685 1 1 1 47s
Ở đây chúng ta sử dụng Velero CLI để tạo thủ công bản sao lưu (backup) resource trong namespace Nginx-example :
velero backup create nginx-backup --include-namespaces nginx-example
Chúng ta có thể xác nhận rằng quá trình sao lưu hoàn tất thành công bằng cách thực hiện:
velero backup get NAME STATUS ERRORS WARNINGS CREATED EXPIRES STORAGE LOCATION SELECTOR nginx-backup Completed 0 0 2020-10-31 09:09:10 -0400 EDT 29d default <none>
Lưu ý: Sử dụng Google Cloud Console, bạn cũng có thể thấy rằng bucket GSC hiện có các tệp trong đó.
Bên dưới, Velero sử dụng một số custom resource của Kubernetes để quản lý các bản sao lưu, ví dụ: Bản sao lưu :
kubectl describe backups nginx-backup -n velero
Name: nginx-backup
Namespace: velero
Labels: velero.io/storage-location=default
Annotations: velero.io/source-cluster-k8s-gitversion: v1.17.12-gke.1504
velero.io/source-cluster-k8s-major-version: 1
velero.io/source-cluster-k8s-minor-version: 17+
API Version: velero.io/v1
Kind: Backup
Metadata:
Creation Timestamp: 2020-10-31T13:09:10Z
Generation: 5
Resource Version: 65241
Self Link: /apis/velero.io/v1/namespaces/velero/backups/nginx-backup
UID: 34b31deb-d54a-42f8-a025-656807791179
Spec:
Default Volumes To Restic: false
Hooks:
Included Namespaces:
nginx-example
Storage Location: default
Ttl: 720h0m0s
Volume Snapshot Locations:
default
Status:
Completion Timestamp: 2020-10-31T13:09:12Z
Expiration: 2020-11-30T13:09:10Z
Format Version: 1.1.0
Phase: Completed
Progress:
Items Backed Up: 14
Total Items: 14
Start Timestamp: 2020-10-31T13:09:10Z
Version: 1
Events: <none>
Bây giờ chúng ta mô phỏng một lỗi bằng cách xóa namespace Nginx-example bằng cách thực thi:
kubectl delete namespace nginx-example
Chúng ta thực sự quan sát thấy rằng namespace và các resource của nó đã bị xóa:
kubectl get all -n nginx-example No resources found in nginx-example namespace.
Sau đó, chúng ta có thể khôi phục từ bản sao lưu bằng cách thực hiện:
velero restore create --from-backup nginx-backup
Chúng ta có thể xác nhận trạng thái khôi phục bằng cách thực hiện:
velero restore get NAME BACKUP STATUS STARTED COMPLETED ERRORS WARNINGS CREATED SELECTOR nginx-backup-20201031091820 nginx-backup Completed 2020-10-31 09:18:20 -0400 EDT 2020-10-31 09:18:21 -0400 EDT 0 0 2020-10-31 09:18:20 -0400 EDT <none>
Chúng ta có thể xác nhận rằng namspace và tài nguyên đã xóa được khôi phục bằng cách thực hiện:
kubectl get all -n nginx-example NAME READY STATUS RESTARTS AGE pod/nginx-86c57db685-487xf 1/1 Running 0 70s NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/nginx 1/1 1 1 71s NAME DESIRED CURRENT READY AGE replicaset.apps/nginx-86c57db685 1 1 1 71s
Dọn dẹp
Sau khi đã trải nghiệm Velero, chúng ta có thể gỡ cài đặt ví dụ bằng cách thực thi:
kubectl delete namespace nginx-example
Khi chúng ta cài đặt Velero từ đầu ra của một lần dry run, bằng cách sử dụng velero.yaml , chúng ta có thể gỡ cài đặt Velero bằng cách thực hiện:
kubectl delete -f velero.yaml
Từ thư mục project, chúng ta có thể xóa tất cả tài nguyên GCP bằng cách thực hiện:
terraform destroy
Cuối cùng, chúng ta có thể close project GCP.
Hy vọng bạn thấy điều này hữu ích.
