搬家到 AWS 碰到的那些坑

2017/01/02 IT&数码

经过将近一个月的研究,阅读了 N 多的技术博客,终于在麻婆豆腐的文章指引下(同时也参考了其他多人的博客文章),终于成功的将公司网站和个人博客迁移到了 AWS 上,用上了一年的免费试用。

最开始是看到了 paul 的文章《Amazon AWS —— 免费的午餐不好吃》,所以在开始前做了很多准备工作,翻阅了很多相关文章,教程,youtube 视频,以防止不小心出现超额费用。

准备工作

亚马逊云,也就是 AWS (Amazon Web Services)对新用户提供一年的免费试用,其中包含的项目多达十几种,且仍在继续增加中,通过上面提到的文章,我大概规划出了可能用到的这么几项。EC2,S3,EBS,RDS,Cloud Front,Elasticache,Cloud Watch, 还有IAM,VPC 这些基本属于全局的一些管理工具了。好了,决定了要用哪些,就开始真正的着手准备吧。

首先,你需要有一个可以支付美元的信用卡,亚马逊的 AWS 不支持 Paypal一类的第三方工具,连自己的礼品卡都不行,所以这个还是很重要的。最好是有腾讯的国际虚拟卡,后来不能申请了,幸运的是我还有,用这个的好处就是不怕 AWS 乱扣钱,因为扣不到。

然后你需要一个美国的电话号码,看别人的文章,似乎有些不需要验证你的信息,不过还好,我有 Google Voice 提供的号码。

既然有网站放在上面,最起码你要有个域名吧,免费的 .tk 或者自行注册的 .com 一类。

IAM Role

首先按照 AWS - 创建一个高可用的WordPress 博客 (二)里面提到的方法,我们需要先创建一个IAM的角色 ec2-s3,可以允许关联的虚拟机默认就有访问S3 Bucket的权限。 IAM

文中单独创建 VPC 我就忽略掉了,全部用系统默认的就好了。

Security Group 也用默认的。

为了安全起见,根用户和 IAM 用户我都添加了两步验证。推荐大家也把两步验证用起来,其实很简单,用 Google Authenticator 扫一下二维码就好了。

创建 RDS 数据库

我一直都是用 wordpress 来构建网站的,所以用 RDS 里面的 MySQL 即可,现在 AWS 又有了兼容 MySQL 的 Aurora,喜欢折腾的可以试用下。

RDS-MySQL

自己的小站,不需要负载均衡,免费试用的话不要勾选 multi-AZ

这里要选择 t2.micro, 版本随意,大小不要超过 30 GB。

t2.micro

下方自行设置数据库的名称,管理员账号及密码。

好了,坑出现了,默认 RDS 是有两个 subnet 的。subnet 这里千万不要用 default,默认的一定和你 EC2 不一样的, 要进去手动勾选一个。我就在这里吃过亏。选错了也没关系,可以回头来修改,但一定不要默认。

subnet

然后就创建成功了,不过成功后要多等一会才会出现。

success

完成之后就会出现 endpoint 的地址,这个用的时候需要复制粘贴过去的。

endpoint

到此,RDS 就创建好了。

EC2 主机创建

现在需要我们来操作 EC2 了。

进入 EC2 后需要选择一个镜像,我习惯用 CentOS 了,所以我去 AWS Marketplace 里面挑选了 CentOS 7 的官方镜像。各位有需要的话按自己喜好查找即可。记得要找 free tier eligible 的,否则软件也要额外收费的。

创建时需要选定 t2.micro, VPC 用默认的,subnet 手动选和 RDS 一致的。IAM role 选前面创建的 ec2-s3. 选定好容量之后就可以了。

最后一步是要创建秘钥,然后保存在本地

秘钥

创建好 EC2 之后页面上方有个 connect 按钮,点击之后又连接说明,按提示操作即可。

我用的 macbook,在 Terminal 里把秘钥权限设为 400, 然后 ssh 登录就可以了。默认 CentOS 系统的用户名是 centos,不是 root 也不是 ec2-user. 其实只要注意看连接按钮点击后的页面就不会出错的。连接之后输入 sudo -i 即可获取 root 权限。

创建之初需要选择 region,我选的是日本,RDS 也一样要是日本,否则会有 data transfer 的费用产生。

EC2 创建好以后即可申请 Elastic IP,申请到以后要马上绑定到 EC2 主机上,否则也会导致费用产生。这一项是不绑定才产生,和其他用了才产生的完全相反。不用的时候要及时 detach 和 release。

这个坑挖的有点大,什么时候才能填上啊。

搭建环境

完成了 EC2 的创建后,我们需要搭建建站环境了。这里我用的是 oneinstack,国内用户用的比较多的一般是 LNMP 其中也提供了 LAMP 或 LNMPA 的环境,在本地虚拟机搭建过之后我还是觉得 oneinstack 最好用,创建站点时可以自动申请 let’s encrypt 的证书并且可以自动更新,定制也更灵活。

因为 AWS 上的 CentOS 基本上是个 minimal 的环境,screen 什么的也是需要安装的。

yum -y install wget screen curl python   #for CentOS/Redhat # 
apt-get -y install wget screen curl python  #for Debian/Ubuntu 
wget http://aliyun-oss.linuxeye.com/oneinstack-full.tar.gz    #阿里云用户下载 
wget http://mirrors.linuxeye.com/oneinstack-full.tar.gz    #包含源码,国内外均可下载 
wget http://mirrors.linuxeye.com/oneinstack.tar.gz    #不包含源码,建议仅国外主机下载 
tar xzf oneinstack-full.tar.gz 
cd oneinstack    #如果需要修改目录(安装、数据存储、Nginx日志),请修改options.conf文件 
screen -S oneinstack    #如果网路出现中断,可以执行命令 screen -r oneinstack 重新连接安装窗口 
./install.sh     #注:请勿sh install.sh或者bash install.sh这样执行

当然了,操作这一步前我建议大家先 yum update 一下。

oneinstack 新上的图好清楚

mMxEb1.png

装好之后建议马上安装附加组件里的 let’s encrypt 的客户端,这样建站时就会自动申请并绑定 SSL 证书了。

./addons.sh

mMxgjz.png

下面添加虚拟主机

./vhost.sh

mMxMeO.png

这里我可以选择不安装数据库,可以节省 EC2 上的不少空间。

phpmyadmin 在 /data/wwwroot/default 里面,需要修改 config.inc.php 这个文件里面的 server 设置

$i++;
/* Authentication type */
$cfg['Servers'][$i]['auth_type'] = 'cookie';
/* Server parameters */
/* RDS对应的Endpoint*/
$cfg['Servers'][$i]['host'] = 'xxxx.xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com';
$cfg['Servers'][$i]['connect_type'] = 'tcp';
$cfg['Servers'][$i]['compress'] = false;
$cfg['Servers'][$i]['AllowNoPassword'] = false;

只改 host 一项即可,其他可以不用修改。登录的时候就用 RDS 上创建的用户名和密码。但权限稍低,在创建数据库的时候建议先创建数据库,然后创建用户,再给用户分配某数据库的管理权限。否则,你懂得,error。

开始建站

前面提到了命令这里再重复一下 ./vhost.sh,根据需要选择好。数据库那边创建好之后,记好数据库名,用户名和密码。

在新建号的网站目录下,例如 /data/wwwroot/domain.com 下使用 wget https://wordpress.org/latest.tar.gz 然后解压缩,再把目录下 wordpress 里的全部文件上移一级,即可登录 domain.com 开始创建网站了。简单到发指有木有?!

mMbCPQ.jpg

这里的数据库地址要用 RDS 的 endpoint 地址。 mMbUax.png

用 wordpress 的推荐大家安装 Google Authenticator 这个插件已启用二步验证。

Security Group

关于安全组,这里需要说两句。默认开启 80 和 443 端口以供 http 和 https 访问使用。

SSH 是 22 端口,不过建议设为本机 IP 访问,以防恶意扫描端口并登陆。EC2 上的 ftp 是 passive mode,请根据自己客户端情况设定开放端口。我用的 transmit 需要开放 2000-3000 端口,默认的 20-21 端口也需要开启,依然设为限本地 IP 登陆。anywhere 要慎用

3306 端口开放给自己的 RDS,CIDR 复制进去就好了,够安全,连接也不会有问题。

BONUS

oneinstack 里自带了一键 SS,安装好后只需要在安全组里开放端口即可使用。当然,最好限定本机IP,还是那句话anywhere 要慎用

S3

S3 其实很简单,创建 bucket 然后向里面扔文件就好了。 只是每次用 ftp 工具时记得要填入 Access key ID 和 Secret access key。前面之所以要创建 ec2-s3 iam role 就是为了要省去单独设置 s3 访问权限。

后面关键的来了,加个小标题把。

防盗链

对于防盗链,我一开始是一头雾水的,直到我看到了 sean 的 关于 Amazon S3 的访问权限以及存储桶策略这篇文章。依葫芦画瓢设置了自以为最安全的方法。

   "Version": "2012-10-17",
   "Id": "PreventHotLinking",
   "Statement": [
     {
       "Sid": "Allow get requests referred by www.mysite.com and mysite.com",
       "Effect": "Allow",
       "Principal": "*",
       "Action": "s3:GetObject",
       "Resource": "arn:aws:s3:::examplebucket/*",
       "Condition": {
         "StringLike": {"aws:Referer": ["http://www.example.com/*","http://example.com/*"]}
       }
     },
      {
        "Sid": "Explicit deny to ensure requests are allowed only from specific referer.",
        "Effect": "Deny",
        "Principal": "*",
        "Action": "s3:*",
        "Resource": "arn:aws:s3:::examplebucket/*",
        "Condition": {
          "StringNotLike": {"aws:Referer": ["http://www.example.com/*","http://example.com/*"]}
        }
      }
   ]
}

然后发现悲催了,网站无法显示图片了。wordpress 安装了 s3 lite 的插件也无法访问到我设置的存储桶。于是又是一番研究,翻阅文章。终于找到了症结所在。默认是类似于根用户的权限,我先是给每个网站添加了一个用户,每个用户应用一个 inline policy,如下:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Stmt1479792159000",
            "Effect": "Allow",
            "Action": [
                "s3:CreateBucket",
                "s3:DeleteBucket",
                "s3:DeleteObject",
                "s3:GetObject",
                "s3:PutObject"
            ],
            "Resource": [
                "arn:aws:s3:::examplebucket/*"
            ]
        }
    ]
}

这样,该网站对应的用户只允许访问一个指定的 bucket, 然后 bucket 再添加一个针对这个用户的权限。

	"Version": "2012-10-17",
	"Id": "PreventHotLinking",
	"Statement": [
		{
			"Sid": "Explicit deny",
			"Effect": "Deny",
			"Principal": {
				"AWS": "*"
			},
			"Action": "s3:GetObject",
			"Resource": "arn:aws:s3:::examplebucket/*",
			"Condition": {
				"StringNotLike": {
					"aws:Referer": [
						"https://www.example.com/*",
						"https://example.com/*"
					]
				},
				"NotIpAddress": {
					"aws:SourceIp": "EC2 的内网 CIDR"
				}
			}
		}
	]
}

这样一来不是指定域名的不可以访问,不是指定 ec2 机器的请求也不予通过。安全性大概提高,之后测试过,粘贴到其他地址确实是无法访问了。

结语

其实到这里基本上已经够大家用了。

Cloud Front 设置很简单,可以设定域名整体的,也可以设定 S3 上文件的,创建好之后会有一个 XXX.cloudfront.net 的地址,在 S3 lite 的插件里面填入这个地址就可以启用 CDN 了。

ElastiCache 也类似,建议大家搜索吧,如果个人使用的话,这些付费产品应该不大会涉及。

还有一个额外的坑,当你为 EC2 申请 Elastic IP 的时候,如果你网站 A 记录存的是该 IP 地址,那么你会被收取 Data Transfer 费用的,默认使用 IP 是按照外网访问来处理的,只有当你设置 ec2-IP.region.compute.amazonaws.com 开头的 public DNS 地址时才会按内网来处理,内网内的流量都是不计费的。但是当你把裸域名,也就是 domain.com 而不是 www.domain.com 设置为 Public DNS 地址,你就会发现你的 mx 记录不生效了,所以仍然要把裸域名设置为 A 记录,使用 IP 地址,同时在创建网站的时候设置裸域名转向到 www.domain.com 的地址,www.domain.com 的地址创建 CNAME 指向 Public DNS。对于想要使用裸域名来访问的,我告诉你,不花钱的情况下是没办法的。花钱的前提下,使用 AWS 的 Route 53 服务,把 NS 改成 AWS 的地址,就全解决了,前提是,这个不在 free tier 里面,每条记录都是要花钱的。

基本上我碰到的坑都列出来了,也顺便做个了小教程,给自己看,也给有需要的朋友参考使用。

Search

    Post Directory