DevOps

Ngày 12: Tổng quan về Dữ liệu

Sao lưu theo hướng tập trung vào ứng dụng

Chúng ta đã dành thời gian nói về các dịch vụ dữ liệu hoặc các ứng dụng đòi hỏi nhiều dữ liệu như cơ sở dữ liệu. Đối với các dịch vụ dữ liệu này, chúng ta phải xem xét cách quản lý tính nhất quán, đặc biệt khi nói đến tính nhất quán của ứng dụng.

Trong bài viết này, chúng ta sẽ đi sâu vào yêu cầu bảo vệ dữ liệu ứng dụng một cách nhất quán.

Để làm điều này, công cụ chúng ta chọn sẽ là Kanister

Giới thiệu về Kanister

Kanister là một dự án mã nguồn mở của Kasten, cho phép chúng ta quản lý (sao lưu và khôi phục) dữ liệu ứng dụng trên Kubernetes. Bạn có thể triển khai Kanister như một ứng dụng helm vào cụm Kubernetes của mình.

Kanister sử dụng các tài nguyên tùy chỉnh của Kubernetes, các tài nguyên tùy chỉnh chính được cài đặt khi Kanister được triển khai là

  • Profile – là một vị trí mục tiêu để lưu trữ các bản sao lưu và khôi phục từ đó. Thông thường nhất, đây sẽ là lưu trữ đối tượng.
  • Blueprint – các bước cần thực hiện để sao lưu và khôi phục cơ sở dữ liệu nên được duy trì trong Blueprint.
  • ActionSet – là hành động để chuyển bản sao lưu của chúng ta đến Profile của chúng ta cũng như các hành động khôi phục.

Hướng dẫn Thực hiện

Trước khi thực hành, chúng ta nên xem qua quy trình mà Kanister thực hiện để bảo vệ dữ liệu ứng dụng. Đầu tiên, controller được triển khai bằng helm vào cụm Kubernetes, Kanister sống trong namespace của nó. Chúng ta lấy Blueprint của mình, có nhiều blueprint hỗ trợ cộng đồng có sẵn, chúng ta sẽ trình bày chi tiết hơn về điều này ngay sau đây. Sau đó, chúng ta có workload cơ sở dữ liệu của mình.

Chúng ta sau đó tạo ActionSet của mình.

ActionSet cho phép chúng ta chạy các hành động được định nghĩa trong blueprint với dịch vụ dữ liệu cụ thể.

ActionSet lần lượt sử dụng các chức năng của Kanister (KubeExec, KubeTask, Resource Lifecycle) và đẩy bản sao lưu của chúng ta đến kho lưu trữ mục tiêu của chúng ta (Profile).

Nếu hành động đó hoàn thành/thất bại, trạng thái tương ứng được cập nhật trong ActionSet.

Triển khai Kanister

Một lần nữa, chúng ta sẽ sử dụng cụm minikube để thực hiện sao lưu ứng dụng này. Nếu bạn vẫn chạy nó từ phiên trước, chúng ta có thể tiếp tục sử dụng.

Tại thời điểm viết bài này, chúng ta đang ở image version 0.75.0, với lệnh helm sau, chúng ta sẽ cài đặt kanister vào cụm Kubernetes của mình.

helm install kanister --namespace kanister kanister/kanister-operator --set image.tag=0.75.0 --create-namespace

Chúng ta có thể sử dụng kubectl get pods -n kanister để đảm bảo pod đang chạy và sau đó chúng ta cũng có thể kiểm tra các định nghĩa tài nguyên tùy chỉnh của chúng ta hiện có sẵn (Nếu bạn chỉ cài đặt Kanister thì bạn sẽ thấy 3 mục được đánh dấu)

Triển khai một Cơ sở dữ liệu

Triển khai MySQL qua helm:

APP_NAME=my-production-app
kubectl create ns ${APP_NAME}
helm repo add bitnami https://charts.bitnami.com/bitnami
helm install mysql-store bitnami/mysql --set primary.persistence.size=1Gi,volumePermissions.enabled=true --namespace=${APP_NAME}
kubectl get pods -n ${APP_NAME} -w

Nạp dữ liệu ban đầu vào cơ sở dữ liệu MySQL, chạy lệnh sau:

MYSQL_ROOT_PASSWORD=$(kubectl get secret --namespace ${APP_NAME} mysql-store -o jsonpath="{.data.mysql-root-password}" | base64 --decode)
MYSQL_HOST=mysql-store.${APP_NAME}.svc.cluster.local
MYSQL_EXEC="mysql -h ${MYSQL_HOST} -u root --password=${MYSQL_ROOT_PASSWORD} -DmyImportantData -t"
echo MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}

Tạo MySQL CLIENT

Chúng ta sẽ chạy một container image như một client

APP_NAME=my-production-app
kubectl run mysql-client --rm --env APP_NS=${APP_NAME} --env MYSQL_EXEC="${MYSQL_EXEC}" --env MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} --env MYSQL_HOST=${MYSQL_HOST} --namespace ${APP_NAME} --tty -i --restart='Never' --image  docker.io/bitnami/mysql:latest --command -- bash
Note: nếu bạn đã có một pod client MySQL đang chạy, hãy xóa với lệnh

kubectl delete pod -n ${APP_NAME} mysql-client

Thêm Dữ liệu vào MySQL

echo "create database myImportantData;" | mysql -h ${MYSQL_HOST} -u root --password=${MYSQL_ROOT_PASSWORD}
MYSQL_EXEC="mysql -h ${MYSQL_HOST} -u root --password=${MYSQL_ROOT_PASSWORD} -DmyImportantData -t"
echo "drop table Accounts" | ${MYSQL_EXEC}
echo "create table if not exists Accounts(name text, balance integer); insert into Accounts values('nick', 0);" |  ${MYSQL_EXEC}
echo "insert into Accounts values('albert', 112);" | ${MYSQL_EXEC}
echo "insert into Accounts values('alfred', 358);" | ${MYSQL_EXEC}
echo "insert into Accounts values('beatrice', 1321);" | ${MYSQL_EXEC}
echo "insert into Accounts values('bartholomew', 34);" | ${MYSQL_EXEC}
echo "insert into Accounts values('edward', 5589);" | ${MYSQL_EXEC}
echo "insert into Accounts values('edwin', 144);" | ${MYSQL_EXEC}
echo "insert into Accounts values('edwina', 233);" | ${MYSQL_EXEC}
echo "insert into Accounts values('rastapopoulos', 377);" | ${MYSQL_EXEC}
echo "select * from Accounts;" |  ${MYSQL_EXEC}
exit

Bạn sẽ có thể thấy một số dữ liệu như hình dưới đây.

Tạo Kanister Profile

Kanister cung cấp một CLI, kanctl và một tiện ích khác kando được sử dụng để tương tác với nhà cung cấp lưu trữ đối tượng của bạn từ blueprint và cả hai tiện ích này.

Tải xuống CLI

Tôi đã tạo một AWS S3 bucket mà chúng ta sẽ sử dụng làm profile target và restore location. Tôi sẽ sử dụng các biến môi trường để tôi có thể vẫn hiển thị cho bạn các lệnh tôi đang chạy với kanctl để tạo kanister profile.

kanctl create profile s3compliant --access-key $ACCESS_KEY --secret-key $SECRET_KEY --bucket $BUCKET --region eu-west-2 --namespace my-production-app

Tạo Blueprint

Đừng lo lắng bạn không cần phải tạo blueprint của riêng mình từ đầu trừ khi dịch vụ dữ liệu của bạn không được liệt kê ở trong Kanister Examples nhưng bằng mọi cách, đóng góp cộng đồng là cách dự án này nâng cao nhận thức.

Blueprint mà chúng ta sẽ sử dụng là dưới đây.

apiVersion: cr.kanister.io/v1alpha1
kind: Blueprint
metadata:
  name: mysql-blueprint
actions:
  backup:
    outputArtifacts:
      mysqlCloudDump:
        keyValue:
          s3path: "{{ .Phases.dumpToObjectStore.Output.s3path }}"
    phases:
    - func: KubeTask
      name: dumpToObjectStore
      objects:
        mysqlSecret:
          kind: Secret
          name: '{{ index .Object.metadata.labels "app.kubernetes.io/instance" }}'
          namespace: '{{ .StatefulSet.Namespace }}'
      args:
        image: ghcr.io/kanisterio/mysql-sidecar:0.75.0
        namespace: "{{ .StatefulSet.Namespace }}"
        command:
        - bash
        - -o
        - errexit
        - -o
        - pipefail
        - -c
        - |
          s3_path="/mysql-backups/{{ .StatefulSet.Namespace }}/{{ index .Object.metadata.labels "app.kubernetes.io/instance" }}/{{ toDate "2006-01-02T15:04:05.999999999Z07:00" .Time  | date "2006-01-02T15-04-05" }}/dump.sql.gz"
          root_password="{{ index .Phases.dumpToObjectStore.Secrets.mysqlSecret.Data "mysql-root-password" | toString }}"
          mysqldump --column-statistics=0 -u root --password=${root_password} -h {{ index .Object.metadata.labels "app.kubernetes.io/instance" }} --single-transaction --all-databases | gzip - | kando location push --profile '{{ toJson .Profile }}' --path ${s3_path} -
          kando output s3path ${s3_path}
  restore:
    inputArtifactNames:
    - mysqlCloudDump
    phases:
    - func: KubeTask
      name: restoreFromBlobStore
      objects:
        mysqlSecret:
          kind: Secret
          name: '{{ index .Object.metadata.labels "app.kubernetes.io/instance" }}'
          namespace: '{{ .StatefulSet.Namespace }}'
      args:
        image: ghcr.io/kanisterio/mysql-sidecar:0.75.0
        namespace: "{{ .StatefulSet.Namespace }}"
        command:
        - bash
        - -o
        - errexit
        - -o
        - pipefail
        - -c
        - |
          s3_path="{{ .ArtifactsIn.mysqlCloudDump.KeyValue.s3path }}"
          root_password="{{ index .Phases.restoreFromBlobStore.Secrets.mysqlSecret.Data "mysql-root-password" | toString }}"
          kando location pull --profile '{{ toJson .Profile }}' --path ${s3_path} - | gunzip | mysql -u root --password=${root_password} -h {{ index .Object.metadata.labels "app.kubernetes.io/instance" }}
  delete:
    inputArtifactNames:
    - mysqlCloudDump
    phases:
    - func: KubeTask
      name: deleteFromBlobStore
      args:
        image: ghcr.io/kanisterio/mysql-sidecar:0.75.0
        namespace: "{{ .Namespace.Name }}"
        command:
        - bash
        - -o
        - errexit
        - -o
        - pipefail
        - -c
        - |
          s3_path="{{ .ArtifactsIn.mysqlCloudDump.KeyValue.s3path }}"
          kando location delete --profile '{{ toJson .Profile }}' --path ${s3_path}

Để thêm điều này, chúng ta sẽ sử dụng lệnh kubectl create -f mysql-blueprint.yml -n kanister

Tạo ActionSet và Bảo vệ ứng dụng

Chúng ta sẽ bây giờ thực hiện sao lưu dữ liệu MySQL bằng cách tạo một ActionSet định nghĩa sao lưu cho ứng dụng này. Tạo một ActionSet trong cùng namespace với controller.

kubectl get profiles.cr.kanister.io -n my-production-app Lệnh này sẽ hiển thị profile mà chúng ta đã tạo trước đó, chúng ta có thể có nhiều profile được cấu hình ở đây vì vậy chúng ta có thể muốn sử dụng các profile cụ thể cho các ActionSet khác nhau

Chúng ta sau đó sẽ tạo ActionSet của mình với lệnh sau sử dụng kanctl

kanctl create actionset --action backup --namespace kanister --blueprint mysql-blueprint --statefulset my-production-app/mysql-store --profile my-production-app/s3-profile-dc5zm --secrets mysql=my-production-app/mysql-store

Bạn có thể thấy từ lệnh trên chúng ta đang định nghĩa blueprint mà chúng ta đã thêm vào namespace, statefulset trong namespace my-production-app của chúng ta và cả các secrét để truy cập vào ứng dụng MySQL.

Kiểm tra trạng thái của ActionSet bằng cách lấy tên ActionSet và sử dụng lệnh này kubectl --namespace kanister describe actionset backup-qpnqv

Cuối cùng, chúng ta có thể đi và xác nhận rằng hiện đang có dữ liệu trong bucket AWS S3 của mình.

Khôi phục

Chúng ta cần gây ra một số thiệt hại trước khi có thể khôi phục bất cứ thứ gì, chúng ta có thể làm điều này bằng cách xóa bảng của mình, có thể đó là một tai nạn, có thể không phải.

Kết nối với pod MySQL của chúng ta.

APP_NAME=my-production-app
kubectl run mysql-client --rm --env APP_NS=${APP_NAME} --env MYSQL_EXEC="${MYSQL_EXEC}" --env MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} --env MYSQL_HOST=${MYSQL_HOST} --namespace ${APP_NAME} --tty -i --restart='Never' --image  docker.io/bitnami/mysql:latest --command -- bash

Bạn có thể thấy rằng cơ sở dữ liệu importantdata của chúng ta ở đó với echo "SHOW DATABASES;" | ${MYSQL_EXEC}

Sau đó để xóa chúng ta chạy echo "DROP DATABASE myImportantData;" | ${MYSQL_EXEC}

Và xác nhận rằng nó đã biến mất với một vài lần thử để hiển thị cơ sở dữ liệu của chúng ta.

Chúng ta bây giờ có thể sử dụng Kanister để lấy lại dữ liệu quan trọng của chúng ta bằng cách sử dụng kubectl get actionset -n kanister để tìm tên ActionSet mà chúng ta đã lấy trước đó. Sau đó, chúng ta sẽ tạo một ActionSet khôi phục để khôi phục dữ liệu của mình bằng cách sử dụng kanctl create actionset -n kanister --action restore --from "backup-qpnqv"

Chúng ta có thể xác nhận dữ liệu của mình đã quay lại bằng cách sử dụng lệnh dưới đây để kết nối với cơ sở dữ liệu của mình.

APP_NAME=my-production-app
kubectl run mysql-client --rm --env APP_NS=${APP_NAME} --env MYSQL_EXEC="${MYSQL_EXEC}" --env MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} --env MYSQL_HOST=${MYSQL_HOST} --namespace ${APP_NAME} --tty -i --restart='Never' --image  docker.io/bitnami/mysql:latest --command -- bash

Bây giờ chúng ta đang ở trong MySQL Client, chúng ta có thể thực hiện lệnh echo "SHOW DATABASES;" | ${MYSQL_EXEC} và chúng ta có thể thấy cơ sở dữ liệu đã quay lại. Chúng ta cũng có thể thực hiện lệnh echo "select * from Accounts;" | ${MYSQL_EXEC} để kiểm tra nội dung của cơ sở dữ liệu và dữ liệu quan trọng của chúng ta đã được khôi phục.

Trong phần tiếp theo, chúng ta sẽ xem xét Khôi phục Thảm họa trong Kubernetes.

Khôi phục thảm họa (DR)

Chúng ta đã đề cập đến các kịch bản sự cố khác nhau sẽ đòi hỏi các yêu cầu khôi phục khác nhau. Khi nói đến các kịch bản Lửa, Lũ lụt và Máu, chúng ta có thể xem đây là các tình huống thảm họa mà chúng ta cần phải có các ứng dụng của mình hoạt động ở một vị trí hoàn toàn khác càng nhanh càng tốt hoặc ít nhất với mục tiêu thời gian khôi phục gần như bằng không (RTO).

Điều này chỉ có thể đạt được ở quy mô lớn khi bạn tự động hóa việc sao chép toàn bộ stack ứng dụng sang một môi trường dự phòng.

Điều này cho phép việc chuyển đổi nhanh chóng giữa các cloud regions, nhà cung cấp cloud hoặc giữa on-premise và cloud.

Tiếp tục với chủ đề này, chúng ta sẽ tập trung vào việc làm sao có thể đạt được điều này bằng cách sử dụng Kasten K10 với cụm minikube mà chúng ta đã triển khai và cấu hình trong các bài viết trước.

Chúng ta sẽ sau đó tạo một cụm minikube khác với Kasten K10 cũng được cài đặt để đóng vai trò là cụm dự phòng của chúng ta, mà về lý thuyết có thế đặt tại bất cứ đâu.

Kasten K10 cũng có chức năng tích hợp để đảm bảo rằng nếu có gì đó xảy ra với cụm Kubernetes mà nó đang chạy, dữ liệu danh mục sẽ được sao chép và có sẵn trong một cụm mới K10 Khôi phục Thảm họa.

Thêm object storage vào K10

Điều đầu tiên chúng ta cần làm là thêm một object storage bucket làm target location để các bản sao lưu của chúng ta đến. Điều này không chỉ đóng vai trò như một vị trí ngoài site mà chúng ta còn có thể tận dụng nó làm nguồn dữ liệu khôi phục thảm họa.

Tôi đã dọn sạch bucket S3 mà chúng ta đã tạo cho bản demo Kanister trong phiên trước.

Chuyển tiếp cổng để truy cập bảng điều khiển K10, mở một terminal mới để chạy lệnh dưới đây:

kubectl --namespace kasten-io port-forward service/gateway 8080:8000

Bảng điều khiển Kasten sẽ khả dụng tại http://127.0.0.1:8080/k10/#/

Để xác thực với bảng điều khiển, chúng ta cần token mà chúng ta có thể lấy bằng các lệnh sau.

TOKEN_NAME=$(kubectl get secret --namespace kasten-io|grep k10-k10-token | cut -d " " -f 1)
TOKEN=$(kubectl get secret --namespace kasten-io $TOKEN_NAME -o jsonpath="{.data.token}" | base64 --decode)

echo "Token value: "
echo $TOKEN

Bây giờ chúng ta lấy token này và nhập vào trình duyệt, sau đó bạn sẽ được yêu cầu nhập email và tên công ty.

Sau đó, chúng ta sẽ truy cập được vào bảng điều khiển Kasten K10.

Bây giờ khi chúng ta đã quay lại bảng điều khiển Kasten K10, chúng ta có thể thêm hồ sơ vị trí của mình, chọn “Settings” ở đầu trang và “New Profile”.

Bạn có thể thấy như hình dưới rằng chúng ta có nhiều lựa chọn về vị trí của hồ sơ này, chúng ta sẽ chọn Amazon S3 và thêm vào thông tin đăng nhập, region và tên bucket.

Nếu chúng ta cuộn xuống trong cửa sổ tạo New Profile, bạn sẽ thấy rằng chúng ta cũng có thể bật các bản sao lưu không thể thay đổi bằng cách sử dụng API Object Lock của S3. Trong bản demo này, chúng ta sẽ không sử dụng tính năng đó.

Nhấn “Save Profile” và bạn sẽ thấy hồ sơ vị trí vừa được tạo hoặc thêm của chúng ta như bên dưới.

Tạo policy để bảo vệ ứng dụng Pac-Man trong object storage

Trong phiên trước, chúng ta chỉ tạo một bản snapshot ngẫu nhiên của ứng dụng Pac-Man, vì vậy chúng ta cần tạo một chính sách sao lưu sẽ gửi các bản sao lưu ứng dụng của chúng ta đến vị trí obeject strorage mới tạo của chúng ta.

Nếu bạn quay lại bảng điều khiển và chọn thẻ Chính sách, bạn sẽ thấy một màn hình như bên dưới. Chọn “Create New Policy”.

Đầu tiên, chúng ta có thể đặt tên và mô tả hữu ích cho chính sách của mình. Chúng ta cũng có thể xác định tần suất sao lưu của mình cho mục đích demo, tôi đang sử dụng theo yêu cầu.

Tiếp theo, chúng ta muốn bật sao lưu qua xuất Snapshot có nghĩa là chúng ta muốn gửi dữ liệu của mình đến location profile. Nếu bạn có nhiều profile, bạn có thể chọn profile nào bạn muốn gửi các bản sao lưu của mình đến.

Tiếp theo, chúng ta chọn ứng dụng theo tên hoặc nhãn, tôi sẽ chọn theo tên và tất cả các tài nguyên.

Dưới Advanced settings, chúng ta sẽ không sử dụng bất kỳ cài đặt nào trong số này nhưng chúng ta có thể tận dụng Kanister như một phần của Kasten K10 để lấy các bản sao nhất quán của dữ liệu của chúng ta.

Cuối cùng, chọn “Create Policy” và bạn sẽ thấy chính sách trong cửa sổ Policy.

Ở cuối chính sách được tạo, bạn sẽ thấy “Show import details”, chúng ta cần chuỗi này để có thể nhập vào cụm dự phòng của mình. Sao chép nó vào nơi an toàn ngay bây giờ.

Trước khi tiếp tục, chúng ta chỉ cần chọn “run once” để gửi một bản sao lưu đến object storage bucket.

Dưới đây là ảnh chụp màn hình để hiển thị bản sao lưu thành công và xuất dữ liệu của chúng ta.

Tạo cụm MiniKube mới & triển khai K10

Sau đó, chúng ta cần triển khai một cụm Kubernetes thứ hai dùng bất kỳ phiên bản Kubernetes nào được hỗ trợ, bao gồm cả OpenShift, cho mục đích học tập, chúng ta sẽ sử dụng phiên bản MiniKube miễn phí với một tên khác.

Sử dụng minikube start --addons volumesnapshots,csi-hostpath-driver --apiserver-port=6443 --container-runtime=containerd -p standby --kubernetes-version=1.21.2, chúng ta có thể tạo cụm mới của mình.

Sau đó, chúng ta có thể triển khai Kasten K10 trong cụm này bằng cách sử dụng:

helm install k10 kasten/k10 --namespace=kasten-io --set auth.tokenAuth.enabled=true --set injectKanisterSidecar.enabled=true --set-string injectKanisterSidecar.namespaceSelector.matchLabels.k10/injectKanisterSidecar=true --create-namespace

Điều này sẽ mất một thời gian nhưng trong khi chờ đợi, chúng ta có thể sử dụng kubectl get pods -n kasten-io -w để theo dõi tiến trình của các pod đến khi hoàn tất.

Đáng lưu ý rằng vì chúng ta đang sử dụng MiniKube, ứng dụng của chúng ta sẽ chỉ chạy khi chúng ta chạy chính sách nhập của mình, storageclass của chúng ta là như nhau trên cụm dự phòng này. Tuy nhiên, một điều chúng ta sẽ đề cập trong phiên cuối là tính di động và biến đổi.

Khi các pod đã chạy, chúng ta có thể theo dõi các bước mà chúng ta đã thực hiện trong các bước trước đó trong cụm khác.

Chuyển tiếp cổng để truy cập bảng điều khiển K10, mở một terminal mới để chạy lệnh dưới đây

kubectl --namespace kasten-io port-forward service/gateway 8080:8000

Bảng điều khiển Kasten sẽ khả dụng tại http://127.0.0.1:8080/k10/#/

Để xác thực với bảng điều khiển, chúng ta cần token mà chúng ta có thể lấy bằng các lệnh sau.

TOKEN_NAME=$(kubectl get secret --namespace kasten-io|grep k10-k10-token | cut -d " " -f 1)
TOKEN=$(kubectl get secret --namespace kasten-io $TOKEN_NAME -o jsonpath="{.data.token}" | base64 --decode)

echo "Token value: "
echo $TOKEN

Bây giờ chúng ta lấy token này và nhập vào trình duyệt, sau đó bạn sẽ được yêu cầu nhập email và tên công ty.

Sau đó, chúng ta sẽ truy cập được vào bảng điều khiển Kasten K10.

Import Pac-Man vào cụm MiniKube mới

Tại thời điểm này, chúng ta có thể tạo một chính sách import vào cụm dự phòng đó và kết nối với các bản sao lưu trên object storage bucket và xác định những gì và cách chúng ta muốn điều này trông như thế nào.

Đầu tiên, chúng ta thêm Location Profile mà chúng ta đã thực hiện trong cụm khác, dark mode ở đây để hiển thị sự khác biệt giữa hệ thống sản xuất của chúng ta và vị trí dự phòng DR của chúng ta.

Bây giờ chúng ta quay lại bảng điều khiển và vào tab policy để tạo một policy mới.

Tạo import policy như hình dưới. Khi hoàn tất, chúng ta có thể tạo một policy. Có các tùy chọn ở đây để khôi phục sau khi import và một số người có thể muốn tùy chọn này, điều này sẽ được khôi phục vào cụm dự phòng của chúng ta sau khi hoàn tất. Chúng ta cũng có thể thay đổi cấu hình của ứng dụng khi nó được khôi phục và đây là những gì tôi đã ghi lại.

Tôi đã chọn import theo yêu cầu, nhưng bạn có thể đặt lịch khi bạn muốn nhập này diễn ra. Vì điều này, tôi sẽ chạy một lần.

Bạn có thể thấy bên dưới import policy job thành công.

Nếu chúng ta quay lại bảng điều khiển và vào thẻ Applications, chúng ta có thể chọn thả xuống nơi bạn thấy bên dưới “Removed” bạn sẽ thấy ứng dụng của chúng ta ở đây. Chọn Restore

Tại đây, chúng ta có thể thấy các điểm khôi phục mà chúng ta có sẵn; đây là công việc sao lưu mà chúng ta đã chạy trên cụm chính đối với ứng dụng Pac-Man của chúng ta.

Tôi sẽ không thay đổi bất kỳ mặc định nào vì tôi muốn trình bày chi tiết hơn về điều này trong bài viết tiếp theo.

Khi bạn nhấn “Restore” nó sẽ yêu cầu bạn xác nhận.

Chúng ta có thể thấy bên dưới rằng chúng ta đang ở trong cụm dự phòng và nếu chúng ta kiểm tra các pod của mình, chúng ta có thể thấy rằng chúng ta đã có ứng dụng đang chạy.

Chúng ta có thể sau đó chuyển tiếp cổng (trong các môi trường thực tế / sản xuất, bạn sẽ không cần bước này để truy cập ứng dụng, bạn sẽ sử dụng ingress)

Tiếp theo, chúng ta sẽ xem xét tính di động và biến đổi của ưng dụng.

Tính di động của Dữ liệu & Ứng dụng

Trong bài viết cuối này, tôi sẽ trình bày về tính di động của dữ liệu và ứng dụng. Tôi sẽ tập trung cụ thể vào Kubernetes nhưng yêu cầu trên đa nền tảng ngày càng tăng và gặp nhiều trong thực tế.

Trường hợp là “Tôi muốn di chuyển khối lượng công việc, ứng dụng và dữ liệu của mình từ một vị trí đến vị trí khác” vì nhiều lý do khác nhau, có thể là chi phí, rủi ro hoặc để cung cấp dịch vụ tốt hơn cho doanh nghiệp.

Trong bài viết này, chúng ta sẽ di chuyển một workload trên Kubernetes từ một cụm đến một cụm khác, nhưng trong quá trình đó, chúng ta sẽ thay đổi cách ứng dụng hoạt động ở vị trí đích.

Nó sử dụng nhiều đặc điểm mà chúng ta đã thảo luận trong Khôi phục Thảm họa

Yêu cầu

Cụm Kubernetes hiện tại của chúng ta không thể xử lý nhu cầu và chi phí của chúng ta đang tăng vọt, dẫn đến quyết định kinh doanh rằng chúng ta muốn di chuyển cụm Kubernetes sản xuất của mình đến DR site của chúng ta, nằm trên một đám mây công cộng khác sẽ cung cấp khả năng mở rộng nhưng cũng với chi phí rẻ hơn. Chúng ta cũng có thể tận dụng một số dịch vụ cloud native có sẵn.

Ứng dụng quan trọng của chúng ta (Pac-Man) có một cơ sở dữ liệu (MongoDB) và đang chạy trên lưu trữ có tốc độ chậm, chúng ta muốn di chuyển đến một tier lưu trữ mới nhanh hơn.

Giao diện Pac-Man hiện tại (NodeJS) không có tính mở rộng tốt, và chúng ta muốn tăng số lượng pod có sẵn ở chỗ mới.

Bắt đầu

Chúng ta đã có mô tả và thực tế là chúng ta đã có các bản import trên cụm Kubernetes Khôi phục Thảm họa (DR).

Công việc đầu tiên chúng ta cần làm là xóa thao tác khôi phục mà chúng ta đã thực hiện để kiểm tra Khôi phục Thảm họa.

Chúng ta có thể làm điều này bằng cách sử dụng lệnh kubectl delete ns pacman trên cụm minikube “dự phòng”.

Để bắt đầu, hãy vào Bảng điều khiển Kasten K10 và chọn thẻ Applications. Từ trình đơn thả xuống chọn “Removed”

Sau đó, chúng ta sẽ nhận được danh sách các điểm khôi phục có sẵn. Chúng ta sẽ chọn điểm có sẵn vì nó chứa dữ liệu quan trọng của chúng ta. (Trong ví dụ này, chúng ta chỉ có một điểm khôi phục.)

Khi chúng ta thực hiện quy trình Khôi phục Thảm họa, chúng ta để mọi thứ mặc định. Tuy nhiên, các tùy chọn khôi phục bổ sung này có sẵn nếu bạn có quy trình Khôi phục Thảm họa yêu cầu chuyển đổi ứng dụng của bạn. Trong trường hợp này, chúng ta có yêu cầu thay đổi lưu trữ và số lượng bản sao.

Chọn tùy chọn “Apply transforms to restored resources”.

May mắn thay, hai ví dụ tích hợp sẵn cho việc chuyển đổi mà chúng ta muốn thực hiện là những gì chúng ta cần cho yêu cầu của mình.

Yêu cầu đầu tiên là trên cụm chính của chúng ta, chúng ta đang sử dụng một Storage Class gọi là csi-hostpath-sc và trong cụm mới của chúng ta, chúng ta muốn sử dụng standard vì vậy chúng ta có thể thực hiện thay đổi đó ở đây.

Trông ổn, nhấn nút tạo chuyển đổi ở dưới cùng.

Yêu cầu tiếp theo là chúng ta muốn mở rộng front-end deployment của Pac-Man lên “5”

Nếu bạn đang theo dõi, bạn sẽ thấy cả hai chuyển đổi của chúng ta như bên dưới.

Bây giờ bạn có thể thấy từ hình ảnh dưới rằng chúng ta sẽ khôi phục tất cả các hiện vật được liệt kê bên dưới, nếu chúng ta muốn, chúng ta cũng có thể chi tiết về những gì chúng ta muốn khôi phục. Nhấn nút “Restore”

Một lần nữa, chúng ta sẽ được yêu cầu xác nhận các hành động.

Điều cuối cùng cần hiển thị bây giờ là nếu chúng ta quay lại terminal và kiểm tra cụm của mình, bạn có thể thấy rằng chúng ta có 5 pod cho các pod Pacman và storageclass của chúng ta bây giờ được đặt thành standard thay vì csi-hostpath-sc

Nhiều tùy chọn khác nhau có thể đạt được thông qua chuyển đổi. Điều này không chỉ bao gồm di chuyển mà còn cả các kịch bản Khôi phục Thảm họa, thử nghiệm và phát triển và nhiều hơn nữa.

API và Tự động hóa

Tôi chưa đề cập đến khả năng tận dụng API và tự động hóa một số tác vụ này, nhưng các tùy chọn này có sẵn và trong giao diện người dùng, có một số chỉ dẫn cung cấp các bộ lệnh để tận dụng các API cho các tác vụ tự động hóa.

Điều quan trọng cần lưu ý về Kasten K10 là khi triển khai, nó được triển khai bên trong cụm Kubernetes và sau đó có thể được gọi thông qua API Kubernetes.

Và vậy là chúng ta đã kết thúc phần về Lưu trữ và Bảo vệ dữ liệu của bạn.

Tài liệu tham khảo

Kết thúc

Vậy là chúng ta đã cùng nhau hoàn thành hành trình 12 ngày học DevOps. Mình hy vọng những kiến thức và kinh nghiệm chia sẻ trong loạt bài viết này đã giúp các bạn có cái nhìn rõ ràng hơn về DevOps cũng như cách áp dụng nó vào công việc thực tế.

Mình xin chân thành cảm ơn các bạn đã dành thời gian theo dõi và học hỏi cùng mình. Sự ủng hộ và phản hồi của các bạn là động lực lớn để mình tiếp tục chia sẻ những kiến thức hữu ích hơn nữa.

Nếu các bạn có bất kỳ câu hỏi hay thắc mắc nào, đừng ngần ngại để lại bình luận hoặc liên hệ với mình. Mình rất mong được nghe ý kiến và góp ý từ các bạn.

Chúc các bạn thành công trên con đường sự nghiệp và luôn đạt được những thành tựu mới!

Hẹn gặp lại các bạn trong những bài viết tiếp theo.

Các bài viết là bản tiếng Việt của tài liệu 90DaysOfDevOps của Micheal Cade và có qua sửa đổi, bổ sung. Tất cả đều có license [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License][cc-by-nc-sa]

Mọi thắc mắc xin hãy liên hệ
Email: [email protected]

(Nguồn: vntechies.dev)

Previous page 1 2

Related Articles

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top button