常用公有云接入——华为

版权声明:本文为博主原创文章,纯粹自娱。 https://blog.csdn.net/moakun/article/details/90115064

一、介绍

1、什么是弹性云服务器?

弹性云服务器是由CPU、内存、镜像、云硬盘组成的一种可随时获取、弹性可扩展的计算服务器,同时它结合虚拟私有云、虚拟防火墙、数据多副本保存等能力,为您打造一个高效、可靠、安全的计算环境,确保您的服务持久稳定运行。弹性云服务器创建成功后,您就可以像使用自己的本地PC或物理服务器一样,在云上使用弹性云服务器。

弹性云服务器的开通是自助完成的,您只需要指定CPU、内存、镜像规格、登录鉴权方式即可,同时也可以根据您的需求随时调整您的弹性云服务器规格。

产品架构

通过和其他产品、服务组合,弹性云服务器可以实现计算、存储、网络、镜像安装等功能:

  • 弹性云服务器在不同可用区中部署(可用区之间通过内网连接),一个可用区发生故障后不会影响同一区域内的其它可用区。
  • 可以通过虚拟私有云建立专属的网络环境,设置子网、安全组,并通过弹性公网IP实现外网链接(需带宽支持)。
  • 通过镜像服务,可以对弹性云服务器安装镜像,也可以通过私有镜像批量创建弹性云服务器,实现快速的业务部署。
  • 通过云硬盘服务实现数据存储,并通过云硬盘备份服务实现数据的备份和恢复。

图1 ECS产品架构 

2、区域和可用区

区域指弹性云服务器所在的物理位置。

同一区域内可用区间内网互通,不同区域间内网不互通。

公有云在世界不同地区有数据中心。与此相应,弹性云服务器可用于不同地区。通过在不同地区创建弹性云服务器,可以将应用程序设计的更接近特定客户的要求,或满足不同地区的法律或其他要求。弹性云服务器使用定价因区域而异。

每个区域包含许多不同的称为“可用区”的位置,即在同一区域下,电力、网络隔离的物理区域,可用区之间内网互通,不同可用区之间物理隔离。每个可用区都被设计成不受其他可用区故障的影响,并提供低价、低延迟的网络连接,以连接到同一地区其他可用区。通过使用独立可用区内的弹性云服务器,可以保护您的应用程序不受单一位置故障的影响。

3、存储

云硬盘的类型

弹性云服务器使用的云硬盘类型有如下几种:

  • 普通IO:该类型云硬盘的最大IOPS为2200,适用于大容量、读写速率中等、事务性处理较少的应用场景,例如企业的日常办公应用或者小型测试等。
  • 高IO:该类型云硬盘的最大IOPS可达5000,最低读写时延为1 ms,适用于主流的高性能、高可靠应用场景,例如企业应用、大型开发测试以及Web服务器日志等。
  • 超高IO:该类型云硬盘的最大IOPS可达33000,最低读写时延为1 ms,适用于超高IO,超大带宽的读写密集型应用场景,例如高性能计算应用场景,用来部署分布式文件系统,或者I/O密集型应用场景,用来部署各类NoSQL/关系型数据库。
  • 超高IO (时延优化):该类型的云硬盘提供低至1 ms的读写时延和高达1 GB/s的吞吐量,可运行企业核心业务,如SAP HANA。 说明:

    超高IO (时延优化)云硬盘,当前仅支持挂载到SAP HANA云服务器使用。

云硬盘的磁盘模式

云硬盘的磁盘模式分为VBD (虚拟块存储设备 , Virtual Block Device) 类型和SCSI (小型计算机系统接口, Small Computer System Interface) 类型。

  • VBD类型:

    当您通过管理控制台创建云硬盘时,云硬盘的磁盘模式默认为VBD类型。VBD类型的云硬盘只支持简单的SCSI读写命令。

  • SCSI类型:

    您可以通过管理控制台创建SCSI类型的云硬盘,该类型的云硬盘支持SCSI指令透传,允许弹性云服务器操作系统直接访问底层存储介质。除了简单的SCSI读写命令,SCSI类型的云硬盘还可以支持更高级的SCSI命令。

4、虚拟私有云

通过虚拟私有云(Virtual Private Cloud,以下简称VPC),您可以在自己的逻辑隔离区域中定义虚拟网络,为弹性云服务器构建一个逻辑上完全隔离的专有区域。您还可以在VPC中定义安全组、VPN、IP地址段、带宽等网络特性,方便管理、配置内部网络,进行安全、快捷的网络变更。同时,您可以自定义安全组内与组间弹性云服务器的访问规则,加强弹性云服务器的安全保护。

5、镜像

镜像

镜像是一个包含了软件及必要配置的弹性云服务器模板,至少包含操作系统,还可以包含应用软件(例如,数据库软件)和私有软件。通过镜像,您可以创建弹性云服务器。

镜像分为公共镜像和私有镜像,公共镜像为系统默认提供的镜像,私有镜像为用户自己创建的镜像。用户可以灵活便捷的使用公共镜像或者私有镜像申请弹性云服务器。同时,用户还能通过已有的弹性云服务器创建私有镜像,这样能快速轻松地启动能满足您一切需求的新弹性云服务器。例如,如果您的应用程序是网站或Web服务,您的镜像可能会包含Web服务器、相关静态内容和动态页面代码。因此,您通过这个镜像创建弹性云服务器之后,您的Web服务器将启动,并且您的应用程序已准备好接受请求。

镜像类型

表1 镜像类型列表

镜像类型

说明

公共镜像

常见的标准操作系统镜像,所有用户可见,包括操作系统以及预装的公共应用。

私有镜像

用户基于弹性云服务器或者云硬盘备份(系统盘备份)创建的个人镜像,仅用户自己可见。包含操作系统、预装的公共应用以及用户的私有应用。

私有镜像包括系统镜像和数据镜像,其中:

  • 系统镜像:包含用户运行业务所需的操作系统、应用软件的镜像。系统镜像可以用于创建云服务器,迁移用户业务到云。
  • 数据镜像:只包含用户业务数据的镜像。数据镜像可以用于创建云硬盘,将用户的业务数据迁移到云上。

共享镜像

由其他用户共享的私有镜像。

市场镜像

提供预装操作系统、应用环境和各类软件的优质第三方镜像。无需配置,可一键部署,满足建站、应用开发、可视化管理等个性化需求。

镜像和弹性云服务器

镜像是弹性云服务器的操作系统。可以通过镜像创建弹性云服务器,也可以将弹性云服务器转化为镜像。

6、生命周期

生命周期是指弹性云服务器从创建到删除(或释放)历经的各种状态。

表1 弹性云服务器状态说明

状态

状态属性

说明

API对应的状态

创建中

中间状态

创建弹性云服务器实例后,在弹性云服务器状态进入运行中之前的状态。

BUILD/BUILDING

正在开机

中间状态

弹性云服务器实例从关机到运行中的中间状态。

SHUTOFF

运行中

稳定状态

弹性云服务器实例正常运行状态。

在这个状态的实例可以运行您的业务。

ACTIVE

正在关机

中间状态

弹性云服务器实例从运行中到关机的中间状态。

ACTIVE

关机

稳定状态

弹性云服务器实例被正常停止。

在这个状态下的实例,不能对外提供业务。

SHUTOFF

重启中

中间状态

弹性云服务器实例正在进行重启操作。

REBOOT

更新规格中

中间状态

弹性云服务器实例接收变更请求,开始进行变更操作。

RESIZE

更新规格校验中

中间状态

弹性云服务器实例正在校验变更完成后的配置。

VERIFY_RESIZE

删除中

中间状态

弹性云服务器实例处于正在被删除的状态。

如果长时间处于该状态,则说明出现异常,需要联系管理员处理。

ACTIVE/SHUTOFF/REBOOT/RESIZE/VERIFR_RESIZE/ /HARD_REBOOT/ REVERT_RESIZE/ERROR

已删除

中间状态

弹性云服务器实例已被正常删除。在该状态下的实例,不能对外提供业务,并在短时间内从系统中彻底清除。

DELETED

故障

稳定状态

弹性云服务器实例处于异常状态。

在这个状态下的实例,不能对外提供业务,需要联系管理员进行处理。

ERROR

重装操作系统中

中间状态

弹性云服务器实例接收到重装操作系统请求,处于重装操作系统的过程中。

SHUTOFF

重装操作系统失败

稳定状态

弹性云服务器实例接收到重装操作系统请求,进行重装的过程中发生异常,导致重装失败。

在这个状态下的实例,不能对外提供业务,需要联系管理员进行处理。

SHUTOFF

切换操作系统中

中间状态

弹性云服务器实例接收到切换操作系统请求,处于切换操作系统的过程中。

SHUTOFF

切换操作系统失败

稳定状态

弹性云服务器实例接收到切换操作系统请求,进行切换的过程中发生异常,导致切换失败。

在这个状态下的实例,不能对外提供业务,需要联系管理员进行处理。

SHUTOFF

强制重启中

中间状态

弹性云服务器实例正在进行强制重启操作。

HARD_REBOOT

更新规格回退中

中间状态

弹性云服务器实例正在回退变更规格的配置。

REVERT_RESIZE

冻结

稳定状态

云服务器实例订单到期或欠费,被系统管理员停止。

在这个状态下的实例,不能对外提供业务。系统保留一段时间后,如果未续费,将自动被删除。

SHUTOFF

锁定

中间状态/稳定状态

状态栏显示,表示云服务器被锁定,处于保护状态。此时,部分操作将会被禁用,具体请以界面提示为准。

您可以点击锁图标下方的超链接,查看加锁资源。

-

二、Java SDK

GITHUT地址

package sample;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import com.huawei.openstack4j.model.compute.StopType;
import com.huawei.openstack4j.model.compute.RebootType;
import com.huawei.openstack4j.api.OSClient.OSClientV3;
import com.huawei.openstack4j.model.common.Identifier;
import com.huawei.openstack4j.model.compute.Action;
import com.huawei.openstack4j.model.compute.Server;
import com.huawei.openstack4j.model.compute.Server.Status;
import com.huawei.openstack4j.openstack.OSFactory;

import com.huawei.openstack4j.openstack.ecs.v1.contants.IpType;
import com.huawei.openstack4j.openstack.ecs.v1.contants.NetworkChargingMode;
import com.huawei.openstack4j.openstack.ecs.v1.contants.ShareType;
import com.huawei.openstack4j.openstack.ecs.v1.contants.VolumeType;
import com.huawei.openstack4j.openstack.ecs.v1.domain.Bandwidth;
import com.huawei.openstack4j.openstack.ecs.v1.domain.CloudServer;
import com.huawei.openstack4j.openstack.ecs.v1.domain.CloudServer.CloudServers;
import com.huawei.openstack4j.openstack.ecs.v1.domain.DataVolume;
import com.huawei.openstack4j.openstack.ecs.v1.domain.FloatingIPCreate;
import com.huawei.openstack4j.openstack.ecs.v1.domain.Personality;
import com.huawei.openstack4j.openstack.ecs.v1.domain.ResizeServer;
import com.huawei.openstack4j.openstack.ecs.v1.domain.RootVolume;
import com.huawei.openstack4j.openstack.ecs.v1.domain.ServerCreate;
import com.huawei.openstack4j.openstack.ecs.v1.domain.ServerExtendParam;
import sun.misc.BASE64Encoder;

public class CloudServerV1 {
	public static void main(String[] args) throws InterruptedException {
		
		// Using credentials for authentication
		String authUrl = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; //endpoint Url
		String user = "xxxxx"; //username
		String password = "xxxxx"; //password
		String projectId = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; //projectId
		String userDomainId = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; //domainId

		//create connection	
		OSClientV3 os = OSFactory.builderV3()
		.endpoint(authUrl)
		.credentials(user, password, Identifier.byId(userDomainId))
		.scopeToProject(Identifier.byId(projectId)).authenticate();
		
		int count = 1;
		String flavorId = "s2.xlarge.1";
		String imageId = "a1e6a557-e6c5-43a0-9d4e-a90fdf376afb";
		String vpcId = "0d85e49a-6aef-42a9-8583-c86e4317a7e2";
		String networkId = "319944c8-baac-46da-a3a8-f07956105a4e";
		String secGroup = "114f5982-ecdc-4297-ae23-e6aa17763c78";
		
		String userData_org = "#!/bin/bash \r\n echo 'root:Cloud.1234' | chpasswd ;";
	    byte[] userData_byte = userData_org.getBytes();
	    String userData = new BASE64Encoder().encode(userData_byte);
	    
		Bandwidth bandwidth = Bandwidth.builder().size(10).shareType(ShareType.PER).chargeMode(NetworkChargingMode.TRAFFIC).build();
		FloatingIPCreate FIPbuild = FloatingIPCreate.builder().ipType(IpType.BGP).bandwidth(bandwidth).build();
		
		ServerCreate creation = ServerCreate.builder()
				.name("test-name")
                .flavorRef(flavorId)
                .imageRef(imageId)
                .userData(userData)
                .vpcId(vpcId)
                .addNetwork(networkId)
                .availabilityZone("eu-de-02")
                .addSecurityGroup(secGroup)
                .addTag("key", "testvalue")
                .publicIP(FIPbuild)
                .keyName("KeyPair-a6c5")
                .addMetadata("Group", "testGroup")
                .addPersonality(Personality.builder().contents("some content").path("/etc/test.txt").build())
                .rootVolume(RootVolume.builder().type(VolumeType.SSD).build())
                .addDataVolume(DataVolume.builder().size(10).type(VolumeType.SATA).multiAttach(true).passthrough(true).build())
                .extendParam(ServerExtendParam.builder().autoRecovery(true).build())
                .count(count).build();
				
		//create server
		String jobId = os.ecs().servers().create(creation);
		if (null != jobId) {
			System.out.println("create server success, jobId = " + jobId);
		} else {
			System.out.println("create server failed");
		}
		
		//get list of server
		List<? extends Server> serverList = os.compute().servers().list();
		if (serverList.size() > 0) {
			System.out.println("get serverList success, size = " + serverList.size());
		} else {
			System.out.println("get serverList failed");
		}
		
		//find server, wait for server status to ACTIVE
		Map<String , String> filterName = new HashMap<String, String>();
		filterName.put("name", "test-name");
		List<? extends Server> servers = os.compute().servers().list(filterName);
		ArrayList<String> serverIds = new ArrayList<String>();
		servers = os.compute().servers().list(filterName);
		for (Server server : servers) {
			os.compute().servers().waitForServerStatus(server.getId(), Status.ACTIVE, 10, TimeUnit.MINUTES);
			//get server
			CloudServer serverInfo = os.ecs().servers().get(server.getId());
			if (null != serverInfo) {
				System.out.println("get serverInfo success, name = " + serverInfo.getName());
			} else {
				System.out.println("get serverInfo server failed");
			}
			serverIds.add(server.getId());
		}
		
		//reboot server
		String rebootJobId = os.ecs().servers().reboot(serverIds, RebootType.SOFT);
		if (null != rebootJobId) {
			System.out.println("batch reboot server success, jobId = " + rebootJobId);
		} else {
			System.out.println("batch reboot server failed");
		}
		
		//stop server
		String stopJobId = os.ecs().servers().stop(serverIds, StopType.SOFT);
		if (null != stopJobId) {
			System.out.println("batch stop server success, jobId = " + stopJobId);
		} else {
			System.out.println("batch stop server failed");
		}
		
		//start server
		String startJobId = os.ecs().servers().start(serverIds);
		if (null != startJobId) {
			System.out.println("batch start server success, jobId = " + startJobId);
		} else {
			System.out.println("batch start server failed");
		}
		
		//delete server
		String deleteJobId = os.ecs().servers().delete(serverIds, false, false);
		if (null != deleteJobId) {
			System.out.println("batch delete server success, jobId = " + deleteJobId);
		} else {
			System.out.println("batch delete server failed");
		}
		
		//resize server
		String newFlavorId = "s2.medium.2";
		String serverId = "ac91c721-9e8e-4147-83d9-b4f07ad607ed";
		ResizeServer resize = ResizeServer.builder().flavorRef(newFlavorId).build();
		os.compute().servers().action(serverId, Action.STOP);
		os.compute().servers().waitForServerStatus(serverId, Status.SHUTOFF, 3, TimeUnit.MINUTES);
		String resizeJobId = os.ecs().servers().resize(resize, serverId);
		if (null != resizeJobId) {
			System.out.println("Start to resize server, jobId = " + resizeJobId);
		} else {
			System.out.println("resize server failed");
		}

		//get count and list of server
		CloudServers cloudServer = os.ecs().servers().listWithCount();
		System.out.println("server count: " + cloudServer.getCount());
		System.out.println("server list: " + cloudServer.getServers());

		//get count and list of server with parameters
		Map<String, String> filter = new HashMap<String, String>();
		filter.put("offset", "0");
		filter.put("status", "ACTIVE");
		CloudServers serverObjects = os.ecs().servers().listWithCount(filter);
		System.out.println("server count: " + serverObjects.getCount());
		System.out.println("server list: " + serverObjects.getServers());
	}
}

三、REST API

(1)介绍

1、请求URI

请求URI由如下部分组成:

{URI-scheme}://{Endpoint}/{resource-path}?{query-string}

尽管请求URI包含在请求消息头中,但大多数语言或框架都要求您从请求消息中单独传递它,所以在此单独强调。

表1 URI中的参数说明

参数

描述

URI-scheme

表示用于传输请求的协议。

Endpoint

指定承载REST服务端点的服务器域名或IP,从地区和终端节点获取。

resource-path

资源路径,也即API访问路径。从具体接口的URI模块获取,例如“v3/auth/tokens”。

query-string

可选参数,例如API版本或资源选择标准。

请求方法

HTTP方法(也称为操作或动词),它告诉服务你正在请求什么类型的操作。

表2 HTTP方法

方法

说明

GET

请求服务器返回指定资源。

PUT

请求服务器更新指定资源。

POST

请求服务器新增资源或执行特殊操作。

DELETE

请求服务器删除指定资源,如删除对象等。

HEAD

请求服务器资源头部。

PATCH

请求服务器更新资源的部分内容。

当资源不存在的时候,PATCH可能会去创建一个新的资源。

2、请求消息头

可选的附加请求头字段,如指定的URI和HTTP方法所要求的字段。详细的公共请求消息头字段请参见 表3

表3 公共请求消息头

名称

描述

是否必选

示例

X-Sdk-Date

请求的发生时间,格式为YYYYMMDD'T'HHMMSS'Z'。

取值为当前系统的GMT时间。

使用AK/SK认证时该字段必选。

20150907T101459Z

Authorization

签名认证信息。

该值来源于请求签名结果。

使用AK/SK认证时该字段必选。

SDK-HMAC-SHA256 Credential=ZIRRKMTWPTQFQI1WKNKB/20150907//ec2/sdk_request, SignedHeaders=content-type;host;x-sdk-date, Signature=55741b6...e1994

Host

请求的服务器信息,从服务API的URL中获取。值为hostname[:port]。端口缺省时使用默认的端口,https的默认端口为443。

使用AK/SK认证时该字段必选。

code.test.com

or

code.test.com:443

Content-Type

发送的实体的MIME类型。推荐用户默认使用application/json,如果API是对象、镜像上传等接口,媒体类型可按照流类型的不同进行确定。

application/json

Content-Length

请求body长度,单位为Byte。

3495

X-Project-Id

project id,项目编号。请参考获取项目ID章节获取项目编号。

如果是DeC的请求或者多project的请求则必须传入project id。

如果是专属云场景采用AK/SK 认证方式的接口请求或者多project场景采用AK/SK认证的接口请求则该字段必选。

e9993fc787d94b6c886cbaa340f9c0f4

X-Auth-Token

用户Token。

获取Token,请参考《统一身份认证服务API参考》的“获取用户Token”章节。请求响应成功后在响应消息头中包含的“X-Subject-Token”的值即为Token值。

使用Token认证时该字段必选。

注:以下仅为Token示例片段

MIIPAgYJKoZIhvcNAQcCo...ggg1BBIINPXsidG9rZ

3、请求消息体

该部分可选。请求消息体通常以结构化格式(如JSON或XML)发出,与请求消息头中Content-Type对应,传递除请求消息头之外的内容。

若请求消息体中的参数支持中文,则中文字符必须为UTF-8编码。

4、响应消息头

响应消息头包含如下两部分:

  • 一个HTTP状态代码,从2xx成功代码到4xx或5xx错误代码,或者可以返回服务定义的状态码。
  • 附加响应头字段,如Content-Type响应消息头。详细的公共响应消息头字段请参考 表4
    表4 公共响应消息头

    名称

    描述

    示例

    Content-Length

    响应消息体的字节长度,单位为Byte。

    --

    Date

    系统响应的GMT时间。

    Wed, 27 Dec 2016 06:49:46 GMT

    Content-Type

    响应消息体的MIME类型。

    application/json

5、响应消息体

该部分可选。响应消息体通常以结构化格式(如JSON或XML)返回,与响应消息头中Content-Type对应,传递除响应消息头之外的内容。

发送请求

共有三种方式可以基于已构建好的请求消息发起请求,分别为:

  • cURL

    cURL是一个命令行工具,用来执行各种URL操作和信息传输。cURL充当的是HTTP客户端,可以发送HTTP请求给服务端,并接收响应消息。cURL适用于接口调试。关于cURL详细信息请参见https://curl.haxx.se/

  • 编码

    通过编码调用接口,组装请求消息,并发送处理请求消息。

  • REST客户端

    Mozilla、Google都为REST提供了图形化的浏览器插件,发送处理请求消息。针对Firefox,请参见FirefoxREST Client;针对Chrome,请参见Postman

(2)API示例

当您使用Token认证方式完成认证鉴权时,需要获取用户Token并在调用接口时增加“X-Auth-Token”到业务接口请求消息头中。

  • IAM获取token的API
  • ECS创建云服务器的API

具体步骤

  1. Token认证,具体操作请参考获取请求认证
  2. 发送“POST https://ECS的Endpoint/v1/{tenant_id}/cloudservers”。
  3. 在Request Header中增加“X-Auth-Token”。
  4. 在Request Body中传入参数如下:
    {
    	"server": {
    	"availability_zone": "az1.dc1", //可用区称
    		"name": "ecs-test", //自定义弹性云服务器名称
    		"imageRef": "ff49b1f1-3e3e-4913-89c6-a026041661e8", //镜像ID
    		"flavorRef": "c2.medium", //规格
    		"root_volume": {
    			"volumetype": "SATA", //系统盘类型
    			"size": 40 //系统盘大小
    		},
    		"vpcid": "ba7992d4-db4b-4bb5-b9fb-e9652513bc0e", //云服务器所在的虚拟私有云
    		"nics": [{
    			"subnet_id": "2191971a-8bf2-4ead-b207-0511dc85d8a3" //子网ID
    		}],
    		"security_groups": [{
    			"id": "6a38a731-7854-4983-a176-491c001c27db" //安全组ID
    		}],
    		"count": 1, //创建的弹性云服务器数量
    		"key_name": "KeyPair-d3c1" //使用的密钥名称
    	}
    }

    请求响应成功后,返回job_id。

    若请求失败,则会返回错误码及对应的错误信息说明,详细错误码信息请参考错误码说明

  1. 根据job_id查询job详情,具体操作请参考查询任务的执行状态

    查询job详情返回状态status为“SUCCESS”,则表示弹性云服务器创建成功。

    请求异常返回值说明请参考通用请求返回值

  2. 查询job详情的body体中可以获取到云服务器ID,根据获取到的云服务器ID可对弹性云服务器进行查询、删除、变更规格、开机、关机等操作。

(3)API接口

生命周期管理

状态管理

规格管理

网卡管理

磁盘管理

租户配额管理

查询Job状态

猜你喜欢

转载自blog.csdn.net/moakun/article/details/90115064