2013年10月29日

AWS Auto Scaling with ELB 設定

設定目標

1. Auto Scaling 使用一個事先建立好的 AMI 來建構不同環境(production, staging, testing)
2. Auto Scaling 自動喚起的 instance 必須自動加入某個已經設定好的 Elastic load balancer
3. Auto Scaling 必需根據系統訊號 CloudWatch alarm 調整 instances 數量

準備工作
首先下載 Auto Scaling, Load Balancing 和 CloudWatch command line tool
並且預先準備 EC2 key pair 以及 AWS ACCESS KEY / AWS SECRET KEY
這裡要注意的是,AWS SECRET KEY 只有在建立的時候找的到,如果遺失了就要重建一個
之前別人很好心的幫我先建立了一組,我登入後找不到 SECRET
準備好要使用的 AMI,一個你已經鍛鍊很久的 AMI
準備好你的 EC2 instance 所需要的 security group
準備一組 shell script ,instances 開啟的時候你希望能夠執行的 startup script / launch script
這個 launch script 最有可能用來設定你需要的執行環境,包括設定環境變數,準備執行階段需要的 code
如果你需要的環境已經完整的設定在AMI之中,那你可能不需要 launch script
為了讓 "Why this problem doesn't appear in my environment?" 發生的機會減到最小,
並且避免每次修改系統都要建立很多的 AMI,我們決定共用一個終極的 AMI
這樣就需要 launch script 的加持,在 EC2 command line 中就是使用 user-data / user-data-file 參數來設定
ec2-run-instances ami-12345678 -k my-aws-key -g my-ec2-security-group -t ti.micro --user-data-file my-launch-script.sh 關於 user-data script 有幾點分享
第一個是這個 launch script 最好只是一個啟動器來呼叫其他 script,
因為這個 user-data script 在設定之後要變更很麻煩,並不能動態改變,
所以在 user-data script 設定環境之後,我會儘快的更新 code base 然後用新的 fabric script 做接下來的動作
這個 user-data script 是用 root 的身分來執行的,如果需要改以某種身分來執行(比如說 git pull)可以使用
su - username -c "command" 但是這個 user 沒有 session 所以不能又在其中執行 sudo command ,
會產生 sudo: sorry, you must have a tty to run sudo
這個問題原本可以藉由修改 /etc/sudoers
把 Defaults requiretty 改為 #Defaults requiretty (不建議)
但是其實遠本就有 root 身分可以用了
另外藉由修改 /etc/profile.d/ 裡面的 script 可以讓使用者登入的時候共同執行某些 script 也是不建議的方式
環境設定必須要在許多服務啟動之前,不然就是動態修改 config 再重起服務
另外也要注意估算一下從啟動到 instance ready 狀態需要多少時間,預設 EC2 會給 5 分鐘的 graceful time


設定環境變數

vi ~/.bash_profile #ec2 Settings export EC2_HOME=~/.ec2 export PATH=$PATH:$EC2_HOME/bin export EC2_URL=https://ec2.ap-northeast-1.amazonaws.com #tokyo #ec2 project settings export EC2_KEYPAIR=my-aws-key export AWS_CREDENTIAL_FILE=~/.ec2/aws_my_credentials export ELASTICBEANSTALK_URL="https://elasticbeanstalk.ap-northeast-1.amazonaws.com" export AWS_ACCESS_KEY=$(grep '^AWSAccessKeyId' "$AWS_CREDENTIAL_FILE" | cut -d= -f2) export AWS_SECRET_KEY=$(grep '^AWSSecretKey' "$AWS_CREDENTIAL_FILE" | cut -d= -f2) export AWS_REGION='ap-northeast-1' export EC2_REGION=${AWS_REGION} export EC2_URL=ec2.${AWS_REGION}.amazonaws.com export AWS_SNS_URL=http://sns.${AWS_REGION}.amazonaws.com export AWS_ELB_URL=https://elasticloadbalancing.${AWS_REGION}.amazonaws.com #ec2 load balancing export AWS_ELB_HOME=~/EC2/ElasticLoadBalancing-1.0.17.0 PATH=${PATH}:${AWS_ELB_HOME}/bin #ec2 cloud watching export AWS_CLOUDWATCH_HOME=~/EC2/CloudWatch-1.0.13.4 PATH=${PATH}:${AWS_CLOUDWATCH_HOME}/bin #ec2 auto scaling export AWS_AUTO_SCALING_HOME=~/EC2/AutoScaling-1.0.61.3 PATH=${PATH}:${AWS_AUTO_SCALING_HOME}/bin export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Home/ [[ -s /Users/sushih-wen/.nvm/nvm.sh ]] && . /Users/sushih-wen/.nvm/nvm.sh # This loads NVM export PATH
接下來開始設定 Auto Scaling Group
設定 launch config
cd $EC2_HOME as-create-launch-config staging-lc --image-id ami-12345678 --instance-type m1.large --key my-aws-key --group ec2-group --user-data-file launch-staging.sh 請注意看,在第一個階段就指定了 user-data-file
而且因為 launch config 無法修改,所以之後要修改這個 script,等於全部重做
as-create-auto-scaling-group staging-asg --launch-configuration staging-lc -z ap-northeast-1a,ap-northeast-1c --load-balancers staging --max-size 10 --min-size 2 --desired-capacity 2 --health-check-type ELB --grace-period 300 --tag "k=Stack, v=staging, p=true" 以上這裡設定了 auto scale group 在多個工作區( multiple availability zone ),但是到此為止還無法跨 side
多個工作區同時失敗的機率已經很小,但是我們還是可以設定跨 side 提供服務,晚上可以睡的比較好
另外也特別設定了 Stack tag 幫助之後辨識不同 auto scale group,也可以不用設定,預設就會有個比較醜的 aws:auto-scale tag
雖然 Name 也是一個tag,但是這個 tag 無法藉由這樣的方式設定成 Name
設定到此 EC2 istances 就會自己起床工作了,並且在 Healthy 狀態自動掛到 Load Balancer 底下
也可以觀察 Auto scaling 會盡量平均 instance 數量到不同的 availability zone
來查看設定 as-describe-auto-scaling-groups staging-asg --headers 如果要刪除 Auto Scaling 必須要先關掉底下所有的 instance as-update-auto-scaling-group staging-asg --max-size 0 --min-size 0 as-delete-auto-scaling-group staging-asg 如果要暫停下來修改的話 as-suspend-processes staging-asg 回復運作 as-resume-processes staging-asg 接下來服用橡膠果實 從簡單的開始,假設我們希望在平均 CPU > 50 的時候增加一個 instance,反之減少一個 instance as-put-scaling-policy staging-scaleup --auto-scaling-group staging-asg --adjustment=1 --type ChangeInCapacity mon-put-metric-alarm staging-scaleup-cpu --metric-name CPUUtilization --namespace "AWS/EC2" --statistic Average \ --period 60 --threshold 50 --unit Percent \ --comparison-operator GreaterThanThreshold \ --dimensions AutoScalingGroupName=staging-asg --evaluation-periods 3 \ --alarm-actions 以上這樣設定就是用平均的角度來看,每分鐘檢查一次,如果連續三次 CPU 都超過 50 ,那就會啟動這個 CloudWatch Alarm 執行相對應的動作,可以執行一個以上的動作 以下是 scale down CloudWatch Alarm with Monitor Policy 檢查 CPU utilization 20次每次1分鐘 as-put-scaling-policy staging-scaledown --auto-scaling-group staging-asg --adjustment=-1 --type ChangeInCapacity mon-put-metric-alarm staging-scaledown-cpu --metric-name CPUUtilization --namespace "AWS/EC2" --statistic Average \ --period 60 --threshold 50 --unit Percent \ --comparison-operator LessThanThreshold \ --dimensions AutoScalingGroupName=staging-asg --evaluation-periods 20 \ --alarm-actions 查看有哪些 policy as-describe-policies 刪除 policy (刪除 Auto Scaling Group 會自動刪除相關的 policy) as-delete-policy 檢查你的 CPU 數據 mon-get-stats CPUUtilization --statistics "Average" --namespace "AWS/EC2" --dimensions "AutoScalingGroupName=staging-asg" 設定完要注意的是,Alarm action 只會在狀態改變的時候被觸動,並不是一直處在 Alarm 狀態就會一直觸動 所以設定一個完整的 Auto Scaling 機制必須要建立多個 Alarm action