< Back

aws note

VPC

Virtual Private Cloud,能建立一个跨实例分享资源的网络。

为了减少延迟,aws在世界各地有各种Region,一个Region包含很多Availability Zone,Availability Zone是真正包含物理数据中心的地方,为aws provide redundancy。比方说一个Region的有三个Zone 分别为A,B,C,如果遇到什么灾害,A挂了,我们依然能够访问数据,因为数据A中的数据会被同步到B,C。

拿家庭网络来说,首先也是最重要的是你的网络提供商要提供一个你家里到互联网的连接。要使得你的设备能连接到互联网,你需要一个gateway,而modem就是用来当作gateway,modem连接着一个有线或者无线路由,这个路由能使你家中的设备能连接到彼此,并且通过cabel modem访问到互联网。

img

当终端设备,像手机电脑,要访问网络的话,首先要经过的是firewall,firewall设计为提供一个安全层,用来阻止一些不希望的流量(比如病毒),以及允许一些特定的流量通过。比如如果要访问某个网页的页面,就得允许80端口的开放,然后请求才能通过firewall到达路由器,然后到modem然后到互联网。

img

如果放到VPC中来说呢?

img

图中EC2就相当于家中的终端设备,如果EC2要访问某个网页,首先要经过的就是NACL,NACL的行为就类似于firewall,我们需要允许80端口的流量通过NACL,允许后,流量会到达Route Table,他来决定要如果处理该流量,是发到互联网还是本地的其他VPC,如果该流量的目的地是互联网,那就把他发送到 Internet gateway,Internet gateway 可以类比下modem,把流量传输到互联网中。比较家庭网络的例子,可以看到他们基本的处理流程是很相似的。

当创建了一个AWS账户的时候,会同时创建一个默认的VPC,包括一些基本的组件(Internet gateway ,route table,NACL and subnets),来使得你的VPC正常工作。

Internet gateway

有的时候缩写为IGW,概念上来讲,IGW类似于家庭网络中的modem。简单定义为:是硬件和软件的组合,用来给你的私有网络提供一个通往外部世界(Internet)的道路。所以如果没有gateway,那么你的VPC是无法连接到互联网的。在你考虑IGW的时候,就想象下modem是如何连通你的ISP的。

一个VPC任意时间只能attach一个IGW。

Route Tables

有时候缩写为RTs,定义为包含一套被称作routes的rules,用来决定流量导向何处。

控制台的Route Tables页面上的路由标签下可以看到指定路由的所有的规则,Destination列表示如果收到的流量指向的ip范围是在当前列范围内,则把该流量送到该行的target去,比如local,就是送到本地的其他VPC。如果不是在这个范围内,则去匹配下面下面的路由,有个默认的0.0.0.0/0,表示的就是匹配所有路由,送到外面的网络中去,target是一个IGW,即可以流量交给modem。

当VPC没有attach任何IGW的时候,本质上你的数据还是会被通过路由转发到IGW,但是IGW没有办法将数据发送到外网。就好比你的modem仍然在线,但是连不上你的ISP了。此时你控制台的路由规则标签页会在0.0.0.0/0的那行的status那里显示Black Hole,就表示当前行的IGW detached了。值得注意的时候,Destination是和特定IGW挂钩的,VPC如果attach了其他的IGW,但是路由规则里没有配置到这个IGW,那么VPC还是无法访问外网的。

Network Access Control List(NACLs)

NACL的行为像是firewall,控制着流量的进出。

在控制台的NACL页面,找到入站规则标签页,创建VPC的时候,会默认创建一个NACL,同时会默认创建入站规则和出站规则,规则列是数字和*号,这列表示的是规则的优先级别,数值越小的优先。比如创建一个规则#为80的ssh,源为0.0.0.0/0,deny的规则,此时ssh就连不上了。再同样创建一个优先级为70,但是allow的规则,就可以连上了。因为优先匹配70这条规则。

Subnets

是网络的一个subsection,通常来说,一个subnet包括一个特定区域内的所有计算机。想象之前ISP的类比,ISP是一个网络,而你的家庭网络就可以看作是一个subnet,不过这个比喻没有那么好。

subnet有public和private两种,通常来说public subnet里面一般放ec2,private subnet里放RDS,public有连通到外网的route,但是private只能和其他subnet通信。所以,事实上的private subnet也就是route table里没有配置去往外网的路由,即没有给他配IGW,没有IGW,当然就去不了外网。通过这种方式使他只能和本地的其他subnet交流。

Availability Zones

之前也提到,aws的全球基础设施,有多个Region,Region下有多个Availability Zone,每个Zone下有物理意义上的数据中心。当你创建一个VPC的时候,会自动在多个Availability Zone下创建subnet,这样就可以把数据放在多个zone下,使得即使一个zone挂了,其他的可以继续提供服务

EC2

概念上来说,ec2就是一台在aws上计算机。对比一下通常意义上的计算机的话,cpu对应实例类型(instance type),硬盘对应EBS,网卡对应IP Addressing,这是一个虚拟的网络适配器,他能使我们访问VPC中的网络,防火墙对应安全组,内存对应RAM。

Amazon Machine Images (AMIs)

AMIs是预先配置好了一些用于启动一个ec2实例的包,包括操作系统,一些软件包,以及一些设置。嗯,镜像嘛。

AMI分为社区AMI,AWS Marketplace,自己的AMI。

社区AMI就是基本没有附带其他软件的,你可以自己手动安装你要的。

AWS Marketplace是镜像市场,有一些厂家卖他们做的AMI。

Elastic Block Store(EBS)

ec2的一种存储卷,高度可用,可靠的存储卷。在同一个Zone下,可以被attach到任何正在运行的实例上。

IOPS:input/output Operations per Second。EBS的一个性能指标。

每个ec2实例都会有一个根存储卷,这个卷可能是EBS,也可能不是。创建实例选择卷的时候,有个Delete on Termination的选项,勾上就表示,如果以后把这个ec2干掉了,那么这个卷也会同时被干掉,不勾就会保留下来,处于一个没有被attach到任何实例上的状态。

根卷之外新建的卷可以很方便的从这个ec2上detach掉,然后attach到另一台ec2上。

Security Group

安全组很像之前VPC中的NACLs,用来控制进出流量,只是安全组是实例层级的,而不是subnet层级的。aws把安全组定义为虚拟防火墙。

NACLs有deny的选项,安全组没有,没有配置流量会默认deny掉。NACL有那个优先级的数字,而安全组没有。

img

ELB负责负载均衡,控制进来的流量要交给哪个实例,如果两个实例的安全组配置不一样,比如一个允许80端口,一个不允许,那么当ELB将该流量分配给那个不允许的端口的时候,就会返回一个错误。所以NACL和安全的规则配置是很重要的。

另一个和NACL不同的是,安全组是stateful的。意思就是,任何被允许的流量进来后,即时没有匹配任何出站规则,也是默认可以让他出去的。而NACL是stateless的,如果没有匹配一个出站规则,那么该流量就会被deny掉。

IP Addressing

简单来说,它负责为你的ec2提供一个public IP address,使其能够和互联网进行交流,如果没有这个ip地址,那么ec2是不能和VPC外面的世界交流的。简单来说,ip地址就是网络上一个实例的地址。

默认每个实例会有public和private IP地址,私有地址让你的ec2可以和其他实例交流,只要他们在同一个VPC,或者broader private network。

img

如果你的实例连不上网了,那么上图这些实例的配置都需要好好检查。

ECS

ecs服务器可以跨zone运行。ecs有两两种模式:Fargate模式和ec2模式,他们有不同的网络接口。

Fargate

任务都是通过Fargate来启动,Fargate是ecs的一个计算引擎,让用户不用监控cluster就可以启动容器。 ecs是一个管理容器的服务。

这里说的任务(task)有两个组件:ecs容器实例,容器代理?(container agent)。

ecs容器实例是运行了ecs容器代理的aws ec2实例的一部分。

容器代理负责ecs和实例的交流,同时也提供正在运行的容器的状态。平时一般不需要去折腾容器代理,不需要什么配置,他就自己运行自己的。

Elastic network interface,是一个虚拟接口网络,用来连接实例,容器与容器之间的交互,容器与ec2的交互,容器与外面的互联网的交互。

Amazon ECS cluster,ecs实例集群

ECR

configure

aws configure

https://docs.aws.amazon.com/zh_cn/cli/latest/userguide/cli-configure-quickstart.html#cli-configure-quickstart-format

login

// cli v2
// log in to ECR
aws ecr get-login-password \
    --region <region> \
| docker login \
    --username AWS \
    --password-stdin <aws_account_id>.dkr.ecr.<region>.amazonaws.com

docker push <ECR_URL>/repository_name:tag

填上<region>和最后的其实是ecr仓库地址,成功的话可以看到Login Succeeded

push

docker

docker push <ECR_URL>/repository_name:tag

docker-compose

docker-compose push

如果是docker-compose的话,就得在docker-compose.yml里加上image,比如:

version: '3'
services:
  server:
    image: <ECR_URL>

set network

不想要容器在能公开访问的网络里跑,通常都是通过负载均衡器来访问。

  • 创建vpc。IPv4 CIDR填上比如10.0.0.0/16

  • 创建subnet。在刚创建的vpc上创建4个subnet,指定两个为public subnet,用来跑负载均衡器,两个为private subnet,用来跑我们的task。

    • 创建public subnet

      VPC ID选择刚创建的那个,然后 IPv4 CIDR 块 填比如10.0.1.0/24,区域选择xxx.a

      创建第二个,10.0.2.0/24,xxx.b

    • 创建private subnet

      第一个,10.0.3.0/24,xxx.a

      第二个,10.0.4.0/24,xxx.b

  • attach internet gateway。为了使我们的public subnet真的成为public。

    在互联网网关那里创建一个vpc,填个名字,然后attach到刚创建的vpc

  • create route table

    • 创建public route table

      填好刚才的vpc,点击创建。然后再路由表列表页面选中刚创建的路由表,选择下面的编辑路由-->添加路由:0.0.0.0/0目标选择刚创建的igw。创建完了后需要关联到子网。

      子网关联--->编辑子网关联--->选中刚创建的两个public subnet---> save

    • 创建private route table

      这个不需要获取互联网,因此不用添加添加规则,创建完了后需要关联到子网。

      子网关联--->编辑子网关联--->选中刚创建的两个private subnet---> save

网络设置就到这为止,接下来会将负载均衡放在public subnet中,容器任务放在private中

set cluster

ecs页面创建cluster,选择默认那个fargate的,勾上创建VPC选项,就用他默认的配置,然后点创建。

选择侧边栏的任务定义---->fargate。任务角色这里,如果该应用要访问aws的其他服务那么就要配置,不需要则不要配置,这里选择不配置。

任务执行角色选择创建新角色。任务内存1GB,任务CPU 0.5vCPU。

添加容器,镜像填上刚push到ecr的image url,然后填上映射端口。然后点击最下面的创建来完成创建。

回到cluster页面,到之前创建的cluster里面,这个时候还没有任何服务的。选择创建(服务),启动类型fargate,任务定义选择刚创建的那个任务,任务数2,其他的默认,然后下一步。

集群 VPC选择之前创建的VPC,子网选择之前的两个private子网,安全组点编辑,会看到默认80端口对任何源开放,但是这里应该是要填负载均衡器的,由于还没创建,所以之后来填。

负载均衡器类型选择Application Load Balancer,上面的运行状况检查宽限期填个30,下面提示找不到负载均衡器的话就点击他提供的连接创建一个,选择Application Load Balancer,然后因为是要把80端口供外界访问的,所以可用区选择对应的VPC,然后子网那里都选刚才的两个public subnet,下一步,会弹一个警告,不用管,下一步,安全组创建一个新的,填好名称,然后类型选http,源是那几个0那种,表示对所有的开放,下一步,配置路由,这里必须要选择IP,因为我们在ECS中创建的service会从我们的VPC中创建任务,所以他会使用private subnet中特定的ip地址,并且会分配这些ip地址给task或者container,所以我们的ALB应该要分发流量到这些ip地址。下一步注册目标,这里不去指定ip,让他自动去分配,然后创建。

回到创建集群服务的页面,刷新负载均衡器名称,就能看到刚创建的alb,添加容器到负载均衡,填写target group为刚创建的,取消勾选service discovery,然后两个下一步,直到创建。

这个时候能能在我们的集群里看到有一个服务,且有两个任务,但是是pending,等了很久最后stopped了,这是因为在dockerfile里有npm install的操作,而这个操作是要访问互联网的,但是task却是放在private里面了,无法访问外界。(这里有点没想通,push上去的不是已经都装好了的麽,跟dockerfile有什么关系???)

这个时候到vpc里的NAT网关里,要选一个子网,因为这个nat是要访问外网的,因此选择一个public的,点击分配弹性ip,创建网关。

用 VPC 筛选那里选择我们的VPC,然后点击路由表,选择private的,编辑路由,添加一个0.0.0.0/0,目标选择NAT,找到刚创建的NAT,创建。(NAT是要钱的!!!我靠)

这个时候回到ecs界面,可能等一会而,就能看到任务已经是running状态了。

接下来还要做另一件事,我们之前已经分配了一个安全组给这个service,所以我们要确保这个安全组的进站规则包含了attach到elb的安全组。

到服务页面点更新,直接下一步,到网络配置的页面,新标签打开安全组的链接,可以看到这个安全组的进站是允许所有的源的,这里要去限制到只能通过elb来访问。

到ec2的页面,找到负载均衡器那里,找到我们的负载均衡器,打开他的安全组,可以看到是允许所有进站的,要做的就是我们只允许这个elb访问我们的任务,复制elb的安全组id,回到service的安全组页面,编辑规则,选择all tcp(所有TCP),将elb的安全组id粘贴到源那里,保存。

回到elb页面,侦听器,可以看到正在转发什么的,也就是说所有从这里80端口进来的流量都会被转发到这个目标组,

CodePipeline

在build阶段出现如下错误

authorization failed for primary source and source version

https://stackoverflow.com/questions/64300151/aws-build-failed-client-error-authorization-failed-for-primary-source-and-sourc

是有个什么connection permission要添加,按照这个文档的Add CodeBuild GitClone permissions for connections to Bitbucket, GitHub, or GitHub Enterprise Server做就能跑过去。

然后又出现了

An error occurred (AccessDeniedException) when calling the GetAuthorizationToken operation: User: 

直接给codebuild的role加了个AmazonEC2ContainerRegistryFullAccess权限,又过了。

然后又出现了

error pulling image configuration: toomanyrequests: Too Many Requests. Please see https://docs.docker.com/docker-hub/download-rate-limit/

确定显然没有用完他的限制,然后查了下这两个链接,解决了,用的那个kms的方法:

https://medium.com/rockedscience/fixing-docker-hub-rate-limiting-errors-in-ci-cd-pipelines-ea3c80017acb

https://dev.classmethod.jp/articles/codebuild-has-to-use-dockerhub-login-to-avoid-ip-gacha/

build是通过了,然后buildspec里记得加下面代码,参考https://stackoverflow.com/questions/48955491/codepipeline-insufficient-permissions-unable-to-access-the-artifact-with-amazon

post_build:
    commands:
      - printf '[{"name":"your.task.definition.name","imageUri":"%s"}]' $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG > imagedefinitions.json

artifacts:
    files: imagedefinitions.json

这样deploy没出错,但是一直卡着没成功,没有办法,我把之前的两个private subnet的路由加上了0000的那玩意,抱着试一试的心态,诶,居然成功了。

Simple Notification Service(SNS)

可以基于你aws发生了什么事件来发送邮件或者短信来提醒你。比如支付,你设置了一个限度,如果超过这个值,通过邮件或者短信给你发送一条提醒。

在aws有两种client,发布者和订阅者,或者说是生产者和消费者。大致的流程是,设定一个topic,发布者针对这个topic发布消息,然后订阅者订阅这个topic,收到提醒,并作出处理。

Cloud Watch

能监控各种aws元素的一种服务,比如ec2,rds,s3等。基于这些元素发生的事件,通过cloud watch来触发警报或者发送提醒给我们,或者通过定义的一些规则来自动做出处理。

CloudTrail:用来监控动作,比如有人停掉或者删除ec2,可以追踪到是谁干的。用这玩意要注意下费用。

ELB(Elasic Load Balance)

将流量平均的分配给ec2,同时也能检查不健康的ec2。

Create ELB

创建ELB的时候,有三个可以选,有个Classic Load Balancer,是以前的老的,给个灰色的,说明亚马逊真的不推荐你用那个。

ELB负责将流量发给目标,因此在创建ELB的时候选择target,本质上是说的EC2。ELB会对Target Group中的实例进行一个健康检查。健康检查要填一个协议和路径,拿web服务器来说,访问一个路径就返回一个页面,如果没有返回一个页面,那说明这个实例可能是不健康的了。

Auto Scaling

Load Balance是可以平均分配EC2的能力,确保没有ec2过载。Scalability是有能力去增加ec2。可以通过改变实例类型和更大的处理器,更大的内存,更大的网络吞吐量,或者增加更多的实例来处理工作量。

Launch Configuration:当auto scaling要增加服务器到Auto Scaling Group时的EC2模板。

Auto Scaling Group:拥有所有当要自动增加或者删除服务器时的规则。

Route53

route53是你配置管理托管在aws上的网站的域名的地方。route53执行三个主要的功能。

  • 域名注册。

域名和DNS是如何用户可以访问网站的?

当用户在浏览器打上网址的时候,浏览器不知道该网站服务器在互联网上的位置,所以电脑需要去解决这个问题,但是电脑也不知道,只能去请求DNS服务器,他上面有域名和对应ip。

我们去Route53注册域名,它将为托管该域名内容的主机提供域名和ip地址(到DNS服务器?)。然后用户电脑通过dns拿到ip地址。可以用Route53作为registrar(注册商?)和DNS service,或者把Route53作为DNS service,但是使用其他的注册商。

访问网站是先通过Route53的,但是本质上是加载的ELB,ELB页面会有个DNS地址。

CloudFront

在世界范围内复制数据和应用来减少延迟,使访问更快。本质上是通过将数据复制到世界各地的edge location,如果用户想要访问的数据已经在edge location了,那么就可以马上访问到,如果不存在,则去源头找到数据复制过来,实际上就是一种缓存。

CDK

Constructs

有两种类型:Hight level constructs和Low level constructs

Hight level constructs:为底层aws资源提供一个抽象层(provides an abstraction layer for underlying aws resources),他们还处理CloudFormation资源所需的大部分繁重工作和逻辑(they also handle most of the heavy lifting and the logic required by CloudFormation resources),所以大多数时间都使用到这种。

Low level constructs:就是那些直接调用CloudFormation资源的东西,所有的这类东西都会以Cfn关键字开头。

img

Prepare

aws account setup

IAM增加一个用户比如cdkadmin,勾选编程访问,然后给个AdministratorAccess权限。成功后下载csv文件

然后开始本地配置用户

aws configure --profile cdkdemo

填写csv中的Access key ID和Secret access key。

aws sts get-caller-identity --profile cdkdemo

能看到刚配置的用户信息。

Installation

npm install -g aws-cdk
cdk --version

Setup CDK Project

具体参见:https://cdkworkshop.com/20-typescript/20-create-project/100-cdk-init.html

cdk init sample-app --language typescript

cdk.json:context,告诉aws如何启动你的stack(不是你的应用)