如何从自建的K8S集群迁移到AWS EKS

314 阅读7分钟

背景

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

迁移方案

▌架构图

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:

velero.io/

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

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

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

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

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

下图为 Velero 的工作流程图:

df637e9bbba3e6f758adabb16f1964b3.jpeg

▌迁移原理

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

restic:

github.com/restic/rest…

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 以上,在这里我们使用 Amazon EKS 为例

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

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

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

github.com/vmware-tanz…

● 创建 S3 存储桶

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

BUCKET=
REGION=
aws s3api create-bucket \
    --bucket $BUCKET \
    --region $REGION \
    --create-bucket-configuration LocationConstraint=$REGION
 
 
aws s3api create-bucket \
    --bucket $BUCKET \
    --region us-east-1

● 为 Velero 设置权限

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

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

aws iam create-user --user-name velero

创建 policy:

cat > velero-policy.json <<EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ec2:DescribeVolumes",
                "ec2:DescribeSnapshots",
                "ec2:CreateTags",
                "ec2:CreateVolume",
                "ec2:CreateSnapshot",
                "ec2:DeleteSnapshot"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:DeleteObject",
                "s3:PutObject",
                "s3:AbortMultipartUpload",
                "s3:ListMultipartUploadParts"
            ],
            "Resource": [
                "arn:aws:s3:::${BUCKET}/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::${BUCKET}"
            ]
        }
    ]
}
EOF
 
 
aws iam put-user-policy \
  --user-name velero \
  --policy-name velero \
  --policy-document file://velero-policy.json

为 Velero 用户创建 AKSK:

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

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

{
  "AccessKey": {
        "UserName": "velero",
        "Status": "Active",
        "CreateDate": "2017-07-31T22:24:41.576Z",
        "SecretAccessKey": ,
        "AccessKeyId": 
  }
}

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

$aws configure
 
 
[default]
aws_access_key_id=
aws_secret_access_key=

● 安装 Velero CLI

#下载安装velero CLI
wget https://github.com/vmware-tanzu/velero/releases/download/v1.10.0/velero-v1.10.0-linux-amd64.tar.gz
tar -xvzf velero-v1.10.0-linux-amd64.tar.gz
sudo mv velero /usr/local/bin/
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 应用

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

$kubectl apply -f mysql.yaml
---
apiVersion: v1
kind: Namespace
metadata:
  name: mysql
  labels:
    app: mysql
---
apiVersion: v1
kind: Service
metadata: 
  name: mysql
  labels: 
    app: mysql
    app.kubernetes.io/name: mysql
spec: 
  ports: 
  - name: mysql
    port: 3306
  clusterIP: None
  selector: 
    app: mysql
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-mysql
  namespace: mysql
  labels:
    app: mysql
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 2Gi
---
apiVersion: apps/v1
kind: Statefulset
metadata:
  name: s-mysql
  namespace: mysql
  labels:
    app: mysql
spec:
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - image: mysql:5.6
        name: mysql
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: Password123!
        ports:
        - containerPort: 3306
          name: port-mysql
        volumeMounts:
        - name: vol-mysql
          mountPath: /var/lib/mysql
      volumes:
      - name: vol-mysql
        persistentVolumeClaim:
          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

Clean up

kubectl delete namespace/velero clusterrolebinding/velero
kubectl delete crds -l component=velero
kubectl delete ns mysql

04

结论

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