ubuntu install kasten

Kasten 精英训练营教材升级 - 加入基于CSI快照的备份操作

前言

创新与迭代是 Veeam 的核心价值观之一,我们近日又对 Kasten 精英训练营的教材进行了升级, 在新升级的教材中有以下更新。

  • 升级 Ubuntu 到 22.04,继利用4C,8G,200G 这个单个虚拟机配置完成实验
  • 使用 External Hostpath CSI 和 External Snapshotter
  • Kasten K10 升级到 5.0.11
  • 利用 Kasten 调用 Hostpath CSI 和 快照进行备份

本文主要内容

[toc]

作者观察 -- 来自 KubeCon 的消息

近日 KubeCon + CloudNativeCon 2022 在底特律的密歇根市如期进行,做为钻石级赞助商的 Kasten by Veeam 在 KubeCon 宣布推出全新的 Kasten by Veeam K10 V5.5,这将包括一系列新的功能。

20221030160606

Kasten K10 V5.5 的新功能包括:

  • 智能策略
    Kasten K10 具有智能决策功能,可大规模简化数据保护流程。用户可以依策略建议在非高峰时间指定备份时间窗口。Kasten K10 不仅会灵活的建议备份时间窗口,还会进一步自动化底层备份作业的排序。这优化了底层基础设施的利用率,并可以在多个策略时并发时自动处理冲突。

  • 提高部署和扩展的便利性
    Kasten K10 通过提供直观的图形向导来生成最合适的安装清单,以进一步简化了部署环节。Kasten K10 5.5 还支持IPv6,支持 Amazon EKS 与 IPv6 Pod 间通信和 GitOps 工作流集成,提供可扩展的工作流以实现高效的应用程序部署以及备份/恢复。

  • 扩展的云原生生态系统
    确保客户能够在不断增加的工作负载类型、地理区域、存储类型和安全性方面获得最新的进步。Kasten K10 现在支持 RedHat OpenShift 虚拟化,使您能够在 Red Hat OpenShift 上并行运行和管理 VM 和容器工作负载。此外,Kasten K10 增加了对 OCP 4.10、Kubernetes 1.23、Azure 文件服务作为备份目标和 Azure 托管身份的支持,以及 AWS 和 GCP 更多区域的支持。

Kasten by Veeam Announces NEW Kasten K10 V5.5 to Simplify Kubernetes Data Protection at Scale with Autonomous Operations and Cloud Native Expansion
https://www.veeam.com/news/kasten-by-veeam-announces-new-kasten-k10-v5-5-to-simplify-kubernetes-data-protection-at-scale-with-autonomous-operations-and-cloud-native-expansion.html
kubeCon + CloudnativeCon 大会详情
https://events.linuxfoundation.org/kubecon-cloudnativecon-north-america/

1. Kasten K10 实验环境准备

1.1. 配置虚拟机

  • 虚拟机配置
    4C 8G 200G HDD, IP: NAT + Static IP, User: Supervisors User and Root(Option)
  • 操作系统
    Ubuntu 20.04 LTS or Ubuntu 22.04 LTS 为了实验方便,Desktop 版本就可以使用。可使用以下链接进行下载。

    Ubuntu 下载链接

1.2. 虚拟机系统环境准备

在安装了操作系统之后,我们要对虚拟机进行一系列软件包的安装

#主机配置,option 自己了解环境就好
$ sudo apt install systemd
#hostname config
$ hostnamectl set-hostname mars-k8s1 $hostnamectl
$ sudo apt install vim
# 多节点时用 (Option)
$ sudo vim /etc/hosts
172.16.124.70 mars-k8s-master1
172.16.124.71 mars-k8s-worker1
# 软件配置,option 自己了解环境就好
$ sudo apt-get install openssh-server
$ sudo apt-get install -y apt-transport-https ca-certificates \
curl gnupg lsb-release
$ sudo apt-get update
# 安装 helm
$ sudo snap install helm --classic

1.3. Docker安装环境准备

#Docker 环境清理
$ sudo apt-get remove -y docker docker-engine \ docker.io containerd runc
#关闭 Swap
$ sudo swapoff -a
$ sudo sed -i -e '/swap/d' /etc/fstab $ swapon --show
#安装Docker 环境
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg \ | sudo gpg --dearmor \
-o /usr/share/keyrings/docker-archive-keyring.gpg
$ echo \
"deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu
$(lsb_release -cs) stable" \
| sudo tee /etc/apt/sources.list.d/docker.list
$ sudo apt-get update
$ sudo apt-get install -y docker-ce docker-ce-cli containerd.io
$ sudo mkdir -p /etc/docker
$ cat <<EOF | sudo tee /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=systemd"], "log-driver": "json-file",
"log-opts": {"max-size": "100m"}, "storage-driver": "overlay2"
} EOF
# Docker 开机启动,赋权
$ sudo systemctl restart docker
$ sudo systemctl enable docker
$ sudo usermod -aG docker $USER

1.4. Kubernetes安装与配置

#kubernetes Install
$ curl -s https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | sudo apt-key add -
$ sudo tee /etc/apt/sources.list.d/kubernetes.list <<EOF
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF
$ sudo apt-get update
$ sudo apt-get install -y kubeadm=1.23.1-00 kubectl=1.23.1-00 kubelet=1.23.1-00
#kubernetes 开机启动
$ sudo systemctl enable kubelet
$ sudo -i
# 以下带♯命令需要在Root权限下运行
♯ systemctl enable kubelet 
♯ systemctl stop etcd
♯ rm -rf /var/lib/etcd
# kubernetes 集群初始化
♯ kubeadm init --kubernetes-version=1.23.1 --pod-network-cidr 10.16.0.0/16 --image-repository registry.aliyuncs.com/google_containers
♯ exit
# 设置kubeconfig
$ mkdir -p $HOME/.kube
$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config $ sudo chown $(id -u):$(id -g) $HOME/.kube/config
# 查看 Node 状态
$ kubectl get node
# 去除污点
$ kubectl taint nodes --all node-role.kubernetes.io/master-

1.5. 配置 Kubernetes网络

#安装 CNI
$ kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml
#查看 Calico 服务启动的情况
$ kubectl get pod -n kube-system -w
#注意 CNI 在这里是 Calico 是 CoreDNS 启动的前题条件,Pull Image 有时需要等待和自查。

$ kubectl get po -n kube-system
NAMESPACE     NAME                                       READY   STATUS    RESTARTS      AGE
kube-system   calico-kube-controllers-54965c7ccb-w944s   1/1     Running   0             40m
kube-system   calico-node-rzrww                          1/1     Running   0             39m
kube-system   coredns-6d8c4cb4d-5gz58                    1/1     Running   0             39m
kube-system   coredns-6d8c4cb4d-kl28q                    1/1     Running   0             39m
kube-system   etcd-mars-k8s-1                            1/1     Running   2 (32m ago)   8h
kube-system   kube-apiserver-mars-k8s-1                  1/1     Running   2 (32m ago)   8h
kube-system   kube-controller-manager-mars-k8s-1         1/1     Running   2 (32m ago)   8h
kube-system   kube-proxy-k78cr                           1/1     Running   2 (32m ago)   8h
kube-system   kube-scheduler-mars-k8s-1                  1/1     Running   3 (32m ago)   8h

1.6.安装配置存储与快照组件 StorageClass 和 VolumeSnapshotClass

HostPath 是一种云原生存储类型,它使用的卷是指计划运行 Pod 的节点(虚拟机/计算机)上的目录。我们将为 Kubernetes 集群启用 HostPath 并测试 VolumeSnapshot 功能,这是 Kasten k10 运行的先决条件。请按照以下步骤安装和验证主机路径 CSI 驱动程序:

1.6.1 安装存储类与快照类

安装 volumesnapshot, volumesnapshotcontent, volumesnapshotclass crds

# Create snapshot controller CRDs
$ kubectl apply -f https://github.com/kubernetes-csi/external-snapshotter/raw/v5.0.1/client/config/crd/snapshot.storage.k8s.io_volumesnapshotclasses.yaml
$ kubectl apply -f https://github.com/kubernetes-csi/external-snapshotter/raw/v5.0.1/client/config/crd/snapshot.storage.k8s.io_volumesnapshotcontents.yaml
$ kubectl apply -f https://github.com/kubernetes-csi/external-snapshotter/raw/v5.0.1/client/config/crd/snapshot.storage.k8s.io_volumesnapshots.yaml

# Create snapshot controller
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/${SNAPSHOTTER_VERSION}/deploy/kubernetes/snapshot-controller/rbac-snapshot-controller.yaml
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/${SNAPSHOTTER_VERSION}/deploy/kubernetes/snapshot-controller/setup-snapshot-controller.yaml

External snapshot CRDs and Controller 参考链接
external snapshotter controller
external snapshotter crd

1.6.2 配置 CSI-Driver 部署脚本

$ git clone https://github.com/kubernetes-csi/csi-driver-host-path.git
$ cd csi-driver-host-path/deploy/kubernetes-1.XX
$ ./deploy.sh

# 查看运行情况 
$kubectl get po -A
NAMESPACE     NAME                                       READY   STATUS    RESTARTS        AGE
default       csi-hostpath-socat-0                       1/1     Running   0               4m47s
default       csi-hostpathplugin-0                       8/8     Running   0               4m47s
kube-system   calico-kube-controllers-54965c7ccb-w944s   1/1     Running   0               5h46m
kube-system   calico-node-rzrww                          1/1     Running   0               5h46m
kube-system   coredns-6d8c4cb4d-5gz58                    1/1     Running   0               5h45m
kube-system   coredns-6d8c4cb4d-kl28q                    1/1     Running   0               5h46m
kube-system   etcd-mars-k8s-1                            1/1     Running   2 (5h39m ago)   13h

# csi-hostpathplugin 包括 8 个 容器,看名字我们可以大体知道它们的作用
$ kubectl describe po csi-hostpathplugin-0 |grep Image:
    Image:         registry.k8s.io/sig-storage/hostpathplugin:v1.9.0
    Image:         registry.k8s.io/sig-storage/csi-external-health-monitor-controller:v0.6.0
    Image:         registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.5.1
    Image:         registry.k8s.io/sig-storage/livenessprobe:v2.7.0
    Image:         registry.k8s.io/sig-storage/csi-attacher:v3.5.0
    Image:         registry.k8s.io/sig-storage/csi-provisioner:v3.2.1
    Image:         registry.k8s.io/sig-storage/csi-resizer:v1.5.0
    Image:         registry.k8s.io/sig-storage/csi-snapshotter:v6.0.1

1.6.3 查看与配置 storageclass 与 snapshotclass

# 存储类
$ kubectl get sc
NAME                        PROVISIONER           RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
csi-hostpath-sc (default)   hostpath.csi.k8s.io   Retain          Immediate           false                  3s
# 快照类
$ kubectl get volumesnapshotclasses
NAME                     DRIVER                DELETIONPOLICY   AGE
csi-hostpath-snapclass   hostpath.csi.k8s.io   Delete           31m

# 标记存储类给K10
$ kubectl annotate volumesnapshotclass csi-hostpath-snapclass k10.kasten.io/is-snapshot-class=true
volumesnapshotclass.snapshot.storage.k8s.io/csi-hostpath-snapclass annotated
# 为存储类标记 snapshotclass
$ kubectl annotate storageclass csi-hostpath-sc k10.kasten.io/volume-snapshot-class=csi-hostpath-snapclass

1.6.4. 用 Kasten Pre-Flight Checks 脚本验证存储类与快照是否工作正常

$ curl https://docs.kasten.io/tools/k10_primer.sh | bash
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  7113  100  7113    0     0  12513      0 --:--:-- --:--:-- --:--:-- 12522
Namespace option not pbashrovided, using default namespace
Checking for tools
 --> Found kubectl
 --> Found helm
Checking if the Kasten Helm repo is present
 --> The Kasten Helm repo was found
Checking for required Helm version (>= v3.0.0)
 --> No Tiller needed with Helm v3.7.0
K10Primer image
 --> Using Image (gcr.io/kasten-images/k10tools:5.0.11) to run test
Checking access to the Kubernetes context kubernetes-admin@kubernetes
 --> Able to access the default Kubernetes namespace
K10 Kanister tools image
 --> Using Kanister tools image (ghcr.io/kanisterio/kanister-tools:0.83.0) to run test

Running K10Primer Job in cluster with command- 
     ./k10tools primer
serviceaccount/k10-primer created
clusterrolebinding.rbac.authorization.k8s.io/k10-primer created
job.batch/k10primer created
Waiting for pod k10primer-lfc5l to be ready - ContainerCreating
Waiting for pod k10primer-lfc5l to be ready - ContainerCreating
Pod Ready!

Kubernetes Version Check:
  Valid kubernetes version (v1.23.1)  -  OK

RBAC Check:
  Kubernetes RBAC is enabled  -  OK

Aggregated Layer Check:
  The Kubernetes Aggregated Layer is enabled  -  OK

         Found multiple snapshot API group versions, using preferred.
CSI Capabilities Check:
  Using CSI GroupVersion snapshot.storage.k8s.io/v1  -  OK

Validate Generic Volume Snapshot:
  Pod created successfully  -  OK
  GVS Backup command executed successfully  -  OK
  Pod deleted successfully  -  OK

serviceaccount "k10-primer" deleted
clusterrolebinding.rbac.authorization.k8s.io "k10-primer" deleted
job.batch "k10primer" deleted

安装测试用的 workload -- mysql

# add bitnami repo
$ helm repo add bitnami https://charts.bitnami.com/bitnami 
# helm install mysql
$ helm install mysql-release bitnami/mysql --namespace mysql --create-namespace \
 --set auth.rootPassword='Start123' \
 --set primary.persistence.size=10Gi
# check mysql status
$ kubectl get all -n mysql
NAME                  READY   STATUS    RESTARTS   AGE
pod/mysql-release-0   1/1     Running   0          99s

NAME                             TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
service/mysql-release            ClusterIP   10.104.247.217   <none>        3306/TCP   48m
service/mysql-release-headless   ClusterIP   None             <none>        3306/TCP   48m

NAME                             READY   AGE
statefulset.apps/mysql-release   1/1     48m

2. Kasten K10 的安装与配置

2.1. 安装 Kasten K10

# Add helm chart for Kasten
$ helm repo add kasten https://charts.kasten.io/ 
# Check if kasten repo already added
$ helm repo list
# Fetch the charts
$ helm fetch kasten/k10 --version=5.0.11
# install kasten with following parameters
$ helm install k10 k10-6.0.2.tgz --namespace kasten-io --create-namespace --set global.airgapped.repository=ccr.ccs.tencentyun.com/kasten \
--set auth.tokenAuth.enabled=true \
--set metering.mode=airgap \
--set injectKanisterSidecar.enabled=true \
--set-string injectKanisterSidecar.namespaceSelector.matchLabels.k10/injectKanisterSidecar=true \
--set global.persistence.storageClass=csi-hostpath-sc

$ helm install k10 k10-6.0.2.tgz --namespace kasten-io --create-namespace --set global.airgapped.repository=public.ecr.aws/kasten-images \
--set auth.tokenAuth.enabled=true \
--set metering.mode=airgap \
--set injectKanisterSidecar.enabled=true \
--set-string injectKanisterSidecar.namespaceSelector.matchLabels.k10/injectKanisterSidecar=true \
--set global.persistence.storageClass=csi-hostpath-sc

# 要确定所有的 Pod 都是 Running 状态才能进行下一步
$ kubectl get po -n kasten-io
NAME                                     READY   STATUS    RESTARTS   AGE
aggregatedapis-svc-5cb69ccb87-f728h      1/1     Running   0          7m18s
auth-svc-59f8597cd-kkm87                 1/1     Running   0          7m19s
catalog-svc-5cc7f8c865-g9wqt             2/2     Running   0          7m18s
controllermanager-svc-64c5fcf9c4-ncwjf   1/1     Running   0          7m19s
crypto-svc-cf68bdd99-n528w               4/4     Running   0          7m19s
dashboardbff-svc-669449d5f4-kxhrw        1/1     Running   0          7m19s
executor-svc-56d8fff95d-7q9gf            2/2     Running   0          7m19s
executor-svc-56d8fff95d-kc769            2/2     Running   0          7m19s
executor-svc-56d8fff95d-zzmhm            2/2     Running   0          7m19s
frontend-svc-7bff945b6c-mndws            1/1     Running   0          7m19s
gateway-78946b9fd7-rsq4t                 1/1     Running   0          7m19s
jobs-svc-c556bffd7-jgwng                 1/1     Running   0          7m18s
k10-grafana-58b85c856d-8pctz             1/1     Running   0          7m19s
kanister-svc-6db7f4d4bc-nhxdw            1/1     Running   0          7m19s
logging-svc-7b87c6dc8-zqfgg              1/1     Running   0          7m19s
metering-svc-b45bfb675-xzp26             1/1     Running   0          7m19s
prometheus-server-64877fdd68-z4ws6       2/2     Running   0          7m19s
state-svc-786864ddc6-tk99x               2/2     Running   0          7m18s

# 设置采 Kasten k10 的 Gateway Service 暴露出来,用 Node Port 方式访问 GUI
$ kubectl expose service gateway -n kasten-io --type=NodePort --name=gateway-nodeport
$ kubectl get svc -n kasten-io gateway-nodeport
NAME               TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
gateway-nodeport   NodePort   10.97.233.211   <none>        8000:32612/TCP   93s
$ kubectl get nodes -owide
NAME         STATUS   ROLES                  AGE   VERSION   INTERNAL-IP    EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME
mars-k8s-1   Ready    control-plane,master   20h   v1.23.1   172.16.60.90   <none>        Ubuntu 22.04.1 LTS   5.15.0-52-generic   docker://20.10.21 

☞ 浏览器访问 K10 UI: http://172.16.60.90:32612/k10/#

20221030200444

2.2. 登录 Kasten K10 GUI 管理界面

☞ 浏览器访问:http://172.16.60.90:32612/k10/#

☞ 用以下命令得到 Token, 以登录到 K10 控制台

$ sa_secret=$(kubectl get serviceaccount k10-k10 -o jsonpath="{.secrets[0].name}" --namespace kasten-io) && kubectl get secret $sa_secret --namespace kasten-io -ojsonpath="{.data.token}{'\n'}" | base64 --decode

☞ 以登录到 K10 控制台

20221030200658

2.3. 安装 MinIO 做为存储库

# Create MinIO Namespace
$ kubectl create ns minio
# Create MinIO by manifest
$ cat <<EOF | kubectl -n minio create -f -
apiVersion: v1
kind: Service
metadata:
  name: minio
spec:
  ports:
  - port: 9000
    targetPort: 9000
  selector:
    app: minio
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: minio-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 30Gi
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: minio
spec:
  serviceName: "minio"
  replicas: 1
  selector:
    matchLabels:
      app: minio
  template:
    metadata:
      labels:
        app: minio
    spec:
      volumes:
      - name: data
        persistentVolumeClaim:
          claimName: minio-pvc
      containers:
      - name: minio
        volumeMounts:
        - name: data 
          mountPath: "/data"
        image: minio/minio:RELEASE.2020-12-10T01-54-29Z
        args:
        - server
        - /data
        env:
        - name: MINIO_ACCESS_KEY
          value: "minio"
        - name: MINIO_SECRET_KEY
          value: "minio123"
        ports:
        - containerPort: 9000
          hostPort: 9000
EOF

#Check if MinIO Service running normally
$ kubectl get all -n minio
NAME          READY   STATUS    RESTARTS   AGE
pod/minio-0   1/1     Running   0          21m

NAME            TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
service/minio   ClusterIP   10.110.230.23   <none>        9000/TCP   21m

NAME                     READY   AGE
statefulset.apps/minio   1/1     21m 

#Expose MinIO Service for UI Acess
$ kubectl expose service minio -n minio --type=NodePort --name=minio-nodeport
$ kubectl get svc -n minio && kubectl get node -o wide
NAME             TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
minio            ClusterIP   10.110.230.23    <none>        9000/TCP         23m
minio-nodeport   NodePort    10.106.243.153   <none>        9000:31106/TCP   29s
NAME         STATUS   ROLES                  AGE   VERSION   INTERNAL-IP    EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME
mars-k8s-1   Ready    control-plane,master   21h   v1.23.1   172.16.60.90   <none>        Ubuntu 22.04.1 LTS   5.15.0-52-generic   docker://20.10.21

☞ 浏览器访问:http://172.16.60.90:31106/
Access Key: minio
Secret Key: minio123

☞ 点击硬盘图标,Create 名为 Kasten 的 Bucket

20221030201637

2.4. 在 K10 中配置MinIO做为存储库

在 K10 控制台配置存储库

主界面 Settings > Locations > Location Profiles > New Profiles

20221030201456

设定如下参数,点击 “Save Profile”

  • Profile Name: minio
  • Cloud Storage Provider: S3 Compatible
  • Access Key: minio
  • Secret Key: minio123
  • Endpoint: http://minio.minio:9000
  • Check ☑ Skip certificate chain and hostname verification
  • Region:
  • Bucket: kasten

3. 利用快照进行应用程序的备份与恢复

3.1. K10 应用程序发现

主界面 > Applications > mysql 找到我们需要备份的应用

20221030202513

3.2. 创建 Policy 保护 mysql 应用

点击 Crete Policy > 创建备份的策略

选项一切都可默认,点击Create Policy

20221030202924

3.3. 执行备份策略

主界面 > Policies > mysql-backup > Run Once 执行应用备份

20221030203033

3.4. 查看 Dashboard 与命令行中查看备份的执行情况

主界面 > Actions > Policy Run > 点击运行任务查看备份结果

20221030203404

在命令行上查看快照调用的情况

# 查看 volumesnapshot
$ kubectl get volumesnapshot -n mysql
NAME                            READYTOUSE   SOURCEPVC              SOURCESNAPSHOTCONTENT   RESTORESIZE   SNAPSHOTCLASS            SNAPSHOTCONTENT                                    CREATIONTIME   AGE
k10-csi-snap-r4tn4qk94h674rpg   true         data-mysql-release-0                           10Gi          csi-hostpath-snapclass   snapcontent-af9a8c05-b077-4294-aa4f-e7e1d4265759   2d             2d
# 查看 volumesnapshotcontent
$ kubectl get volumesnapshotcontent -n mysql
NAME                                               READYTOUSE   RESTORESIZE   DELETIONPOLICY   DRIVER                VOLUMESNAPSHOTCLASS      VOLUMESNAPSHOT                  VOLUMESNAPSHOTNAMESPACE   AGE
snapcontent-af9a8c05-b077-4294-aa4f-e7e1d4265759   true         10737418240   Delete           hostpath.csi.k8s.io   csi-hostpath-snapclass   k10-csi-snap-r4tn4qk94h674rpg   mysql                     2d

3.5. 在 K10 中还原 mysql 数据到另一个 Namespace

主界面 > Applications > mysql > 点击 Restore查看还原点

20221030204015

点击还原点 > 在 Applications Name 下 > 点击 Create a New Namespace > 输入 mysql-restore > 点击 Create > 点击 Restore

20221030204220

在 Confirm Restore 对话框中, 点击 Restore
20221030204522

3.6.查看 Dashboard 上 mysql-restore 数据还原的情况

20221030204811

3.7.对数据还原的情况进行分析

此时,让我们来观察一下快照的还原机制,通过查看 volumesnapshotcontent, 我们可以发现这里有一个名为 k10-csi-snap-wh9m8wgjg5gzj2x4 的快照,它的快照类为 k10-clone-csi-hostpath-snapclass, DELETIONPOLICY 为 Retain, 很明显这是 K10 为还原而创建的。同时,在对这个 mysql-restore 的 PVC 的描述时,可以发现,这就是源自于这个快照的。

$ kubectl get volumesnapshotcontent -n mysql-restore
NAME                                                                         READYTOUSE   RESTORESIZE   DELETIONPOLICY   DRIVER                VOLUMESNAPSHOTCLASS                VOLUMESNAPSHOT                  VOLUMESNAPSHOTNAMESPACE   AGE
k10-csi-snap-wh9m8wgjg5gzj2x4-content-9e561840-c004-4e0f-88e9-6c7374438a2f   true         10737418240   Retain           hostpath.csi.k8s.io   k10-clone-csi-hostpath-snapclass   k10-csi-snap-wh9m8wgjg5gzj2x4   mysql-restore             2m41s
snapcontent-af9a8c05-b077-4294-aa4f-e7e1d4265759                             true         10737418240   Delete           hostpath.csi.k8s.io   csi-hostpath-snapclass             k10-csi-snap-r4tn4qk94h674rpg   mysql                     2d1h

$ kubectl get pvc -n mysql-restore
mysql-restore   data-mysql-release-0   Bound    pvc-13d8ed12-0173-4f59-b7d5-b5b01d98ea16   1        csi-hostpath-sc   4m51s

$ kubectl -n mysql-restore describe pvc data-mysql-release-0
Name:          data-mysql-release-0
Namespace:     mysql-restore
StorageClass:  csi-hostpath-sc
Status:        Bound
Volume:        pvc-13d8ed12-0173-4f59-b7d5-b5b01d98ea16
Labels:        app.kubernetes.io/component=primary
               app.kubernetes.io/instance=mysql-release
               app.kubernetes.io/name=mysql
Annotations:   pv.kubernetes.io/bind-completed: yes
               pv.kubernetes.io/bound-by-controller: yes
               volume.beta.kubernetes.io/storage-provisioner: hostpath.csi.k8s.io
               volume.kubernetes.io/storage-provisioner: hostpath.csi.k8s.io
Finalizers:    [kubernetes.io/pvc-protection]
Capacity:      10Gi
Access Modes:  RWO
VolumeMode:    Filesystem
DataSource:
  APIGroup:  snapshot.storage.k8s.io
  Kind:      VolumeSnapshot
  Name:      k10-csi-snap-wh9m8wgjg5gzj2x4
Used By:     mysql-release-0
Events:
  Type    Reason                 Age    From                                                                           Message
  ----    ------                 ----   ----                                                                           -------
  Normal  ExternalProvisioning   7m29s  persistentvolume-controller                                                    waiting for a volume to be created, either by external provisioner "hostpath.csi.k8s.io" or manually created by system administrator
  Normal  Provisioning           7m29s  hostpath.csi.k8s.io_csi-hostpathplugin-0_38bf5516-630c-48d9-abf4-56ec8da0599b  External provisioner is provisioning volume for claim "mysql-restore/data-mysql-release-0"
  Normal  ProvisioningSucceeded  7m28s  hostpath.csi.k8s.io_csi-hostpathplugin-0_38bf5516-630c-48d9-abf4-56ec8da0599b  Successfully provisioned volume pvc-13d8ed12-0173-4f59-b7d5-b5b01d98ea16

4. 总结

本文中我们利用一个简单的 Ubuntu 虚拟机,创建了存储类与快照类,并利用 Kasten K10 对调用快照进行备份与还原,使大家在做 K10 的实验时,可以得到与企业级存储快照同样的体验,欢迎关注并转发!

5. 参考链接

Ubuntu 下载链接
https://ubuntu.com/download
external snapshotter controller
https://github.com/kubernetes-csi/external-snapshotter/tree/master/deploy/kubernetes/snapshot-controller
external snapshotter crd
https://github.com/kubernetes-csi/external-snapshotter/tree/v5.0.1/client/config/crd
Kasten Document
https://docs.kasten.io/latest/

kubectl get --raw /apis/apps.kio.kasten.io/v1alpha1/
{"kind":"APIResourceList","apiVersion":"v1","groupVersion":"apps.kio.kasten.io/v1alpha1","resources":[{"name":"applications","singularName":"","namespaced":true,"kind":"Application","verbs":["get","list"]},{"name":"applications/details","singularName":"","namespaced":true,"kind":"Application","verbs":["get"]},{"name":"clusterrestorepoints","singularName":"","namespaced":false,"kind":"ClusterRestorePoint","verbs":["delete","get","list"]},{"name":"clusterrestorepoints/details","singularName":"","namespaced":false,"kind":"ClusterRestorePoint","verbs":["get"]},{"name":"restorepointcontents","singularName":"","namespaced":false,"kind":"RestorePointContent","verbs":["delete","get","list"]},{"name":"restorepointcontents/details","singularName":"","namespaced":false,"kind":"RestorePointContent","verbs":["get"]},{"name":"restorepoints","singularName":"","namespaced":true,"kind":"RestorePoint","verbs":["create","delete","get","list"]},{"name":"restorepoints/details","singularName":"","namespaced":true,"kind":"RestorePoint","verbs":["get"]}]}

> kubectl get -n kasten-io reports.reporting.kio.kasten.io -oyaml
apiVersion: v1
items:
- apiVersion: reporting.kio.kasten.io/v1alpha1
  kind: Report
  metadata:
    creationTimestamp: "2023-03-22T09:46:18Z"
    generateName: scheduled-v4bsr-
    generation: 1
    labels:
      k10.kasten.io/doNotRetire: "true"
    name: scheduled-v4bsr-rrhwk
    namespace: kasten-io
    resourceVersion: "63811398"
    uid: afe8c694-d9db-4faa-afa3-3d9d4583c4e3
  results:
    actions:
      countStats:
        backup:
          cancelled: 0
          completed: 0
          failed: 0
          skipped: 0
        backupCluster:
          cancelled: 0
          completed: 1
          failed: 0
          skipped: 0
        export:
          cancelled: 0
          completed: 0
          failed: 0
          skipped: 0
        import:
          cancelled: 0
          completed: 0
          failed: 0
          skipped: 0
        report:
          cancelled: 0
          completed: 0
          failed: 0
          skipped: 0
        restore:
          cancelled: 0
          completed: 0
          failed: 0
          skipped: 0
        restoreCluster:
          cancelled: 0
          completed: 0
          failed: 0
          skipped: 0
        run:
          cancelled: 0
          completed: 1
          failed: 0
          skipped: 0
    compliance:
      applicationCount: 30
      compliantCount: 0
      nonCompliantCount: 0
      unmanagedCount: 30
    general:
      authType: token
      clusterId: 0a25e9a4-1de6-4e9f-bb6a-cf89af14e804
      infraType:
        isOpenShift: false
        provider: unknown
      k8sVersion: v1.23.13+rke2r1
      k10Version: 5.5.6
      k10namespace: kasten-io
    k10Services:
    - diskUsage:
        freeBytes: 6490685440
        freePercentage: 15
        usedBytes: 36436967424
      name: logging
    - diskUsage:
        freeBytes: 6490685440
        freePercentage: 15
        usedBytes: 36436967424
      name: catalog
    - diskUsage:
        freeBytes: 6490685440
        freePercentage: 15
        usedBytes: 36436967424
      name: jobs
    licensing:
      expiry: null
      nodeCount: 3
      nodeLimit: 5
      status: Valid
      type: Starter
    policies:
      k10DR:
        backupFrequency: '@onDemand'
        immutability:
          protection: Disabled
          protectionDays: 0
        profile: minio
        status: Enabled
      summaries:
      - actions:
        - backup
        frequency: '@hourly'
        name: cluster-scoped-resources-backup
        namespace: kasten-io
        profileNames: []
        validation: Success
      - actions:
        - report
        frequency: '@daily'
        name: k10-system-reports-policy
        namespace: kasten-io
        profileNames: []
        validation: Success
      - actions:
        - backup
        frequency: '@onDemand'
        name: pwms-backup
        namespace: kasten-io
        profileNames:
        - minio
        validation: Success
    profiles:
      summaries:
      - bucket: kasten
        endpoint: http://10.0.4.3:9000
        immutability:
          protection: Disabled
          protectionDays: 0
        name: minio
        objectStoreType: S3
        region: local
        sslVerification: SkipVerification
        type: Location
        validation: Success
    storage:
      objectStorage:
        count: 8
        logicalBytes: 4249154357
        physicalBytes: 16511882
      pvcStats:
        pvcBytes: 166429982720
        pvcCount: 19
      snapshotStorage:
        count: 0
        logicalBytes: 0
        physicalBytes: 0
  spec:
    reportTimestamp: "2023-03-22T09:46:14Z"
    statsIntervalDays: 1
    statsIntervalEndTimestamp: "2023-03-22T09:46:14Z"
    statsIntervalStartTimestamp: "2023-03-21T09:46:14Z"
kind: List
metadata:
  resourceVersion: ""
  selfLink: ""

kubectl get storagerepositories.repositories.kio.kasten.io kopia-volumedata-repository-trvcz5f4jv --namespace kasten-io -oyaml
apiVersion: repositories.kio.kasten.io/v1alpha1
kind: StorageRepository
metadata:
creationTimestamp: "2023-03-03T14:32:53Z"
labels:
k10.kasten.io/appName: pwms
k10.kasten.io/exportProfile: minio
name: kopia-volumedata-repository-trvcz5f4jv
namespace: kasten-io
resourceVersion: "533"
uid: 4823062e-b9d0-11ed-b828-d69ba0d3704c
status:
appName: pwms
backendType: kopia
contentType: volumedata
location:
objectStore:
endpoint: http://10.0.4.3:9000
name: kasten
objectStoreType: S3
path: k10/0a25e9a4-1de6-4e9f-bb6a-cf89af14e804/migration/repo/7bafde09-dd63-41bb-80ab-d3da307a1b79/
pathType: Directory
region: local
skipSSLVerify: true
type: ObjectStore

kubectl get profiles.config.kio.kasten.io --namespace kasten-io
NAME STATUS AGE
minio Success 18d
kubectl get profiles.config.kio.kasten.io minio --namespace kasten-io -oymal
error: unable to match a printer suitable for the output format "ymal", allowed formats are: custom-columns,custom-columns-file,go-template,go-template-file,json,jsonpath,jsonpath-as-json,jsonpath-file,name,template,templatefile,wide,yaml
kubectl get profiles.config.kio.kasten.io minio --namespace kasten-io -oyaml
apiVersion: config.kio.kasten.io/v1alpha1
kind: Profile
metadata:
creationTimestamp: "2023-03-03T14:30:23Z"
generation: 2
name: minio
namespace: kasten-io
resourceVersion: "51712136"
uid: 32bbc40e-a12d-4cde-8c24-32e3bcc5154a
spec:
locationSpec:
credential:
secret:
apiVersion: v1
kind: secret
name: k10secret-n7nx8
namespace: kasten-io
secretType: AwsAccessKey
objectStore:
endpoint: http://10.0.4.3:9000
name: kasten
objectStoreType: S3
path: k10/0a25e9a4-1de6-4e9f-bb6a-cf89af14e804/migration
pathType: Directory
region: local
skipSSLVerify: true
type: ObjectStore
type: Location
status:
hash: 2681627176
validation: Success

kubectl get restorepoints.apps.kio.kasten.io --all-namespaces

kubectl get restorepoints.apps.kio.kasten.io --namespace pwms
NAME CREATED AT
manualbackup-q9qds 2023-03-04T03:31:26Z
scheduled-nj5sn 2023-03-04T03:23:46Z
scheduled-2r89m 2023-03-04T03:10:54Z
scheduled-g64r4 2023-03-04T02:43:26Z

kubectl get restorepoints.apps.kio.kasten.io manualbackup-q9qds --namespace pwms -oyaml

kubectl get restorepoints.apps.kio.kasten.io manualbackup-q9qds --namespace pwms -oyaml
kubectl get restorepoints.apps.kio.kasten.io scheduled-6wcb7 --namespace nginx-example -oyaml
apiVersion: apps.kio.kasten.io/v1alpha1
kind: RestorePoint
metadata:
creationTimestamp: "2023-03-04T03:31:26Z"
labels:
k10.kasten.io/appName: pwms
k10.kasten.io/appNamespace: pwms
name: manualbackup-q9qds
namespace: pwms
resourceVersion: "535"
uid: 0bac9a5a-ba3d-11ed-b828-d69ba0d3704c
spec:
restorePointContentRef:
name: pwms-manualbackup-q9qds
status:
actionTime: "2023-03-04T03:31:26Z"
logicalSizeBytes: 1030000000
physicalSizeBytes: 271

kubectl get restorepointcontents.apps.kio.kasten.io \
--selector=k10.kasten.io/appName=pwms

kubectl get restorepointcontents.apps.kio.kasten.io \
--selector=k10.kasten.io/appName=pwms
NAME CREATED AT
pwms-manualbackup-q9qds 2023-03-04T03:31:26Z
pwms-scheduled-nj5sn 2023-03-04T03:23:46Z
pwms-scheduled-2r89m 2023-03-04T03:10:54Z
pwms-scheduled-g64r4 2023-03-04T02:43:26Z

kubectl get restorepointcontents.apps.kio.kasten.io pwms-scheduled-nj5sn -oyaml

kubectl get restorepointcontents.apps.kio.kasten.io pwms-scheduled-nj5sn -oyaml
apiVersion: apps.kio.kasten.io/v1alpha1
kind: RestorePointContent
metadata:
creationTimestamp: "2023-03-04T03:23:46Z"
labels:
k10.kasten.io/appName: pwms
k10.kasten.io/appNamespace: pwms
k10.kasten.io/isRunNow: "true"
k10.kasten.io/policyName: pwms-backup
k10.kasten.io/policyNamespace: kasten-io
k10.kasten.io/runActionName: policy-run-mdrz4
name: pwms-scheduled-nj5sn
resourceVersion: "426"
uid: f90630ed-ba3b-11ed-b828-d69ba0d3704c
status:
actionTime: "2023-03-04T03:23:46Z"
restorePointRef:
name: scheduled-nj5sn
namespace: pwms
scheduledTime: "2023-03-04T03:23:39Z"
state: Bound

kubectl get restorepoints.apps.kio.kasten.io --all-namespaces
NAMESPACE NAME CREATED AT
ns05 backup-ns05-hqxzw 2023-03-12T15:04:50Z
ns06 backup-ns06-nrfhn 2023-03-12T15:04:50Z
ns07 backup-ns07-nzbbc 2023-03-12T15:04:50Z
ns03 backup-ns03-z5trx 2023-03-12T15:04:49Z
ns04 backup-ns04-xm26r 2023-03-12T15:04:49Z
ns01 backup-ns01-h9qsh 2023-03-12T15:04:48Z
ns02 backup-ns02-xzszg 2023-03-12T15:04:48Z
ns07 backup-ns07-nn5lk 2023-03-12T15:02:35Z
ns05 backup-ns05-f52hr 2023-03-12T15:02:34Z
ns06 backup-ns06-v5kth 2023-03-12T15:02:34Z
ns02 backup-ns02-sr5qv 2023-03-12T15:02:33Z
ns03 backup-ns03-fd55j 2023-03-12T15:02:33Z
ns04 backup-ns04-9zzbr 2023-03-12T15:02:33Z
ns01 backup-ns01-jsgvk 2023-03-12T15:02:32Z
ns05 backup-ns05-dqrnr 2023-03-12T14:36:46Z
ns06 backup-ns06-lzqnt 2023-03-12T14:36:46Z
ns07 backup-ns07-gxntx 2023-03-12T14:36:46Z
ns03 backup-ns03-gxrll 2023-03-12T14:36:45Z
ns04 backup-ns04-7rns9 2023-03-12T14:36:45Z
ns01 backup-ns01-llttn 2023-03-12T14:36:44Z
ns02 backup-ns02-qt67z 2023-03-12T14:36:44Z
ns07 backup-ns07-6crpb 2023-03-12T13:44:52Z
ns05 backup-ns05-b56vp 2023-03-12T13:44:51Z
ns06 backup-ns06-5dhq5 2023-03-12T13:44:51Z
ns03 backup-ns03-jdzt7 2023-03-12T13:44:50Z
ns04 backup-ns04-p9ffq 2023-03-12T13:44:50Z
ns01 backup-ns01-ng6l4 2023-03-12T13:44:49Z
ns02 backup-ns02-l4rps 2023-03-12T13:44:49Z
ns01 backup-ns01-xt2x6 2023-03-12T13:43:55Z
pwms manualbackup-q9qds 2023-03-04T03:31:26Z
pwms scheduled-nj5sn 2023-03-04T03:23:46Z
pwms scheduled-2r89m 2023-03-04T03:10:54Z
pwms scheduled-g64r4 2023-03-04T02:43:26Z

kubectl get restorepoints.apps.kio.kasten.io manualbackup-q9qds --namespace pwms -oyaml |grep -E 'logicalSizeBytes|physicalSizeBytes'

kubectl get restorepoints.apps.kio.kasten.io scheduled-7s4k72q6gw --namespace mysql-restore -oyaml

for restorepoint in $(kubectl get restorepoints.apps.kio.kasten.io --all-namespaces |wc -l)

do
echo "file: $restorepoints"
done

kubectl get restorepoints.apps.kio.kasten.io --all-namespaces > 1.txt
export text_path=1.txt
cat $text_path |while read i
do
j=echo $i | awk '{print $1}'
k=echo $i | awk '{print $2}'
echo $j
echo $k
kubectl get restorepoints.apps.kio.kasten.io $j --namespace $k -oyaml |grep logicalSizeBytes |awk '{print $2}'
done

l= kubectl get restorepoints.apps.kio.kasten.io $j --namespace $k -oyaml |grep logicalSizeBytes
p= kubectl get restorepoints.apps.kio.kasten.io $j --namespace $k -oyaml |grep physicalSizeBytes
echo $l $p

mars@mars-k8s-1:~$ kubectl get --raw /apis/apps.kio.kasten.io/v1alpha1/applications/items[0]/metadata/name |jq 

kubectl get pods --all-namespaces -o jsonpath="{.items[].spec.containers[].image}" |\
tr -s '[[:space:]]' '\n' |\
sort |\
uniq -c

kubectl get pods --namespace kasten-io -o jsonpath="{.items[].spec.containers[].image}" |\
tr -s '[[:space:]]' '\n' |\
sort |\
uniq -c

  2     image: ccr.ccs.tencentyun.com/kasten/bloblifecyclemanager:6.0.2
  2     image: ccr.ccs.tencentyun.com/kasten/crypto:6.0.2
  2     image: ccr.ccs.tencentyun.com/kasten/events:6.0.2
  2     image: ccr.ccs.tencentyun.com/kasten/garbagecollector:6.0.2

ccr.ccs.tencentyun.com/kasten/admin:6.0.2
ccr.ccs.tencentyun.com/kasten/aggregatedapis:6.0.2
ccr.ccs.tencentyun.com/kasten/auth:6.0.2
ccr.ccs.tencentyun.com/kasten/bloblifecyclemanager:6.0.2
ccr.ccs.tencentyun.com/kasten/catalog:6.0.2
ccr.ccs.tencentyun.com/kasten/cephtool:6.0.2
ccr.ccs.tencentyun.com/kasten/configmap-reload:6.0.2
ccr.ccs.tencentyun.com/kasten/controllermanager:6.0.2
ccr.ccs.tencentyun.com/kasten/crypto:6.0.2
ccr.ccs.tencentyun.com/kasten/dashboardbff:6.0.2
ccr.ccs.tencentyun.com/kasten/emissary:6.0.2
ccr.ccs.tencentyun.com/kasten/events:6.0.2
ccr.ccs.tencentyun.com/kasten/executor:6.0.2
ccr.ccs.tencentyun.com/kasten/frontend:6.0.2
ccr.ccs.tencentyun.com/kasten/garbagecollector:6.0.2
ccr.ccs.tencentyun.com/kasten/grafana:6.0.2
ccr.ccs.tencentyun.com/kasten/jobs:6.0.2
ccr.ccs.tencentyun.com/kasten/kanister:6.0.2
ccr.ccs.tencentyun.com/kasten/kanister-tools:k10-0.93.0
ccr.ccs.tencentyun.com/kasten/logging:6.0.2
ccr.ccs.tencentyun.com/kasten/metering:6.0.2
ccr.ccs.tencentyun.com/kasten/prometheus:6.0.2
ccr.ccs.tencentyun.com/kasten/state:6.0.2
ccr.ccs.tencentyun.com/kasten/vbrintegrationapi:6.0.2

aggregatedapis-svc-7965d69fb8-txrpq 1/1 Running 0 8h
auth-svc-7568966449-hzjfn 1/1 Running 0 8h
catalog-svc-7bd57d5f-pjs5f 2/2 Running 0 8h
controllermanager-svc-7bc6ff9bc-zzl6j 1/1 Running 0 8h
crypto-svc-674465d56d-cf4bt 4/4 Running 0 8h
dashboardbff-svc-5bb989cbd9-gjljx 2/2 Running 0 8h
executor-svc-5ff4d49fcf-29gv8 2/2 Running 0 8h
executor-svc-5ff4d49fcf-d4cws 2/2 Running 0 8h
executor-svc-5ff4d49fcf-fx9q6 2/2 Running 0 8h
frontend-svc-5fcb699996-ktv6n 1/1 Running 0 8h
gateway-d747f797-zt4nw 1/1 Running 0 8h
jobs-svc-88b49cfd5-9j96p 1/1 Running 0 8h
k10-grafana-6d745654f5-4tn4x 1/1 Running 0 8h
kanister-svc-6696987d75-fphts 1/1 Running 0 8h
logging-svc-76bd7c976-cj9zz 1/1 Running 0 8h
metering-svc-554789c888-788mk 1/1 Running 0 8h
prometheus-server-bc497c594-hjv86 2/2 Running 0 8h
state-svc-cb8ddd78b-rklm8 2/2 Running 0 8h

kubectl get pod catalog-svc-7bd57d5f-pjs5f -n kasten-io -o yaml | grep images

kubectl get pod controllermanager-svc-7bc6ff9bc-zzl6j -n kasten-io -o yaml | grep image:
kubectl get pod crypto-svc-674465d56d-cf4bt -n kasten-io -o yaml | grep image:
kubectl get pod state-svc-cb8ddd78b-rklm8 -n kasten-io -o yaml | grep image: |sort|uniq -c
kubectl get pod catalog-svc-7bd57d5f-pjs5f -n kasten-io -o yaml | grep image:
kubectl get pod catalog-svc-7bd57d5f-pjs5f -n kasten-io -o yaml | grep image:
kubectl get pod catalog-svc-7bd57d5f-pjs5f -n kasten-io -o yaml | grep image:
kubectl get pod catalog-svc-7bd57d5f-pjs5f -n kasten-io -o yaml | grep image:
kubectl get pod catalog-svc-7bd57d5f-pjs5f -n kasten-io -o yaml | grep image:
kubectl get pod catalog-svc-7bd57d5f-pjs5f -n kasten-io -o yaml | grep image:
kubectl get pod catalog-svc-7bd57d5f-pjs5f -n kasten-io -o yaml | grep image:
kubectl get pod catalog-svc-7bd57d5f-pjs5f -n kasten-io -o yaml | grep image:
kubectl get pod catalog-svc-7bd57d5f-pjs5f -n kasten-io -o yaml | grep image:
kubectl get pod catalog-svc-7bd57d5f-pjs5f -n kasten-io -o yaml | grep image:

kubectl get po -n kasten-io | awk 'NR>1 {print $1}' |xargs -I{} kubectl get pod {} -n kasten-io -o yaml | grep image: |sort|uniq -c

'{}'

Kasten Kanister Blueprints 详解

本文重要章节

Kasten Kanister Blueprints 详解
1.Kubernetes 原生备份
2.Kanister vs K10
3.Kasten Kanister blurpint 核心概念
3.1 Kanister blurpint 动作集
3.2 Kanister blurpint 核心元素
4.Kasten Kanister Blueprint 备份最佳实践
4.1 Kasten K10 安装
4.2 访问 K10 的仪表盘
4.3 配置数据应用的存储类
4.4 配置 MinIO 对象存储
4.5 在 K10 中配置 Location Profile 备份存储库
4.6 安装 MySQL 建立 Demo 数据库
4.7 在 Mysql 应用中定义 Blueprint 以实现逻辑备份
4.8 创建与运行 K10 备份策略
4.9 模拟灾难 删除 MySQL 数据
4.10 恢复 Mysql 数据
4.11 验证 Mysql 数据恢复效果
5.总结
6.参考链接

1.Kubernetes 原生备份

Kubernetes 作为最快增长的基础架构平台,正在迅速成为所有应用程序的基础,它的部署方式非常灵活,从物理到虚拟再到云都可以适配,这使其成为下一个企业平台的首选。,可以说 Kubernetes 已经成为企业的核心基础架构。

20230601100914

Kubernetes 原生应用的备份是以 Kubernetes 作为基础架构的企业面临的关键问题之一。Kubernetes 平台与以往所有的计算基础架构有着本质的不同,它使用独特的放置与部署策略来在所有服务器上分布应用程序组件,以实现容错和性能。因此,不同应用程序的部署位置可能位于集群的任何地方。此外,云原生环境的动态性也很重要,即容器可以在不同节点上动态重新调度或缩扩容,以实现更好的负载平衡。时时刻刻发生的新部署可能涉及滚动升级,并且新的应用程序组件可以随时添加或删除。简而言之,云原生应用程序的定义不断变化。数据管理解决方案需要了解这种云原生架构模式,能够处理缺乏IP地址稳定性的情况,并能够处理持续的变化。

专为 Kubernetes 而建的 Kasten K10 为企业运维团队提供了一个易于使用、可扩展的应用与数据安全的保护系统,用于 Kubernetes 应用程序的备份/恢复、灾难恢复和迁移等。

2.Kanister vs K10

对于有状态的云原生应用,数据操作通常需要由具有对数据语义理解的工具来执行,其实现效果就是使用数据厂家的原生工具,来执行数据操作,以保证数据的一致性。而在云原生平台有状态的应用。借用是来自于 Dynatrace 的报告 Kubernetes in the wild report 2023 从报告中可以发现,以数据库和数据服务的增长非常快速的。

20230601101453

而 Kubernetes 编排器提供的卷级备份,不足以支持像复杂的分布式数据库的备份/恢复等数据工作流。K10 支持多种社区数据库,包括 MySQL、PostgreSQL、MongoDB 和 Cassandra 等。

为了弥合这些应用程序的操作要求和 Kubernetes 之间的差距,开源项目 Kanister 应运而生。Kanister 是一个框架,用于支持 Kubernetes 中的应用程序级数据管理。它允许开发人员定义工具和应用程序之间的关系,然后使在 Kubernetes 中运行这些工具变得简单。

Kasten 的 K10 平台使用 Kanister 提供的 Kubernetes 自定义资源进行数据管理。这使数据服务领域专家能够在蓝图(Blueprint)中捕获特定于应用程序的数据管理任务,如 数据的备份、恢复、删除,这些任务可以轻松共享和扩展。该框架负责处理在 Kubernetes 上执行的繁琐细节,并在应用程序规模上呈现均匀的操作体验。此外,它为用户提供了一种自然的框架机制,通过添加个人代码来修改执行数据生命周期管理的任何所需步骤,从而扩展 K10 平台。

3.Kasten Kanister blurpint 核心概念

3.1 Kanister blurpint 动作集

数据处理动作(Actions) API 资源是用于启动 Kasten K10 数据管理操作的。这些操作可以与备份策略(Policy)相关联,也可以作为独立的按需操作。操作还允许跟踪所请求操作的执行状态。

Kasten K10平台公开了许多不同的操作类型。

BackupAction
备份操作用于启动应用程序的备份处理过程。备份操作可以作为策略的一部分或作为独立操作提交。

RestoreAction
还原操作用于从还原点将应用程序还原到已知的良好状态。

ExportAction
导出操作用于使用现有还原点将应用程序导出到外部数据存储,例如 S3 兼容的对象存储。

BackupClusterAction
备份集群操作用于启动集群范围资源的备份操作。备份集群操作可以作为策略的一部分或作为独立操作提交。

RestoreClusterAction
还原集群操作用于从 ClusterRestorePoint 还原集群范围资源。还原集群操作可以作为策略的一部分或作为独立操作提交。

RunAction
RunActions 用于手动执行和监视与策略运行相关的操作。

CancelAction
CancelActions 用于停止另一个操作的进度并防止任何剩余的重试。取消是最佳尝试,不是每个操作的每个阶段都可以取消。当操作被取消时,其状态变为已取消。

ReportAction
创建 ReportAction 资源以生成 K10 报告并提供有关系统性能和状态的见解。成功的ReportAction会产生一个K10报告,其中包含在ReportAction时收集的信息。

Kasten Action 定义
https://docs.kasten.io/latest/api/actions.html

3.2 Kanister blurpint 核心元素

Policies - 策略

策略用于自动化数据管理工作流程。策略自定义资源(CR)用于执行 K10 策略的操作。K10 策略允许您在规模上管理应用程序保护和迁移。

K10策略的信息
https://docs.kasten.io/latest/usage/protect.html#protect

Policy Scheduling - 策略时间表

在策略API类型中,K10可控制以下内容:

  • 主快照或导入操作应执行的频率
  • 快照应导出到备份的频率
  • 要保留哪些和多少个快照和备份
  • 主快照或导入操作应在何时执行

Profiles - 备份存储库配置

用于从快照创建备份,将应用程序及其数据在不同集群之间或不同云之间移动,并随后将这些备份或导出导入到另一个集群中。为了启用跨任何一个集群的生命周期的这些操作,需要配置 K10 以访问外部对象存储或外部 NFS 文件存储。这是通过创建

备份存储库配置文件
https://docs.kasten.io/latest/usage/configuration.html#location-profiles

Profile 备份存储库配置,在 K8S 中属于客户自定义资源(CR)用于对 K10 Profiles 执行操作。您可以在备份存储库配置中完成,您可以通过以下的 K10 Profiles 文档了解更多信息。

备份存储库配置
https://docs.kasten.io/latest/usage/configuration.html#k10-config

Kanister-Enabled Applications

在捕获数据服务时,K10 默认使用卷快照操作,但有些情况下需要进行定制。例如,保护应用程序数据的最佳方法可能是对数据库进行逻辑转储。这需要使用特定于该数据库的工具。

Kanister 使用 蓝图 Blueprint 来定义这些特定于数据库的工作流程,并且为多个流行应用程序提供开源蓝图。同时,也可以轻松定制现有的蓝图或添加新的蓝图。
当配置为这样做时,K10 将自动使用 Kanister 蓝图并管理生成的应用程序级别的 Kanister Artifect。

Kanister 开源的蓝图开以从以下 Github 站点中找到。

在 Github 上的 Kanister 开源的蓝图
https://github.com/kanisterio/kanister/tree/master/examples

插入 Kanister 蓝图

若要请求 K10 使用自定义 Kanister Blueprint 来管理工作负载(例如 Deployment 或 StatefulSet ),请按照以下步骤:
(1)在 K10 Namespace ,默认为 kasten-io 中创建 Blueprint
(2)使用已创建的 Blueprint 的名称注释工作负载,如下所示:

$ kubectl --namespace=<app-namespace> annotate <workload>/<workload-name> \
    kanister.kasten.io/blueprint=<blueprint-name>

最后,请注意所使用的 Blueprint 必须定义了 backup 和 restore 等操作,并最好也定义了 delete 操作以便进行数据清理与退役操作。

使用测试用例

安装应用程序后,您将能够使用 K10 仪表板 通过创建一个或多个策略来使应用程序符合规定并保护它。您还可以随后将应用程序及其数据恢复到之前的版本。您可以在本文档的 保护应用程序 和 恢复应用程序 部分中找到更详细的说明。

静默应用

静默是指暂停或更改设备或应用程序以达到一致状态,通常是为了备份或其他维护而进行。如果需要在卷快照启动之前使数据服务静默,则可以启用应用程序一致的备份。

为了获得应用程序一致的备份,首先调用应用程序蓝图中定义的 quiescing function,然后进行卷快照。

为了缩短应用程序暂停的时间,一旦存储系统表明已经开始对底层卷进行时点拷贝,就根据蓝图定义unquiesced。备份将在卷快照完成后异步完成,换句话说,在 unquiescing 应用程序后,K10 等待快照完成。这种方法的优点是在整个卷快照过程中不会锁定数据库。

4.Kasten Kanister Blueprint 备份最佳实践

4.1 Kasten K10 安装

安装 Kasten K10, 安装 Kasten K10 的文章很多,并不是本文的重点,如果希望更多的了解 Kasten K10 的安装,请关注以往的文章。

$ helm install k10 kasten/k10 --namespace=kasten-io --create-namespace
NAME: k10
LAST DEPLOYED: Sat May 13 00:14:07 2023
NAMESPACE: kasten-io
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Thank you for installing Kasten’s K10 Data Management Platform 5.5.10!

Documentation can be found at https://docs.kasten.io/.

How to access the K10 Dashboard:

To establish a connection to it use the following `kubectl` command:

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

The Kasten dashboard will be available at: `http://127.0.0.1:8080/k10/#/`

为了保证 Kasten K10 已经正常的运行起来,我们在这里用 watch命令每 2 秒检查一次每个 Pod 的运行状态,直至所有的 Pod 都已经达到 Running 的状态

$ watch -n 2 "kubectl -n kasten-io get pods"
Every 2.0s: kubectl -n kasten-io get pods                         kubernetes: Sat May 13 00:16:55 2023

NAME                                    READY   STATUS    RESTARTS   AGE
aggregatedapis-svc-7644455fbf-szrmc     1/1     Running   0          2m46s
auth-svc-7ff97f77fb-rx2sd               1/1     Running   0          2m46s
catalog-svc-778544bf69-zdsl6            2/2     Running   0          2m45s
controllermanager-svc-cdc99b667-hkt2n   1/1     Running   0          2m47s
crypto-svc-c4fddb596-t55kl              4/4     Running   0          2m46s
dashboardbff-svc-b4b59cf49-985tg        2/2     Running   0          2m46s
executor-svc-7b59bb5597-5nglj           2/2     Running   0          2m45s
executor-svc-7b59bb5597-l9lmg           2/2     Running   0          2m45s
executor-svc-7b59bb5597-xj69k           2/2     Running   0          2m46s
frontend-svc-56cb4f756c-4jnpx           1/1     Running   0          2m46s
gateway-594c5c8966-s2fgx                1/1     Running   0          2m47s
jobs-svc-65fd8dc85-xwdvs                1/1     Running   0          2m46s
k10-grafana-59cd57f6fc-8lfgb            1/1     Running   0          2m47s
kanister-svc-569d9448b4-rnzrh           1/1     Running   0          2m46s
logging-svc-548c678d7b-vdvhk            1/1     Running   0          2m45s
metering-svc-5c664859d5-fh95f           1/1     Running   0          2m46s
prometheus-server-6884f544d-659lh       2/2     Running   0          2m47s
state-svc-7774c468b6-76266              2/2     Running   0          2m46s

一旦我们确定所有的 Pod 都已经达到运行的状态,我们可以按 CTRL + C 退出 watch

4.2 访问 K10 的仪表盘

我们通过以下命令,创建 NodePort 通过这个方法,使 K10 的仪表盘暴露出来,以供用户在图形界面上操作。

首先,我们来撰写 nodeport 的 yaml 文件。

cat > k10-nodeport-svc.yaml << EOF
apiVersion: v1
kind: Service
metadata:
  name: gateway-nodeport
  namespace: kasten-io
spec:
  selector:
    service: gateway
  ports:
  - name: http
    port: 8000
    nodePort: 32000
  type: NodePort
EOF

然后,通过这个 yaml 文件我们来创建 NodePort 服务。

$ kubectl apply -f k10-nodeport-svc.yaml
service/gateway-nodeport created

$ kubectl get svc -n kasten-io
NAME                    TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                               AGE
aggregatedapis-svc      ClusterIP   10.96.201.26    <none>        443/TCP                               6m36s
auth-svc                ClusterIP   10.96.251.83    <none>        8000/TCP                              6m36s
catalog-svc             ClusterIP   10.96.192.220   <none>        8000/TCP                              6m36s
controllermanager-svc   ClusterIP   10.96.99.78     <none>        8000/TCP,18000/TCP                    6m36s
crypto-svc              ClusterIP   10.96.187.71    <none>        8000/TCP,8003/TCP,8001/TCP,8002/TCP   6m36s
dashboardbff-svc        ClusterIP   10.96.253.141   <none>        8000/TCP,8001/TCP                     6m36s
executor-svc            ClusterIP   10.96.118.49    <none>        8000/TCP                              6m36s
frontend-svc            ClusterIP   10.96.139.164   <none>        8000/TCP                              6m36s
gateway                 ClusterIP   10.96.158.239   <none>        8000/TCP                              6m36s
gateway-admin           ClusterIP   10.96.166.35    <none>        8877/TCP                              6m36s
gateway-nodeport        NodePort    10.96.34.25     <none>        8000:32000/TCP                        33s
jobs-svc                ClusterIP   10.96.141.248   <none>        8000/TCP                              6m36s
k10-grafana             ClusterIP   10.96.144.85    <none>        80/TCP                                6m36s
kanister-svc            ClusterIP   10.96.117.135   <none>        8000/TCP                              6m36s
logging-svc             ClusterIP   10.96.214.208   <none>        8000/TCP,24224/TCP,24225/TCP          6m36s
metering-svc            ClusterIP   10.96.206.50    <none>        8000/TCP                              6m36s
prometheus-server       ClusterIP   10.96.50.196    <none>        80/TCP                                6m36s
prometheus-server-exp   ClusterIP   10.96.168.237   <none>        80/TCP                                6m36s
state-svc               ClusterIP   10.96.76.63     <none>        8000/TCP,8001/TCP                     6m36s

这样, 我们通过 NodePort:32000/#/k10 就可以查看 K10 的 Dashboard 了。

4.3 配置数据应用的存储类

K10 部署完毕开始运行后,用以下的命令配置应用程序使用的存储快照类,使 K10 可以方便利用存储级别的快照进行保护

$ kubectl annotate volumesnapshotclass csi-hostpath-snapclass k10.kasten.io/is-snapshot-class=true
volumesnapshotclass.snapshot.storage.k8s.io/csi-hostpath-snapclass annotated

4.4 配置 MinIO 对象存储

在本次最佳实践的步骤中,我将利用 MinIO 对象存储来搭建备份存储库,并用它来进行备份数据的存储。

MinIO是一个高性能的对象存储解决方案, 遵从 Apache License v2.0 的使用规则. 它的 API 与 Amazon S3 云存储高度一致。

创建 MinIO 的 namespace

$ kubectl create namespace minio
$ kubectl get ns 
NAME                 STATUS   AGE
default              Active   92d
kasten-io            Active   8m57s
kube-node-lease      Active   92d
kube-public          Active   92d
kube-system          Active   92d
local-path-storage   Active   92d
minio                Active   25s

配置 MinIO Helm repo

$ helm repo add minio https://helm.min.io
$ helm repo list
NAME    URL                      
kasten  https://charts.kasten.io/
minio   https://helm.min.io

安装 MinIO Chart

$ helm install minio minio/minio --namespace=minio --version=8.0.0 --set accessKey="AKIAIOSFODNN7EXAMPLE",secretKey="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",defaultBucket.enabled=true,defaultBucket.name=kanister --wait --timeout 5m

NAME: minio
LAST DEPLOYED: Sat May 13 00:33:22 2023
NAMESPACE: minio
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Minio can be accessed via port 9000 on the following DNS name from within your cluster:
minio.minio.svc.cluster.local

To access Minio from localhost, run the below commands:

  1. export POD_NAME=$(kubectl get pods --namespace minio -l "release=minio" -o jsonpath="{.items[0].metadata.name}")

  2. kubectl port-forward $POD_NAME 9000 --namespace minio

Read more about port forwarding here: http://kubernetes.io/docs/user-guide/kubectl/kubectl_port-forward/

You can now access Minio server on http://localhost:9000. Follow the below steps to connect to Minio server with mc client:

  1. Download the Minio mc client - https://docs.minio.io/docs/minio-client-quickstart-guide

  2. Get the ACCESS_KEY=$(kubectl get secret minio -o jsonpath="{.data.accesskey}" | base64 --decode) and the SECRET_KEY=$(kubectl get secret minio -o jsonpath="{.data.secretkey}" | base64 --decode)

        3. mc alias set minio-local http://<External-IP>:9000 "$ACCESS_KEY" "$SECRET_KEY" --api s3v4

  4. mc ls minio-local

Alternately, you can use your browser or the Minio SDK to access the server - https://docs.minio.io/categories/17

4.5 在 K10 中配置 Location Profile 备份存储库

接下来,我们将在 K10 仪表盘中配置 Location Profile。

  • 点击 K10 Dashboard
  • 点击 Settings
  • 点击 Locations
  • 点击 New Profile
  • 输入 profile 名称 k10
  • 选择 S3 Compatible
  • 填入如下信息

20230531114039

当这个 Location Profile 创建完成时,点击 Check 以确保它的成功。

20230531114421

4.6 安装 MySQL 建立 Demo 数据库

为了体验云原生数据库的备份与恢复,我们安装 MySQL并建立数据库。

首先, 使用如下命令安装 MySQL

$ kubectl create namespace mysql
$ helm install mysql bitnami/mysql --namespace=mysql

为了保证 MySQL 已经正常的运行起来,我们在这里用 watch命令每 2 秒检查一次每个 Pod 的运行状态,直至所有的 Pod 都已经达到 Running 的状态

$ watch -n 2 "kubectl -n mysql get pods"
Every 2.0s: kubectl -n mysql get pods                            kubernetes: Sat May 13 00:30:59 2023
NAME      READY   STATUS    RESTARTS   AGE
mysql-0   1/1     Running   0          66s

一旦我们确定所有的 Pod 都已经达到运行的状态,我们可以按 CTRL + C 退出 watch ,然后运行如下命令,以创建数据库。

$ MYSQL_ROOT_PASSWORD=$(kubectl get secret --namespace mysql mysql -o jsonpath="{.data.mysql-root-password}" | base64 --decode; echo)

$ kubectl exec -it --namespace=mysql $(kubectl --namespace=mysql get pods -o jsonpath='{.items[0].metadata.name}') \
  -- env MYSQL_PWD=$MYSQL_ROOT_PASSWORD mysql -u root -e "CREATE DATABASE k10demo"

4.7 在 Mysql 应用中定义 Blueprint 以实现逻辑备份

以下命令将安装 MySQL Blueprint 在 K10 的 namespace 并在 MySQL 的 Deployment 中加上 annotation, 以使 K10 使用 Blueprint 中 定义的 ActionSet 来完成对数据的备份。

$ kubectl --namespace mysql annotate statefulset/mysql \
    kanister.kasten.io/blueprint=mysql-blueprint
statefulset.apps/mysql annotated

4.8 创建与运行 K10 备份策略

我们将创建 Policy 来对 MySQL 进行备份,并将备份的数据集传送了之前创建的对象存储 MinIO 中。
登录 K10 仪表盘, 点击 Policies.

点击 Create New Policy:

  • 输入 Policy 名称: mysql-backup
  • Action 处,选择 Snapshot 
  • 在 Action Frequency 处,选择 Hourly 
  • 选择 By Name for Select Applications 然后, 选择 mysql
  • 选择 Location Profile k10
  • 点击 Create Policy

运行策略
以上策略会在预定时间运行。首先我们要手动运行策略第一次,点击策略页面上的 “Run Once”。,然后返回主仪表板以查看作业运行情况。请验证作业已成功完成。

20230531120353

此时上我们 点击 “View Action YAML” 查看并理解一下这个 BackupAction

kind: BackupAction
apiVersion: actions.kio.kasten.io/v1alpha1
metadata:
  name: scheduled-4fvcv
  namespace: mysql
  uid: c0a78908-f126-11ed-b0a8-deea831af3eb
  resourceVersion: "41"
  creationTimestamp: 2023-05-13T00:40:26Z
  labels:
    k10.kasten.io/appName: mysql
    k10.kasten.io/appNamespace: mysql
    k10.kasten.io/isRunNow: "true"
    k10.kasten.io/policyName: mysql-backup
    k10.kasten.io/policyNamespace: kasten-io
    k10.kasten.io/runActionName: policy-run-95447
status:
  state: Complete
  startTime: 2023-05-13T00:40:26Z
  endTime: 2023-05-13T00:41:05Z
  restorePoint:
    name: scheduled-4fvcv
    namespace: mysql
  result:
    name: ""
  progress: 100
spec:
  subject:
    name: mysql
    namespace: mysql
  scheduledTime: 2023-05-13T00:40:25Z
  filters: {}
  profile:
    name: k10
    namespace: kasten-io

通过查看 Restore Point 我们来确认已经建立了还原点

20230531120829

4.9 模拟灾难 删除 MySQL 数据

$ MYSQL_ROOT_PASSWORD=$(kubectl get secret --namespace mysql mysql -o jsonpath="{.data.mysql-root-password}" | base64 --decode; echo)
$ kubectl exec -it --namespace=mysql $(kubectl --namespace=mysql get pods -o jsonpath='{.items[0].metadata.name}') -- env MYSQL_PWD=$MYSQL_ROOT_PASSWORD mysql -u root -e "SHOW DATABASES;"

+--------------------+
| Database           |
+--------------------+
| information_schema |
| my_database        |
| mysql              |
| performance_schema |
| sys                |
| k10demo            |
+--------------------+
6 rows in set (0.00 sec)

$ kubectl exec -it --namespace=mysql $(kubectl --namespace=mysql get pods -o jsonpath='{.items[0].metadata.name}') -- env MYSQL_PWD=$MYSQL_ROOT_PASSWORD mysql -u root -e "DROP DATABASE k10demo;"

$ kubectl exec -it --namespace=mysql $(kubectl --namespace=mysql get pods -o jsonpath='{.items[0].metadata.name}') -- env MYSQL_PWD=$MYSQL_ROOT_PASSWORD mysql -u root -e "SHOW DATABASES;"

+--------------------+
| Database           |
+--------------------+
| information_schema |
| my_database        |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.00 sec)

4.10 恢复 Mysql 数据

要恢复 Mysql 数据库,我们登录到 K10 控制台,单击 Applications,然后在MySQL卡上选择 Restore

还原点按计划执行时间显示和排序。选择我们刚刚创建的还原点。选择默认的Application Name选项以还原到原始的 Namespace。保留其它可选项不变,单击 Restore并确认操作。

20230531122609

让我们观察 Activity 确认还原任务已经完成。

20230531122937

此时上我们 点击 “View Action YAML” 查看并理解一下这个 RestoreAction

kind: RestoreAction
apiVersion: actions.kio.kasten.io/v1alpha1
metadata:
  name: mysql-m9gd9
  namespace: mysql
  uid: f9dab81d-f127-11ed-b0a8-deea831af3eb
  resourceVersion: "47"
  creationTimestamp: 2023-05-13T00:49:11Z
  labels:
    k10.kasten.io/appName: mysql
    k10.kasten.io/appNamespace: mysql
status:
  state: Complete
  startTime: 2023-05-13T00:49:11Z
  endTime: 2023-05-13T00:50:02Z
  restorePoint:
    name: ""
  result:
    name: ""
  actionDetails:
    phases:
      - attempt: 1
        endTime: 2023-05-13T00:50:02Z
        name: Restoring Application Components
        startTime: 2023-05-13T00:49:15Z
        state: succeeded
        updatedTime: 2023-05-13T00:50:02Z
  progress: 100
spec:
  subject:
    apiVersion: apps.kio.kasten.io/v1alpha1
    kind: RestorePoint
    name: scheduled-4fvcv
    namespace: mysql
  targetNamespace: mysql

4.11 验证 Mysql 数据恢复效果

要验证我们的数据已恢复,请在终端中运行以下命令以查看已恢复的数据库:

$ MYSQL_ROOT_PASSWORD=$(kubectl get secret --namespace mysql mysql -o jsonpath="{.data.mysql-root-password}" | base64 --decode; echo)
$ kubectl exec -it --namespace=mysql $(kubectl --namespace=mysql get pods -o jsonpath='{.items[0].metadata.name}') -- env MYSQL_PWD=$MYSQL_ROOT_PASSWORD mysql -u root -e "SHOW DATABASES;"

+--------------------+
| Database           |
+--------------------+
| information_schema |
| my_database        |
| mysql              |
| performance_schema |
| sys                |
| k10demo            |
+--------------------+
6 rows in set (0.00 sec)

5.总结

Kubernetes 已经成为有效部署应用程序和微服务的首选平台,而有状态应用的备份已经成为 Kubernetes 运维过程中不可或缺的重要组成部分。Kanister 的能力可以帮助集群管理员集中管理 Kubernetes 资源,并自动部署应用的备份并执行数据管理操作,使运维更加简单。在本文中,学习了有关 Kanister Blueprint 的知识,我们鼓励您亲自下载软件并试用,快来试一试吧!

6.参考链接

Kasten 官方文档
https://docs.kasten.io/latest/
Kanister 官方文档
https://docs.kanister.io/
Kasten k10 实战系列 07 - Kanister 应用感知框架的使用
https://www.data2clouds.com/?p=77
B站视频-使用 Kanister 为你的云原生应用数据保驾护航
https://www.bilibili.com/video/BV19b4y1H7pa/?vd_source=057f1951cfaa4472f2abecc567d773f9
在 Github 上的 Kanister 开源的蓝图
https://github.com/kanisterio/kanister/tree/master/examples

在 Kubernetes 中使用(或不使用)Sidecar 的原因

在 Kubernetes 中使用(或不使用)Sidecar 的原因

Sidecar 容器为需要在大规模容器应用集群中进行管理的开发人员提供了极大的便利。但这是否总是正确的方法呢?

Kubernetes 引入 Sidecar 容器来解决一个根本性的挑战:当您通过 Kubernetes 部署应用程序时,往往很难直接将应用程序与各种外部监控工具、日志系统和其他组件集成在一起,这些工具通常对于使用传统服务器的开发人员来说是随时可用的。

Sidecar 容器方法通过在自己的 Kubernetes Pod 实例中运行应用程序的核心进程,同时运行在其旁边的伴随 Pod,来解决这个问题,从而方便访问外部资源和与外部系统通信。换句话说,在 Kubernetes 中使用 Sidecar 可以让您同时实现两个目标。

然而,使这种方法行之有效的关键在于理解何时以及如何使用 Sidecar 容器。让我们检查一些 Sidecar 容器方法的主要优点和缺点,并回顾一些指南,以帮助您决定是否应采用这种方法。

Sidecar 容器的优点

在 Kubernetes 中,Sidecar 容器方法主要是一种用于突破干扰抽象的方法。在这种情况下,它们提供了几个重要优点:

  • 隔离。主要应用程序可以在一个容器中独立运行,而 Sidecar 则可以运行补充进程和工具。这也使得应用程序的主代码库对与之连接的外部服务隐藏起来,可以帮助隔离故障。
  • 快速部署。部署 Sidecar 容器相对较容易,比尝试添加额外层次到主应用程序容器中来集成 Sidecar 中托管的任何功能要容易得多。
  • 可扩展性。一旦您将 Sidecar 容器放置在适当的位置,就可以轻松扩展以支持所需的 Pod 数量。如果您想要,您可以部署一百个 Sidecar 容器,就像部署一个容器一样容易。

Sidecar 容器的缺点

当然,使用 Kubernetes 中的 Sidecar 并非免费的。以下是一些与 Sidecar 容器相关的明显缺点:

  • 资源消耗。更多的容器意味着更多的内存消耗和 CPU 利用率。从资源的角度来看,有时在单个容器中托管所有进程或在节点级别运行补充任务更有效。
  • 管理复杂性。Sidecar 增加了您需要监视和管理的容器总数,更不用说它们之间的关系。您需要一个全面的监控系统,能够跟踪例如 Sidecar 容器故障如何影响您的主应用程序。
  • 更新兼容性。确保更新主应用程序容器与支持它的 Sidecar 兼容可能需要更多的工作,以及这些更新是否可以跨所有相关组件无问题传递。

Sidecar 容器方法的替代方案

Sidecar 容器不是在 Kubernetes 抽象层中建立通道的唯一方法。当然,最明显的选择是直接将您需要的任何额外功能添加到应用程序容器本身中,前提是这不会损害性能。类似地,您可以配置您的全局软件网络,使应用程序可以通过网络本身与外部软件和工具交互。

在许多情况下,还可以向每个 Kubernetes 节点添加类似 DaemonSets 的管理组件,以执行无法在单个容器内部处理的任务。

决定是否值得使用 Sidecar

一般来说,管理 Kubernetes 集群的大型和复杂的团队最终会依赖于 Sidecar 容器。因此,在 Kubernetes Pod 与世界其他部分之间形成的抽象中,Sidecar 已成为一个应对方案。然而,他们并非没有缺点,因此开发团队在随意部署 Sidecar 之前需要仔细考虑。

为了确定 Sidecar 是否是正确的方法,问自己以下几个问题:

  • 您的性能需求是什么? Sidecar 不是运行补充工具的最有效方法,并且如果您只需要为相对简单的任务优化性能,则可能会成为问题。
  • 您的规模是多少? 由于它们易于大规模部署,因此 Sidecar 容器在大型集群中提供最大的利益。在较小的集群中,您可能可以不使用 Sidecar。
  • 功能修改有多困难? 如果您能够轻松将所需的功能添加到应用程序的主代码库或容器中,而不会引起太多问题,则 Sidecar 容器可能是一种过度方法。
  • 您能够管理多少集群复杂性? 尽管它可能简化主应用程序容器,但 Sidecar 通过增加您需要部署和监视的容器数量来增加您的 Pod 集群的复杂性。考虑将复杂性添加到单个实例而不是整个集群的权衡。

Veeam Backup for Salesforce SaaS 灾备解决方案

1.数据洞察与发现 - Salesforce 是企业数据生产力的核心

在客户关系管理 (CRM) 平台这个细分领域,Salesforce 是无可争议的市场领导者,来自市场和消费者数据提供商 IDC 的洞察表明,在 2022年 Salesforce 市场份额为 22.9%。并且该公司以巨大的利润率引领市场,紧随 Salesforce 之后的是 Microsoft 和 Oracle,SAP 和 Adobe。

20221108215946

在全球有超过 150,000 家公司信任 Salesforce ,并用它来管理企业中的数据生态系统——从收集和转换潜在客户到机会,到管理信息以了解和吸引客户,从数据中提取洞察力,到在整个组织内共享信息,一应俱全。显而易见,Salesforce 是企业价值链的核心,但您的组织中最重要的资产——您的数据有多安全?让我们来探讨一下这个问题。

Salesforce Ranked #1 in CRM Market Share for Ninth Consecutive Year
https://www.salesforce.com/news/stories/idc-crm-market-share-ranking-2022/

很明显,Salesforce 是企业价值链的核心,但您的组织中最重要的资产——您的数据有多安全?让我们来探讨一下这个问题。

2. Saleforce 的责任共担模式

总体而言,在数据安全方面,Salesforce 的主要职责是保持其全球基础设施的正常运行。在每个实例上都有如此多的客户,在 Salesforce API 内部和外部限制以及云基础设施的访问安全,这需要进行大量工作来保持平台运行。 Salesforce 专注于履行其对您的承诺,以便您的企业可以通过利用其工具和资源尽可能地取得成功。

与此同时,我们再了解一下企业对数据的责任。通过手动或自动流程创建和更改数据是企业用户的责任。因为企业在实时的创建定制化需求、工作流程、字段和验证规则等等。当由于人为错误、(用户或管理员)集成错误和数据损坏等情况导致数据和元数据丢失时,企业有责任确保这些数据和元数据能够及时恢复,以避免影响到组织正常的运营。

20221108232635

总之,数据安全与合规是企业的责任,每个组织的合规性和法律要求都不同,但 Salesforce 的角色只是数据处理者的角色。即使企业的数据驻留在 Salesforce 中,需要明确的是,企业仍然是数据所有者,为遵守公司和行业法规,数据保护是第一要务。那么原生 Salesforce 备份和恢复服务的效果如何?让我们继续进行深入的讨论。

Salesforce Shared Responsibility Model
https://www.veeam.com/blog/salesforce-shared-responsibility-model.html

3. 原生 Salesforce 备份和恢复服务的效果如何?

来自 Salesforce 自身的说法,Salesforce 保留了一份客户数据副本,用于灾难恢复,但对于客户来说,制定数据备份和恢复策略作为其整体数据管理和安全模型的一部分非常重要。Salesforce 数据恢复服务是一个昂贵且耗时的过程,仅应在没有其他数据副本可用时作为最后手段使用。

根据行业分析师的说法,使用自带的备份功能和恢复功能可能具有以下缺点: 

  • 数据备份恢复时间目标 (RTO) 需要 6 到 8 周 
  • Salesforce 数据恢复服务非常昂贵,每个组织每次恢复的成本为 10,000 美元 
  • 备份不包括重要的 Salesforce 元数据。您将错过自定义字段、页面布局、报告、仪表板和自定义代码备份。 
  • Salesforce 于 2020 年 7 月以质量问题为由终止了其数据恢复服务,在客户要求提供本机备份服务后,该服务于 2021 年 3 月恢复。 
  • Salesforce 建议使用第三方备份作为数据备份策略的一部分。

备份和恢复 Salesforce 数据的最佳实践
https://help.salesforce.com/s/articleView?id=000386692&type=1

4. Veeam Backup for Salesforce 解决方案介绍

Salesforce 数据的增长和业务关键性是毋庸置疑的,尽管 Salesforce 本身也在大声呼吁使用第三方备份作为数据备份策略的一部分,但企业的相关组织却很少备份它。

Veeam Backup for Salesforce 消除了丢失 Salesforce 数据和元数据的风险,从而可靠地保护企业的业务。做为第三方的备份厂商,Veeam Backup for Salesforce 让企业可以自由选择数据存储在哪里,避免存储锁定,并可以将备份基础架构部署到企业选择的任何位置,大大提高了灵活性。Veeam 专为 Salesforce 的 API 而构建,只需单击一下即可恢复记录、字段、文件和元数据,从而帮助您防止人为错误和集成问题。

全新 Veeam Backup for Salesforce 的主要功能包括:

  • Salesforce 原生:专为创建备份和恢复 Salesforce 数据和元数据而构建
  • 快捷恢复:恢复 Salesforce 记录、层次结构、字段、文件和元数据
  • 安全数据:随时随地运行与部署备份环境,本地或云(AWS,Microsoft Azure等)
  • 定制计划:在对象级别设置精细的备份计划和长期保留设置
  • 简化管理:从一个控制台管理多个 Salesforce 实例
  • 增量更改:通过增量同步和灵活性调度,您几乎可以连续备份 Salesforce 数据和元数据
  • 简单易用:通过向导式界面,管理员可在几分钟内运行备份策略和恢复作业
  • 查看比较:在恢复时,管理员可查看记录和元数据的版本,并快速将其与生产进行比较
  • 层次结构:将链接对象精细地还原到任何记录,包括父/子记录

20221108224310

5. Veeam Backup for Salesforce 现已登录 Salesforce AppExchange

Salesforce AppExchange 是领先的企业云市场,提供可立即安装的应用程序和解决方案,可让您将 Salesforce 的功能得到扩展。目前 Veeam Backup for Salesforce 已经登录 Salesforce AppExchange,马上就开展试用吧。

20221108223422

https://appexchange.salesforce.com/listingDetail?listingId=a0N3u00000PuyFpEAJ&tab=e

6. 欢迎下载与试用

本文中所提到的内容与应用场景只是简单的说明,我们希望您可以亲自尝试,并把您的感受与经验分享给我们,以下是试用的链接。

试用链接:

Veeam Backup for Salesforce 试用链接
https://aws.amazon.com/marketplace/pp/B082BJM5M3?qid=1584172885627&sr=0-3&ref_=srh_res_product_title

7. 参考资料

和往常一样,Veeam 擅长从知识管理中的过程中解决客户的疑问,从以下资源列表中,您可以下载任何想要的报告与白皮书。

Veeam Salesforce Protection Trends Report 2022
https://go.veeam.com/wp-veeam-salesforce-protection-trends-report-2022

Salesforce Backup 傻瓜书
https://www.veeam.com/wp-salesforce-backup-dummies.html

企业需要Salesforce备份的9大原因
https://www.veeam.com/wp-salesforce-backup-reasons.html

How to connect Veeam Backup for Salesforce with Salesforce CRM
https://www.veeam.com/kb4240

Kasten 精英训练营教材升级 – 加入基于CSI快照的备份操作

Kasten 精英训练营教材升级 - 加入基于CSI快照的备份操作

前言

创新与迭代是 Veeam 的核心价值观之一,我们近日又对 Kasten 精英训练营的教材进行了升级, 在新升级的教材中有以下更新。

  • 升级 Ubuntu 到 22.04,继利用4C,8G,200G 这个单个虚拟机配置完成实验
  • 使用 External Hostpath CSI 和 External Snapshotter
  • Kasten K10 升级到 5.0.11
  • 利用 Kasten 调用 Hostpath CSI 和 快照进行备份

本文主要内容

[toc]

作者观察 -- 来自 KubeCon 的消息

近日 KubeCon + CloudNativeCon 2022 在底特律的密歇根市如期进行,做为钻石级赞助商的 Kasten by Veeam 在 KubeCon 宣布推出全新的 Kasten by Veeam K10 V5.5,这将包括一系列新的功能。

20221030160606

Kasten K10 V5.5 的新功能包括:

  • 智能策略
    Kasten K10 具有智能决策功能,可大规模简化数据保护流程。用户可以依策略建议在非高峰时间指定备份时间窗口。Kasten K10 不仅会灵活的建议备份时间窗口,还会进一步自动化底层备份作业的排序。这优化了底层基础设施的利用率,并可以在多个策略时并发时自动处理冲突。

  • 提高部署和扩展的便利性
    Kasten K10 通过提供直观的图形向导来生成最合适的安装清单,以进一步简化了部署环节。Kasten K10 5.5 还支持IPv6,支持 Amazon EKS 与 IPv6 Pod 间通信和 GitOps 工作流集成,提供可扩展的工作流以实现高效的应用程序部署以及备份/恢复。

  • 扩展的云原生生态系统
    确保客户能够在不断增加的工作负载类型、地理区域、存储类型和安全性方面获得最新的进步。Kasten K10 现在支持 RedHat OpenShift 虚拟化,使您能够在 Red Hat OpenShift 上并行运行和管理 VM 和容器工作负载。此外,Kasten K10 增加了对 OCP 4.10、Kubernetes 1.23、Azure 文件服务作为备份目标和 Azure 托管身份的支持,以及 AWS 和 GCP 更多区域的支持。

Kasten by Veeam Announces NEW Kasten K10 V5.5 to Simplify Kubernetes Data Protection at Scale with Autonomous Operations and Cloud Native Expansion
https://www.veeam.com/news/kasten-by-veeam-announces-new-kasten-k10-v5-5-to-simplify-kubernetes-data-protection-at-scale-with-autonomous-operations-and-cloud-native-expansion.html
kubeCon + CloudnativeCon 大会详情
https://events.linuxfoundation.org/kubecon-cloudnativecon-north-america/

1. Kasten K10 实验环境准备

1.1. 配置虚拟机

  • 虚拟机配置
    4C 8G 200G HDD, IP: NAT + Static IP, User: Supervisors User and Root(Option)
  • 操作系统
    Ubuntu 20.04 LTS or Ubuntu 22.04 LTS 为了实验方便,Desktop 版本就可以使用。可使用以下链接进行下载。

    Ubuntu 下载链接

1.2. 虚拟机系统环境准备

在安装了操作系统之后,我们要对虚拟机进行一系列软件包的安装

#主机配置,option 自己了解环境就好
$ sudo apt install systemd
#hostname config
$ hostnamectl set-hostname mars-k8s1 $hostnamectl
$ sudo apt install vim
# 多节点时用 (Option)
$ sudo vim /etc/hosts
172.16.124.70 mars-k8s-master1
172.16.124.71 mars-k8s-worker1
# 软件配置,option 自己了解环境就好
$ sudo apt-get install openssh-server
$ sudo apt-get install -y apt-transport-https ca-certificates \
curl gnupg lsb-release
$ sudo apt-get update
# 安装 helm
$ sudo snap install helm --classic

1.3. Docker安装环境准备

#Docker 环境清理
$ sudo apt-get remove -y docker docker-engine \ docker.io containerd runc
#关闭 Swap
$ sudo swapoff -a
$ sudo sed -i -e '/swap/d' /etc/fstab $ swapon --show
#安装Docker 环境
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg \ | sudo gpg --dearmor \
-o /usr/share/keyrings/docker-archive-keyring.gpg
$ echo \
"deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu
$(lsb_release -cs) stable" \
| sudo tee /etc/apt/sources.list.d/docker.list
$ sudo apt-get update
$ sudo apt-get install -y docker-ce docker-ce-cli containerd.io
$ sudo mkdir -p /etc/docker
$ cat <<EOF | sudo tee /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=systemd"], "log-driver": "json-file",
"log-opts": {"max-size": "100m"}, "storage-driver": "overlay2"
} EOF
# Docker 开机启动,赋权
$ sudo systemctl restart docker
$ sudo systemctl enable docker
$ sudo usermod -aG docker $USER

1.4. Kubernetes安装与配置

#kubernetes Install
$ curl -s https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | sudo apt-key add -
$ sudo tee /etc/apt/sources.list.d/kubernetes.list <<EOF
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF
$ sudo apt-get update
$ sudo apt-get install -y kubeadm=1.23.1-00 kubectl=1.23.1-00 kubelet=1.23.1-00
#kubernetes 开机启动
$ sudo systemctl enable kubelet
$ sudo -i
# 以下带♯命令需要在Root权限下运行
♯ systemctl enable kubelet 
♯ systemctl stop etcd
♯ rm -rf /var/lib/etcd
# kubernetes 集群初始化
♯ kubeadm init --kubernetes-version=1.23.1 --pod-network-cidr 10.16.0.0/16 --image-repository registry.aliyuncs.com/google_containers
♯ exit
# 设置kubeconfig
$ mkdir -p $HOME/.kube
$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config $ sudo chown $(id -u):$(id -g) $HOME/.kube/config
# 查看 Node 状态
$ kubectl get node
# 去除污点
$ kubectl taint nodes --all node-role.kubernetes.io/master-

1.5. 配置 Kubernetes网络

#安装 CNI
$ kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml
#查看 Calico 服务启动的情况
$ kubectl get pod -n kube-system -w
#注意 CNI 在这里是 Calico 是 CoreDNS 启动的前题条件,Pull Image 有时需要等待和自查。

$ kubectl get po -n kube-system
NAMESPACE     NAME                                       READY   STATUS    RESTARTS      AGE
kube-system   calico-kube-controllers-54965c7ccb-w944s   1/1     Running   0             40m
kube-system   calico-node-rzrww                          1/1     Running   0             39m
kube-system   coredns-6d8c4cb4d-5gz58                    1/1     Running   0             39m
kube-system   coredns-6d8c4cb4d-kl28q                    1/1     Running   0             39m
kube-system   etcd-mars-k8s-1                            1/1     Running   2 (32m ago)   8h
kube-system   kube-apiserver-mars-k8s-1                  1/1     Running   2 (32m ago)   8h
kube-system   kube-controller-manager-mars-k8s-1         1/1     Running   2 (32m ago)   8h
kube-system   kube-proxy-k78cr                           1/1     Running   2 (32m ago)   8h
kube-system   kube-scheduler-mars-k8s-1                  1/1     Running   3 (32m ago)   8h

1.6.安装配置存储与快照组件 StorageClass 和 VolumeSnapshotClass

HostPath 是一种云原生存储类型,它使用的卷是指计划运行 Pod 的节点(虚拟机/计算机)上的目录。我们将为 Kubernetes 集群启用 HostPath 并测试 VolumeSnapshot 功能,这是 Kasten k10 运行的先决条件。请按照以下步骤安装和验证主机路径 CSI 驱动程序:

1.6.1 安装存储类与快照类

安装 volumesnapshot, volumesnapshotcontent, volumesnapshotclass crds

# Create snapshot controller CRDs
$ kubectl apply -f https://github.com/kubernetes-csi/external-snapshotter/raw/v5.0.1/client/config/crd/snapshot.storage.k8s.io_volumesnapshotclasses.yaml
$ kubectl apply -f https://github.com/kubernetes-csi/external-snapshotter/raw/v5.0.1/client/config/crd/snapshot.storage.k8s.io_volumesnapshotcontents.yaml
$ kubectl apply -f https://github.com/kubernetes-csi/external-snapshotter/raw/v5.0.1/client/config/crd/snapshot.storage.k8s.io_volumesnapshots.yaml

# Create snapshot controller
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/${SNAPSHOTTER_VERSION}/deploy/kubernetes/snapshot-controller/rbac-snapshot-controller.yaml
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/${SNAPSHOTTER_VERSION}/deploy/kubernetes/snapshot-controller/setup-snapshot-controller.yaml

External snapshot CRDs and Controller 参考链接
external snapshotter controller
external snapshotter crd

1.6.2 配置 CSI-Driver 部署脚本

$ git clone https://github.com/kubernetes-csi/csi-driver-host-path.git
$ cd csi-driver-host-path/deploy/kubernetes-1.XX
$ ./deploy.sh

# 查看运行情况 
$kubectl get po -A
NAMESPACE     NAME                                       READY   STATUS    RESTARTS        AGE
default       csi-hostpath-socat-0                       1/1     Running   0               4m47s
default       csi-hostpathplugin-0                       8/8     Running   0               4m47s
kube-system   calico-kube-controllers-54965c7ccb-w944s   1/1     Running   0               5h46m
kube-system   calico-node-rzrww                          1/1     Running   0               5h46m
kube-system   coredns-6d8c4cb4d-5gz58                    1/1     Running   0               5h45m
kube-system   coredns-6d8c4cb4d-kl28q                    1/1     Running   0               5h46m
kube-system   etcd-mars-k8s-1                            1/1     Running   2 (5h39m ago)   13h

# csi-hostpathplugin 包括 8 个 容器,看名字我们可以大体知道它们的作用
$ kubectl describe po csi-hostpathplugin-0 |grep Image:
    Image:         registry.k8s.io/sig-storage/hostpathplugin:v1.9.0
    Image:         registry.k8s.io/sig-storage/csi-external-health-monitor-controller:v0.6.0
    Image:         registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.5.1
    Image:         registry.k8s.io/sig-storage/livenessprobe:v2.7.0
    Image:         registry.k8s.io/sig-storage/csi-attacher:v3.5.0
    Image:         registry.k8s.io/sig-storage/csi-provisioner:v3.2.1
    Image:         registry.k8s.io/sig-storage/csi-resizer:v1.5.0
    Image:         registry.k8s.io/sig-storage/csi-snapshotter:v6.0.1

1.6.3 查看与配置 storageclass 与 snapshotclass

# 存储类
$ kubectl get sc
NAME                        PROVISIONER           RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
csi-hostpath-sc (default)   hostpath.csi.k8s.io   Retain          Immediate           false                  3s
# 快照类
$ kubectl get volumesnapshotclasses
NAME                     DRIVER                DELETIONPOLICY   AGE
csi-hostpath-snapclass   hostpath.csi.k8s.io   Delete           31m

# 标记存储类给K10
$ kubectl annotate volumesnapshotclass csi-hostpath-snapclass k10.kasten.io/is-snapshot-class=true
volumesnapshotclass.snapshot.storage.k8s.io/csi-hostpath-snapclass annotated
# 为存储类标记 snapshotclass
$ kubectl annotate storageclass csi-hostpath-sc k10.kasten.io/volume-snapshot-class=csi-hostpath-snapclass

1.6.4. 用 Kasten Pre-Flight Checks 脚本验证存储类与快照是否工作正常

$ curl https://docs.kasten.io/tools/k10_primer.sh | bash
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  7113  100  7113    0     0  12513      0 --:--:-- --:--:-- --:--:-- 12522
Namespace option not pbashrovided, using default namespace
Checking for tools
 --> Found kubectl
 --> Found helm
Checking if the Kasten Helm repo is present
 --> The Kasten Helm repo was found
Checking for required Helm version (>= v3.0.0)
 --> No Tiller needed with Helm v3.7.0
K10Primer image
 --> Using Image (gcr.io/kasten-images/k10tools:5.0.11) to run test
Checking access to the Kubernetes context kubernetes-admin@kubernetes
 --> Able to access the default Kubernetes namespace
K10 Kanister tools image
 --> Using Kanister tools image (ghcr.io/kanisterio/kanister-tools:0.83.0) to run test

Running K10Primer Job in cluster with command- 
     ./k10tools primer
serviceaccount/k10-primer created
clusterrolebinding.rbac.authorization.k8s.io/k10-primer created
job.batch/k10primer created
Waiting for pod k10primer-lfc5l to be ready - ContainerCreating
Waiting for pod k10primer-lfc5l to be ready - ContainerCreating
Pod Ready!

Kubernetes Version Check:
  Valid kubernetes version (v1.23.1)  -  OK

RBAC Check:
  Kubernetes RBAC is enabled  -  OK

Aggregated Layer Check:
  The Kubernetes Aggregated Layer is enabled  -  OK

         Found multiple snapshot API group versions, using preferred.
CSI Capabilities Check:
  Using CSI GroupVersion snapshot.storage.k8s.io/v1  -  OK

Validate Generic Volume Snapshot:
  Pod created successfully  -  OK
  GVS Backup command executed successfully  -  OK
  Pod deleted successfully  -  OK

serviceaccount "k10-primer" deleted
clusterrolebinding.rbac.authorization.k8s.io "k10-primer" deleted
job.batch "k10primer" deleted

安装测试用的 workload -- mysql

# add bitnami repo
$ helm repo add bitnami https://charts.bitnami.com/bitnami 
# helm install mysql
$ helm install mysql-release bitnami/mysql --namespace mysql --create-namespace \
 --set auth.rootPassword='Start123' \
 --set primary.persistence.size=10Gi
# check mysql status
$ kubectl get all -n mysql
NAME                  READY   STATUS    RESTARTS   AGE
pod/mysql-release-0   1/1     Running   0          99s

NAME                             TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
service/mysql-release            ClusterIP   10.104.247.217   <none>        3306/TCP   48m
service/mysql-release-headless   ClusterIP   None             <none>        3306/TCP   48m

NAME                             READY   AGE
statefulset.apps/mysql-release   1/1     48m

2. Kasten K10 的安装与配置

2.1. 安装 Kasten K10

# Add helm chart for Kasten
$ helm repo add kasten https://charts.kasten.io/ 
# Check if kasten repo already added
$ helm repo list
# Fetch the charts
$ helm fetch kasten/k10 --version=5.0.11
# install kasten with following parameters
$ helm install k10 k10-5.0.11.tgz --namespace kasten-io --create-namespace --set global.airgapped.repository=ccr.ccs.tencentyun.com/kasten \
--set auth.tokenAuth.enabled=true \
--set metering.mode=airgap \
--set injectKanisterSidecar.enabled=true \
--set-string injectKanisterSidecar.namespaceSelector.matchLabels.k10/injectKanisterSidecar=true \
--set global.persistence.storageClass=csi-hostpath-sc

# 要确定所有的 Pod 都是 Running 状态才能进行下一步
$ kubectl get po -n kasten-io
NAME                                     READY   STATUS    RESTARTS   AGE
aggregatedapis-svc-5cb69ccb87-f728h      1/1     Running   0          7m18s
auth-svc-59f8597cd-kkm87                 1/1     Running   0          7m19s
catalog-svc-5cc7f8c865-g9wqt             2/2     Running   0          7m18s
controllermanager-svc-64c5fcf9c4-ncwjf   1/1     Running   0          7m19s
crypto-svc-cf68bdd99-n528w               4/4     Running   0          7m19s
dashboardbff-svc-669449d5f4-kxhrw        1/1     Running   0          7m19s
executor-svc-56d8fff95d-7q9gf            2/2     Running   0          7m19s
executor-svc-56d8fff95d-kc769            2/2     Running   0          7m19s
executor-svc-56d8fff95d-zzmhm            2/2     Running   0          7m19s
frontend-svc-7bff945b6c-mndws            1/1     Running   0          7m19s
gateway-78946b9fd7-rsq4t                 1/1     Running   0          7m19s
jobs-svc-c556bffd7-jgwng                 1/1     Running   0          7m18s
k10-grafana-58b85c856d-8pctz             1/1     Running   0          7m19s
kanister-svc-6db7f4d4bc-nhxdw            1/1     Running   0          7m19s
logging-svc-7b87c6dc8-zqfgg              1/1     Running   0          7m19s
metering-svc-b45bfb675-xzp26             1/1     Running   0          7m19s
prometheus-server-64877fdd68-z4ws6       2/2     Running   0          7m19s
state-svc-786864ddc6-tk99x               2/2     Running   0          7m18s

# 设置采 Kasten k10 的 Gateway Service 暴露出来,用 Node Port 方式访问 GUI
$ kubectl expose service gateway -n kasten-io --type=NodePort --name=gateway-nodeport
$ kubectl get svc -n kasten-io gateway-nodeport
NAME               TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
gateway-nodeport   NodePort   10.97.233.211   <none>        8000:32612/TCP   93s
$ kubectl get nodes -owide
NAME         STATUS   ROLES                  AGE   VERSION   INTERNAL-IP    EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME
mars-k8s-1   Ready    control-plane,master   20h   v1.23.1   172.16.60.90   <none>        Ubuntu 22.04.1 LTS   5.15.0-52-generic   docker://20.10.21 

☞ 浏览器访问 K10 UI: http://172.16.60.90:32612/k10/#

20221030200444

2.2. 登录 Kasten K10 GUI 管理界面

☞ 浏览器访问:http://172.16.60.90:32612/k10/#

☞ 用以下命令得到 Token, 以登录到 K10 控制台

$ sa_secret=$(kubectl get serviceaccount k10-k10 -o jsonpath="{.secrets[0].name}" --namespace kasten-io) && kubectl get secret $sa_secret --namespace kasten-io -ojsonpath="{.data.token}{'\n'}" | base64 --decode

☞ 以登录到 K10 控制台

20221030200658

2.3. 安装 MinIO 做为存储库

# Create MinIO Namespace
$ kubectl create ns minio
# Create MinIO by manifest
$ cat <<EOF | kubectl -n minio create -f -
apiVersion: v1
kind: Service
metadata:
  name: minio
spec:
  ports:
  - port: 9000
    targetPort: 9000
  selector:
    app: minio
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: minio-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 30Gi
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: minio
spec:
  serviceName: "minio"
  replicas: 1
  selector:
    matchLabels:
      app: minio
  template:
    metadata:
      labels:
        app: minio
    spec:
      volumes:
      - name: data
        persistentVolumeClaim:
          claimName: minio-pvc
      containers:
      - name: minio
        volumeMounts:
        - name: data 
          mountPath: "/data"
        image: minio/minio:RELEASE.2020-12-10T01-54-29Z
        args:
        - server
        - /data
        env:
        - name: MINIO_ACCESS_KEY
          value: "minio"
        - name: MINIO_SECRET_KEY
          value: "minio123"
        ports:
        - containerPort: 9000
          hostPort: 9000
EOF

#Check if MinIO Service running normally
$ kubectl get all -n minio
NAME          READY   STATUS    RESTARTS   AGE
pod/minio-0   1/1     Running   0          21m

NAME            TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
service/minio   ClusterIP   10.110.230.23   <none>        9000/TCP   21m

NAME                     READY   AGE
statefulset.apps/minio   1/1     21m 

#Expose MinIO Service for UI Acess
$ kubectl expose service minio -n minio --type=NodePort --name=minio-nodeport
$ kubectl get svc -n minio && kubectl get node -o wide
NAME             TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
minio            ClusterIP   10.110.230.23    <none>        9000/TCP         23m
minio-nodeport   NodePort    10.106.243.153   <none>        9000:31106/TCP   29s
NAME         STATUS   ROLES                  AGE   VERSION   INTERNAL-IP    EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME
mars-k8s-1   Ready    control-plane,master   21h   v1.23.1   172.16.60.90   <none>        Ubuntu 22.04.1 LTS   5.15.0-52-generic   docker://20.10.21

☞ 浏览器访问:http://172.16.60.90:31106/
Access Key: minio
Secret Key: minio123

☞ 点击硬盘图标,Create 名为 Kasten 的 Bucket

20221030201637

2.4. 在 K10 中配置MinIO做为存储库

在 K10 控制台配置存储库

主界面 Settings > Locations > Location Profiles > New Profiles

20221030201456

设定如下参数,点击 “Save Profile”

  • Profile Name: minio
  • Cloud Storage Provider: S3 Compatible
  • Access Key: minio
  • Secret Key: minio123
  • Endpoint: http://minio.minio:9000
  • Check ☑ Skip certificate chain and hostname verification
  • Region:
  • Bucket: kasten

3. 利用快照进行应用程序的备份与恢复

3.1. K10 应用程序发现

主界面 > Applications > mysql 找到我们需要备份的应用

20221030202513

3.4. 创建 Policy 保护 mysql 应用

点击 Crete Policy > 创建备份的策略

选项一切都可默认,点击Create Policy

20221030202924

3.5. 执行备份策略

主界面 > Policies > mysql-backup > Run Once 执行应用备份

20221030203033

3.6. 查看 Dashboard 与命令行中查看备份的执行情况

主界面 > Actions > Policy Run > 点击运行任务查看备份结果

20221030203404

在命令行上查看快照调用的情况

# 查看 volumesnapshot
$ kubectl get volumesnapshot -n mysql
NAME                            READYTOUSE   SOURCEPVC              SOURCESNAPSHOTCONTENT   RESTORESIZE   SNAPSHOTCLASS            SNAPSHOTCONTENT                                    CREATIONTIME   AGE
k10-csi-snap-r4tn4qk94h674rpg   true         data-mysql-release-0                           10Gi          csi-hostpath-snapclass   snapcontent-af9a8c05-b077-4294-aa4f-e7e1d4265759   2d             2d
# 查看 volumesnapshotcontent
$ kubectl get volumesnapshotcontent -n mysql
NAME                                               READYTOUSE   RESTORESIZE   DELETIONPOLICY   DRIVER                VOLUMESNAPSHOTCLASS      VOLUMESNAPSHOT                  VOLUMESNAPSHOTNAMESPACE   AGE
snapcontent-af9a8c05-b077-4294-aa4f-e7e1d4265759   true         10737418240   Delete           hostpath.csi.k8s.io   csi-hostpath-snapclass   k10-csi-snap-r4tn4qk94h674rpg   mysql                     2d

3.9. 在 K10 中还原 mysql 数据到另一个 Namespace

主界面 > Applications > mysql > 点击 Restore查看还原点

20221030204015

点击还原点 > 在 Applications Name 下 > 点击 Create a New Namespace > 输入 mysql-restore > 点击 Create > 点击 Restore

20221030204220

在 Confirm Restore 对话框中, 点击 Restore
20221030204522

3.10.查看 Dashboard 上 mysql-restore 数据还原的情况

20221030204811

3.10.对数据还原的情况进行分析

此时,让我们来观察一下快照的还原机制,通过查看 volumesnapshotcontent, 我们可以发现这里有一个名为 k10-csi-snap-wh9m8wgjg5gzj2x4 的快照,它的快照类为 k10-clone-csi-hostpath-snapclass, DELETIONPOLICY 为 Retain, 很明显这是 K10 为还原而创建的。同时,在对这个 mysql-restore 的 PVC 的描述时,可以发现,这就是源自于这个快照的。

$ kubectl get volumesnapshotcontent -n mysql-restore
NAME                                                                         READYTOUSE   RESTORESIZE   DELETIONPOLICY   DRIVER                VOLUMESNAPSHOTCLASS                VOLUMESNAPSHOT                  VOLUMESNAPSHOTNAMESPACE   AGE
k10-csi-snap-wh9m8wgjg5gzj2x4-content-9e561840-c004-4e0f-88e9-6c7374438a2f   true         10737418240   Retain           hostpath.csi.k8s.io   k10-clone-csi-hostpath-snapclass   k10-csi-snap-wh9m8wgjg5gzj2x4   mysql-restore             2m41s
snapcontent-af9a8c05-b077-4294-aa4f-e7e1d4265759                             true         10737418240   Delete           hostpath.csi.k8s.io   csi-hostpath-snapclass             k10-csi-snap-r4tn4qk94h674rpg   mysql                     2d1h

$ kubectl get pvc -n mysql-restore
mysql-restore   data-mysql-release-0   Bound    pvc-13d8ed12-0173-4f59-b7d5-b5b01d98ea16   1        csi-hostpath-sc   4m51s

$ kubectl -n mysql-restore describe pvc data-mysql-release-0
Name:          data-mysql-release-0
Namespace:     mysql-restore
StorageClass:  csi-hostpath-sc
Status:        Bound
Volume:        pvc-13d8ed12-0173-4f59-b7d5-b5b01d98ea16
Labels:        app.kubernetes.io/component=primary
               app.kubernetes.io/instance=mysql-release
               app.kubernetes.io/name=mysql
Annotations:   pv.kubernetes.io/bind-completed: yes
               pv.kubernetes.io/bound-by-controller: yes
               volume.beta.kubernetes.io/storage-provisioner: hostpath.csi.k8s.io
               volume.kubernetes.io/storage-provisioner: hostpath.csi.k8s.io
Finalizers:    [kubernetes.io/pvc-protection]
Capacity:      10Gi
Access Modes:  RWO
VolumeMode:    Filesystem
DataSource:
  APIGroup:  snapshot.storage.k8s.io
  Kind:      VolumeSnapshot
  Name:      k10-csi-snap-wh9m8wgjg5gzj2x4
Used By:     mysql-release-0
Events:
  Type    Reason                 Age    From                                                                           Message
  ----    ------                 ----   ----                                                                           -------
  Normal  ExternalProvisioning   7m29s  persistentvolume-controller                                                    waiting for a volume to be created, either by external provisioner "hostpath.csi.k8s.io" or manually created by system administrator
  Normal  Provisioning           7m29s  hostpath.csi.k8s.io_csi-hostpathplugin-0_38bf5516-630c-48d9-abf4-56ec8da0599b  External provisioner is provisioning volume for claim "mysql-restore/data-mysql-release-0"
  Normal  ProvisioningSucceeded  7m28s  hostpath.csi.k8s.io_csi-hostpathplugin-0_38bf5516-630c-48d9-abf4-56ec8da0599b  Successfully provisioned volume pvc-13d8ed12-0173-4f59-b7d5-b5b01d98ea16

4. 总结

本文中我们利用一个简单的 Ubuntu 虚拟机,创建了存储类与快照类,并利用 Kasten K10 对调用快照进行备份与还原,使大家在做 K10 的实验时,可以得到与企业级存储快照同样的体验,欢迎关注并转发!

5. 参考链接

Ubuntu 下载链接
https://ubuntu.com/download
external snapshotter controller
https://github.com/kubernetes-csi/external-snapshotter/tree/master/deploy/kubernetes/snapshot-controller
external snapshotter crd
https://github.com/kubernetes-csi/external-snapshotter/tree/v5.0.1/client/config/crd
Kasten Document
https://docs.kasten.io/latest/

Kasten k10 云原生应用安全系列 04 – 深度解读 Kasten K10 RBAC 基于角色的访问控制机制

本文主要内容

  1. RBAC 简介
  2. RBAC 在 Kubernetes 上的应用
  3. 使用 RBAC 为多租户环境配置 Kasten K10
  4. 总结
  5. 参考文献

前言

由于备份是应对勒索病毒攻击等威胁的最后一道防线,因此对备份环境的访问机制的保护尤为重要。作为领先的 Kubernetes 备份和恢复解决方案,Kasten K10 by Veeam 提供了保护 K10 环境所需的细粒度身份和访问管理控制,并可轻松为用户提供其角色所需的访问权限。在这篇文章中,我们将详细讲解 Kasten K10 中基于角色的访问控制 (RBAC) 功能。

继续阅读“Kasten k10 云原生应用安全系列 04 – 深度解读 Kasten K10 RBAC 基于角色的访问控制机制”

Kasten k10 云原生应用安全系列 01 – 使用 keycloak 为 K10 配置基于 OIDC 的身份验证

使用 keycloak 为 K10 配置基于 OIDC 的身份验证

[toc]

前言

访问控制是云原生安全的重要组成部分,也是 Kubernetes 集群在多租户环境中必不可少的基本安全加固手段。在 Kubernetes 中,访问控制分为三个部分:请求认证、授权和准入控制,今天我们的话题重点放在 Kasten K10 的认证和授权这两方面。 Kasten K10 作为云原生数据管理平台,专为 Kubernetes 而构建,符合 Kubernetes 的安全标准, 旨在为为企业运营团队提供是一个易于使用、可扩展且安全的数据管理应用平台,助力企业实现 Kubernetes 应用程序的备份恢复、灾难恢复和应用移动性。本文展示了我们如何通过启用基于 OpenID Connect (OIDC) 的身份验证方式进行身份验证,Kasten K10 支持多个厂商如 Okta、Google、Dex、Keycloak 和 Ping ID 等,本文以开源的 Keycloak 为例,向大家阐述 K10 在认证与授权方面的特性。

继续阅读“Kasten k10 云原生应用安全系列 01 – 使用 keycloak 为 K10 配置基于 OIDC 的身份验证”

Kasten K10 基础知识系列 — Kubernetes 备份定义

Kubernetes 备份定义

Kubernetes 备份的过程是备份在 Kubernetes 编排平台中运行的组件的过程,它是容器化应用程序和服务的抽象层。Kubernetes 集群的组件包括 pod、节点、控制平面和卷,其中每一个组件都需要一定程度的保护。与单体应用程序不同,现代应用程序在 Kubernetes 环境中的容器内包含多个微服务。保护 Kubernetes 集群的主要组件至关重要。随着企业越来越依赖容器化应用程序,Kubernetes 正在成为企业 IT 环境的重要组成部分。Kubernetes 备份可以部署在现场、异地或云端。

业务应用程序和微服务生成大量数据,需要使用强大的数据保护解决方案进行保护。Kubernetes 备份软件使企业能够执行备份并恢复包含容器的所有文件和微服务。

继续阅读“Kasten K10 基础知识系列 — Kubernetes 备份定义”

Kasten k10 云原生应用安全系列 02 – Kasten 调用 HashiCorp Vault 加密备份数据

Kasten 调用 HashiCorp Vault 加密备份数据

1. 数据加密备份的意义

数据是企业的资产,在备份存储库上的数据在保留状态时必须提防恶意行为。数据中心的安全操作规范中对备份数据加密的规定是保护备份基础架构的关键。Kasten by Veeam 将数据保留到存储库时会将备份数据进行加密,以达成存储环境安全的目的。本期文章我们一起学习如何用 HashiCorp Vault 对备份数据进行加密保护。

本文目录
1.数据加密备份的意义
2.Kasten K10 加密的工作原理与设置
3.HashiCorp Vault 与 Transit Secrets Engine 介绍
4.利用 HashiCorp Vault 加密 Kasten k10 备份数据
5.设置 Kasten K10 与 Vault 集成
6.总结

继续阅读“Kasten k10 云原生应用安全系列 02 – Kasten 调用 HashiCorp Vault 加密备份数据”

Kasten k10 云原生应用安全系列 03 – 利用 Kyverno 策略引擎实施和自动化 Kubernetes 数据保护策略

本文重点章节

  • 作者观察
  • Kasten 与 Kyverno
  • Kyerno + Kasten 数据保护策略快速上手
    • Kyerno 策略引擎介绍
    • Kyvero 的安装与部署
    • Kyvero 策略实践 - Kasten 数据保护的策略检查
  • Kasten 数据保护策略的说明
  • 关键要点总结
  • 参考文献

1.作者观察

随着云原生基础架构的普及,越来越多的企业开始把工作重点放在云原生的安全策略上。从 Redhat 公司 《2022 年 Kubernetes 安全现状报告》中,我们发现,受访者最担心由于容器和 Kubernetes 环境中的错误配置而导致的风险。应对这一挑战的最佳方法是尽可能自动化配置管理,以便用安全工具(而不是人工)提供帮助开发人员和 DevOps 团队更安全地配置容器和 Kubernetes 的护栏。

继续阅读“Kasten k10 云原生应用安全系列 03 – 利用 Kyverno 策略引擎实施和自动化 Kubernetes 数据保护策略”