/ AWS

[AWS] 自動佈署、擴展與高可用性實作筆記

有好一段時間,在網路服務的設備建置上面,都是幾台機器,開個虛擬化,然後丟到 IDC 之後,就這樣上線服務了。近些年來因為 Amazon 掀起的雲端熱潮,所以,手邊的機器蒙主寵招紛紛丟上雲端也是挺合理的。

有興趣的可以先看看我之前寫的文章,

[AWS] Amazon AWS 實戰筆記與心得

佈署一二三

在 AWS 上面要開啟一台機器其實不是很困難的事情。但是,當我們的維運環境比較特殊的時候,我們就必須要作一些設定,來讓我們的機器符合運作的環境需求。

只是,每一次開一台機器,都要作一次相關的設定,不是很煩嗎?所以,這個時候我們也可以把 EC2 Instance 給快照(snapshot)下來,然後每次利用這個快照去開機器就好。

那,有沒有不使用快照的方式?或是,我除了使用快照開啟一台新的機器之外,我還需要額外的動作呢?這種方式有沒有比較好一點的運作方法?

有的。

Cloud Init

如果你是使用 Ubuntu 系統,那麼在 10.10 之後,Ubuntu 就支援了 CloudInit 的技術,而且,這個工具也能夠使用在 AWS EC2 所提供的 Ubuntu Images 上面。

所以,當你在啟動一個 EC2 Instance 的時候,你會有這個畫面,

Launch Instance

當中的 User Data 就是暗藏玄機的地方!我們可以利用這個欄位,與其關於 CloudInit 的相關技術,來讓你的 Instance _自動的_去完成一些事情。

首先我們先來了解一下這個設定檔的規則,

  • 支援 Gzip 壓縮(User Data 檔案大小限制在 16384 bytes,這是 Amazon 的限制)
  • 支援 mime-multi part 檔案形式(使用 write-mime-multipart
  • 自訂的 shell-script(使用 #! 開頭)
  • 外部載入檔案(#include
  • 系統設定(#cloud-config
  • 啟動服務(#upstart-job
  • 開機一次性執行命令(#boothook
  • 批次運行控制命令(#part-handler

我這裡只拿 #cloud-config 來作範例,檔案的話大家可以去這裡找,

cloud-init-dev/cloud-init/trunk

這裡我解說一下 cloud-config.txt 這個檔案做了什麼事情,

#cloud-config
# 第一行代表我用哪一種規則,這裡是 cloud-config

# 更新 apt 資料庫,預設是開啟
apt_update: true

# 升級 apt 套件,預設是關閉
apt_upgrade: false

# 增加 apt 的套件來源
# 設定鏡像來源,通常會是用 <region>.ec2.archive.ubuntu.com
# 然後如果找不到來源,會使用 apt_mirror_search 去尋找
apt_mirror: http://us.archive.ubuntu.com/ubuntu/
apt_mirror_search:
 - http://archive.ubuntu.com

# 沒用過 XD,請 Google "configure Acquire::HTTP::Proxy"
apt_proxy: 

# 關閉 pipelining 功能,基本上是因為 S3 不支援的關係
apt_pipelining: false

# 複寫預設的 soruces.list 內容,倘若開啟,那 apt_mirror 會無效
apt_preserve_sources_list: true

# 自訂套件來源
apt_sources:
 - source: "deb http://ppa.launchpad.net/byobu/ppa/ubuntu precise main"
   keyid: F430BBAS
   filename: byobu-ppa.list
 # 也可以使用 ppa
 - source: "ppa:byobu/ppa"
 # 也可以使用自訂的來源套件庫
 - source: deb http://ppa.launchpad.net/byobu/ppa/ubuntu precise main 
 key: | # PGP 公鑰放置方法
    -----BEGIN PGP PUBLIC KEY BLOCK-----
    Version: SKS 1.0.10

    mI0ESY8IVwEEALW6ef/McyEoO3jvMURrYdaHp7obBOxWUjuZhM09bUUysfWyDY2VIPGMvuAX
    jjnJkC9zGsKWqLhhmvcP2MpIpGb6RbdKINT9RkVNYPe09rGPfTcEYh4enFRLxUA+dcDkLR2h
    JFB+ScFoCz4B0hslaZuRZXPVBQP9wizg7+hXzKuLABEBAAG0MkxhdW5jaHBhZCBQUEEgZm9y
    IFVidW50dSBTY3JlZW4gUHJvZmlsZSBEZXZlbG9wZXJziLYEEwECACAFAkmPCFcCGwMGCwkI
    BwMCBBUCCAMEFgIDAQIeAQIXgAAKCRDPXnSW9DC7pU7hA/4t2hD6udZZofQGmpURmrdHXyEg
    D9lXpfDst4RmK2p9Hxo4eVF6Jjcgfw00WkdNb/69jG6AqHInfv+5ihH+JsErN0GZJBUsNe9E
    OIOGiOh7ASpUW0+VB5gWqOZgqocQwJoGxZgXriu7NgnRIA9r5MJgnGsKS3EKK17LgiHvD1Bn
    yw==
    =1clR
    -----END PGP PUBLIC KEY BLOCK-----

# 預設安裝套件
packages:
 - git

# 預設掛載點
# 格式與 fstab 相同
# [ fs_spec, fs_file, fs_vfstype, fs_mntops, fs-freq, fs_passno ]
mounts:
 - [ xvdh, /opt/data, "auto", "defaults,nobootwait", "0", "0" ]

# 預設掛載點預設值
# 當掛載點設定不完全的時候,使用這邊的預設值補滿
mount_default_fields: [ None, None, "auto", "defaults,nobootwait", "0", "2" ]

# 加入公開認證金鑰
ssh_authorized_keys:
  - ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAGEA3FSyQwBI6Z+nCSjUUk8EEAnnkhXlukKoUPND/RRClWz2s5TCzIkd3Ou5+Cyz71X0XmazM3l5WgeErvtIwQMyT1KjNoMhoJMrJnWqQPOt5Q8zWd9qG7PBl9+eiH5qV7NZ [email protected]
  - ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA3I7VUf2l5gSn5uavROsc5HRDpZdQueUq5ozemNSj8T7enqKHOEaFoU2VoPgGEWC9RyzSQVeyD6s7APMcE82EtmW4skVEgEGSbDc1pvxzxtchBj78hJP6Cf5TCMFSXw+Fz5rF1dR23QDbN1mkHs7adr8GW4kSWqU7Q7NDwfIrJJtO7Hi42GyXtvEONHbiRPOe8stqUly7MvUoN+5kfjBM8Qqpfl2+FNhTYWpMfYdPUnE7u536WqzFmsaqJctz3gBxH9Ex7dFtrxR4qiqEr9Qtlu3xGn7Bw07/+i1D+ey3ONkZLN+LQ714cgj8fRS4Hj29SCmXp5Kt5/82cD/VN3NtHw== [email protected]

# 加入機器認證金鑰與私鑰
ssh_keys:
  rsa_private: |
  -----BEGIN RSA PRIVATE KEY-----
  MIIBxwIBAAJhAKD0YSHy73nUgysO13XsJmd4fHiFyQ+00R7VVu2iV9Qcon2LZS/x
  1cydPZ4pQpfjEha6WxZ6o8ci/Ea/w0n+0HGPwaxlEG2Z9inNtj3pgFrYcRztfECb
  1j6HCibZbAzYtwIBIwJgO8h72WjcmvcpZ8OvHSvTwAguO2TkR6mPgHsgSaKy6GJo
  PUJnaZRWuba/HX0KGyhz19nPzLpzG5f0fYahlMJAyc13FV7K6kMBPXTRR6FxgHEg
  L0MPC7cdqAwOVNcPY6A7AjEA1bNaIjOzFN2sfZX0j7OMhQuc4zP7r80zaGc5oy6W
  p58hRAncFKEvnEq2CeL3vtuZAjEAwNBHpbNsBYTRPCHM7rZuG/iBtwp8Rxhc9I5w
  ixvzMgi+HpGLWzUIBS+P/XhekIjPAjA285rVmEP+DR255Ls65QbgYhJmTzIXQ2T9
  luLvcmFBC6l35Uc4gTgg4ALsmXLn71MCMGMpSWspEvuGInayTCL+vEjmNBT+FAdO
  W7D4zCpI43jRS9U06JVOeSc9CDk2lwiA3wIwCTB/6uc8Cq85D9YqpM10FuHjKpnP
  REPPOyrAspdeOAV+6VKRavstea7+2DZmSUgE
  -----END RSA PRIVATE KEY-----

  rsa_public: ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAGEAoPRhIfLvedSDKw7XdewmZ3h8eIXJD7TRHtVW7aJX1ByifYtlL/HVzJ09nilCl+MSFrpbFnqjxyL8Rr/DSf7QcY/BrGUQbZn2Kc22PemAWthxHO18QJvWPocKJtlsDNi3 [email protected]

  dsa_private: |
  -----BEGIN DSA PRIVATE KEY-----
  MIIBuwIBAAKBgQDP2HLu7pTExL89USyM0264RCyWX/CMLmukxX0Jdbm29ax8FBJT
  pLrO8TIXVY5rPAJm1dTHnpuyJhOvU9G7M8tPUABtzSJh4GVSHlwaCfycwcpLv9TX
  DgWIpSj+6EiHCyaRlB1/CBp9RiaB+10QcFbm+lapuET+/Au6vSDp9IRtlQIVAIMR
  8KucvUYbOEI+yv+5LW9u3z/BAoGBAI0q6JP+JvJmwZFaeCMMVxXUbqiSko/P1lsa
  LNNBHZ5/8MOUIm8rB2FC6ziidfueJpqTMqeQmSAlEBCwnwreUnGfRrKoJpyPNENY
  d15MG6N5J+z81sEcHFeprryZ+D3Ge9VjPq3Tf3NhKKwCDQ0240aPezbnjPeFm4mH
  bYxxcZ9GAoGAXmLIFSQgiAPu459rCKxT46tHJtM0QfnNiEnQLbFluefZ/yiI4DI3
  8UzTCOXLhUA7ybmZha+D/csj15Y9/BNFuO7unzVhikCQV9DTeXX46pG4s1o23JKC
  /QaYWNMZ7kTRv+wWow9MhGiVdML4ZN4XnifuO5krqAybngIy66PMEoQCFEIsKKWv
  99iziAH0KBMVbxy03Trz
  -----END DSA PRIVATE KEY-----

  dsa_public: ssh-dss AAAAB3NzaC1kc3MAAACBAM/Ycu7ulMTEvz1RLIzTbrhELJZf8Iwua6TFfQl1ubb1rHwUElOkus7xMhdVjms8AmbV1Meem7ImE69T0bszy09QAG3NImHgZVIeXBoJ/JzByku/1NcOBYilKP7oSIcLJpGUHX8IGn1GJoH7XRBwVub6Vqm4RP78C7q9IOn0hG2VAAAAFQCDEfCrnL1GGzhCPsr/uS1vbt8/wQAAAIEAjSrok/4m8mbBkVp4IwxXFdRuqJKSj8/WWxos00Ednn/ww5QibysHYULrOKJ1+54mmpMyp5CZICUQELCfCt5ScZ9GsqgmnI80Q1h3Xkwbo3kn7PzWwRwcV6muvJn4PcZ71WM+rdN/c2EorAINDTbjRo97NueM94WbiYdtjHFxn0YAAACAXmLIFSQgiAPu459rCKxT46tHJtM0QfnNiEnQLbFluefZ/yiI4DI38UzTCOXLhUA7ybmZha+D/csj15Y9/BNFuO7unzVhikCQV9DTeXX46pG4s1o23JKC/QaYWNMZ7kTRv+wWow9MhGiVdML4ZN4XnifuO5krqAybngIy66PMEoQ= [email protected]

# 關閉 EC2 Instance 的 metadata
# 預設是否
disable_ec2_metadata: true

# 執行命令
# 類似於 rc.local 的執行階段
runcmd:
 - [ ls, -l, /]

# 開機命令
# 這裡的命令每次開機都會執行一次,在 boothook 後會執行
bootcmd:
 - [ cloud-init-per, once, mymkfs, mkfs, /dev/vdb ]

# 模組額外設定
# 要使用這個東西,需要 Cloud Init 的 CloudConfig 當中有 `cc_` 開頭的 python 檔案才行
# 不過我並不太確定 Amazon 上面是否有這些東西,所以沒有使用過這項功能
cloud_config_modules:
 - mounts
 - ssh-import-id
 - ssh
 - grub-dpkg
 - [ apt-update-upgrade, always ]
 - puppet
 - updates-check
 - disable-ec2-metadata
 - runcmd
 - byobu

# 引入 ssh 使用者
ssh_import_id: [somser]

# 建立預設文件,我也沒用過
# 詳情可以參考 [建立預先設置文件](http://www.debian.org/releases/stable/s390/apbs03.html.zh_CN)
debconf_selections: |
        debconf debconf/priority select critical

# byobu 設定
byobu_by_default: system

# 關閉 root 登入
disable_root: true

# 關閉 root 功能
# 預設沒開,所以基本上我也沒用過這功能
#disable_root_opts: no-port-forwarding,no-agent-forwarding,no-X11-forwarding,command="echo 'Please login as the user \"$USER\" rather than the user \"root\".';echo;sleep 10"

# 設定預設語系
locale: en_US.UTF-8

# 語言設定檔
locale_configfile: /etc/default/locale

# 設定 log 檔案
rsyslog:
 - ':syslogtag, isequal, "[CLOUDINIT]" /var/log/cloud-foo.log'
 - content: "*.*   @@192.0.2.1:10514"
 - filename: 01-examplecom.conf
   content: |
   *.*   @@syslogd.example.com

# 自動調整 rootfs 大小
resize_rootfs: true

# 設定 hostname
# 沒用過,所以跳過 XD

# 完成開機後的最後一則訊息
final_message: "The system is finally up, after $UPTIME seconds"

# 設定檔案最後輸出訊息
output:
 init: "> /var/log/my-cloud-init.log"
 config: [ ">> /tmp/foo.out", "> /tmp/foo.err" ]
 final:
   output: "| tee /tmp/final.stdout | tee /tmp/bar.stdout"
   error: "&1"

# phone_home,類似做好事情打個電話回家 XD
phone_home:
 url: http://my.example.com/$INSTANCE_ID/
 post: [ pub_key_dsa, pub_key_rsa, pub_key_ecdsa, instance_id ]

# 設定時區
timezone: Asia/Taipei

# 設定 log 檔案
def_log_file: /var/log/my-logging-file.log
syslog_fix_perms: syslog:root

# 關於使用者與密碼部份
# 沒用過,跳過 XD

# 清除 instance 快取
# 沒用過,保留預設
manual_cache_clean: false

# 最後的 CloudConfig 執行命令
# 沒用過,跳過 XD

# ssh 相關設定,沒用過,跳過

然後我跳過了一狗票的設定資訊(被揍飛。其實,我不得不說,當我們把環境建置好之後,也建立好快照之後,實際上我們並不需要再次的對新啟動的機器重新設定,所以,這個 user-data 我們只要挑我們想要的方式來操作即可。

擴展自動設定

關於擴展這件事情,我在上一篇文章中已經有稍微提到。我們先撇開 CloudWatch 幫我們作的事情,就單純的以啟動 Instance 來繼續提供服務這件事情來說。

我們如果需要啟動一台 Instance,以命令列模式我們可以這樣作,

$ ec2-run-instances ami-1234de7b \
    --instance-type m1.small \
    --region ap-northeast-1 \
    --key XXXX \
    --group GGGG \
    --user-data-file my_user_data.txt

還是要提醒你,請留意 --region 的設定,不要開錯區域了。然後最重要的就是 my_user_data.txt 這個檔案。他是我們對於這台機器的 cloud-config 設定。

我這裡以我自己設定的機器為例子來說明,

#cloud-config
apt_update: true
apt_upgrade: true
apr_sources:
 - source: "ppa:ondrej/php5"
 - source: "ppa:nginx/stable"
# 如果你是用已經包好的 AMI 來建立 Instance
# 那這個 packages 就可以略過了
packages:
 - mysql-client
 - nginx
 - php5-fpm
 - php5-cli
 - php5-common
 - php5-curl
 - php5-dev
 - php5-mcrypt
 - php5-mysqlnd
 - imagemagick
 - exiv2
 - curl

# 這是你的機器上面的金鑰,為的是要 SSH 可以直接進來這台機器
ssh_authorized_keys:
 - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDgMasClLAUjwZKIBVjCSdhLCT9stmrCxkMw4ri5uX0lzmz263Ow0q7Ej/k0OxVQXL+QHmInddL58IrqPihNSMw2/3ny1odPWRPMl7/QIDOnXeSYrh1UlwWAIXRh4zU5A2xmIaEVPWyi2vkWumkwXrt1sK/bxCRUUIYjvjsC7KBAvbbgZFy/lYyc3rPFc4G8HC9wjQDVjXqVb5Tdc4R3F/6SyNdx+wa7/7UbnEV1vpgjQMwkUvtb+fX4EwGzpHA0xLz8eonn4l+4+sJRWNrU0ngVbiUpTn/G19RxwvEwdnVl065L8A+/HOwUXnYbpBi70eeBPWMjry2i6SNwo9 hinablue

byobu_by_default: system
locale: zh_TW.UTF-8
# 這麼作是為了省錢(沒有誤
# 然後我們把我們的網站原始碼利用 git archive 打包丟上 s3
# 這邊我們把他拉下來,打開就可以用了
# 保險起見我們重新啟動一下 nginx
runcmd:
 - [ mkdir, -p, /mnt/tmp ]
 - [ mkdir, -p, /mnt/log ]
 - [ chmod, -R, 777, /mnt/tmp ]
 - [ chmod, -R, 777, /mnt/log ]
 - [ wget, -c, http://s3-ap-northeast-1.amazonaws.com/codes/xxx.tar.gz ]
 - [ mkdir, -p, /var/www ]
 - [ tar, -zxf, xxx.tar.gz, /var/www ]
 - [ /etc/init.d/nginx, restart ]

這裡還有一些心得,我們容後再述。

高可用性

一般來說,我們所謂的高可用性(Hight Availability)通常是 A 機器掛點了,那麼馬上會有一台 B 機器接手去作。這件事情 Amazon 的 ELB 可以幫我們作分配這件事,但是機器還是得自己生。

我的前一篇有講到 CloudWatch 的設定,主要的目的就是讓自己的服務可靠度能提高,利用監控的方式來動態的產生機器,讓服務不會被中斷掉。

這樣的動作,你可以套用到 RDS 也是可行的。

但是!

當我的機器有更新,而快照(snapshot)卻還是舊的,而機器卻已經正式上線了,我該怎麼確保我上線機器不會有問題呢?

我們思考一下需要做到的事情,

  • 每一台機器的原始碼都得更新
  • 每一台機器的環境設定可能得變動
  • 機器的快照需要更新
  • 遠端原始碼壓縮檔案需要更新

我們從最簡單的開始,放在 s3 上面的檔案我們當然只要上傳就好了。那,已經啟動在 ELB 底下的機器怎麼辦呢?必要之惡是,我們得先將其中一台抽離 ELB 的控制之下,將那一台機器的原始碼更新到最新,系統環境更新到最新,接著作快照。

人品夠好的話,快照做完就可以回到 ELB 的懷抱了。

那剩下的機器怎麼辦?假設我們總共有 10 台機器正在 ELB 後面作服務的動作,那麼,扣掉已經更新過的那一台,我們還有 9 台機器。

所以,我們可以這樣作,

  • 先把 4 台抽離 ELB,對這 4 台作更新動作
  • 把更新好的 4 台上線,另外 5 台未更新的抽離 ELB
  • 把剩下的 5 台更新,並放回 ELB

同樣的,人品夠好的話,你的服務就可以繼續跑下去了。

那,請問這樣的動作要作 10 次,那萬一有 100 台怎麼辦?兄弟,要是我有 100 台機器需要 deployment 的話,你覺得我還會在這邊寫部落格嗎

遠端佈署與操作

我們剛剛開機器的時候,加入了 ssh_authorized_keys 的作用來了,由於加入了公鑰,所以我們可以直接使用 SSH 來連接我們所有的 Instances,所以,我們就可以遠端來作發佈或是修改的動作。

我們會需要用到的有,

  • ec2-api-tools
  • elb
  • ssh

首先我們要知道有幾台 Instances 在 ELB 裡面服務,

$ elb-describe-lbs --region ap-northeast-1

# 因為吐出資訊太多,我只列出重點的地方
...| member= InstanceId=i-99d4ba71 member= InstanceId=i-c7fa93e7 |...

這時候我們知道我們的 ELB 裡面有兩台 Instances 在跑,這裡暫時不考慮他的健康狀況,我們假設他們都是 InService 的狀態。

所以我們要作的事情有,

  • 遠端登入 Instance
  • 把上面的程式碼更新
  • 把機器狀態更新
  • 必要的話重新啟動服務

所以我們要先知道 Instances 的 Public DNS,才能作 scp 或是 ssh 的動作。

$ ec2-describe-instances --region ap-northeast-1

# 因為吐出資訊太多,所以我只列出重點
...| ec2-53-21-168-130.ap-northeast-1.compute-1.amazonaws.com |...

上面就是其中一台機器的公開位址了,我們就可以針對這個位置進行操作,首先我們要把檔案從 s3 上面抓下來,並且將他放到正確的位子上。

$ ssh -i ~/XXXXX.pem [email protected] \
  'wget -c http://s3-ap-northeast-1.amazonaws.com/codes/xxx.tar.gz'

$ ssh -i ~/XXXXX.pem [email protected] \
  'tar -zxf xxx.tar.gz /var/www'

# 必要的話你也可以這樣遠端重起服務
$ ssh -i ~/XXXXX.pem [email protected] \
  'sudo /etc/init.d/nginx restart'

疑?做完了!是的,這樣就做完了如果你遇到權限問題,請不要來問我。

那系統設定怎麼辦?兩種作法,

  • 一台一台改(認真
  • 把機器關掉,用新做成的快照直接開機器

為什麼我會說一台一台改?因為,有些需要 sudo 的事情,而且又是更改系統設定這樣的事情,如果你能夠確保,使用 ssh 去遠端執行命令,而且不會出問題的話,那麼你可以這麼做。

只是,通常我們心臟並沒有那麼那麼大顆,所以,使用新的快照來開機器比較妥當。

開機器的方法我剛剛說過了,請參考 ec2-run-instance 的那一段(請往上捲動

偷吃步

每次都要跑命令列其實也是很討人厭的事情,既然是身為一個什麼都不會的 PHPer,所以用一下 AWS SDK for PHP 也是挺合理的。

這裡我漏寫了一些東西,請自己補上,基本上就是用偷懶的方式,把 ELB 裡面的 InstanceId 拿出來,然後再用 EC2 的工具把 publicDNS 拿出來而已,沒什麼技術。

<?php

$elb = new AmazonELB();
$ec2 = new AmazonEC2();

$elb->set_region(AmazonELB::REGION_TOKYO);
$ec2->set_region(AmazonEC2::REGION_TOKYO);

$lbs = $elb->describe_load_balancers(
        array(
            'LoadBalancerNames' => 'myELB'
            )
        );

$instances = [];

if ($lbs->isOK()) {
    foreach($lbs->body
            ->DescribeLoadBalancersResult
            ->LoadBalancerDescriptions
            ->member
            ->Instances
            ->member as $instance) 
    {
        array_push($instances, $instance->InstanceId);
    }
}

$dnss = $ec2->describe_instances(
        array(
            'InstanceId' => $instances
            )
        );

if ($dnss->isOK()) {
    foreach($dnss->body
            ->reservationSet
            ->item
            ->instancesSet
            ->item as $item)
    {
        print($item->dnsName);
    }
} 

結語

佈署的部份其實我有問過幾位神人,建議是相當不錯的,

  • 使用 EBS + snapshot 直接狂開,然後掛載
  • 使用 S3 + rsync
  • 使用 ssh git pull

最後我是利用 S3 + git archive + wget 來做佈署動作,雖然很麻煩,而且也沒那麼自動化,但是,我覺得我這樣做可以解決一些事情,

  • 建立/掛載 EBS 需要重新開機,人品夠好的話,開的起來,不好的話...
  • rsync 立意雖好,但整組蓋掉反而省事,畢竟不是常態性更新
  • ssh git pull 可以控制狀況,但是相對操作比較繁雜(我人懶
  • git archive 一方面可以定時備份,一方面要 rollback 比較快(笑
  • wget 或是 curl 也可以,反正只是抓檔(被揍飛

所以上述所說的遠端佈署,只要用 SDK 做好小工具,跑個迴圈就可以佈署完畢了。當然啦,前提是人品夠好的話,個人覺得這是玩 AWS 必備條件之一(沒有劃錯重點

Update

Michael Su 提到關於資料佈署的 EBS 作法,這個方式我也實作過,不過由於我人品不太好的關係,EBS 掛好常常死機。不過還是寫一下大略的方式,

  • 開一個 EBS 專門放程式碼
  • 當程式碼更新時,挑一台機器更新程式碼
  • 將更新過後的 EBS 快照起來
  • 其他的機器先停掉 web server
  • 把程式碼區塊的 EBS 卸載(umount, detach
  • 從剛剛的新快照建立一個新的 EBS
  • 把新的 EBS 掛載(attch, mount

這是在僅只更新資料的狀態下,使用 EBS 的方式來作更新,好處是速度相當快,而且可以全部在 console 底下完成。

簡單建立作法大概是這樣,先是建立一個 Volume,

$ ec2-create-volume -s 1 --region ap-northeast-1 -z ap-northeast-1b

VOLUME    vol-3fe44b5e    1        ap-northeast-1b    creating    2012-05-22T03:34:58+0000
REQUEST ID    1b888564-cc6d-431e-8db9-ea457a63a272

然後再把這個 Volume 黏到某台 Instance 上面,

ec2-attach-volume vol-3fe44b5e --region ap-northeast-1 -i i-77fe92aa -d /dev/sdd

ATTACHMENT    vol-3fe44b5e    i-77fe92aa    /dev/sdd    attaching    2012-05-22T03:51:38+0000

然後你就可以進去那台 EC2 把那個磁區格式化,並且掛載(mount)起來用了。刪除的方式也是一樣,但是記得要先卸載(umount),不然如果你強制把他從 EBS 拔掉的話,你的 EC2 是會死掉的

建立快照的方式大抵上是這樣,

$ ec2-create-snapshot --region ap-northeast-1 -d "My Core" vol-3fe44b5e

SNAPSHOT    snap-fec85a92    vol-3fe44b5e    pending    2012-05-22T03:57:17+0000        889683449203    1    My Core

刪除快照是這樣,

$ ec2-delete-snapshot --region ap-northeast-1 snap-fec85a92

SNAPSHOT    snap-fec85a92

我不太想說,我操作快照最高紀錄弄死了 10 台 EC2... 所以我應該把人品點滿再來玩 AWS 比較適合吧(哭