You need to enable JavaScript to run this app.
导航
火山引擎云原生迁移解决方案
最近更新时间:2023.11.17 18:28:13首次发布时间:2022.04.11 18:44:17

本文介绍基于火山引擎容器服务(VKE),实现多场景中的云原生改造。本文以从自建 Kubernetes 迁移到 VKE 为例,为您介绍云原生改造过程。

背景介绍

云原生的时代已经到来,云原生技术正在重塑整个软件生命周期,越来越多的用户开始咨询如何对自己的应用做云原生化改造、如何把业务平滑地迁移到云上。每个用户的业务场景都是不同的,有些差异化的业务场景对容器平台也有一些定制化的需求,火山引擎梳理了过去帮助用户迁移的经验,总结出了一些解决方案、最佳实践和工具来帮助用户迁移。

迁移分类

alt

火山引擎容器服务优势


火山引擎容器服务依托火山引擎稳定可靠的 IaaS 能力,提供多种工作负载支持,支持快速弹性伸缩能力,帮助用户提高资源利用率。自研 VPC-CNI 插件将容器网络与 VPC 打通,无性能损耗,显著提升容器网络性能。结合字节跳动内部大规模容器实践经验,输出了一整套完善的容器最佳实践,能够支撑春晚红包等特大活动。同时,火山引擎容器服务拥有 Kubernetes 一致性认证,完全兼容原生 Kubernetes,用户完全不需要担心被单一厂商绑定的问题。

火山引擎容器服务和自建 Kubernetes 集群对比关系,如下表所示。

对比项火山引擎容器服务自建 Kubernetes
成本Master 全托管+专业服务Master 资源消耗 + 研发运维投入
弹性HPA、ClusterAutoscaler、VCIHPA
云服务融合CLB、NAS、TOS、TLS、AMS等自建对接
实践经验大量用户验证 + 字节跳动春节红包验证摸索踩坑
性能与优化高性能服务器 + VPC-CNI 网络性能提升网络损耗大
安全专业云安全中心 + 镜像漏洞扫描人工修复 + 处理不及时 + 周期较长

前置条件

  • 控制面全托管,需要确认应用是否有需要开启特殊的 apiserver 参数配置。
  • 出于性能考虑,目前不支持 networkpolicy,需要确认是否有使用到。
  • 集群节点是否有定制特殊的内核参数或者调优,云上使用统一的 velinux 操作系统,需要提前确认操作系统差异。

方案设计

迁云到 VKE 需要涉及到的组件、数据、服务切换等相关设计。

  • 集群:需要根据自己业务场景的不同来选择不同的机器类型,例如 CPU 机器还是 GPU 机器,虚拟服务器 ECS 还是裸金属服务器等。
  • 网络:涉及到集群内 Pod 之间进行通信模式,例如 Flannel 模式还是 VPC-CNI 模式等。
  • 容量:可以根据自身成本以及预算,规划一个可满足初期业务正常运行的容量,随后可以配置动态扩缩容随时弹缩集群规模。
  • 安全防护提升:镜像安全,例如使用私有镜像并定义镜像安全扫描。
  • 监控切换:监控切换相当于自建 Kubernetes 会更加全维度和立体,从基础设施到容器运行时监控一应俱全,并可根据阈值设定触发报警通知。建议把自建的日志收集方案切换成火山引擎的日志服务产品。
  • 数据迁移:云原生迁移操作中非常重要的一部分,主要包括数据库数据、存储数据、容器镜像等。对接火山引擎上的企业级数据库产品以及迁移工具,以保证数据迁云的可靠性、安全性。
  • 应用改造:主要涉及镜像地址的更新,服务暴露方式的优化,以及存储盘挂载方式的更新适配。
  • CICD 方案:提供一个满足用户快速迭代上线产品的 CICD 方案。

上述从集群规划到生产流量切换,便是用户业务迁移上云所需要涉及到的方方面面。调试完以上各个组件后,即可进行一部分生产流量的切换。

全栈迁云架构思路


全栈迁云架构思路分两种:一种是整体迁移,一种是平滑迁移。这两种方式相比,整体迁移更简单,平滑迁移相对复杂但对业务影响小,所以也需要根据用户的实际场景做选择。

  • 整体迁移:是指应用全部迁移上云后,各个组件调试完毕、测试验收通过后,可以整体切换生产流量到线上集群,待线上集群上的业务稳定运行一段时间后再下线原有环境。
  • 平滑迁移:是指可以使用线上容器服务 VKE 集群与线下集群混合组网对外提供服务,逐步改造业务组件上云后将原有环境下线。

容器化整体迁云

容器化整体迁云部分有如下两个小场景:

  • 从自建 Kubernetes 集群迁移到 VKE:此场景下的应用已经做了很大一部分的云原生化改造,迁移工作相对来说会简单些。
  • 从虚拟机或者裸金属服务器迁移到 VKE:部分传统应用直接运行在虚拟机或者裸金属服务器上,没有做过任何云原生化的改造。对于这部分场景,VKE 也提供了相关工具或方案,帮助用户进行云原生化的迁云改造,例如通过自动检测源码项目类型,生成 Dockerfile 和用于应用部署编排的 YAML 文件。更多信息,请参见 使用持续交付打包 Java 应用制作容器镜像

数据搬迁

在进行数据迁移时,可靠迁移是关键。根据数据类型的不同,VKE 会使用与之匹配的企业级迁移工具。数据、应用迁云完成后,需要进一步适配监控、日志等组件,待各个组件调试完毕并通过验收后,可以使用智能 DNS 进行生产流量的切割。

说明

使用的域名需要在火山引擎上进行 域名备案和接入

alt

容器镜像迁移操作

传统迁移方式的局限性

在 Kubernetes 集群迁移场景中,镜像仓库之间进行镜像迁移和镜像同步复制是基本需求。而使用 docker pulldocker push 结合脚本的传统方式进行镜像同步,有如下几个局限性:

  • 依赖磁盘存储:需要及时进行本地镜像的清理,并且落盘造成多余的时间开销,难以胜任生产场景中大量镜像的迁移。
  • 依赖 Docker 程序:Docker Daemon 对 Pull 和 Push 的并发数进行了严格的限制,无法进行高并发同步。
  • 使用成本高:部分功能只能通过 HTTP API 进行操作,仅使用 Docker CLI 无法做到,使脚本变得复杂。

image-syncer 简介

image-syncer 是一个简单、易用的批量镜像迁移和同步复制工具,支持目前主流的基于 Docker Registry V2 搭建的镜像存储服务,例如 CR、Docker、Hub、Quay、自建 Harbor 等。目前 image-syncer 已经初步经过了 TB 级别的生产环境镜像迁移验证。更多信息,请参见image-syncer

image-syncer 提供了以下几项功能:

  • 支持多对多镜像仓库同步。
  • 支持基于 Docker Registry V2 搭建的 Docker 镜像仓库服务。例如,火山引擎镜像仓库(CR)、Docker Hub、Quay、 阿里云镜像服务(ACR)、Harbor 等。镜像同步复制只经过内存和网络,不依赖磁盘存储,同步速度快。
  • 支持增量同步。通过对同步过的镜像 Blob 信息落盘,不会对已同步的镜像进行重复同步。
  • 支持并发同步。可以通过配置文件调整并发数。
  • 支持自动重试失败的同步任务,解决大部分镜像同步中的网络抖动问题。不依赖 Docker 以及其他程序。

使用 image-syncer 时,只需要保证 image-syncer 的运行环境与需要同步的镜像仓库网络连通,即可快速地完成镜像迁移、复制以及增量同步。同时 image-syncer 对硬件资源几乎没有要求,可较大程度减少迁移操作成本。

说明

image-syncer 严格控制网络连接数目等于并发数。只有在单个镜像层过大的情况下,若并发数目过大时,可能会占满内存(内存占用 <= 并发数 * 最大镜像层大小)。

除了使用重传机制规避同步过程中可能出现的偶发问题之外,image-syncer 会在运行结束时统计最后同步失败的镜像个数,并且打印出详细的日志,帮助使用者定位同步过程中出现的问题。

准备工作

使用 image-syncer 时,需要提供一个配置文件,内容示例如下:

{
    "auth": {                   // 认证字段,其中每个对象为一个registry的一个账号和
                                // 密码;通常,同步源需要具有pull以及访问tags权限,
                                // 同步目标需要拥有push以及创建仓库权限,如果没有提供,则默认匿名访问

        "quay.io": {            // registry的url,需要和下面images中对应registry的url相同
            "username": "user-1",               // 用户名,可选
            "password": "********",         // 密码,可选
            "insecure": true                 // registry是否是http服务,如果是,insecure字段需要为true,默认是false,可选,支持这个选项需要image-syncer版本 > v1.0.1
        },
        "cr-demo-cn-beijing.cr.volces.com": {
            "username": "user-2",
            "password": "********"
        },
        "registry.hub.docker.com": {
            "username": "user-3",
            "password": "********"
        }
    },
    "images": {
        // 同步镜像规则字段,其中一条规则包括一个源仓库(键)和一个目标仓库(值)

        // 同步的最大单位是仓库(repo),不支持通过一条规则同步整个namespace以及registry

        // 源仓库和目标仓库的格式与docker pull/push命令使用的镜像url类似(registry/namespace/repository:tag)
        // 源仓库和目标仓库(如果目标仓库不为空字符串)都至少包含registry/namespace/repository
        // 源仓库字段不能为空,如果需要将一个源仓库同步到多个目标仓库需要配置多条规则
        // 目标仓库名可以和源仓库名不同(tag也可以不同),此时同步功能类似于:docker pull + docker tag + docker push
        "quay.io/coreos/kube-rbac-proxy": "quay.io/ruohe/kube-rbac-proxy",
        "xxxx":"xxxxx",
        "xxx/xxx/xx:tag1,tag2,tag3":"xxx/xxx/xx"
        // 当源仓库字段中不包含tag时,表示将该仓库所有tag同步到目标仓库,此时目标仓库不能包含tag
        // 当源仓库字段中包含tag时,表示只同步源仓库中的一个tag到目标仓库,如果目标仓库中不包含tag,则默认使用源tag
        // 源仓库字段中的tag可以同时包含多个(例如"a/b/c:1,2,3"),tag之间通过","隔开,此时目标仓库不能包含tag,并且默认使用原来的tag

        // 当目标仓库为空字符串时,会将源镜像同步到默认registry的默认namespace下,并且repo以及tag与源仓库相同,默认registry和默认namespace可以通过命令行参数以及环境变量配置,参考下面的描述
    }     
}

从自建 Harbor 同步镜像到火山引擎 CR 标准版实例

  1. 创建火山引擎镜像仓库标准版实例,操作方法参见 创建标准版实例

    说明

    若使用子用户操作,需要提前使用火山引擎账号(主账号)对子用户进行 IAM 授权,然后子用户创建自己的镜像仓库密码。操作方法参见 授权 IAM 用户标准版实例访问凭证

  2. 华北 2 (北京) 地域创建名空间(本示例命名空间为 test),用于将自建 Harbor 同步到 CR 标准版实例中。操作步骤,请参见 创建命名空间

  3. 安装 image-syncer Linux amd64 版本。

  4. 创建配置文件 demo.json,将本地搭建的 Harbor 中的 library/nginx 仓库同步到步骤 2 中已创建的 test 命名空间。

    {
        "auth": {
            "harbor.test.com:32000": {
                "username": "admin",
                "password": "xxxxxxxxx",
                "insecure": true
            },
            "cr-demo-cn-beijing.cr.volces.com": {
                "username": "cr_demo",
                "password": "xxxxxxxx"
            }
        },
        "images": {
            "harbor.test.com:32000/library/nginx": ""
        }
    }
    
  5. 执行如下命令完成镜像迁移。

    ./image-syncer --proc=10 --config=./demo.json --registry=cr-demo-cn-beijing.cr.volces.com --namespace=test --retries=10 --log=./log
    

操作结果

一次镜像同步会经历生成同步任务、执行同步任务、重试失败任务三个阶段。其中,每个同步任务都代表了一个需要同步的镜像(tag)。如果配置文件中某条规则没有指定 tag,在 生成同步任务 阶段会自动列出源仓库所有 tag,并生成对应的同步任务。如果生成同步任务失败,也会在重试阶段进行重试。