当前位置:   article > 正文

Kubernetes 有状态服务跨云迁移到 Amazon EKS

gcp迁移到aws ec2

4740c1e2591a0e95814940cc97fb828b.gif

01

背景

Kubernetes 和云原生技术在过去几年中经历了惊人的增长,企业采用 Kubernetes 的主要原因是它可以快速扩展,提高资源利用率,并且可迁移性优势明显。从本地部署 Kubernetes 向公有云托管 Kubernetes 环境迁移和跨云进行 Kubernetes 迁移的趋势正在加速,因为云上托管的 Kubernetes 服务的维护更加简单,可用性和可靠性更高。

 有状态服务迁移的需求

Kubernetes 平台上运行的应用一般是无状态(Stateless)应用为主,但是有状态(Stateful)应用也不少见,各种数据库就是最常见的有状态应用,另外就是一些应用有数据持久化到磁盘的需求。而无状态应用则与有状态应用相对应,常见的无状态应用包括各种页面前端、Httpd、Nginx 中间件等。

无状态服务在迁移的过程中一般使用 yaml 文件手工重新部署或利用 CICD 平台进行自动部署,不用过多考虑将原有 Kubernetes 平台上的应用数据恢复到新集群中。但是一些有持久化数据的服务在迁移时要将原有数据也迁移到新集群中,这些服务通常采用 Deployment+PVC 或 StatefulSet 的方式进行部署,这时选择什么样的迁移方式显得很重要。对于类似数据库这样实时性要求高的,一般建议采用专业工具来进行在线迁移,如:Amazon DMS;如果是对实时性要求没有非常高要求的情况下,可以采用一些开源的数据迁移工具来进行,本文就是针对这种场景,推荐大家使用 Velero 这个工具协助大家迁移有持久化数据的服务。

什么是有状态服务

有状态应用(Stateful Application)通常是指有持久化存储需求的各种应用。有状态在 Kubernetes 中的定义是:StatefulSet 是用来管理有状态应用的工作负载 API 对象。StatefulSet 用来管理某些 Pod 集合的部署和扩缩, 并为这些 Pod 提供持久存储和持久标识符。

StatefulSet:

https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/statefulset/

Pod :

https://kubernetes.io/zh-cn/docs/concepts/workloads/pods/

为什么有状态服务难迁移

有状态应用在容器平台迁移时面临一个问题:在应用需要数据不丢失的情况下,必须要能做到持久化数据与容器一同进行迁移,否则原有数据将会丢失或无法访问。另外从技术角度讲,在跨平台迁移时因为底层存储驱动大多不一样,导致无法直接将数据迁移到另外的平台。目前,通用迁移方案大多依赖于有状态服务自身提供的备份和恢复机制来实现,然而在迁移操作过程中存在需要人工参与、操作时间过长等问题。

02

迁移方案

▌架构图

7cf850734ce1d9a777bb6f7547a72ffa.jpeg

▌方案说明

1. 在源 Kubernetes 集群所在云虚拟机上安装 Velero CLI

2. 在源 Kubernetes 集群上安装并启动 Velero server

3. 通过 Velero CLI 创建源 Kubernetes 集群上的有状态应用备份文件并存储到 Cloud Object Storage 中

4. 使用命令行工具将 Cloud Object Storage 中的备份文件同步到 Amazon S3

5. 在 Amazon EC2 上同样安装 Velero CLI

6. 在 Amazon EKS 上安装并启动 Velero server

7. 使用 Velero CLI 将 Amazon S3 桶中的备份文件恢复到 Amazon EKS 集群上

▌Velero 工具说明

Velero (之前的版本叫做 Heptio Ark),一个开源工具,可以对 Kubernetes 集群进行安全备份和恢复,迁移 Kubernetes 集群资源和持久卷,对于应用部署类型,无论 Deployment 还是 StatefulSet 都可以支持。

Velero:

https://velero.io/

在 Kubenetes 集群中部署 Velero,可以实现以下功能:

● 备份集群资源,丢失时恢复

● 将集群资源迁移到其他集群

● 将生产集群资源复制到开发和测试集群

关于 Velero 的更多信息,请参见 Velero (https://velero.io/) 官方文档。

下图为 Velero 的工作流程图:

df637e9bbba3e6f758adabb16f1964b3.jpeg

▌迁移原理

Velero 使用名为 restic 的免费开源备份工具备份和恢复 Kubernetes 卷。Velero 引入了三个 CRD (Custom Resource Definitions) 和关联的 Controllers。

restic:

https://github.com/restic/restic

ResticRepository 用来管理 Velero 的 restic 存储库的生命周期,当请求备份时,Velero 会为每个 namespace 创建一个 restic 库,用于存储备份数据。PodVolumeBackup 用于 pod 中卷的静态备份,主 Velero 备份进程在找到带注释的 pod 时会为其创建备份,集群中的每个 node 上都会运行一个备份 controller 用来处理该节点上的 pod 的 PodVolumeBackup。PodVolumeRestore 是用于卷的静态恢复的 controller,Velero 执行 restic restore 命令来恢复 pod volume 数据。

在跨云迁移 Kubernetes 集群中的有状态服务时,由于经常使用的 Kubernetes 源集群的 CSI (Cloud Storage Interface) 不同于目标集群的 CSI,会导致无法直接使用 Snapshot 来进行备份、恢复,这是在跨云迁移时的一个难题(不同云平台之间的 CSI Driver 并不相同)。

所以使用 Snapshot 并不能完成有状态服务的迁移,在这里我们使用 Velero 的 File System Backup 功能来实现。Velero 不支持容器中 hostpath 的备份,所以请注意 Velero 支持的场景和功能是否满足需求。如果在迁移需求中需要进行增量数据迁移,此时建议使用应用自带的迁移方法,如可使用 Amazon DMS 去满足数据库的全量+增量数据迁移。

下面是备份恢复过程中的相关概念:

● Kubernetes Volume

de9b33043607bbf31ed4be6300d965d3.jpeg

Container 中的文件在磁盘上是临时存放的,这给 Container 中运行的较重要的应用程序带来一些问题。问题之一是当容器崩溃时文件丢失。第二个问题是在同一 Pod 中运行多个容器并共享文件时,如果 kubelet 重新启动容器,但容器会以干净的状态重启,此时无法共享数据。 Kubernetes 卷(Volume) 这一抽象概念能够解决这两个问题。

● Snapshot

在 Kubernetes 中,VolumeSnapshot 表示存储系统上卷的快照。

841fee0fecbd8e0d861ac1bde864edbb.jpeg

● File System Backup

bcf5714e1276d2bec5e54785e86f295a.jpeg

Velero 支持从卷的文件系统备份和恢复附加到 Pod 的 Kubernetes 卷,称为文件系统备份(简称 FSB)或 Pod 卷备份。

03

迁移过程 Demo

 环境部署

▌前提要求

● 具有某公有云(源)和 Amazon(目标)的账号

● 具有源和目标公有云的对象存储服务权限,这里我们使用 GCP Cloud Storage 和 Amazon S3

● 具有两个(源和目标)Kubernetes 集群,版本要求 1.16 以上,在这里我们使用 GCP GKE 和 Amazon EKS 为例

● 两个 Kubernetes 集群都要安装 Velero,后面介绍具体的安装过程

▌在 GCP 环境中部署 Velero CLI 并安装启动 Velero

参考:GitHub – vmware-tanzu/velero-plugin-for-gcp: Plugins to support Velero on Google Cloud Platform (GCP)

https://github.com/vmware-tanzu/velero-plugin-for-gcp

● 创建 GCS Bucket

  1. BUCKET=
  2. gsutil mb gs://$BUCKET/

● 为 Velero 创建 Service Account

注意:在 GCP 平台为 Velero 赋权有两种方式:第一种为 Service Account Key;第二种为 Workload Identity。在本文中我们使用第一种方式,如果需要第二种请参考上面的链接中的内容。

  1. #查看当前的配置
  2. gcloud config list
  3. #设置PROJECT_ID
  4. PROJECT_ID=$(gcloud config get-value project)
  5. #创建service account
  6. GSA_NAME=velero
  7. gcloud iam service-accounts create $GSA_NAME \
  8.    --display-name "Velero service account"
  9. #查看上面创建的service account
  10. gcloud iam service-accounts list
  11. #设置$SERVICE_ACCOUNT_EMAIL变量
  12. SERVICE_ACCOUNT_EMAIL=$(gcloud iam service-accounts list \
  13.  --filter="displayName:Velero service account" \
  14.  --format 'value(email)')

左滑查看更多

● 为 Velero 创建带有权限的 Role

  1. ```bash
  2. ROLE_PERMISSIONS=(
  3. compute.disks.get
  4. compute.disks.create
  5. compute.disks.createSnapshot
  6. compute.snapshots.get
  7. compute.snapshots.create
  8. compute.snapshots.useReadOnly
  9. compute.snapshots.delete
  10. compute.zones.get
  11. storage.objects.create
  12. storage.objects.delete
  13. storage.objects.get
  14. storage.objects.list
  15. )
  16. gcloud iam roles create velero.server \
  17. --project $PROJECT_ID \
  18. --title "Velero Server" \
  19. --permissions "$(IFS=","; echo "${ROLE_PERMISSIONS[*]}")"
  20. gcloud projects add-iam-policy-binding $PROJECT_ID \
  21. --member serviceAccount:$SERVICE_ACCOUNT_EMAIL \
  22. --role projects/$PROJECT_ID/roles/velero.server
  23. gsutil iam ch serviceAccount:$SERVICE_ACCOUNT_EMAIL:objectAdmin gs://${BUCKET}
  24. ```

左滑查看更多

● 为 Velero 的 Service Account 生成 Key

  1. gcloud iam service-accounts keys create credentials-velero \
  2.    --iam-account $SERVICE_ACCOUNT_EMAIL

左滑查看更多

● 下载 Velero CLI

  1. wget https://github.com/vmware-tanzu/velero/releases/download/v1.10.0/velero-v1.10.0-linux-amd64.tar.gz
  2. tar -xvzf velero-v1.10.0-linux-amd64.tar.gz
  3. sudo mv velero /usr/local/bin/
  4. velero help

左滑查看更多

● 安装 Velero

在参考上面 GCP 的安装过程时,注意如下类似的安装命令的变量部分,此命令安装 Velero 以及 GCP 的插件,指定存储位置和指定使用 node-agent 来执行 File System Backup。

velero install  --provider gcp  --plugins velero/velero-plugin-for-gcp:v1.6.0  --bucket $bucketname  --secret-file ./credentials-velero  --use-volume-snapshots=false  --use-node-agent

左滑查看更多

安装完后注意检查如下内容,确认是否安装成功:

f342f86e585922bc37b5c93642182b43.jpeg

6ffc643e2f9d480671b682cff87930b6.jpeg

▌在 Amzon 环境中部署 Velero CLI 并安装启动 Velero

参考:GitHub – vmware-tanzu/velero-plugin-for-aws: Plugins to support Velero on Amzon

https://github.com/vmware-tanzu/velero-plugin-for-aws

● 创建 S3 存储桶

注意:us-east-1 does not support a LocationConstraint. If your region is us-east-1, omit the bucket configuration:

  1. BUCKET=
  2. REGION=
  3. aws s3api create-bucket \
  4.    --bucket $BUCKET \
  5.    --region $REGION \
  6.    --create-bucket-configuration LocationConstraint=$REGION
  7. aws s3api create-bucket \
  8.    --bucket $BUCKET \
  9.    --region us-east-1

左滑查看更多

● 为 Velero 设置权限

注意:在 Amzon 为 Velero 赋权有两种方式:第一种为使用 IAM USER AKSK;第二种为使用 kube2iam。在本文中我们使用第一种方式,如果需要第二种请参考上面的链接中的内容。

创建用户 Velero。也可以使用原有的用户的 AKSK,只需要替换掉 Velero 用户名即可:

aws iam create-user --user-name velero

左滑查看更多

创建 policy:

  1. cat > velero-policy.json <<EOF
  2. {
  3.    "Version": "2012-10-17",
  4.    "Statement": [
  5.        {
  6.            "Effect": "Allow",
  7.            "Action": [
  8.                "ec2:DescribeVolumes",
  9.                "ec2:DescribeSnapshots",
  10.                "ec2:CreateTags",
  11.                "ec2:CreateVolume",
  12.                "ec2:CreateSnapshot",
  13.                "ec2:DeleteSnapshot"
  14.            ],
  15.            "Resource": "*"
  16.        },
  17.        {
  18.            "Effect": "Allow",
  19.            "Action": [
  20.                "s3:GetObject",
  21.                "s3:DeleteObject",
  22.                "s3:PutObject",
  23.                "s3:AbortMultipartUpload",
  24.                "s3:ListMultipartUploadParts"
  25.            ],
  26.            "Resource": [
  27.                "arn:aws:s3:::${BUCKET}/*"
  28.            ]
  29.        },
  30.        {
  31.            "Effect": "Allow",
  32.            "Action": [
  33.                "s3:ListBucket"
  34.            ],
  35.            "Resource": [
  36.                "arn:aws:s3:::${BUCKET}"
  37.            ]
  38.        }
  39.    ]
  40. }
  41. EOF
  42. aws iam put-user-policy \
  43.  --user-name velero \
  44.  --policy-name velero \
  45.  --policy-document file://velero-policy.json

左滑查看更多

为 Velero 用户创建 AKSK:

aws iam create-access-key --user-name velero

左滑查看更多

上面的命令生成类似如下内容:

  1. {
  2.  "AccessKey": {
  3.        "UserName": "velero",
  4.        "Status": "Active",
  5.        "CreateDate": "2017-07-31T22:24:41.576Z",
  6.        "SecretAccessKey": ,
  7.        "AccessKeyId":
  8.  }
  9. }

左滑查看更多

使用上面的 AKSK 生成 credential 文件 credentials-velero:

  1. $aws configure
  2. [default]
  3. aws_access_key_id=
  4. aws_secret_access_key=

● 安装 Velero CLI

  1. #下载安装velero CLI
  2. wget https://github.com/vmware-tanzu/velero/releases/download/v1.10.0/velero-v1.10.0-linux-amd64.tar.gz
  3. tar -xvzf velero-v1.10.0-linux-amd64.tar.gz
  4. sudo mv velero /usr/local/bin/
  5. velero help

左滑查看更多

● 安装 Velero server

在参考上面 Amzon 的安装过程时,注意如下类似的安装命令的变量部分。另外,此处的 –secret-file 使用的是上面生成的 credentials 文件:credentials-velero,也可以直接使用之前存 AKSK 的 credential 文件,如:~/.aws/credentials

velero install --provider aws --plugins velero/velero-plugin-for-aws:v1.6.0 --bucket $bucketname --backup-location-config region=$REGION --snapshot-location-config region=$REGION --secret-file /home/ec2-user/.aws/credentials --use-node-agent restic/restic

左滑查看更多

安装完后注意检查如下内容:

69bdea291aa8f252ee22b7a018a1c527.png

202d62ed23a83ca20a24e3609fc09eb2.png

确认完以上类似内容出现后表示安装成功。

部署 Demo 应用

在 GKE 的源 cluster 上部署 Demo 应用,使用下面的 yaml 文件:

  1. $kubectl apply -f mysql.yaml
  2. ---
  3. apiVersion: v1
  4. kind: Namespace
  5. metadata:
  6.  name: mysql
  7.  labels:
  8.    app: mysql
  9. ---
  10. apiVersion: v1
  11. kind: Service
  12. metadata:
  13.  name: mysql
  14.  labels:
  15.    app: mysql
  16.    app.kubernetes.io/name: mysql
  17. spec:
  18.  ports:
  19.  - name: mysql
  20.    port: 3306
  21.  clusterIP: None
  22.  selector:
  23.    app: mysql
  24. ---
  25. apiVersion: v1
  26. kind: PersistentVolumeClaim
  27. metadata:
  28.  name: pvc-mysql
  29.  namespace: mysql
  30.  labels:
  31.    app: mysql
  32. spec:
  33.  accessModes:
  34.    - ReadWriteOnce
  35.  resources:
  36.    requests:
  37.      storage: 2Gi
  38. ---
  39. apiVersion: apps/v1
  40. kind: Statefulset
  41. metadata:
  42.  name: s-mysql
  43.  namespace: mysql
  44.  labels:
  45.    app: mysql
  46. spec:
  47.  selector:
  48.    matchLabels:
  49.      app: mysql
  50.  template:
  51.    metadata:
  52.      labels:
  53.        app: mysql
  54.    spec:
  55.      containers:
  56.      - image: mysql:5.6
  57.        name: mysql
  58.        env:
  59.        - name: MYSQL_ROOT_PASSWORD
  60.          value: Password123!
  61.        ports:
  62.        - containerPort: 3306
  63.          name: port-mysql
  64.        volumeMounts:
  65.        - name: vol-mysql
  66.          mountPath: /var/lib/mysql
  67.      volumes:
  68.      - name: vol-mysql
  69.        persistentVolumeClaim:
  70.          claimName: pvc-mysql

左滑查看更多

验证部署是否成功:

f85f80653dff9c5bc6480b32742e26d7.jpeg

在 pod 中写入要持久化存储的测试数据,执行如下命令:

kubectl exec d-mysql-7c748d6f47-j97bt -it /bin/bash -n mysql

左滑查看更多

参考下面图中的操作内容进行数据写入测试:进入 pod;登录数据库,数据库登录密码见上面 yaml 文件中的环境变量 MYSQL_ROOT_PASSWORD;创建数据库 test1:

0d4115c7f58ca449b9e55aa188d2d466.jpeg

使用 Velero 迁移有状态应用

在源集群上备份有状态应用:

a.在源集群上为包含要备份的卷的每个 pod 运行以下命令:

kubectl -n YOUR_POD_NAMESPACE annotate pod/YOUR_POD_NAME backup.velero.io/backup-volumes=YOUR_VOLUME_NAME_1,YOUR_VOLUME_NAME_2,...

左滑查看更多

举例:

kubectl -n mysql annotate pod/d-mysql-7c748d6f47-j97bt backup.velero.io/backup-volumes=vol-mysql

左滑查看更多

b.使用 velero 备份源集群的资源:

velero backup create NAME OPTIONS...

左滑查看更多

举例:

velero backup create mysql-backup-ann --include-namespaces mysql

左滑查看更多

c.查看备份结果:

velero backup describe mysql-backup-ann

左滑查看更多

0005932395a8c96378985bffff0044d0.jpeg

d.将备份内容传输到 Amazon S3 以用于在目标集群进行恢复(这部分内容要提前把 Amazon CLI 的 AKSK 权限设置好,不论是哪家公有云,都可以通过 CLI 的权限进行处理):

gsutil -m rsync -rd gs://velerobucket s3://velero-global-bucket

左滑查看更多

在 Amazon EKS 集群上恢复有状态应用:

a.查看备份内容是否存在:

velero backup get

c8fba80208dced0829701d1ba87c72ed.jpeg

b.进行恢复操作:

velero restore create mysql-restore-ann --from-backup mysql-backup-ann

左滑查看更多

c.查看恢复结果:

velero restore describe mysql-restore-ann

左滑查看更多

3ad3ca5c553063b4a7bc19ea768593e9.jpeg

d.进入 pod 查看数据是否恢复,看到有 test1 这个数据库后证明源集群中的数据被恢复到了目标集群中,操作命令请参考下图:

c2fe526df520579df401311c04a4ceea.jpeg

03

Clean up

  1. kubectl delete namespace/velero clusterrolebinding/velero
  2. kubectl delete crds -l component=velero
  3. kubectl delete ns mysql

左滑查看更多

04

结论

通过上面的测试,我们可以发现 Velero 的 File System Backup 功能可以有效的对源 Kubernetes 集群中的有状态服务进行跨云迁移,这解决了很多想将有状态服务迁移到云上或跨云迁移的客户的问题。

05

注意事项

如果 Velero 在集群上启动不了就调整一下资源限制,命令如下:

  1. kubectl patch deployment velero -n velero —patch '{"spec":{"template":{"spec":{"containers":[{"name": "velero", "resources": {"limits":{"cpu": "300m", "memory": "512Mi"}, "requests": {"cpu": "200m", "memory": "128Mi"}}}]}}}}'
  2. kubectl patch daemonset node-agent -n velero —patch '{"spec":{"template":{"spec":{"containers":[{"name": "node-agent", "resources": {"limits":{"cpu": "300m", "memory": "512Mi"}, "requests": {"cpu": "200m", "memory": "512Mi"}}}]}}}}'
  3. kubectl create secret generic -n velero bsl-credentials --from-file=gcp=/home/user1/credentials-velero
  4. velero backup-location create bsl-gcp   --provider gcp   --bucket $BUCKET   --credential=bsl-credentials=gcp

左滑查看更多

▌Velero File System Backup 功能不支持 HostPath

▌低版本的 kubectl 可能会导致 API 调用失败,这时需要升级 Amzon CLI 到最新版本,然后执行:

Amzon CLI:

https://docs.aws.amazon.com/zh_cn/cli/latest/userguide/getting-started-install.html

  1. aws eks update-kubeconfig --name ${EKS_CLUSTER_NAME} --region ${REGION}
  2. cat ~/.kube/config
  3. #看到:apiVersion: client.authentication.k8s.io/v1beta1

左滑查看更多

▌Velero File System Backup 只能备份在 yaml 中声明的 mountpath 的路径下的内容,除此以外的内容备份不出来

06

参考资料

• GitHub – vmware-tanzu/velero-plugin-for-aws: Plugins to support Velero on Amzon

https://github.com/vmware-tanzu/velero-plugin-for-aws

• GitHub – vmware-tanzu/velero-plugin-for-aws: Plugins to support Velero on Amzon

https://github.com/vmware-tanzu/velero-plugin-for-aws

• Amzon eks update-kubeconfig invalid apiVersion · Issue #6920 · aws/aws-cli · GitHub

https://github.com/aws/aws-cli/issues/6920

• Velero Docs – Overview

https://velero.io/docs/v1.10/index.html

• Velero Docs – Velero File System Backup Performance Guide

https://velero.io/docs/v1.10/performance-guidance/

本篇作者

221b3f0ac03f8720d3d55bf7c8f118e3.png

王建利

亚马逊云科技解决方案架构师,主要负责企业级客户的上云或跨云迁移工作,服务客户涵盖从能源,互联网,传统生产制造,擅长迁移、DevOps 和容器领域。具备十几年 IT 专业服务经验,历任程序设计师、项目经理、解决方案架构师。

06e8bd0a59550fe4e271de31a7332651.gif

34cbdc07c9c27b2243d79233679e6f5d.gif

听说,点完下面4个按钮

就不会碰到bug了!

7981c9688436507df08beb49b443aa99.gif

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/492651
推荐阅读
相关标签
  

闽ICP备14008679号