【不周山之云计算】壹 云平台初探

开发过程中最麻烦的往往不是开发本身,而是环境搭建,尤其是调通各种接口和服务。这一讲我会详细介绍如何把云资源用得像自家电脑一样省心。


更新历史

  • 2017.05.26: 完成初稿

系列文章

注:待更新完成后列出

学习目标

  1. 了解 AWS 和 Azure 的基本概念和使用
  2. 掌握基本的 Linux 命令
  3. 理解不同配置的应用场景

AWS - Amazon Web Service

AWS 是目前最广泛应用的云服务,包含各种不同的服务,比如 Amazon Simple Storage Service (S3) 和 Amazon Elastic Compute Cloud (EC2)。更多的信息请参考 AWS 网站

AWS Authentication

除了 AWS 本身的帐号外,访问 API 以及各类 AWS 服务需要使用的一对『钥匙』:AWS Access Key ID 以及 AWS Secret Key

生成『钥匙』可以按照以下步骤:

  1. 登录 AWS 账户
  2. 在右上角的下拉菜单中选择 Security Credentials (安全证书)
    • 如果是第一次访问的话会弹出一个提示是继续还是看一下教程,可以根据自己的需要来选择
  3. 在 Access Key (访问密钥)那一栏创建一个新的密钥,就会包含 AWS Access Key ID 以及 AWS Secret Key

注意!AWS 密钥拥有控制 AWS 帐号的完全权限,所以务必要保存在安全的地方,做到以下几点:

  1. 不要与任何人共享 AWS 密钥
  2. 不要在代码中用明文保存密钥
  3. 不要把包含 AWS 密钥的代码提交到任何库中

比较安全的做法是利用环境变量来保存密钥:

export AWS_ACCESS_KEY_ID="YOUR_ACCESS_KEY_HERE"
export AWS_SECRET_KEY="YOUR_SECRET_KEY_HERE"

在代码中就可以使用 System.getenv("AWS_ACCESS_KEY_ID") 或者 os.environ['AWS_ACCESS_KEY_ID'] 来访问,不会出现明文,我在自己电脑里用的名字是:AWSAccessKeyIdAWSSecretKey

Elastic Compute Cloud (EC2)

简单来说,EC2 提供计算能力。EC2 实例可以被看做是虚拟机或虚拟服务器,有虚拟 CPU,内存,本地存储和网络带宽,当然运行的时候是要花钱的。具体的配置不能够自定义,只能从几个类型中选择:

  • t1.micro:1 个虚拟 CPU,1 G 内存,无本地存储,低带宽。这种会提供免费的使用时间,基本也就够用了。
  • m1.small
  • m1.large
  • c1.xlarge

具体的类型可以参考亚马逊的介绍,这里不一一列举。

花钱也有不同的方式:

  • 按需:每个 instance 每小时有固定的价钱
  • Reserved:预付款模式
  • Spot Pricing:Bid for unused capacity,给定一个价格,如果浮动到价格以下,那么就帮你开启,并以当时的价格计价

instance 的存储会在 Elastic Block Storage(EBS)。

Amazon Machine Image (AMI) = 操作系统 + 软件。

一旦一个 instance 启动之后,就有了一个公网的 IP,可以通过 Security Group 来进行访问,比如 22 端口 SSH,80 端口 HTTP,3306 端口 MySQL。

利用密钥对来访问 EC2 instances。

总结一下,启动一个 instance 有以下几个步骤:

  1. 选择一个 instance 类型:t1.micro
  2. 决定一个计价模型:Spot Pricing
  3. 选择一个 AMI:Ubuntu AMI
  4. 定义一个 Security Group
  5. 使用密钥对来连接

启动并连接到 instance

启动 EC2 instance 视频教程(墙外)

具体的步骤如下:

  1. 进入控制台,选择 EC2 控制面板(地区注意选择弗吉尼亚北部,右上角那里)
  2. 点击实例,现在什么都没有,选择创建一个新实例
  3. 之后的 project 中会给出 AMI id,可以在社区 AMI 一栏里搜索选择
  4. 这里我们选择 Amazon Linux AMI,选择 t2.micro
  5. 点击下一步进行具体的配置,这里暂时不需要修改
  6. 点击下一步选择存储
  7. 点击下一步可以给 instance 一些标签,注意格式应该是 Project:<Project Number>,如 Project:0Project:1.1 这样
  8. 点击下一步配置 Security Group,这里可以不用修改,但是如果提高安全性的话可以限制可访问的 ip
  9. 然后可以查看各种选项
  10. 需要选择一个连接的密钥对(也可以在这里创建一个新的),是一个pem 文件,同样注意保存好
  11. 这时候就可以启动 instance

等待一段时间,启动之后就可以连接到这个 instance,具体的步骤如下:

  1. 从面板中得到 Public DNS 地址
  2. 使用 ssh -i key_file.pem ec2-user@ec2-50-19-54-72-compute-1.amazonaws.com 来进行连接
  3. 需要使用 chmod 600 key_file.pem 来修改权限
  4. 如果需要 root,直接 sudo 即可

Simple Storage Service(S3)

Amazon S3 提供了一个简单的用来存储和访问任何数据的 web 服务接口。可以存储的对象数量是无限的,每个对象都可以通过一个唯一的,由开发者指定的 key 来访问。

和常见的文件系统比较起来,S3 没有文件夹的概念,唯一的容器就是一个 bucket,但是文件名例可以有 / 来标记不同的层级。

可以通过 web 界面,命令行工具和 API 三种方式来访问 S3。假设在 S3 中有一个文件的路径是

  • s3://wdxtub/dawang.txt

那么可以通过以下两种方式用 http 来访问:

  • http://s3.amazonaws.com/wdxtub/dawang.txt
  • http://wdxtub.s3.amazonaws.com/dawang.txt

其中 wdxtub 是 bucket 名,必须是全局唯一的。如果想要所有人都能够访问,需要设置一下对应的权限

其他一些常用的工具有:

  • AWS Command Line Tool (aws-cli)
    • 在 Mac 下可以直接使用 pip install awscli 来进行安装,具体的教程可以参考官方文档
  • CloudWatch
    • 简单来说,CloudWatch 就是一个监控各种云服务的工具

AWS API

AWS 可以通过命令行工具或者 SDK 来访问几乎所有的功能,这一节主要介绍一些最常用的工具和功能。

Java AWS SDK 包括:

  • AWS Java Library:总而言之就是所需的各种包,网络请求,验证,错误处理等等
  • 样例代码
  • Eclipse 支持:包含一个插件

这里找到对应的工具,找到 SDK 中对应的库。主要过程有三步:

  1. 用密钥初始化 AWS 连接
  2. 使用 API 进行操作
  3. 关闭 AWS 连接

先下载好 SDK 和 Eclipse 插件(在 eclipse 里安装,Amazon 有给出教程)

Amazon EC2 API

可以通过 API 做这些事情:

  • 创建 EC2 密钥对
  • 位实例创建安全组并且打开端口
  • 创建启动停止重启和终止 EC2 实例

下面是 Java 和 Python 的代码

Java:

//Load the Properties File with AWS Credentials
Properties properties = new Properties();
properties.load(RunInstance.class.getResourceAsStream("/AwsCredentials.properties"));
BasicAWSCredentials bawsc = new BasicAWSCredentials(properties.getProperty("accessKey"), properties.getProperty("secretKey"));
//Create an Amazon EC2 Client
AmazonEC2Client ec2 = new AmazonEC2Client(bawsc);
//Create Instance Request
RunInstancesRequest runInstancesRequest = new RunInstancesRequest();
//Configure Instance Request
runInstancesRequest.withImageId("ami-3b44d352")
.withInstanceType("t1.micro")
.withMinCount(1)
.withMaxCount(1)
.withKeyName("project1_test")
.withSecurityGroups("MySecurityGroup");
//Launch Instance
RunInstancesResult runInstancesResult = ec2.runInstances(runInstancesRequest);
//Return the Object Reference of the Instance just Launched
Instance instance=runInstancesResult.getReservation().getInstances().get(0);

Python:

from boto.ec2.connection import EC2Connection
# Create a connection
conn = boto.ec2.connect_to_region("us-east-1")
# Launching instance
reservation = conn.run_instances("ami-3b44d352",instance_type = "t1.micro",
key_name = "project1_test", security_groups = "MySecurityGroup")
instance = reservation.instances[0]

我们同样可以通过 EC2 的 API 来查看实例的状态,例如类 DescribeInstanceStatusRequest 的状态:

  • Running
  • Pending
  • Shutting down 等等

更多的文档参考 AWS SDK for Java Documentation AWS Java API Referenceboto

AWS CLI

我们同样也可以利用命令行来操作 AWS,主页在这里。如果打算使用命令行,那么需要:

  1. 在实例中下载和安装命令行工具
  2. 通过 aws configure 来设置密钥(注意这里地区要选择 us-east-1,参考链接

下面是简单的使用 AWS 命令行工具的视频介绍

AWS 命令行工具(墙外)

启动实例之前先要配置,如下:

$ aws configure
AWS Access Key ID [None]: YOUR AWS ACCESS KEY
AWS Secret Access Key [None]: YOUR AWS SECRET ACCESS KEY
Default region name [None]: us-east-1
Default output format [None]: json

然后可以用下面的命令来创建安全组,密钥对和角色

$ aws ec2 create-security-group --group-name devenv-sg --description "security group for development environment in EC2"
$ aws ec2 authorize-security-group-ingress --group-name devenv-sg --protocol tcp --port 22 --cidr 0.0.0.0/0
$ aws ec2 create-key-pair --key-name devenv-key --query 'KeyMaterial' --output text > devenv-key.pem
$ chmod 400 devenv-key.pem

然后就可以启动并连接实例了,这里需要提供 AMI_ID(ami-xxxxx) 和 安全组(sg-xxxxx)

$ aws ec2 run-instances --image-id YOUR_AMI_ID --security-group-ids SECURITY_GROUP_ID --count 1 --instance-type t2.micro --key-name devenv-key --query 'Instances[0].InstanceId'

Amazon CloudWatch 部分之前有介绍过,详细介绍可以查看文档

Microsoft Azure

简单来说,就是微软提供的云服务,提供 PaaS 和 IaaS 服务,于此同时支持不同的编程语言/工具/框架。可以通过访问 Azure Portal 或者 Azure Manage 来访问 Azure 控制台,其中 Azure Portal 是一个新的控制台,尽量用这个。需要更多信息,可以查看这里

Microsoft Azure Compute

按照以下步骤来创建一个虚拟机:

  1. 登录Azure Portal
  2. 新建 -> 计算 -> Ubuntu Server 14.04 LTS,选择 资源管理器 作为 部署模型
  3. 设置姓名、用户名和密码,新建一个资源组,点击确定
  4. 然后在大小选择中点击查看全部,选择 A0 标准,也就是最便宜的那个
  5. 后面的大部分内容都可以用默认值,然后点击确定就创建完成了

Azure 有两种不同的部署模型:Azure Service Manager(ASM) 和 Azure Resource Manager(ARM),后者更新也有更好的 API,所以我们尽量用后一种。

注意,在一种模型例部署的资源在另一种里看不到,更多信息可以访问这里

Microsoft Azure Storage

类似于 Amazon S3,是一个可拓展的存储系统,有下面四种形态:

  1. Azure Blobs,类似 Amazon S3 的对象存储系统
  2. Azure Tables,数据库
  3. Azure Queues,应用的消息队列
  4. Azure Files,文件系统

现在我们主要接触一下 Azure Blobs,首先先要建立一个 Azure Storage 账户,按照下面步骤即可:

  1. 新建 -> 数据+存储器 -> 存储(Storage account)
  2. 部署模型 选择 资源管理器,然后指定唯一的名字
  3. 指定一个现有的资源组(刚才新建的那个就可以),然后在类型里选择 L 本地冗余(最便宜那个)
  4. 然后就可以创建了

等待一段时间部署,部署完成后就可以通过 Azure 命令行工具来进行访问了。

Linux 基础

如果你对前面的命令感觉一头雾水,那么这一节要好好阅读了。下面是一些教程:

  1. The Advanced Bash Scripting Guide
  2. The Art of the Command Line 中文版本
  3. Perl 指南
  4. Python 指南

读的时候需要注意下面的内容:

  1. 脚本语法,本地变量和环境变量
  2. bash 中的 Quoting and back-ticks
  3. 利用 unix 管道进行输入输出重定向
  4. 使用类似 grep, awk, sed, cut 等等来做基本的文本操作

Secure Shell(SSH)

简单来说 SSH 是一个用来进行安全数据通信、远程登录和远程命令执行的网络协议。

要想让一台服务器支持 SSH,需使用 sudo apt-get install openssh-server 安装服务,对应的配置文件在 /etc/ssh/sshd.config 中。可以使用 sudo /etc/init.d/sshsudo service sshd [start|stop|restart] 来进行管理。

SSH 支持若干中验证机制。比较常见的是通过密码验证。密码验证的安全性取决于密码的长度和复杂度,由于可以被暴力或者基于字典破解,所以对于公共访问的 EC2 instance 来说是比较危险的。

为此,所有的 EC2 instance 都使用基于公钥加密的 key-based 验证。一对密钥包含公钥和私钥,由数学方式如 RSA/DSA 生成并链接。只知道一个 key 的话,几乎不可能破解另外一个 key。

我们也可以生成自己的密钥对,在 Linux 中,密钥对通常存储在 ~/.ssh 目录下,通过下面的代码就可以生成密钥对:

# Generate a new key with your email id as a label
ssh-keygen -t rsa -b 4096 -C "email_id@domain.com"
# Enter the file where you want to save the key: (recommended - choose default)
# You will be asked enter a pass-phrase for your key twice.
# (Use a strong pass-phrase. Longer pass-phrases are more secure than shorter ones.)
# After you provide the pass-phrase. The console will print the location of the key and the key fingerprint

然后就可以导入这个密钥并用以连接 EC2,具体的做法可以看这里

举个例子,下面的代码会在远程实例执行 uname -a 命令,这种做法在批量运行远程实例命令的时候非常有用:

ssh -i private_key_file.pem some-instance.ec2.amazonaws.com 'uname –a'

如果遇到 SSH 的 permission-denied 问题,很可能是由于不正确权限所导致,私钥的 unix permission 为 600 且包含私钥的目录的权限应为 700

在执行 SSH 命令时,如果太久没有操作,就会自动断开,执行的脚本也会终止,如果不希望这样,有以下几种方式可以避免 SSH 超时:

  1. 关闭 SSH 客户端的超时
  2. nohup 执行脚本
  3. 通过远程屏幕管理(remote sreen management)来保持 terminal sessions

通常来说我们用 bash shell 来进行远程操作,但是由于网络的缘故,一旦连接断开,所有已经启动的进程都会被终止。为了避免这种情况,使用 nohup 命令就非常有用了,即使连接断开,仍旧会继续运行命令。

另外一个比较有用的工具是 byobu,是一个多终端管理应用程序,类似于 screen 或者 tmux

注:byobu 比较炫,但是我个人比较喜欢 tmux,参考 tmux 指南

安装软件

用 Ubuntu 的话可以使用强大的 apt-get 来安装软件,例如

sudo apt-get install emacs
sudo apt-get install vim
sudo apt-get update # 用来更新包索引
sudo apt-get upgrade # 用来更新包

文件所有者和权限

Linux 的文件权限分为三个用户组:user, groupothers,每组有三个权限:读(r),写(w),执行(x)。我们可以利用 chmod 命令来修改权限,如:chmod 777 filename.txt

不用数字的话,可以用字母,chmod u+x filename.txt 这个命令就给 user 添加了执行权限。如果要更改文件所属,使用 chown 命令,具体可以参见 man chown

Linux 中的磁盘操作

管理分区

许多 Linux 应用都可以管理磁盘分区,比如说 partedfdiskfdisk 是比较老的分区管理工具,现在几乎已经被 parted 取代,因为 parted 支持 GUID 分区表以及大于 2TB 的磁盘,所以我们这里使用 parted

parted -l 会列出系统中的所有分区。具体的顺序是按照 /dev 下的顺序。在 EC2 实例中,设备是 dev/xvd**/dev/xvda1 是操作系统分区,/dev/xvdb 是实例的存储分区,注意 RAMDISK 不会出现在 parted 的输出当中。

parted 还可以用来为每个分区设置类型和文件系统,例如

parted /dev/xvdX mklabel gpt
parted /dev/xvdX mkpart db ext4 0% 10G

如果不加任何参数,parted 就会进入交互模式,这里你可以利用 mkfs 来格式化一个分区,如 mkfs.ext4 /dev/xvdX1

挂载分区

在分区和格式化之后,如果想要使用就需要把分区挂载在某个挂载点上,通常来说会挂载在 /mnt 或者 /mount 上,可移除的媒介,例如 USB 和 CDROM,会挂载在 /media 上,当然,你可以把分区挂载在任何地方,如:

mkdir /storage/mountpoint
mount /dev/yourdevice /storage/mountpoint

配置服务和启动

如果想要开机启动,需要参考应用本身的帮助文档,但是总体来说,服务需要安装在 /etc/init.d 中,这使得这些脚本可以在启动时运行。例如,如果 mysql 脚本在 /etc/init.d 中,那么可以使用这个命令 service mysql [start|stop|restart]

想要了解更多,请参阅这里

EC2 性能测试

通常来说在云平台上用来计算的资源叫做虚拟机,也叫实例 instance。不是所有的实例都是一样的,在 AWS 中有一些可以定制的选择,比如说操作系统和硬件配置等等。

这一节的主要任务是了解虚拟机并在上面跑一些应用程序,借此来理解不同配置的不同表现。我们都知道更好的配置就性能更强,但是:

  • 更贵的是不是真的更好?
  • 有没有什么办法来测量其性能表现?
  • 性能的差别有多少?

这些问题都不简单,但是这一节会给你一点点启发。

启动不同类型的实例

虽然我们知道有几种不同的配置,但是除了纸面上的差别,真正的性能差别有多少呢?现在我们就来分别测试一下,按照以下步骤进行

  1. 启动三个分别为 t2.small, t2.medium, t2.large 的实例,硬盘选择 30GB 的 General SSD,镜像选择 Ubuntu Server 14.04 LTS (HVM), General SSD Volume Type (ami-d05e75b8)。这里最好选择 spot instances,可以省点钱,更多请查看这里。如果 spot instances 不可用的话,那么选择 on-demand instances
  2. 在启动这些实例的时候,需要指定 Security Group,创建允许 HTTP(TCP 端口 80) 和 SSH(TCP 端口 22) 的 security group
  3. 同样也需要指定一个已经存在的密钥对文件(或者生成一个)以连接这些实例
  4. 启动实例之后,可能需要等待几分钟,在 web 控制台可以查看目前的状况
  5. 用 SSH 及 PEM 文件来连接到这些实例。

系统性能评测

我们需要在已经启动的实例中安装性能测评工具。通过这个来评估完成一个任务所需的最佳实例组合以做到多快好省。

虽然云服务提供商是利用虚拟化技术来提供资源,但是需要知道实例的性能一来不是稳定的,二来也不保证达到某个水平。这里我们使用 sysbench 来评估性能,它是一个轻量级跨平台的性能测试软件,能够快速评估 CPU,内存和文件读写性能。

ssh -i keyfile.pem ubuntu@dnsaddress 来进行连接

然后执行下面的命令安装:

sudo apt-get update
sudo apt-get install sysbench

安装完成之后就可以按照给出的三个配置来进行测试。

CPU 测试

分别在三个不同的机器运行下列命令,统计结果:

sysbench --num-threads=8 --test=cpu --cpu-max-prime=20000 run
sysbench --num-threads=1 --test=cpu --cpu-max-prime=40000 run
sysbench --num-threads=4 --test=cpu --cpu-max-prime=50000 run

表后面的三列分别是 t2.small, t2.medium, t2.large 的总时间

Max Prime Thread Time(s) Time(m) Time(l)
20000 8 29.4015s 14.8129s 14.8693s
40000 1 77.7609s 76.0034s 77.1984s
50000 4 104.8054s 51.5801 52.4278s

可以看到其实在当前任务下,t2.mediumt2.large 的性能差别并不大,就可以根据价格来进行取舍了。

文件 IO 性能测试

AWS 通常会保证 Input/Output Operations per Second (IOPS)。不同的硬盘访问逻辑对性能影响很大(缓存导致),传统的机械硬盘受寻址时间和旋转速度的影响,固态硬盘受驱动和设备控制器的影响。

同样用下面的命令来进行测试:

sysbench --test=fileio --file-total-size=20G prepare
# 可能需要等待30分钟,使用 byobu / screen / tmux 来保持连接
# 或者可以在 iterm 设置中 profiles -> sessions -> When idel, send ASCII code
# 又或者 在客户端的 ~/.ssh/ 文件夹中添加 config 文件,并添加配置: ServerAliveInterval 60
sysbench --test=fileio --file-total-size=20G --file-test-mode=rndrw --init-rng=on --max-time=300 --max-requests=0 run
\ t2.small t2.medium t2.large
Read(Gb) 3.8986 3.9448 5.6735
Written(Gb) 2.599 2.6299 3.7823
Total trans(Gb) 6.4976 6.5747 9.4559
Speed(Mb/sec) 22.178 22.442 32.276

比较一下表中的数据,是不是随着价格的提高,性能也有对应比例的提高?

可以看到从 small 到 medium 几乎没有提升,但是到 large 就有比较大的提升。

Web 服务器性能测试

这里我们会在每个实例中安装和部署一个简单的 web 服务器,修改一下主页以便测试和评分。

LAMP = Linux + Apache + MySQL + PHP

用以下命令安装 apache:sudo apt-get install apache2。安装完成之后,用自己的浏览器访问这个实例的地址,应该就可以看到 Apache 的欢迎页面(这里需要在 Security Group 中允许 HTTP 访问)

如果访问 cd /var/www/html 就可以看到有一个 index.html 页面。我们把这个页面的内容替换成:welcome to cloud computingsudo vim index.html 然后命令模式下 dG),再次访问的时候就可以看到变化了。

然后我们来安装 apachebench,也就是服务器管理器,命令如下:sudo apt-get install apache2-utils。安装完成后,输入 ab 应该能看到命令界面,一个简单的测试命令为:

ab -n 1000 -c 100 http://localhost/ (一次 1000 个 request,一共 100 次,最后是想要测试的页面),然后就可以看到各种数据统计。

总结

第一节就塞这么多内容,不知道大家是感觉很爽还是亚历山大,总结一下,我们了解了不同云服务提供商的不同特点,也实际接触和操作了一把『云』,其中 Linux 基础是我们必须要掌握的。在云计算愈发普遍的今天,其实国内的很多社区也有出很多配套的教程,大家感兴趣的话,一定会被铺天盖地的广告轰炸的(感谢网友指出错别字)。

俗话说的好,万事开头难,接下来我们就会用一些更加接近实战的例子来与云亲密接触了。

参考链接

捧个钱场?