华为云用户手册

  • 定义CRD资源Network 创建文件夹pkg/apis/networking.cci.io/v1beta1,其中networking.cci.io为CRD资源的group,v1beta1为CRD资源版本 mkdir -p pkg/apis/networking.cci.io/v1beta1 在新建文件夹中新建以下文件: doc.go // +k8s:deepcopy-gen=package// +groupName=networking.cci.io// +groupGoName=NetworkingCCIpackage v1beta1 types.go package v1beta1import (metav1 "k8s.io/apimachinery/pkg/apis/meta/v1")// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object// NetworkList is a list of network resource in container.type NetworkList struct {metav1.TypeMeta `json:",inline"`// Standard list metadata.// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata// +optionalmetav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`Items []Network `json:"items" protobuf:"bytes,2,rep,name=items"`}// +genclient// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object// Network is a network resource in container.type Network struct {metav1.TypeMeta `json:",inline"`// +optionalmetav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`// Spec defines the attributes on a network// +optionalSpec NetworkSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"`// Status describes the network status// +optionalStatus NetworkStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`}// NetworkSpec describes the attributes on a network resource.type NetworkSpec struct {// network typeNetworkType string `json:"networkType,omitempty" protobuf:"bytes,5,opt,name=networkType"`// ID of the VPC to attachAttachedVPC string `json:"attachedVPC,omitempty" protobuf:"bytes,4,opt,name=attachedVPC"`// network IDNetworkID string `json:"networkID,omitempty" protobuf:"bytes,7,opt,name=networkID"`// Subnet IDSubnetID string `json:"subnetID,omitempty" protobuf:"bytes,8,opt,name=subnetID"`// available zoneAvailableZone string `json:"availableZone,omitempty" protobuf:"bytes,9,opt,name=availableZone"`// The CIDR of the networkCIDR string `json:"cidr,omitempty" protobuf:"bytes,3,opt,name=cidr"`}// NetworkStatus describes the status of a networktype NetworkStatus struct {// State describes the network state// +optionalState string `json:"state" protobuf:"bytes,1,opt,name=state"`// Message describes why network is in current state// +optionalMessage string `json:"message,omitempty" protobuf:"bytes,2,opt,name=message"`}const (// NetworkInitializing means the network is initializingNetworkInitializing = "Initializing"// NetworkPending means the network is processingNetworkPending = "Pending"// NetworkActive means the network is availableNetworkActive = "Active"// NetworkFailed means the network is not availableNetworkFailed = "Failed"// NetworkTerminating means the network is undergoing graceful terminationNetworkTerminating = "Terminating") register.go package v1beta1import (metav1 "k8s.io/apimachinery/pkg/apis/meta/v1""k8s.io/apimachinery/pkg/runtime""k8s.io/apimachinery/pkg/runtime/schema")// GroupName is the group name use in this packageconst GroupName = "networking.cci.io"// SchemeGroupVersion is group version used to register these objectsvar SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1beta1"}// Resource takes an unqualified resource and returns a Group qualified GroupResourcefunc Resource(resource string) schema.GroupResource {return SchemeGroupVersion.WithResource(resource).GroupResource()}var (// localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes.SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)localSchemeBuilder = &SchemeBuilderAddToScheme = localSchemeBuilder.AddToScheme)// Adds the list of known types to the given scheme.func addKnownTypes(scheme *runtime.Scheme) error {scheme.AddKnownTypes(SchemeGroupVersion,&Network{},&NetworkList{},)// Add the watch version that appliesmetav1.AddToGroupVersion(scheme, SchemeGroupVersion)return nil}
  • 初始化项目 创建项目examples.com/cci-examples。 项目依赖k8s.io/client-go、k8s.io/code-generator,以下版本可供参考 k8s.io/client-go@kubernetes-1.15.0、k8s.io/code-generator@kubernetes-1.15.0 k8s.io/client-go@kubernetes-1.16.0、k8s.io/code-generator@kubernetes-1.16.0 k8s.io/client-go@kubernetes-1.17.0、k8s.io/code-generator@kubernetes-1.17.0 k8s.io/client-go@kubernetes-1.18.0、k8s.io/code-generator@kubernetes-1.18.0 k8s.io/client-go@kubernetes-1.19.0、k8s.io/code-generator@kubernetes-1.19.0 k8s.io/client-go@kubernetes-1.20.0、k8s.io/code-generator@kubernetes-1.20.0 mkdir -p examples.com/cci-examplescd examples.com/cci-examples/go mod init examples.com/cci-examplesgo get k8s.io/client-go@kubernetes-1.15.0go get k8s.io/code-generator@kubernetes-1.15.0
  • 使用Python SDK 您可以前往开发体验馆 Codelabs / Namespace生命周期代码示例(Python)下载相关代码,并在线调试。 首先需要先生成kubeconfig配置文件,参考cci-iam-authenticator使用参考,使用子命令generate-kubeconfig生成kubeconfig配置文件。 这里的示例代码采用了定期刷新token的方式来防止token过期(缓存值token有效期为24小时),您可以增加获取失败重试的操作,以提升可用性。 定期刷新token的方式不适用于该账号权限发生变更的情形,如果账号权限发生变更(如主账号变更子账号权限,导致子账号权限发生变更),变更前获取的token会失效,需要重新获取 # -*- coding: utf-8 -*-import loggingimport timeimport threadingfrom kubernetes import client, configNAMESPACE = "test-k8s-client-namespace"logging.basicConfig( level=logging.INFO, datefmt="%Y-%m-%d %H:%M:%S", format="%(asctime)s %(levelname)s %(message)s",)def create_namespace(): flavor = "general-computing" pool_size = "10" namespace = client.V1Namespace( metadata=client.V1ObjectMeta( name=NAMESPACE, annotations={ "namespace.kubernetes.io/flavor": flavor, "network.cci.io/warm-pool-size": pool_size, }, labels={ "rbac.authorization.cci.io/enable-k8s-rbac": "false", } ) ) logging.info("start to create namespace %s", NAMESPACE) client.CoreV1Api().create_namespace(namespace) logging.info("namespace created")def create_network(): name = "test-k8s-client-namespace-cn-north-7-default-network" project_id = "{project_id}" domain_id = "{domain_id}" security_group_id = "{security_group_id}" available_zone = "{available_zone}" vpc_id = "{vpc_id}" cidr = "{cidr}" network_id = "{network_id}" subnet_id = "{subnet_id}" body = { "apiVersion": "networking.cci.io/v1beta1", "kind": "Network", "metadata": { "annotations": { "network.alpha.kubernetes.io/default-security-group": security_group_id, "network.alpha.kubernetes.io/domain-id": domain_id, "network.alpha.kubernetes.io/project-id": project_id, }, "name": name, }, "spec": { "availableZone": available_zone, "cidr": cidr, "attachedVPC": vpc_id, "networkID": network_id, "networkType": "underlay_neutron", "subnetID": subnet_id, } } api = client.CustomObjectsApi() logging.info("start to create network") api.create_namespaced_custom_object( group="networking.cci.io", version="v1beta1", namespace=NAMESPACE, plural="networks", body=body, ) logging.info("network created")def create_deployment(): app = "test-k8s-client-deployment" image = "library/nginx:stable-alpine-perl" body = client.V1Deployment( api_version="apps/v1", kind="Deployment", metadata=client.V1ObjectMeta(name=app), spec=client.V1DeploymentSpec( replicas=2, selector={"matchLabels": {"app": app}}, template=client.V1PodTemplateSpec( metadata=client.V1ObjectMeta(labels={"app": app}), spec=client.V1PodSpec( containers=[ client.V1Container( name="container-0", image=image, resources=client.V1ResourceRequirements( requests={"cpu": "500m", "memory": "1024Mi"}, limits={"cpu": "500m", "memory": "1024Mi"}, ), ) ], image_pull_secrets=[ client.V1LocalObjectReference(name="imagepull-secret")], priority=0), ), ) ) logging.info("start to create deployment %s/%s", NAMESPACE, app) client.AppsV1Api().create_namespaced_deployment(NAMESPACE, body) logging.info("deployment created")def get_deployment(): app = "test-k8s-client-deployment" resp = client.AppsV1Api().read_namespaced_deployment(app, NAMESPACE) logging.info("deployment detail: %s", resp)def delete_deployment(): app = "test-k8s-client-deployment" logging.info("start to delete deployment") client.AppsV1Api().delete_namespaced_deployment(app, NAMESPACE) logging.info("deployment deleted")def delete_namespace(): logging.info("start to delete namespace: %s", NAMESPACE) client.CoreV1Api().delete_namespace(NAMESPACE)def main(): # Configs can be set in Configuration class directly or using helper # utility. If no argument provided, the config will be loaded from # default location. path = '{path to kubeconfig}' config.load_kube_config(path) # 因为token有效期为24小时,所以这里设置了一个每12小时获取新的token的定时任务 # 注意:如果账号权限发生变更(如主账号变更子账号权限,导致子账号权限发生变更),变更前获取的token会失效,需要重新获取。 # 另外,您可以增加获取失败重试的操作,以提升可用性 def _refresh(): while True: time.sleep(12 * 3600) try: config.load_kube_config(path) except Exception as e: print("load_kube_config error: %s" % e) t = threading.Thread(target=_refresh) t.daemon = True t.start() create_namespace() create_network() # wait for namespace and network to be active logging.info("waiting for namespace and network to be active") time.sleep(30) create_deployment() get_deployment() delete_deployment() delete_namespace()if __name__ == '__main__': main()
  • 核对资源用量是否与实际相符 假设用户在2023/04/08 10:09:06购买了一个按需计费通用计算型云容器实例(Pod规格:CPU 2核,内存 4GB),并在2023/04/08 12:09:06时刻将其删除。 云容器实例流水账单 按需计费云容器实例按秒计费,每一个小时整点结算一次费用,您可以在流水账单中核对每一个计费周期的信息是否和实际相符,具体如表1所示。 表1 云容器实例流水账单 产品类型 云容器实例 CCI 产品 云容器实例 计费模式 按需 消费时间 2023/04/08 10:09:06 ~ 2023/04/08 12:09:06时段计费系统将生成3笔流水账单,对应每一个计费周期,分别如下: 2023/04/08 10:09:06 ~ 2023/04/08 11:00:00 2023/04/08 11:00:00 ~ 2023/04/08 12:00:00 2023/04/08 12:00:00 ~ 2023/04/08 12:09:06 官网价 官网价=使用时长*单价*Core+使用时长*单价*GB 本例中,在第一个计费周期内云容器实例的使用量为3054秒,单价可在云容器实例价格详情中查询,以Pod规格CPU为2核、内存为4GB为例,此Pod价格为0.0001225/Pod/秒,CPU为2核,内存为4GB,那么官网价=3054 * 0.0001225= 0.374115元。同理,您可以计算剩余计费周期内资源的官网价。 优惠金额 用户使用云服务享受折扣优惠如商务折扣、伙伴授予折扣以及促销优惠等减免的金额。基于官网价的优惠金额。 抹零金额 华为云产品 定价精度为小数点后8位(单位:元),因此在计费过程中会产生小数点后8位的资源使用费用。而在实际扣费时,仅扣除到小数点后2位,小数点后第3位到第8位部分金额会被舍弃,这种舍弃部分的金额称作抹零金额。 以第一个计费周期为例,抹零金额为:0.004115 元 应付金额 应付金额=官网价-优惠金额-抹零金额 以第一个计费周期为例,假设优惠金额为0,那么应付金额=0.374115 - 0 - 0.004115 = 0.37 元 云容器实例明细账单 明细账单可以通过多维度展示客户账单的详细信息。一般通过设置统计维度为“按使用量”,统计周期为“按账期”来统计资源在某个月份的总开销,建议您核对表2所示的信息是否和实际相符。 表2 云容器实例明细账单 产品类型 云容器实例 CCI 产品 云容器实例 计费模式 按需 资源名称/ID 云容器实例的名称和ID 例如:cci-272f,4cdeb1cd-7071-4890-9ce4-e6c2299e960e 规格 云容器实例的类型和规格 本例为通用计算型,(Pod规格:CPU 2核,内存 4GB) 使用量类型 按需计费云容器实例的使用量类型为“时长” 单价 按需计费模式为简单 定价 (使用量*单价)时提供单价信息,其他的定价(如EIP公网带宽的阶梯定价)等不提供单价。 按需计费云容器实例属于简单定价,您可以在云容器实例价格详情中查询单价。 单价单位 在云容器实例价格详情中查询到的单价单位:元/Pod/秒 使用量 按产品单价单位显示使用量,云容器实例的单价单位为元/Pod/秒,因此使用量以小时为单位。本例中,2023/04/08 10:09:06 ~ 2023/04/08 12:09:06时段总计使用量为2小时。 使用量单位 小时 官网价 官网价=使用量*单价*容量 本例中,使用量为2小时,单价可在云容器实例价格详情中查询,以0.0001225元/Pod/秒为例,(Pod规格:CPU 2核,内存 4GB),那么官网价=2 * 0.0001225 * 60 * 60 = 0.882 元。 优惠金额 用户使用云服务享受折扣优惠如商务折扣、伙伴授予折扣以及促销优惠等减免的金额。基于官网价的优惠金额。 应付金额 用户使用云服务享受折扣优惠后需要支付的费用金额。
  • 计费说明 云容器实例的计费项由Pod规格组成。具体内容如表1所示。 表1 云容器实例计费项 Pod规格计费项 计费项说明 适用的计费模式 计费公式 通用计算型 计费因子:CPU和内存,不同规格的实例类型提供不同的计算和存储能力 按需计费 CPU:Core数量 * Core单价 * 计费时长 内存:GB数量 * GB单价 * 计费时长 请参见云容器实例价格详情中的“价格详情”。 GPU加速型 计费因子:CPU、内存和GPU,不同规格的实例类型提供不同的计算、存储、GPU加速能力 按需计费 CPU:Core数量 * Core单价 * 计费时长 内存:GB数量 * GB单价 * 计费时长 GPU:GPU数量 * GPU单价 * 计费时长 请参见云容器实例价格详情中的“价格详情”。
  • 变更配置后对计费的影响 如果您在购买按需计费实例后变更了Pod配置,会产生一个新订单并开始按新配置的价格计费,旧订单自动失效。 如果您在一个小时内变更了Pod配置,将会产生多条计费信息。每条计费信息的开始时间和结束时间对应不同配置在该小时内的生效时间。 例如,您在9:00:00购买了一台按需计费Pod,Pod规格为CPU 2核,内存 4GB,并在9:30:00升配为CPU 4核,内存 8GB,那么在9:00:00 ~ 10:00:00间会产生两条计费信息。 第一条对应9:00:00 ~ 9:30:00,Pod规格按照CPU 2核,内存 4GB计费。 第二条对应9:30:00 ~ 10:00:00,Pod规格按照CPU 4核,内存 8GB计费。
  • 计费周期 按需计费CCI资源按秒计费,每一个小时整点结算一次费用(以UTC+8时间为准),结算完毕后进入新的计费周期。计费的起点以CCI实例创建成功的时间点为准,终点以实例删除时间为准。 例如,您在8:45:30购买了一台按需计费的通用计算型云容器实例,相关资源包括CPU和内存,然后在8:55:30将其删除,则计费周期为8:00:00 ~ 9:00:00,在8:45:30 ~ 8:55:30间产生费用,该计费周期内的计费时长为600秒。
  • 计费示例 假设您在2023/04/18 9:59:30购买了一台按需计费通用计算型云容器实例(Pod规格:CPU 2核,内存 4GB),计费资源包括CPU和内存,然后在2023/04/18 10:45:46将其删除,则: 第一个计费周期为9:00:00 ~ 10:00:00,在9:59:30 ~ 10:00:00间产生费用,该计费周期内的计费时长为30秒。 第二个计费周期为10:00:00 ~ 11:00:00,在10:00:00 ~ 10:45:46间产生费用,该计费周期内的计费时长为2746秒。 您需要为每个计费周期付费,各项CCI资源单独计费,计费公式如表2所示。产品价格详情中标出了资源的每秒价格。 表2 计费公式 Pod规格类型 计费公式 资源单价 CPU Core数量 * Core单价 * 计费时长 请参见云容器实例价格详情中的“价格详情”。 内存 GB数量 * GB单价 * 计费时长 请参见云容器实例价格详情中的“价格详情”。
  • 计费构成分析 可以将云容器实例的使用阶段按照规格分为两段: 在2023/03/18 15:30:00 ~ 2023/03/20 9:00:00期间按照Pod规格:CPU 2核,内存 4GB计费,计费时长为41.5小时,费用计算如下: 在2023/03/20 9:00:00 ~ 2023/03/31 23:59:59期间按照Pod规格:CPU 4核,内存 8GB计费,计费时长为279小时,费用计算如下: 由此可见,在3月份,该云容器实例总共产生的费用为: 第一段时间产生费用:0.0001225*41.5*60*60=18.301元 第二段时间产生费用:0.000245*279*60*60=246.078元 总共产生费用:18.301+246.078=264.379元
  • 资源包抵扣顺序规则 当购买了多个相同属性的资源包,会按照资源包过期时间顺序进行抵扣,优先抵扣过期时间近的资源包。 场景示例: 某客户分别购买了两个华北-北京四区域的资源套餐包: 资源包A:CPU规格1,000 核*时,2022年10月1日生效,购买时长1年,即2023年10月1日过期。 资源包B:CPU规格10,000 核*时,2022年11月1日生效,购买时长1年,即2023年11月1日过期。 表2 资源包抵扣顺序示例 时间 抵扣顺序 2022年10月1日~2022年10月31日 只有资源包A生效。 使用资源包A抵扣,超出CPU规格1,000 核*时,部分按需计费。 2022年11月1日~2023年10月1日 资源包A、B同时生效,叠加使用。 优先使用资源包A抵扣,超出CPU规格1,000 核*时部分使用资源包B抵扣,超出CPU规格10,000 核*时部分按需计费。 2023年10月1日~2023年11月1日 资源包A过期,只有资源包B生效。 使用资源包B抵扣,超出CPU规格10,000 核*时部分按需计费。 2023年11月1日~ 资源包A、B均已过期,此时为按需计费。
  • 计费模式概述 云容器实例提供计费模式分为按需计费和套餐包计费两种方式。 按需计费,按需计费一种后付费模式,即先使用再付费,以实例为单位,采用按量付费的计费模式,秒级计费,按小时结算。 套餐包计费,允许您根据实际业务需求灵活地调整资源使用,无需提前预置资源,从而降低预置过多或不足的风险。一般适用于电商抢购等设备需求量瞬间大幅波动的场景。 表1 按需计费模式 计费模式 按需计费 套餐包 付费方式 后付费 按照实例实际使用时长计费。 预付费 按照订单购买的套餐包计费。 计费周期 秒级计费,按小时结算。 按订单购买的套餐包周期计费。 适用计费项 Pod规格包含CPU、内存和GPU。 套餐包分为CPU套餐包和内存套餐包。 变更计费模式 支持变更为套餐包计费模式。 套餐包即买即用,不支持在套餐包未使用完变更计费模式。套餐包使用完后将自动变更为按需计费模式。 变更规格 支持变更Pod规格。 支持变更Pod规格。 适用场景 适用于计算资源需求波动的场景,可以随时开通,随时删除。 一般适用于电商抢购等设备需求量瞬间大幅波动的场景。 父主题: 计费模式
  • 操作流程 操作步骤 说明 准备工作 您需要 注册华为账号 ,并为账户充值。 步骤一:构建镜像并上传至SWR镜像仓库 将应用构建镜像并上传镜像仓库,便于在云容器实例创建负载时,拉取上传的镜像。 步骤二:创建命名空间 您需要在CCI服务中创建一个命名空间,便于项目管理。 步骤三:创建负载 配置基本信息和访问信息。 步骤四:访问负载 通过IP或 域名 去访问创建好的负载。 步骤五:清理资源 如果您在完成实践后不需要继续使用CCI,请及时清理资源以免产生额外扣费。
  • 步骤二:创建命名空间 登录云容器实例管理控制台。 在左侧导航栏中选择“命名空间”,在右侧页面中“通用计算型”命名空间下单击“创建”。 填写命名空间名称。 设置VPC,选择使用已有VPC或新建VPC,新建VPC需要填写VPC网段,建议使用网段:10.0.0.0/8~22,172.16.0.0/12~22,192.168.0.0/16~22。 此处VPC和子网的网段不能为10.247.0.0/16,10.247.0.0/16是云容器实例预留给负载访问的网段。如果您使用此网段,后续可能会造成IP冲突,导致负载无法创建或服务不可用;如果您不需要通过负载访问,而是直接访问Pod,则可以使用此网段。 设置子网网段。 您需要关注子网的可用IP数,确保有足够数量的可用IP,如果没有可用IP,则会导致负载创建失败。 单击“创建”。
  • 准备工作 新建项目(选择“Scrum”模板,命名为“Project01”)。 新建空仓库空模板流水线(命名为“Pipeline01”)。 具有创建部署应用的权限,可参考部署服务编辑权限管理添加权限。 开通购买CCE服务,并在CCE集群中创建服务相关Service和Deployment:创建Service和Deployment。 Service和Deployment资源相关参考:服务(Service)、Deployments。 Service需要配置为关联至Deployment而非Pod,并且有且仅有一个Deployment与之关联。
  • 步骤2:配置发布管理策略 在环境列表页面,单击刚创建的环境名称,进入“环境信息”页面。 单击“发布策略”页签,切换到“发布策略”页面。 单击“自定义策略”旁的,弹出“新建策略”对话框,选择系统提供的“灰度升级模板”。 单击“确定”,然后逐步完成插件配置。 图1 配置发布策略 灰度起负载 表3 灰度起负载参数说明 参数项 说明 部署方式 选择“镜像创建”,将创建与线上配置完全一致的工作负载,仅更新镜像包版本(业务代码及配置)。 命名空间 选择待升级的服务所在的命名空间。 服务 待升级的服务,选择准备工作中已创建的服务。 自定义灰度版本号 开关关闭,系统将自动随机生成灰度版本号;开关开启,用户可以按需配置灰度版本号。这里选择开启开关。 灰度版本号 灰度版本号将作为新旧负载的引流标识,输入“${TIMESTAMP}”,引用系统时间戳环境变量作为灰度版本号,例如:20230401095436。 基于所选Service关联的Deployment替换新镜像,创建新负载(灰度负载)。 新负载内所有配置,如CPU、内存、副本数等,与旧负载(线上负载)完全一致。 新负载不承接任何流量,可供开发人员进行测试,且对旧负载(线上负载)没有任何影响。 新负载名称为“旧负载名称-灰度版本号”。 灰度引流 选择“Service蓝绿引流”,基于Service将所有流量切换至新负载,完成引流后,旧负载不承接任何流量。 灰度下线 默认删除线上的旧负载,无需配置。 人工卡点 为了降低引流过程中的风险,并给运维、测试人员预留充足的测试时间,可以在灰度引流、灰度下线等较高危操作前,添加人工卡点进行验证。 图2 配置人工卡点 表4 人工卡点参数说明 参数项 说明 超时处理 卡点超时后处理方式,选择“卡点失败,发布流终止执行”,即超时未处理则终止执行。 卡点时长 卡点处理时长,可选择最长时间12小时。 卡点说明 自定义描述,如:引流前对灰度负载执行手工验证。 单击“保存并应用”,即可将该策略设置为“使用中”策略,至此完成策略配置。
  • 操作流程 本文介绍在不需要占用集群额外资源安装插件的情况下,基于Kubernetes原生Service的场景完成微服务蓝绿发布,基本操作流程如下: 步骤1:新建发布管理环境 步骤2:配置发布管理策略 步骤3:通过云原生发布插件进行发布 表1 操作流程说明 流程 说明 新建发布管理环境 新建一个用于灰度发布的测试环境,并配置好资源集群等信息。 配置发布管理环境 为发布环境配置发布策略,编排配置发布流程及插件。 通过云原生发布插件进行发布 通过流水线云原生发布插件,发布环境。
  • 方案概述 应用场景 在进行服务发布的时候,通常会碰到这样的问题: 直接在生产环境发布后再进行测试,可能会带来较大风险,对线上用户造成影响。 测试环境虽然和生产环境高度一致,然而实际情况下,由于资源配置、网络环境等,测试环境和生产环境之间总会存在差异,因此难以在测试环境覆盖验证所有场景。 通过灰度发布可以实现在不引发风险的同时,在生产环境进行发布及验证。 方案优势 灰度发布是在生产环境中创建与当前线上服务完全一致的工作负载(灰度负载),仅对其中的包版本(业务代码和配置)进行更新,但是新创建的工作负载不承接任何现网流量,对线上用户没有任何影响,就可以在没有风险的情况下,在生产环境进行测试了。在灰度环境验证无问题之后,就可以逐渐将线上用户的真实访问引流到灰度负载,直至完全引流后,新创建的灰度负载承接所有现网流量,原先的线上负载不承接任何流量,此时就可以安全地删除旧负载,保留新负载,完成一次发布。 按照引流方式的不同,当前常用的灰度发布方式包括:快速完成100%流量切换的蓝绿发布和按流量比例或线上请求内容引流的金丝雀发布。通常情况,蓝绿发布已经足以降低发布风险,蓝绿发布有如下优势: 不需要集群安装额外的插件。 无风险的进行生产环境灰度验证。 快速进行流量切换(从旧负载切换新负载,或从新负载切回旧负载)。 在验证阶段发现问题后,可以快速将线上服务恢复(回滚)至发布前的状态。
  • CodeArts Pipeline最佳实践汇总 本文汇总了基于流水线(CodeArts Pipeline)常见应用场景的操作实践,为每个实践提供详细的方案描述和操作指导,助力用户完成CI/CD持续交付。 表1 CodeArts Pipeline最佳实践一览表 实践 描述 通过微服务变更流水线修复项目BUG并快速发布 CodeArts Pipeline为企业提供了一种微服务模型,将企业大军团的作战方式转变为小团队精英作战方式,支持每个微服务独立进行开发、验证、部署及上线发布,缩短需求发布周期。同时支持企业按照业务功能组织团队,优化管理模型,使运作更精细化,有效提升团队运作效率。 该解决方案介绍如何通过微服务变更流水线模拟修复项目下的一个BUG并快速发布。 配置准出条件并对代码检查结果进行校验 CodeArts Pipeline提供统一的准出条件管理能力,通过配置规则和策略,实现阶段准出校验,并最终控制流水线的执行。用户根据实际需要将策略资源应用到流水线作为准出条件,帮助高效管理项目,保障产品高质量交付。 该解决方案基于流水线准出条件-Check代码检查规则策略,通过添加代码检查任务所在阶段的准出条件,对代码检查任务的检查结果进行自动化校验,只有检查结果满足准出条件,才可以进入下一个阶段。 通过流水线参数串联编译构建服务和部署服务 使用编译构建生成软件包并通过部署服务部署时,手动配置获取软件包容易导致软件包不一致,且页面跳转多操作繁琐。通过流水线参数串联编译构建服务和部署服务,将参数传递给构建任务和部署任务,实现任务间数据流动的统一,只需要配置好流水线参数,即可完成构建、部署任务的数据拉通。 该解决方案以版本号参数为例,介绍如何将流水线参数传递给编译构建任务和部署应用。 通过流水线生成标签名并通过上下文传递为代码仓库创建标签 流水线上下文存储了流水线运行的实例、变量、任务等信息,每个上下文都是一个包含各种属性的对象。使用流水线时,当一个任务生成了数据或结果,且这些数据或结果需要在后续的任务中使用时,可以基于流水线上下文来实现,流水线上下文可以帮助实现任务间的信息传递和协作,使得整个流水线运作更加灵活和高效。 该解决方案以通过流水线自动为代码仓库创建标签为例,介绍流水线上下文在流水线任务间的传递过程。 基于Kubernetes原生Service的场景完成微服务蓝绿发布 灰度发布是在生产环境中创建与当前线上服务完全一致的工作负载(灰度负载),仅对其中的包版本(业务代码和配置)进行更新,但是新创建的工作负载不承接任何现网流量,对线上用户没有任何影响,就可以在没有风险的情况下,在生产环境进行测试了。在灰度环境验证无问题之后,就可以逐渐将线上用户的真实访问引流到灰度负载,直至完全引流后,新创建的灰度负载承接所有现网流量,原先的线上负载不承接任何流量,此时就可以安全地删除旧负载,保留新负载,完成一次发布。 该解决方案介绍在不需要占用集群额外资源安装插件的情况下,基于Kubernetes原生Service的场景完成微服务蓝绿发布。 HE2E DevOps实践:配置流水线 该解决方案以“DevOps全流程示例项目”为例,介介绍如何将代码检查、构建、部署任务串联起来,实现持续交付。
  • 预置流水线简介 示例项目中预置以下5个流水线任务,可根据需要查看并使用。 表1 预置流水线任务 预置流水线任务 任务说明 phoenix-workflow 基本的流水线任务。 phoenix-workflow-test 测试环境对应的流水线任务。 phoenix-workflow-work Worker功能对应的流水线任务。 phoenix-workflow-result Result功能对应的流水线任务。 phoenix-workflow-vote Vote功能对应的流水线任务。
  • 配置准出条件 为了控制代码的质量,代码必须经过扫描,并且错误数量控制在合理范围内,才允许发布。通过添加质量门禁可以有效的自动化控制流程。 在流水线任务“phoenix-workflow”详情页,单击“编辑”。 在阶段“代码检查”中,单击“准出条件”。 在“准出条件”窗口中,单击“标准策略准出条件”插件后的“添加”。 选择“系统策略”,单击“确定”。 单击“保存并执行”,启动流水线任务。 如果代码检查问题数未达到准出条件,流水线任务将执行失败。
  • 操作流程 本文介绍如何通过微服务变更流水线模拟修复项目下的一个BUG并快速发布,基本操作流程如下: 步骤1:新建流水线微服务 步骤2:新建变更流水线 步骤3:新建微服务变更 步骤4:执行变更流水线 表1 操作流程说明 流程 说明 新建流水线微服务 在项目下新建一个微服务,用于管理某个特定的业务功能。 新建变更流水线 在微服务下新建一条变更流水线,用于发布微服务下的变更。 新建微服务变更 在微服务下新建一个变更,承载项目下修复BUG的开发活动。 执行变更流水线 执行流水线,发布变更代码。
  • 方案概述 CodeArts Pipeline为企业提供了一种微服务模型,将企业大军团的作战方式转变为小团队精英作战方式,支持每个微服务独立进行开发、验证、部署及上线发布,缩短需求发布周期。同时支持企业按照业务功能组织团队,优化管理模型,使运作更精细化,有效提升团队运作效率。 在微服务中,用户可以创建流水线资源,并将其设置为变更流水线,用于与微服务下变更资源进行联动,通过变更流水线发布一个或多个变更来实现项目的快速交付。
  • 步骤2:新建变更流水线 在微服务列表页面,单击微服务名称,进入微服务“概览”页面。 切换到“流水线”页签,进入微服务流水线列表页面。 单击“新建流水线”,进入“新建流水线 ”页面,配置以下信息。 表3 新建变更流水线 参数项 说明 所属项目 变更流水线所在的项目,不可更改。 名称 变更流水线的名称,使用自动生成的即可。 代码源 变更流水线关联的源码类型,自动和微服务保持一致。 代码仓 变更流水线关联的源码仓库,自动和微服务保持一致。 默认分支 默认使用的分支,自动和微服务保持一致。 Repo https授权 打开“基于变更触发”后需配置“Repo HTTPS授权”,配置授权扩展点以提升代码仓操作权限。选择准备工作中已创建的授权扩展点“HttpsEndpoint01”。 别名 输入别名,会生成该仓库对应的相关系统参数,这里不设置。 基于变更触发 打开“基于变更触发”,将当前流水线设置为微服务变更流水线。 描述 对变更流水线的介绍说明,选填。 微服务变更流水线仅支持基于变更触发运行,且单个微服务下只能存在一条微服务变更流水线。 单击“下一步”,选择“Maven构建”模板,自动生成阶段和任务,使用默认配置即可。 单击“保存”,完成微服务变更流水线的创建。
  • 步骤4:执行变更流水线 代码更新完成后,即可通过变更流水线执行变更。 在微服务变更列表页面,单击变更名称,进入“变更详情”页面。 单击右上角“提交发布”,弹出“提交发布”确认框,提示是否确认将变更提交至变更流水线。 图1 提交发布 单击“确定”,完成变更提交,页面跳转至对应变更流水线发布列表页面。 单击右上角“执行”,弹出“执行配置”侧滑框,选择刚提交的变更,其他配置保持默认。 图2 执行配置 单击“执行”,启动变更流程。 微服务变更流水线在运行过程中,会自动增加“合并集成分支”和“合并主干”阶段,并将本次变更关联的特性分支合并到该集成分支上。 代码检查、构建任务执行成功后,系统自动进入“合并主干”阶段,并弹出“手动确认”对话框。 图3 执行流水线 单击“继续执行”,“合并主干”阶段执行完成后,系统将自动完成以下事项。 将本次发布的变更状态更新为“已发布”。 将本次发布的变更关联的工作项状态更新为“已关闭”。 将本次发布使用的集成分支代码内容合并到微服务默认分支,实现代码自动合并。 至此,即完成了一次基本的微服务变更发布流程。
  • 步骤3:新建微服务变更 重新进入微服务“概览”页面。 切换到“变更”页签,进入微服务变更列表页面。 单击“新建变更”,进入“新建变更 ”页面,配置以下信息。 表4 新建变更 参数项 说明 变更标题 变更的名称,输入“fix-a-bug”。 代码仓 变更关联的源码仓库,自动和微服务保持一致。 代码分支 变更新需求的开发分支,变更通过流水线发布成功后,会将代码分支自动合并至微服务的默认分支。选择“从默认分支拉取新分支”并输入分支名称“bugfix”。 关联工作项 变更关联的工作项,选择准备工作中已创建的工作项“BUGFIX”。 单击“确定”,完成变更的创建。 变更创建完成后,进入代码开发阶段,系统基于微服务默认分支自动创建出本次变更的特性分支,开发人员可以基于该特性分支进行代码开发,问题修复后,模拟向该分支提交代码。
  • 方案概述 传统软件质量保障以人工验收测试为主,效率低。当前软件能力难以支持业务需要,大量测试验收需要人工手动进行,自动化覆盖率低,且需要人工筛查识别满足验收条件的版本进行后续发布等处理流程,整体测试效率低下。 CodeArts Pipeline提供统一的准出条件管理能力,通过配置规则和策略,实现阶段准出校验,并最终控制流水线的执行。用户根据实际需要将策略资源应用到流水线作为准出条件,帮助高效管理项目,保障产品高质量交付。 通过流水线准出条件-Check代码检查规则策略自动化看护,拦截70%+问题,提高测试效率的同时,提高软件质量。
  • 操作流程 本文基于流水线准出条件-Check代码检查规则策略,通过添加代码检查任务所在阶段的准出条件,对代码检查任务的检查结果进行自动化校验,只有检查结果满足准出条件,才可以进入下一个阶段。 图1 操作流程示意图 基本操作流程如下: 步骤1:新建规则并配置阈值 步骤2:新建策略并添加规则 步骤3:配置流水线 步骤4:执行流水线验证准出条件 表1 操作流程说明 流程 说明 新建规则并配置阈值 新建一个代码检查类型规则,基于代码检查插件的输出结果,设置比较关系和阈值条件,供策略使用,作为准出条件的判断依据。 新建策略并添加规则 新建一个策略,并添加如上代码检查类型规则。 配置流水线 在流水线阶段准出条件添加如上策略,根据设置的规则条件,来控制流水线执行。 执行流水线验证准出条件 执行流水线,验证准出条件拦截结果。 代码检查插件满足规则条件,通过准出条件校验,流水线继续执行。 代码检查插件如果不满足规则条件,没有通过准出条件校验,流水线终止执行。
  • 准备工作 新建项目(选择“Scrum”模板,命名为“Project01”)。 新建代码仓库(选择“Java Maven Demo”模板,命名为“Repo01”)。 新建代码仓库时会自动创建与代码仓库同名的代码检查任务,将代码检查任务名称修改为“CheckTask01”,操作方法请参考创建代码检查任务。 基于“Repo01”仓库新建构建任务(选择“Maven”模板,命名为“BuildTask01”)。 基于已创建的代码仓库新建流水线(选择空模板,命名为“Pipeline01”)。
  • 步骤2:新建策略并添加规则 策略实行分层管理,可分为租户级策略和项目级策略。其中,租户级策略可以应用到当前租户下所有项目的流水线,项目级策略可以应用到当前项目下所有流水线。本节以租户级策略为例进行介绍。 单击左侧导航栏“策略”,进入策略管理页面。 租户级策略中默认存在一条“系统策略”,用户可查看和使用该策略,但不能进行编辑和删除。 单击“新建策略”,进入“新建策略”页面,输入策略名称,勾选步骤1中新建好的规则。 图3 新建策略 单击“确定”,完成策略创建。
  • 操作流程 本文以版本号参数为例,介绍如何将流水线参数传递给编译构建任务和部署应用,基本操作流程如下: 步骤1:新建编译构建任务 步骤2:新建部署应用 步骤3:新建并执行流水线 步骤4:查看编译构建和部署结果 表1 操作流程说明 流程 说明 新编译构建任务 新建编译构建任务,新增版本号参数,并在构建步骤引用该参数。 新建部署应用 新建部署任务,新增软件包参数,并在部署步骤引用该参数。 新建并执行流水线 新建流水线,新增版本号参数,并在流水线上添加编译构建任务及部署应用。 在编译构建任务的版本号参数引用流水线版本号参数。 在部署应用软件包参数引用流水线版本号参数。 查看编译构建和部署结果 分别查看编译构建结果和部署结果。 编译构建包版本号为流水线传递的动态参数。 部署任务成功获取软件包。
共99354条