不论想用自主开发的、开源项目的,还是商业厂商的软件,都需要安装、更新和配置应用程序及其依赖的组件。这一过程称为部署。
在服务器上部署一个典型的网站应用必需的步骤有哪些呢?下面以一个广泛使用的博客平台WordPress为例加以说明。
(1)安装Apache HTTP服务器、MySQL数据库、PHP运行环境、供PHP调用的MySQL访问库和一个SMTP邮件服务器。
(2)下载WordPress应用,然后在服务器上解压缩。
(3)配置Apache网站服务器使之能运行PHP应用。
(4)配置PHP运行环境来调整性能并提高安全性。
(5)编辑wp-config.php文件来配置WordPress应用。
(6)编辑SMTP服务器的配置,确保只有虚拟服务器能发送邮件,以免被垃圾邮件发送者滥用。
(7)启动MySQL、SMTP和HTTP服务。
在服务器启动的时候运行一个脚本是简单、有用并且灵活地进行自动化部署的方法。要把仅有操作系统的服务器完全安装并且配置好,需要遵循下列3个步骤。
(1)启动一台仅有操作系统的虚拟服务器。
(2)在引导程序完成后执行一个脚本。
(3)使用脚本安装并配置应用程序。
首先用户需要选择自己的虚拟服务器所使用的AMI。AMI为用户的虚拟服务器捆绑了操作系统以及预先安装好的软件。当用户从一个仅包含了操作系统,没有安装任何额外软件的AMI启动自己的虚拟服务器时,需要在引导程序结束时对虚拟服务器进行准备工作。把必要的安装和配置应用程序的步骤写成脚本能自动化这一任务。
在每一台虚拟服务器上用户可以插入一小段,不超过16 KB,被称作用户数据的数据。用户可以在创建一台新的虚拟服务器时指定用户数据。大多数AMI,如Amazon Linux Image和Ubuntu AMI都包含了这一典型的运行用户数据的功能。无论何时当用户基于这些AMI启动一台虚拟服务器时,用户数据在引导进程结束时被作为shell脚本被执行。执行的时候利用root用户的权限。
在虚拟服务器上,用户数据可以通过向一个特定URL进行HTTP Get请求来获得。这个URL是http://169.254.169.254/latest/user-data,只能从这台虚拟服务器自己访问到。正如下面的例子中读者将看到的,我们能够通过作为脚本被执行的用户数据的帮助部署任何类型的应用程序。
打开命令行,然后一步步执行命令来启动一台虚拟服务器,并且在上面部署一个VPN服务器。我们已经准备好了一个CloudFormation模板来启动虚拟服务器以及它的依赖项
代码如下(示例):
VpcId=$(aws ec2 describe-vpcs --query Vpcs[0].VpcId --output text) ←--获取默认VPC
$ SubnetId=$(aws ec2 describe-subnets --filters Name=vpc-id,Values=$VpcId \ ←--获取默认子网
--query Subnets[0].SubnetId --output text)
$ SharedSecret=$(openssl rand -base64 30) ←--创建一个随机密码(如果openssl不工作,创建你自己的随机序列)
Name=vpc-id,Values=$VpcId \ ←--获取默认子网
--query Subnets[0].SubnetId --output text)
$ SharedSecret=$(openssl rand -base64 30) ←--创建一个随机密码(如果openssl不工作,创建你自己的随机序列)
$ Password=$(openssl rand -base64 30) ←--创建一个随机共享密钥(如果openssl 不工作,创建你自己的随机序列)
$ aws cloudformation create-stack --stack-name vpn --template-url \ ←--创建一个CloudFormation 堆栈
https://s3.amazonaws.com/awsinaction/chapter5/vpn-cloudformation.json \
--parameters ParameterKey=KeyName,ParameterValue=mykey \
ParameterKey=VPC,ParameterValue=$VpcId \
ParameterKey=Subnet,ParameterValue=$SubnetId \
ParameterKey=IPSecSharedSecret,ParameterValue=$SharedSecret \
ParameterKey=VPNUser,ParameterValue=vpn \
ParameterKey=VPNPassword,ParameterValue=$Password
$ aws cloudformation describe-stacks --stack-name vpn \
--query Stacks[0].Outputs ←--如果状态不是COMPLETE,请在1 min 后重试
最后一行命令的输出应该会列出公有VPN服务器的公有IP地址、共享密钥、VPN用户名和VPN密码。用户可以使用这一信息来从自己的计算机中建立VPN连接:
...]
[
{
"Description": "Public IP address of the vpn server",
"OutputKey": "ServerIP",
"OutputValue": "52.4.68.225"
},
{
"Description": "The shared key for the VPN connection (IPSec)",
"OutputKey": "IPSecSharedSecret",
"OutputValue": "sqmvJll/13bD6YqpmsKkPSMs9RrPL8itpr7m5V8g"
},
{
"Description": "The username for the vpn connection",
"OutputKey": "VPNUser",
"OutputValue": "vpn"
},
{
"Description": "The password for the vpn connection",
"OutputKey": "VPNPassword",
"OutputValue": "aZQVFufFlUjJkesUfDmMj6DcHrWjuKShyFB/d0lE"
}
]
使用自定义用户数据启动一台虚拟服务器,并使用AWS CloudFormation为这台虚拟服务器配置防火墙。
在引导程序结束时执行一个shell脚本,通过程序包管理器来安装应用程序及其依赖项,并且编辑配置文件。
可以使用CloudFormation来启动一台虚拟服务器并且配置一个防火墙。VPN服务器模板包括一个装入用户数据的shell脚本
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "Starts an virtual server (EC2) with OpenSwan [...]",
"Parameters": { ←--参数,使模板复用成为可能
"KeyName": {
"Description": "key for SSH access",
"Type": "AWS::EC2::KeyPair::KeyName"
},
"VPC": {
"Description": "Just select the one and only default VPC.",
"Type": "AWS::EC2::VPC::Id"
},
"Subnet": {
"Description": "Just select one of the available subnets.",
"Type": "AWS::EC2::Subnet::Id"
},
"IPSecSharedSecret": {
"Description": "The shared secret key for IPSec.",
"Type": "String"
},
"VPNUser": {
"Description": "The VPN user.",
"Type": "String"
},
"VPNPassword": {
"Description": "The VPN password.",
"Type": "String"
}
},
"Resources": { ←--描述虚拟服务器
"EC2Instance": {
"Type": "AWS::EC2::Instance",
"Properties": {
"InstanceType": "t2.micro",
"SecurityGroupIds": [{"Ref": "InstanceSecurityGroup"}],
用户数据包含一个用来获取并执行真正的脚本的小脚本vpn-setup.sh,真正的脚本包含所有的安装可执行程序以及配置服务的命令。这样做可以避免以可读性较差的格式插入JSON CloudFormation模板所需的脚本。
使用EC2用户数据与一个shell脚本在一台虚拟服务器上部署一个VPN服务器。在终止虚拟服务器之后,我们将准备学习如何部署一个普通网站应用,而不需要自定义脚本。