一、介绍
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服务器将启动,并且您的应用程序已准备好接受请求。
镜像类型
镜像类型 | 说明 |
---|---|
公共镜像 | 常见的标准操作系统镜像,所有用户可见,包括操作系统以及预装的公共应用。 |
私有镜像 | 用户基于弹性云服务器或者云硬盘备份(系统盘备份)创建的个人镜像,仅用户自己可见。包含操作系统、预装的公共应用以及用户的私有应用。 私有镜像包括系统镜像和数据镜像,其中:
|
共享镜像 | 由其他用户共享的私有镜像。 |
市场镜像 | 提供预装操作系统、应用环境和各类软件的优质第三方镜像。无需配置,可一键部署,满足建站、应用开发、可视化管理等个性化需求。 |
镜像和弹性云服务器
镜像是弹性云服务器的操作系统。可以通过镜像创建弹性云服务器,也可以将弹性云服务器转化为镜像。
6、生命周期
生命周期是指弹性云服务器从创建到删除(或释放)历经的各种状态。
状态 | 状态属性 | 说明 | 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 authenticationString authUrl = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; //endpoint UrlString user = "xxxxx"; //usernameString password = "xxxxx"; //passwordString projectId = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; //projectIdString 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 serverString 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 serverList<? 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 ACTIVEMap<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 serverCloudServer 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 serverString 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 serverString 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 serverString 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 serverString 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 serverString 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 serverCloudServers 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 parametersMap<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包含在请求消息头中,但大多数语言或框架都要求您从请求消息中单独传递它,所以在此单独强调。
参数 | 描述 |
---|---|
URI-scheme | 表示用于传输请求的协议。 |
Endpoint | 指定承载REST服务端点的服务器域名或IP,从地区和终端节点获取。 |
resource-path | 资源路径,也即API访问路径。从具体接口的URI模块获取,例如“v3/auth/tokens”。 |
query-string | 可选参数,例如API版本或资源选择标准。 |
请求方法
HTTP方法(也称为操作或动词),它告诉服务你正在请求什么类型的操作。
方法 | 说明 |
---|---|
GET | 请求服务器返回指定资源。 |
PUT | 请求服务器更新指定资源。 |
POST | 请求服务器新增资源或执行特殊操作。 |
DELETE | 请求服务器删除指定资源,如删除对象等。 |
HEAD | 请求服务器资源头部。 |
PATCH | 请求服务器更新资源的部分内容。 当资源不存在的时候,PATCH可能会去创建一个新的资源。 |
2、请求消息头
可选的附加请求头字段,如指定的URI和HTTP方法所要求的字段。详细的公共请求消息头字段请参见 表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
具体步骤
- Token认证,具体操作请参考获取请求认证。
- 发送“POST https://ECS的Endpoint/v1/{tenant_id}/cloudservers”。
- 在Request Header中增加“X-Auth-Token”。
- 在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。
若请求失败,则会返回错误码及对应的错误信息说明,详细错误码信息请参考错误码说明。
- 根据job_id查询job详情,具体操作请参考查询任务的执行状态。
查询job详情返回状态status为“SUCCESS”,则表示弹性云服务器创建成功。
请求异常返回值说明请参考通用请求返回值。
- 查询job详情的body体中可以获取到云服务器ID,根据获取到的云服务器ID可对弹性云服务器进行查询、删除、变更规格、开机、关机等操作。
(3)API接口
生命周期管理
- 创建云服务器
- 创建云服务器(v1.1版本)
- 删除云服务器
- 查询云服务器详情
- 查询云服务器详情列表
- 批量修改弹性云服务器
状态管理
- 批量启动云服务器
- 批量重启云服务器
- 批量关闭云服务器
- 重装弹性云服务器操作系统(安装Cloud-init)
- 切换弹性云服务器操作系统(安装Cloud-init)
- 重装弹性云服务器操作系统(未安装Cloud-init)
- 切换弹性云服务器操作系统(未安装Cloud-init)
- 查询云服务器是否配置了自动恢复动作
- 管理云服务器自动恢复动作
- 注册云服务器监控
规格管理
- 查询规格详情和规格扩展信息列表
- 变更云服务器规格
- 变更云服务器规格(v1.1版本)
- 查询云服务器规格变更支持列表
网卡管理
- 批量添加云服务器网卡
- 批量删除云服务器网卡
- 云服务器网卡配置虚拟IP地址
- 云服务器网卡解绑虚拟IP地址
磁盘管理
- 查询弹性云服务器磁盘信息
- 查询弹性云服务器单个磁盘信息
- 弹性云服务器挂载磁盘
- 批量挂载指定共享盘
- 弹性云服务器卸载磁盘
租户配额管理
- 查询租户配额
查询Job状态
- 查询任务的执行状态