Jex’s Note

AWS 各項服務

(最後更新: 2016-04-27)

介紹

AWS (Amazon Web Services) 是針對主機或 App 提供整套 solution 的雲端服務

Region & AZ

  • region 是 Data Center 的集合
  • AZ 與 AZ 至少隔70公里以上
  • AZ 與 AZ 是用光纖連接
  • AZ 裡有很多 DC
  • 每個 DC 是 25Tbps
  • 同一 region 我的帳號的 eu-west-1a 跟你的帳號的 eu-west-1a 不一定是同一個 AZ, 避免太多人選擇同一 AZ

IAM

  • 如果有很多開發者要共用一個 AWS 帳號, 這算是必用的服務
  • 可以針對不同開發者給與不同權限
  • 一般來說程式透過 Access key & Secret Key 調用 AWS API 是要寫在程式裡的, 但會遇到 Credentials embedded in code問題, 如果 push 到 public 的 github 就有資安風險, 也可以改成在 ec2 裡(環境)設定 secret key 較安全 (aws command)
  • 角色可分 3 種 :
    • user : 可以讓多個開發者共用同一個 AWS, 每個人可以有不同的登入帳密及權限
    • group : 可以設定權限, 再把要執行這些權限的 user 圈到這個 group 裡
    • role : 這是給 ec2 執行的權限, 開 ec2 時 IAM role 選這個, 而此 ec2 就有權限執行開放的服務

[操作] 增加一個登入帳號給團隊的成員

Users -> Create Users -> 輸入 user name -> copy Access Key ID 及 Secret Access Key (目前還不會用到) -> 回到 Users 列表就會看到剛剛新加的 user

但加完帳號其實還沒有密碼 : Has Password: No, 所以在那 User 下面選擇 Manage Password 可以手動指定一組密碼給它

接著他只要到 IAM users sign-in link 輸入他的 user name 及 password, 就可以登入了

Route 53

DNS 服務, 使用上很直覺簡單. 一個 domain 可以對應多個 ip (可以填 TW 及 US IP)

[操作]

Create Hosted Zone

輸入 Domain Name 後, 會新增一筆 Zone (EX: qq.test.com), 然候進入 Zone 裡面

AWS 預設裡面會有兩筆 Record

自己再新增每一筆 Sub domain record :

s1.qq.test.com   A   55.123.122.33

如果上例設定的 Zone 也是主站的 sub domain, 必須在去主要的 domain 設定

首先先去 qq.test.com 這個 Zone copy NS 那筆 Record 的 Value, 再到 test.com 新增一筆 Record

qq.test.com    NS    (將剛 copy 的 ns value 貼到這的 value field)
  • A : 將 domain 指向 address
  • NS : 將 domain 指向 Name Server

一個 domain 對全球,讓 route 53 自動幫我們把 user 的 region 導到對應的 region 的 elb

1) 先設定 domain 對應到 ELB 的 endpoint

2) domain 右邊設定 Routing Policy 選擇 lantency, Set ID 隨便打,它們就對應好關係了

3) user 連上來會根據 latency 指派到最近 region 的 elb

Internal domain

如果建立 mysql 要使用 interntal domain e.g. mysql.xxx.local 指到那台 endpoint 要記得將它的 VPC 的 hostnames 打開,否則不會通

不知道有沒有打開可以到 VPC 那個網段可以下面是否顯示 DNS hostnames: yes

VPC

  • 切割 sub-net
  • 與 AZ 是沒關係的, 而是用 IP 去指定 AZ
  • (? 不太懂, 不太確定) 它的 group 是 stateless, 而 EC2 的 security group 是 stateful 的, EC2 的防火牆 ACL 進或出其中一個有通就行了, VPC 是進出都要通才行
  • Route 可指定 instance (作 NAT), IGW, VGW (外部儲存 data center)
  • 預設的 VPC 不要刪掉, 否則之後要建立 CloudFormation 會有問題而無法建立

[備註]

  • EIP = Elastic IP
  • NET ACL = NET Access Control List
  • IGW = Internet Gateway
  • ENI = Elastic Network Interfaces

[操作步驟]

1) Your VPCs : 建立一個 VPC, CIDR block 為 10.0.0.0/16
2) Subnets : 實務上可以依這樣分類去切, 這樣對之後設定 security group 比較方便
10.0.1.0/24     : base
10.0.11.0/24    : api-zone-a
10.0.12.0/24    : api-zone-b
10.0.21.0/24    : db-zone-a
10.0.22.0/24    : db-zone-b

能不能對外可以再以 security group 去個別設定某個網段(i.e. 10.0.11.0/24)要不要對外

3) Internet Gateways : 建立一個可以讓外部連進來的 Gateway, 再 attach 到 vpc
4) Route Tables : 建立兩個 Route Table

建立好的 VPC 的 Routes (在畫面下面) 新增 0.0.0.0/0 指向步驟 3 建立的 internet gateway.

Subnet Associations 指向步驟2建立的 subnet

注意! 要連到外面 Routes 一定要將 0.0.0.0/0 指向 internet gateway, 並且 Security Groups 的 SSH Source 也要記得設定成 0.0.0.0/0

5) Security Groups

Inbound :

TYPE            Port    Source
==================================
ALL Traffic     ALL     10.0.0.0/16
SSH             22      0.0.0.0/0
HTTP            80      0.0.0.0/0
HTTPS           443     0.0.0.0/0
ALL ICMP        ALL     0.0.0.0/0           # ping
6) EC2

Security Group 選擇步驟5建立的 Private Group

Public :

Network : 選擇剛建立的 VPC
Subnet : 選擇 Public subnet
Auto-assign Public IP : Enabled

Private :

Network : 選擇建立的 VPC
Subnet : 選擇 Private subnet
Auto-assign Public IP : Use subnet setting (Disable)   => 就算 Enabled 也沒有用, 因為外部無法 Access 到裡面

總結

EC2 主要是看 Security Group, 但 EC2 是掛在 VPC 的 Subnet 裡面, 每個 Subnet 又有他自己的 Route, 所以如果要對外的話

Route 要先設定成對外(加上 internet gateway), 而 EC2 的 Security Group 設定允許外面連進來的的防火牆 rule 才有意義

[VPC connect another vpc in the same region]

VPC 下的 Peering Connections

[VPC cross region, 需透過 VPN 達成]
  • 不同 region 的 VPN 就要其中一邊有一個 EC2 連到另一個 region 的 VGW (只需一台 EC2 即可)
  • Connect Multiple VPCs with EC2 Instances (IPSec or SSL)
  • 在 VPC 主頁(不是 sidebar)下面就有個 Create VPN Connection, 必須要先建立 Private Gateway 才可以建立 VPN
  • 或者用兩個 EIP 的 EC2 用 VPN 軟體將兩個 VPC 連起來

EC2

  • 就像是一台 VPS 主機讓你使用, 不支援 IPv6, 裡面絕對不會有 AWS 程式跑在裡面 (阿里雲好像會)
  • 要注意的是在主機裡面設 iptables 是沒有用的, 必須在 console -> EC2 -> Security group 設定才算生效
  • Design for failure : 務必將兩台EC2放在不同AZ, 避免兩台 EC2 在同一個 AZ 又剛好在同一台物理機上
  • 比較要注意的是 public ip 要不要打開, 建議都要開啟, 否則 apt-get update 都會連不出去

申請固定IP

Elastic IPs -> Allocate New Address

[備註]

  • Create Image : 將指定的 EC2 打成映像檔, 會被存在 AMIs 裡, 需要啟動一樣的 EC2 直接 Launch 就行了
  • Snapshots : EC2 輩份機制存放的地方, 是 server 當前的狀況, 如果要 Launch 要先 Create Image, 再到 AMIs 那 Launch
  • Meta data : dns ip, public ip 等等設定
  • User data : 要執行的 script, 不要用 windows 因為換行字元關係, 所以 EC2 執行會失敗. 最多 16k 字節, 但可以用 wget 來解決此限制

IPv4 and IPv6

IPv6 was supported on “EC2 Classic” but not on EC2 VPC. And EC2 Classic is no longer available for new AWS accounts. Also, EC2 Classic is deprecated and should not be used, all new accounts use VPC.

Update (Sept 2016): IPv6 is now supported for Elastic Load Balancer end points. Internally in the VPC, IPv4 is still used, but it’s now possible to provide an IPv6 endpoint for public web sites (important for Apple devices!)

流量價錢

  • 在 aws services 與 ec2 之間傳輸是不需要算錢的
  • 資料傳輸到 ec2 裡面是不用錢的, 傳出才要收錢 (比較低等級的 ec 為 15 G/month)
  • 可使用 aws 算費用的工具來算 (http://calculator.s3.amazonaws.com/index.html)

t2 CPU Credit

CPU Credit 保持的越高, query 處理的效率會越好, 反之如果 credit 用完了, 它的處理效率就差

如果 cpu 保持低於基礎線以下的話, credit 是會加回來的, 直到加到上限

可以參考官方的連結

CPU Credit usage 如果是 1 的話代表要升級機器了

以 t2.small 為例, credit 基礎線為 CPU utilization 20%, 以上的話會扣 credit, 以下的話會加回來

新開的 ec2 e.g. t2.small 開啟動它的 CPU CreditBalance 是從 0 開始, 而不是 288 (updated on 2018-06-28)

另外建議在 production 不要用 t 系列, 除非是成本考量

因為 CPU Credit Balance 很容易被漏看, 且也需要了解它的規則

對 CPU Credit Balance 做監控比對 CPU Utilization 設重要多了, 因為當 Credit Balance 用完之後, CPU 才會開始衝高, 而且 EC2 CPU 裡面充到 100% 但外面的 CPU Utilization 卻只會顯示只有 20~30%,

而且 EC2 CPU 裡面充到 100% 但外面的 CPU Utilization 卻只會顯示只有 20~30%, 因為主要的 CPU 使用被外面掐住了

ELB / ALB

ELB

Load balance 服務, 可以將多台主機放在 Load balance 下, 做隨機或權重分配, 減輕單一 server 負擔

可以設定接 HTTPS 內部再導向 HTTP, 內部都是走 VPC 的網段

設定完大概15分鐘 ELB 的 DNS 才會通

將 ELB 的 domain 貼在 route53 record 新增的 CNAME item 裡

ELB 有內建 graceful shutdown,當把它移除掉,它會先停接新的 request,等到目前的 request 結束才移除

ALB

需要先設 Target Groups 主要是 port -> EC2 instance

再到 ELB 選擇 application type (一般的 ELB 是 classic) 然候再選擇 url path 對應到哪個 target group

注意:

  • ALB 有自已的 security group ,在 Load Balancers 的 ALB 右鍵 -> Description -> 可以看 e.g. 開放 80 / 443 port 0.0.0.0/0
  • ALB 設定 EC2 的 health check 的連結要在那個 Target Groups 上面右鍵-> Path e.g. /ok.html, EC2 的 security group 要記得設定 80 Port 10.0.0.0/16 讓 alb 可以打進來

SSL

如果在 godaddy 買 domain,用 CNAME 連到這個 ELB 的 dns CNAME,然候再把 godaddy 的憑證上傳到 ELB,然候就 OK 了,

  • private key : 轉過的 .key
  • public key certificate : .crt
  • chain 貼上 openssl x509 -inform PEM -in GC_bundle_SHA2.crt 的結果 (bundle 是 伺服器 SSL 憑證 + 中繼憑證)

Auto Scaling

  • 可以針對網站設定 Policy, 當主機到達某個條件增/減機器 (EC2), 需搭配使用 ELB

[操作]

  1. 一開始要先建立 Launch Configurations (要吃哪個 AMI ID 等等) 才能設定 Auto Scaling Groups (自動調整 size 的 Policy)
  2. 一旦建立好的 Launch Configuration 就不能改 AMI ID 了, 所以主機更新後除了重新打一個新的 Image, 再點原本的 Launch Configuration 複製建立新的並且選擇新的 AMI ID, 再到 Auto Scaling 的 config 選擇新的 Launch Configuration.
  3. 如果要一次對兩個 AZ 輪流新增 instance 的話在選擇 Subnet 時就要選擇兩個 AZ 所屬的 Subnet
  4. IP Address Type 要選擇 Assign a public IP address to every instance. 否則預設不會配 public ip, 但 ELB 走 LAN 還是可以讓此 API 對外開放, 只是如果要更新系統或抓新 code 就會受限無法 access internet
  5. 新啟動的 instance 大約在 1 分鐘內可以上線服務, (讓 CPU% 上升到 100% 的測試指令 : while true; do echo; done)

註: 如果要在機器啟動時執行一些 shell 指令, 可以在 Launch Configuration 的 User data 的 type 選擇 file, 內容 :

#!/bin/sh
echo "qq white into dd" > /tmp/dd

那麼機器啟動時就會執行這份檔案的指令了

[Autoscaling with custom metrics]

1) Put metric data

可以直接在程式引用別人寫好的套件, 直接透過程式做或使用 command line

2) 到 cloudWatch 確認 metric 是否上傳成功 (Metrics 搜尋 JobCount 看是否存在)

成功後寫一個會定時回報 metric 的 script 或程式, 讓 Auto-Scaling 把 AMI 啟動成 EC2 可以自動執行

3) Create Alarm (Action 是當超過設定值要做什麼事, 例如寄信等等的, 可以不用), 目的是為了讓 Auto-Scaling 的判斷機制可以選擇這個 metric

建兩個 Alarm 一個是 JobCount>=100 另一個是 JobCount <=10

4) 將 EC2 打成 Image

5) 建立 Auto Scaling configuration 及 group, 並持續 put-metric-data 測試是否 scale 成功

CloudWatch

監控 EC2 的狀態 (CPU usage, Network I/O ,etc..)

[備註]

預設默認一些 cpu 使用, io 等資訊

但不包括 ram 使用, 因為 AWS 是與 Hight provider 拿取使用狀況, 如果要拿到 ram 使用率勢必要放 agent 在 ec2, 而 aws 沒有做這件事

如果 launch 一個 instance 沒有打開 monitor, 預設的 CloudWatch 會紀錄

  • CPUUtilization
  • DiskReadBytes
  • DiskReadOps
  • DiskWriteBytes
  • DiskWriteOps
  • NetworkIn
  • NetworkOut

打開後會多紀錄

  • CPUCreditUsage
  • CPUCreditBalance
  • SatatusCheckFailed
  • StatusCheckFailed_Instance
  • StatusCheckFailed_System

[Put custom metric (command line)]

1) 安裝 AWS CLI tool

2) EC2 要有權限, 打開 put metric data 給 cloudWatch 的權限有兩種方法

Note: 不需要在 AWS Console 建立一個新的 metric,當你報上來的時候如果是新的 metric name,CloudWatch 會自動新增

第一種是建立 User 並給予對應權限, 再到 EC2 上設定 Access 及 Secret
  1. 到 AWS Console 的 IAM : 新增或選擇舊有的 User, 新增 Policy : AWS Service Roles -> Amazon EC2 (Select) -> cloudWatch 全部權限
  2. 再到主機裡設定 AWS config
1
2
3
4
5
aws configure
AWS Access Key ID [None]: A******************Q
AWS Secret Access Key [None]: 9**************************************O
Default region name [None]: us-west-2   (Oregon 是 us-west-2)
Default output format [None]:text
第二種是建立 Role 然候在起 EC2 的時候指定 Role

(?) 先不要用 role 來做 put-metric-data, 不知道為什麼, 就是會一直噴錯誤

一開始以為到 AWS Console 的 IAM : Create Role -> Role Type 選擇 Amazon EC2 -> CloudWatch Full Access -> Create Role

然候再選擇這個 role 建立 EC2 權限是可以的, 但卻會噴出 A client error (InvalidClientTokenId) occurred when calling the PutMetricData operation: The security token included in the request is invalid. 這樣的錯誤

註 : 目前這個 Role 只能給你目前帳號使用, 假如你跟別人共同開發, IAM 建立多個 User 並且每個人使用不同的 User 登入 AWS Console, 那麼其他人建 EC2 是看不到這個 Role 的, 解決辦法是在其他人的 User 或 Group 增加 Policy 打開 AWS Data Pipeline Full Access, 這樣其他人在建立 EC2 就可以看到 IAM Role 了

再到主機裡設定 AWS config

$ aws configure
AWS Access Key ID [None]: (留空 直接 enter)
AWS Secret Access Key [None]: (留空 直接 enter)
Default region name [None]: us-west-2
Default output format [None]:text

3) 測試 put metric data

aws cloudwatch put-metric-data --namespace "Job worker metrics" --metric-name JobCount --unit "Count" --dimensions "AutoScalingGroupName=myAutoScalingGroup" --value 23

如果沒有其他的訊息代表上傳成功

常收到 State is OK 的通知 OK: "API CPU >= 70%", 但狀態都沒有變成 alarm

這是因為 cloudwatch 沒有收到足夠的資料所以 Alarm updated from OK to INSUFFICIENT_DATA

這時只要修改這個設定將 Treat missing data as: ignore (maintain the alarm state) 就行了,

它就不會在服務正常的時候還報 OK, 只有在 Alarm -> OK 才會收到

EBS

  • SSD 硬碟, EC2 透過 Network I/O 掛載進來
  • 我曾聽一個 AWS 講師說 : AWS 對硬碟的觀念是不管再好的硬碟都有壞的一天, 與其買很好的硬碟不如把備援系統做到最好, 所以他們不怕硬碟常常壞, 反而專注在備援上, 蠻特別的
  • 硬碟直的進到 AWS 但碎的出來, 不讓有心人士還原資料
  • 注意!!! EBS vs Instance Storage

IS 是跟 EC2 同一台機器上; EBS 是在雲上的硬碟.

如果 EC2 stop 再 start, 而 EC2 會換一台機器上, 所以 IS 就無法使用了, 但 EBS 則不受限制

IS 不收錢, 提供比 EBS 更高的 io/ps 因為沒有網路

一開始選擇 OS 時會標示他預設是使用 IS 還是 EBS, 但幾乎都是 EBS, 除非是在 AMI markets 就會看到有些是 IS 的

Glacier

存的資料不常使用, 能接受 3~5 小時的取回時間, 成本只有 s3 的 1/10, EX: 常用來封存 log 等等之類的久放但沒事不會拿出來的資料

RDS

  • 勾選 multi-AZ 會在另一個 AZ 做 slave, 當 master 斷了會將 slave 轉成 master, 而 master 大約會在 5 分鐘恢復
  • 快照 DB schema 或輩份
  • 可以 replica 到另一個 region (做全球 deploy 會需要)
  • memory 到紅色線沒關係 (from 官方)
  • RDS upgrade 一定會有 downtime
  • Security Group 一定要選 MySQL/Aurora, 選 All traffic 不會開到 3306
  • reboot 約需花 6 秒 (按下重啟後前30秒能連, 30秒後突然不能連, 然後6秒後恢復)
  • upgrade / degrade 需花約 70 秒左右 (按下升級後前5分鐘都還能連, 5分鐘後突然不能連, 然後70秒後恢復)

[操作]

1) 建立好 VPC
  1. RDS 預設不是 public, 如果要對外, 在建立 instance 時 Publicly Accessible 要選擇 yes
  2. 也可以使用自定義的 VPC, 先分好網段, 一個對內一個對外

如果勾選 Publicly Accessible 則 VPC 要將 DNS resolution 及 hostnames 打開

2) 先建立 Subnet GRoups
  1. 點擊 Create DB Subnet Group,
  2. 然候選擇 VPC ID 及 VPC 的 public 的 subnet,
  3. Subnet Group 規定 Subnet 要設定可以通兩個 AZ, 所以 VPC 的 Subnet 要有兩組不同的網段對應到不同的 AZ
3) 建立 Security Group, 讓 RDS 可以對外
  • Port : 3306
  • Source : 0.0.0.0/0
4) 建立 RDS MySQL, 並且選擇 Public 的 Subnet, 及 Secruity Group
  • 如果要對外 Publicly Accessible 要選擇 yes,
  • RDS 也要放在可以對外的 Public Subnet, 最外層的防火牆還需要讓 3306 port 可以接收外界

[主 DB 在美西, 其他 region 要 update DB 問題 (全球 DB 佈署問題)]

因為需要考慮到 Auto Scaling 的問題, 新的主機會不知道 IP, 所以無法先設定在 Security Group

有四種方法解決 :

1) singapore 用 mysql 內建的 SSL 連到美西的 DB master, 然候再 call 美西那邊的 security group API 新增讓此 IP 通過的 rule

比較麻煩, 不是個很好的方法

2) 用 VPN IPSec 將兩個 region 的 VPC Subnet 連在一起, 其通道本身就加密了, 所以可以直接通過 LAN 的方式更新

維護主機的成本提高

3) 在美西架一個 API server, 所有主機要更新 DB master 都透過此 API server, 並且用 https, 本身也是很安全的

幾乎不用花時間設定, 但需要花時間寫 API 接口

4) MySQL MMM 架構

需要擔心 DB 互相 sync 時引發的錯誤

結論 : 建議使用第 3 種方法, 可能 Update 速度稍慢, 但出錯的成本最少

RDS - MySQL

max_connection 不同 size 支援的 max_connections 量不同 :

t2.micro    66
t2.small    150
m3.medium   296
t2.medium   312
M3.large    609
t2.large    648
M4.large    648
M3.xlarge   1237
R3.large    1258
M4.xlarge   1320
M2.xlarge   1412
M3.2xlarge  2492
R3.xlarge   2540

從 snapshow 復原 DB

  1. DB Instance Identifier 是 AWS RDS 辨認的 ID, 只要不要重覆就好
  2. 記得取選 Security group
  3. 修改 Master password (也就是 DB admin 的 password)

如果要恢復整個 DB => 將程式 RDS endpoint 直接指向新的, 舊的再砍掉

如果要恢復每個 TABLE => 要先用 mysqldump 指令把那個 TABLE 匯出, 再到要復原的 DB TRUNCATE 那個 TABLE 後再匯入

Slow query

在 instance 下的 Parameter group, 點進去輸入 slow, 看 slow_query_log 有沒有打開

進入 mysql console 去 query mysql.slow_log

找出排名前 5 筆花最久時間的 query

SELECT * FROM slow_log ORDER BY query_time DESC LIMIT 5;

找出某天前 5 筆花最久時間的 query

SELECT * FROM slow_log WHERE start_time BETWEEN '2018-06-28 00:00:00' AND '2018-06-29 00:00:00' ORDER BY query_time DESC LIMIT 5;

Dynamo DB

  • No-sQSL, 性能保證, 使用 SSD, 請求可在 10 毫秒內完成, 也不會因資料量大而變慢
  • 無 DB 概念, 最多 256 個 TABLE
  • 資料是用 partition 機制, 盡量把資料分到各 node, ex: Key=a => Key=a1, a2, a3…
  • 避免 request 都戳到同一個 partition
  • 區域性服務(跨AZ), 雖然是提供一個DNS, 但服務是散佈在很多DC
  • 分散式儲存, 本身就會跨AZ並且複製3份

細節特性

  • 第一個欄位是 Key
  • Key 也可以用兩個欄位組合(composed key),但最多為 2 個
  • 在取資料的時候一定要由 Key 去取,不可以用其中一個欄位 = XXX 來取
  • 有像 Array 的型別,叫作 SS 表示為 { … }
  • 蠻特別的是你可以在 Update 過後傳回舊資料或更新後的資料,官方有定義幾種 type

Elastic Cache

  • Cache 服務
  • 支援 memcache 及 redis
  • 支援 Multi-AZ, 但不能 across region, 外部無法連進來, 即使 security group 允許 0.0.0.0/0, 也就是不支援從 internet 進入, 但可以透過一些 hack 方式例如 ssh 的 port forwarding 做到.

[操作]

先新增 Cache Subnet Groups, 把 VPC 的 Subnet 選進去

Security Group 要開 6379 port

CloudFront

  • CDN 服務
  • s3 如果要 https 的話需要使用 cloudfront
  • 可以指定到 bucket 下的 folder
  • 有支援 pre-signed url
  • 應用 : 在 A bucket 裡有 aa folder 需要 pre-signed url 才能下載, bb folder 不需要(公開下載)

cloudfront + s3 (with custom domain over SSL)

1) 建立

  • Origin Domain Name: (選擇 s3 bucket)
  • Origin Path: (如果要指定哪一個 folder 下才要填 e.g. /cover)

2) 送出後, 設定 route53 把 sub domain 指到這個 cloudfront 的 Domain Name

3) Edit Distribution -> General

  • Alternate Domain Names (CNAMEs): (輸入剛指過來的 sub domain)
  • 選擇 Custom SSL Certificate (example.com):
    • 如果都沒有的話, 要點 Request or Import a Certificate with ACM 新增, 可以透過 Request a certificateImport a certificate, 這裡我選擇前者; domain 要輸入兩個 domain example.com*.example.com, 然候再請這個 domain 的管理者到信箱 approval
    • 如果這個選項是 disabled 的話, 有可能是這個 distribution 的 status 是 In Progress, 因為只要修改過就會是 In Progress, 要等一陣子變成 Deployed 才會是 enabled

4) Edit Distribution -> Origin

  • Restrict Bucket Access: (Yes: 開放透過這個 domain 從外部可以 access 這個 bucket, No: 無法透過這個 domain 從外部 access)

5) 測試

  • 上傳圖片到 s3 bucket, 圖片的 Permissions -> Public access -> Read object 打勾
  • 看上傳的圖片是否可以 access, e.g. https://t1.example.com/test.jpg

pre-signed url + custom domain

  1. 將基本的 cloudfront custom domain 設定好
  2. 建立 cloudfront 專用的 key pair
    • 一定要用主帳號新增 (IAM users can’t create CloudFront key pair. You must log in using root credentials to create key pair.)
    • 右上角帳號選單 -> My Security Credentials -> CloudFront key pairs -> Create New Key Pair -> Download Private Key File (Pulblic Key File 可以先載但用不到) -> Copy Access Key ID (實際上只會用到 Private Key, 它只能載一次)
  3. 設定 Distribution 的 Origin
    • Restrict Bucket Access : Yes.
    • Your Identities : Use an Existing Identity (沒有的話就選 Create a New Identity)
    • Grant Read Permissions on Bucket : Yes, Update Bucket Policy (註1)
  4. 新增 S3 bucket + 放一個 test.jpg 測試是否可以通, (Permissions -> Public access -> Read object 打勾) e.g. https://example.com/test.jpg
  5. 禁止外部直接取得 s3 資源 CloudFront 的 Behavior 設定
    • Viewer Protocol Policy : HTTPS Only or Redirect HTTP to HTTPS
    • Restrict Viewer Access (Use Signed URLs or Signed Cookies) : Yes (允許可以用 signed URL or signed cookie access 檔案)
    • Trusted Signers : Self
  6. 已經禁止外部直接 e.g. https://example.com/test.jpg 就看不到東西了
  7. 將 private_key 上傳到主機並以各語言實作

註1 : 如果本身 bucket 有其他 policy 當你選擇 Yes, Update Bucket Policy 送出後,它會變回 No, I Will Update Permissions,實際上它已經更新 s3 bucket 的 policy 了

{
    "Version": "2008-10-17",
    "Id": "PolicyForCloudFrontPrivateContent",
    "Statement": [
        {
            "Sid": "1",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity E3D7VZ7WMEZSYS"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::test-bucket/*"
        }
    ]
}

ref :

清除 cache

目的: 如果 cloudfront 上的檔案還沒 expire, 你的靜態檔如果更新了, 但拉到也可能還會是舊的, 可以選擇手動將 cache 清掉

CloudFront Distributions -> (選 ID,點進去) -> Invalidations -> Create Invalidation -> 輸入要清除的 uri(也可以用 * 清掉全部) -> Invalidate

S3

  • For web (low latency)
  • 區域性服務 (跨AZ)
  • 適合存放靜態資料
  • 其實是有 region 的, S3 是存放在 AZ 的
  • 當上傳完一個檔案, 但回應成功背景會複製多份到其他 DC 或 AZ, 不會跨 region 複製, 但會在短時間內複製到其他
  • 最嚴重是發生在 us-standard, 不存在 aws 上, 是 s3 特有的, 與其他 region 是分開的 (最終一致性)
  • 資料永久, 唯一地址 (unique key)
  • 事件驅動, 上傳可以傳簡訊(SNS), SQS, Lambda function (圖片壓縮, 上傳檔案時 s3 call function, 自動壓圖)
  • version control, 每次 update 會記錄變動
  • 可透過 cloudFront 做 CDN, 只需要設定一下就好了
  • By default, all Amazon S3 resources are private, including buckets, objects, and related subresources.
  • 上傳不算流量
  • 預設一個 aws account 最多可以建立 100 bucket, 如果超過要聯絡 aws support
  • folder / 檔案 的數量都沒有上限

權限

要先了解 S3 有三種權限控制它

  1. Bucket policies : Attached to bucket
  2. ACLs : Grant access to specific AWS account or anonymous,可以各別定義 Grantee (一種身份) 可以對這個 bucket 做什麼事,預設是 root account 都可以
  3. IAM : Attached to user, json based ,讓你能不能進入 S3 的 WebUI,但實際上跟你有沒有權限用 API 的方式操作這個 Bucket 沒有關係

IAM 需要去 IAM 服務才能給予權限,而 Bucket policies 及 ACLs 可以在 S3 webUI 就可以選擇了

ACLs 只有一些 Group 讓你選 :

  • Authenticated Users – This should be an AWS account’s either email address or canonical user ID.
  • Everyone – For anonymous access
  • Log Delivery – This group is used if you enabled logging on your bucket.

Bucket policies :

  • List – Permission to view a list of the objects in the bucket.
  • Upload/Delete – Permission to upload and delete the object if the grantee is logged in
  • View Permissions – Permission to see the permissions for objects
  • Edit Permissions – Permission to edit the permissions for objects

AWS-SDK / AWS-CLI 上傳及下載 (必要設定)

如果發生沒有設定,在上傳時會發生 Access Denied

upload failed: ./test.txt to s3://buname_name/test.txt A client error (AccessDenied) occurred when calling the PutObject operation: Access Denied

剛建立的 Bucket 你一定要額外給予它被上傳的權限,否則無法透過 API 的方式上傳 (與 IAM Policy AmazonS3FullAccess 無關)

本以為新增 permission (Add more permissions) 就可以做到,但發現是不行的,所以要使用以下的方法去新增它的權限

Properties -> Permission -> Edit bucket policy -> 點選下面的 AWS Policy Generator 它可以幫你產生 Policy,但我們需要把表填一填

  1. Select Type of Policy : S3 Bucket Policy
  2. Effect : Allow (維持預設)
  3. Principal : arn:aws:iam::6**********4:user/app_server (其實就是 IAM 的某位 User 的 User ARN)
  4. AWS Service : Amazon S3 (維持預設)
  5. Actions : 選三個就好 DeleteObject GetObject PutObject
  6. Amazon Resource Name (ARN) : arn:aws:s3:::my-bucket/*

Generate Policy 後複製下來,再貼到 Edit bucket policy 那裡

{
    "Version": "2012-10-17",
    "Id": "Policy1461726945589",
    "Statement": [
        {
            "Sid": "Stmt1461726943472",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::624758352504:user/app_server"
            },
            "Action": [
                "s3:DeleteObject",
                "s3:GetObject",
                "s3:PutObject"
            ],
            "Resource": "arn:aws:s3:::my-bucket/*"
        },

        # 這邊是另外加上的, 讓外部可以直接 Access 檔案
        {
            "Sid": "Stmt1461734747651",
            "Action": [
                "s3:GetObject"
            ],
            "Effect": "Allow",
            "Resource": "arn:aws:s3:::my-bucket/*",
            "Principal": "*"
        }
    ]
}

然候應該就可以上傳,也可以下載了。

下載也是要使用上述的設定才可以設定公開,我試過在 Bucket 最頂層 Add more permission 設定 Grantee : Everyone, Action 只允許 List,但結果是沒有用的

ref : 關於 S3 權限

對這個 bucket 設定任何人都可以下載檔案

click {bucket_name} -> Properties -> Edit bucket policy

{
    "Version": "2008-10-17",
    "Id": "Policy1416798504862",
    "Statement": [
        {
            "Sid": "Stmt1416798496088",
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::{this_bucket_name}/*"
        }
    ]
}

AWS-CLI command 上傳到 s3

安裝 aws cli

sudo apt-get install awscli

上傳

$ aws configure
AWS Access Key ID :
AWS Secret Access Key :
region name : us-west-2                     # 可以在 S3 該 Bucket 的 URL 找到 i.e. ?region=ap-northeast-1#&bucket=
output format : none
$ echo "test" > test.txt
$ aws s3 cp test.txt s3://bucket_name/      # 將 bucket_name 替換為你的 bucket name
$ curl http://bucket_endpoint/test.txt
test

其他相關 cli 指令

aws s3 cp s3://another-bucket/file.txt s3://my-bucket/          # 從其他 bucket copy
aws s3 cp test.txt s3://my-bucket/                              # copy local file to my-bucket
aws s3 ls s3://my-bucket/                                       # my-bucket 下的檔案列表
aws s3 ls                                                       # bucket list

Delete folder

There is no such thing as folders in S3; There are simply files with slashes in the filenames.

Many S3 tools will visualize these slashes as folders, but they’re not real.

You can delete all files with the same prefix, but first you need to look them up with list_objects(), then you can batch delete them.

ref : https://forums.aws.amazon.com/message.jspa?messageID=249514

刪除所有檔案, 目錄也會自動消失

SQS

AWS SQS 是一套 Queue 的系統,儲存要處理的工作,通常都是一個 message 用 json encode 存進去,再來就是自已實作 worker 那一段再串 SQS。

  • 支援 across regions, 即使在特定 region 下建立的 Queue, 但是 URL 是公開的, 外部也可以做 enqueue
  • 在 Send (enqueu) 時可以指定 DelaySeconds (0~900秒),被新增進 Queue 後 delay 多久才可以被取出
  • 你無法在 Send 時又指定 visibility timeout, ref: delay seconds vs visibility timeout
  • 取出 message 後你可以指定 VisibilityTimeout 要多久 (它下次被看到的時間,最長可以到 12 小時)
  • 也可以在取完 message 後再針對這個 message 修改 VisibilityTimeout
  • 內建的 Retry 機制可以透過在 Web UI 或是用程式的方式中修改 Queue 的 attribute 來達到,我們可以利用程式去修改 RedrivePolicy 屬性;我們只需要去指定參數 maxReceiveCount (一個 message 最多被接收幾次)及 deadLetterTargetArn (當達到上限的次數後要把它移到哪一個 Queue),其他就交給 SQS 了
  • 如何知道過去的 queue 有沒有屯積, 還是馬上就被取出? 看該 queue 的 monitoring 的 ApproximateNumberOfMessagesVisible, 最好的狀況是都是0, 代表這個 queue 沒有處理不完的 message

SES

  • 寄 Email 服務
  • 根據 AWS 自己的說法, 因為 AWS 對寄送的郵件有做控管, 所以不太會被當作垃圾信
  • 當使用 SES 寄太多不存在的 email 且到達一定的數量有可能會被暫停寄信, 可以設定 Enabling Email Feedback Forwarding 當有發生不存在的 email 時就通知某個 email

修改 mailed-by

The mailed-by header is the usually used to persist the content of the envelope from or MAIL FROM through forwarding.

Amazon do not allow the MAIL FROM to be customised. The following quote is from an Amazon employee in a comment on an blog post about SPF & DKIM

The headers you mentioned [mailed-by] seem to be something appended by an ISP after the message left Amazon SES, rather than standard message headers.
We unfortunately do not have control over receiver add-ons.
Nevertheless, assuming that the “mailed-by” value is based on the MAIL-FROM, the answer would be that right now all emails sent through Amazon SES have amazonses.com (or a subdomain of that) as the MAIL-FROM domain.
We don't currently support its customization

Posted by Adrian@AWS on November 4, 2014 8:31:29 AM PST

ref : https://serverfault.com/questions/641262/remove-or-replace-mailed-by-field-with-dkim-spf-enabled

gmail 顯示的 from & singed-by

signed-by 顯示的 domain 是通過 domain Auth 的 SES ARN

寄信的時候你可以只指定 from, ses 會判斷 from 的 domain 並且使用對應的 SES ARN

也可以指定 SES ARN 寄信,但其實沒那麼必要,因為 fromdomain 的 SES ARN 的 domain 必須要是一樣的,否則信會寄不出去

當一封信收到後,fromsigned-by 一定會是一樣的

Cloud Formation

將 region 下所有的主機資訊輸出成 JSON, 如果下次要重 build 一個環境可以直接執行, 但記得要改參數

[操作]

  1. 進去會看到兩個按鈕, 上面是 Create New Stack, 如果已有建立好的 Template 就選擇它, 下面是 Launch CloudFormer, 如果還沒有建立 Template 就選擇它, 將你目前的 AWS 的服務轉成 Json
  2. 所以先選 Launch CloudFormer, 注意! 必須要有 AWS 本身 region 的 default VPC, 否則會一直出現 error 啟不起來,
  3. 成功後會自動在 EC2 建立一個 instance, 接著連到這個 instance 的 public IP, 就可以開始設定了 (建立的那個帳號要有 IAM Full Access 權限才可以將 instance 跑起來)
  4. 設定完後會產生一份 JSON 格式的 template, 把它存起來
  5. 需要改的地方, 以 singapore 與 frankfurt 舉例, 簡稱 sin 跟 fr, 將 sin 的 AZ 名稱取代成 fr 的 AZ 名稱

無法解決

Security Group 的 outbound 0.0.0.0/0 一直出現 AWS::EC2::SecurityGroupEgress Encountered unsupported property CidrIP, 找不出解決方法, 最後就放棄使用 CloudFormation 了

Opsworks

  • Deploy 大量主機
  • Configuration Management 管理設定檔, 一次修改多個 config 及升級

Elastic Beanstalk

可以起一個 web server 並且放在 auto scaling 下, 或者是選擇一個 docker file

並且選擇要如何更新 server, 有兩種方法,

  1. 一種是百分比的, 如果是 30%, 那麼 AWS 就會以一次 shutdown 30% 的主機, 進行更新
  2. 另種是一次幾台, 如果是一次一台的話, 那麼就會一台一台更新

Cognito

不需要煩惱及建置後端架構, 透過此服務即可達到 mobile 互相交換訊息

Mobile Analytics

Mobile 的 GA

CloudTrail

AWS console log

Lambda

  • 像 IFTTT 是一個 event trigger 的服務
  • 例如 s3 一有上傳觸發一個你的 function
  • call lambda 時可以自已決定要不要 blocking

建立 Function,使用 IAM Role 讓它可以 call DynamoDB

1) 在 IAM Role 建立一個 role,policy 這個 AmazonDynamoDBFullAccess 就好

2) 到 Lambda 建立 function : Configure function

  • Code entry type 選擇上傳 zip,但上傳檔案先不選,因為會用指令上傳
  • Role 選擇剛剛新增的 role

3) 先選擇 code inline 否則如果一開始沒有檔案會無法建立

讓lambda 的 log 可以紀錄在 cloudwatch Log Groups /aws/lambda/{lambda_name}

先去看該 lambda function 的 Existing role 叫什麼, 然候再到 IAM Role 那將 Policy CloudWatchLogsFullAccess 加到這個 role, 就可以在 cloudwatch 看到執行這個 function 時的 log 了

Index

  • 每個 Table 都一定有一個主鍵,第二鍵則是 optional 的
  • 如果你要 query 的欄位不是主鍵那就要加 index

SMS

寄 簡訊

SNS

  • 可以推送 notification 到手機(支援 APN, GCM 等等..)
  • 可以對它 publish 或讓 (email, lambda, endpoint, etc.) subscribe

Registger SNS

  • 在 AWS Web Console 建立 SNS ARN
  • App 的 token : 如果是 android 會先去跟 gcm 確認身上有沒有 gcm token, 沒有的話就會先去要一把
  • 將 token 帶給 server, server call aws register SNS API, 給它 SNS ARN + token
  • 完成

宣要注意的是

  • AWS SNS 是認 token 的, 只要 token 都是一樣就只能註冊一次, 所以重覆拿同一個 token 註冊是不會成功的

Push Notification

  • 先去 SNS 的 Applications 註冊 Push Notification 的服務
  • 手機裡的 App 會有個 UUID,帶這個上來到 Server
  • 拿這個 UUID 向 SNS 註冊 Token (createPlatformEndpoint 帶上面註冊 SNS 的 ARN, 及 app UUID, enabled: true (enabled 預設是 false, 所以要改成 true)),會拿到 EndpointArn
  • IOS 在 simulator 或是手機 debug mode, 系統會把 token 扔到 sandbox 的 apns 上, 只有在上架版(app store) 下載下來的才會丟到 production,所以要注意的是使用的環境要與 aws sns apns 的環境一致才發送的出去
  • 註冊完後 SNS 後台就有一筆 record ,也可以直接用 web ui 發送 notification 做測試
  • 每筆 record 後面都有 enabled 值,如果是 false 就代表不能推送,只要 SNS 推送一次但送不成功後就會把它改成 false
  • 發送時如果 client 端沒開網路的話,SNS 不會當它是錯誤 (error),等到 client 把網路打開就會收到之前送的 notification
  • 後端要推送只要對 EndpointArn 發送 message 就可以了
  • Mobile 可以選擇要不要過濾 Notification
  • 格式它可以選擇 raw 或 json,要確定送的格式對不對

Create Notification ARN by Platform

  • GCM 申請時需要填上 API key 是手機去 GCM 那裡申請時拿到的, 要用 server key(A*************************************o)來申請
  • APNS 申請時需要有 .p12 檔案及密碼.p12 是手機跟 apple 申請時會拿到,申請 aws arn 只需要上傳 .p12 及輸入密碼,再選它的按鈕 Load credentials from file (上傳的 .p12 檔名用英文, 有遇過中文檔名解失敗的情況)
  • IOS certificate 一年會到期, 所以要每一年申請且到 sns push application 更新 certificate

發送 GCM notification 格式 (不管 production 還是 dev 都用這個)

{ "GCM": "{ \"notification\": { \"body\": \"test body\",\"title\": \"test title\",\"icon\": \"test icon\" },\"data\": { \"custom_field\": \"custom_value\" } }" }

Andriod 的聲音是 app 自已決定的

發送 APNS notification 格式 (production)

 { "APNS":"{\"aps\":{\"alert\":\"Hello World!!\",\"sound\":\"default\"},\"custom_field\": \"custom_value\"}" }

自行決定是否要帶聲音的參數

APNS_SANDBOX 格式 (dev)

 { "APNS_SANDBOX":"{\"aps\":{\"alert\":\"Hello World!!\"},\"custom_field\": \"custom_value\"}" }

Apple notification 的 title 不像 GCM 可以自訂, 它是不能動的, title 固定都顯示 app name.

Other

安裝 AWS CLI tool

$ curl "https://s3.amazonaws.com/aws-cli/awscli-bundle.zip" -o "awscli-bundle.zip"
$ unzip awscli-bundle.zip
$ sudo ./awscli-bundle/install -i /usr/local/aws -b /usr/local/bin/aws

[建立可以看 billing 的帳號]

除了建立一個 IAM User 並給予權限 (AWSAccountActivityAccess), 但光是這樣還是看不到花費狀況, 還要去主帳號的 Dashboard -> 帳號 -> IAM 用戶對賬單信息的訪問權限 -> 激活IAM 訪問權限, 這樣就可以了

現在登入 IAM User 帳號, 應該就能看到帳單資料了

[其他服務]

  • chaos monkey 可以將 EC2 terminal 或 security group 動手腳模擬網路不通測試 single point failure

Comments