相信有那麼一天,我們將可以像畢凱艦長一樣用嘴巴叫所有主機做事!


Cheng Wei Chen



在 AWS - Elastic Benstalk 上運行 Laravel 5.1

續前兩篇試過了 GCP、Azure 之後,繼續我的測試之旅,這次的對象是 AWS 的 Elastic Benstalk。

AWS 的文件與參考資料本來就是爆炸多,隨手就能找到一篇《Deploying a Laravel Application to Elastic Beanstalk》
(謎之音:所以你又要偷懶不寫文了?)

不過 AWS 的中文文件目前只有簡中版,所以這篇文應該還是有一點價值啦!
(謎之音:想充版面就說一聲,找一堆藉口。)


預備 Laravel 5.1 程式碼

老樣子,就直接用 composer create-project 建一個乾淨的 Laravel 5.1 來試試。

composer create-project --prefer-dist laravel/laravel trylaravel "5.1.*"

同時先把這一份 code 打包成 zip 壓縮檔,請參考 AWS 官方教學《Deploying a Laravel Application to Elastic Beanstalk》的作法。

cd trylaravel
zip ../laravel-default.zip -r * .[^.]*

也就是打包成 zip 檔時,不要多那一層資料夾,直接把 code 打包。

而且注意噢,我們是連同 vendor、.env 這些檔案全都一起打包在 zip 中了。
(你也可以打包一個不含 .env 的 zip 檔,後面也有機會用到。)

安裝 aws cli

據說 aws cli 功能超強的,當然要來安裝一下。

安裝方式可以參考官方教學文件《Installing the AWS Command Line Interface》

當然如果你跟我一樣潔癖發作,那可以找一下有沒有 Docker Image 可以直接套用或者自己 build 一個。在 Docker Hub 上搜尋 aws cli 沒能看到哪個比較顯眼的,只有 mesosphere/aws-cli 看起來比較值得信任。但其實針對 Elastic Beanstalk 還有另一個 cli,那就是 aws eb cli。總之兩種 cli 都裝一裝吧!

透過 Web Console 使用 Elastic Beanstalk (Launch Now)

雖然 aws cli 與 aws eb cli 超強的,但這一次我們先從 Web Console 使用 Elastic Beanstalk 開始介紹,因為對初次使用 Elastic Beanstalk 的使用者來說,有些複雜的事情還是在 Web Console 上設定比較簡單,等到比較熟悉 Elastic Beanstalk 的使用方式之後,才比較容易切換到 cli。

首次進入 Web Console 的 Elastic Beanstalk 頁面,會看到如下圖的畫面,AWS 已有一個簡單的 Launch Now,幫助你使用 Elastic Beanstalk 建立第一個 Application。

所以我們就依據引導,先選擇 PHP 並按下 Launch Now

然後就可以離開去泡個咖啡、上廁所了!因為它要花個幾分鐘時間,自動幫你建立名為 “My First Elastic Beanstalk Application” 的 Application,並且在其中建立名為 “Default-Environment” 的 Environment。

如果你想知道 Elastic Beanstalk 做了哪些事情,你可以查看 Dashboard 底下的 Recent Events,或直接進到 Events 查看所有記錄。


當它完成所有動作之後,即可在 Dashboard 看到以下的畫面。
  • Health 檢查是綠色打勾 ok 的狀態。
  • 目前 Running 的 (Code) Version 是 Sample Application。
  • 運行的環境是 64bit Amazon Linux 2016.03 v2.1.4 running PHP 5.6


我們可以先點擊上方麵包屑的 URL,瀏覽目前部署完畢的網站。


這是一個很單純的 php 網頁



接著用我們打包好的 Laravel 取代它,點擊 Dashboard 中間的 “Upload and Deploy”,選擇 zip 檔,並且給予它一個 Version label。


上傳完成後,Health 一樣會維持在綠色打勾 ok 的狀態,但是瀏覽 URL 會出現 Forbidden。


這是因為我們還沒調整 Software Configuration,要配合 Laravel 的設計,將 Document root 改成 /public


然後等待片刻,等待 Elastic Beanstalk 變更完 Environment,再次瀏覽 URL 即可看到 Laravel 的入口網頁。


透過 Web Console 使用 Elastic Beanstalk (Create New Application)

為了更了解 Elastic Beanstalk 有哪些設定,所以我們再用正規的 Create New Application 的方式建立一次。

首先要輸入 Application name。


接著自動帶領你建立第一個 Environment,包含以下數個步驟。


因為我們是要運行 Website,所以選擇 Web Server Environment。


如果的網站有機會爆紅、有大流量,那 Environment Type 你可以選擇 Load balancing, auto scaling,不然也許 Single instance 就夠一般狀況使用了。
(但是通常還是會選擇 Load balancing, auto scaling,畢竟人生不怕一萬,只怕萬一嘛。)


另外就是 PHP 的版本預設會幫你選最新版本 PHP 5.6 on 64bit Amazon Linux 2016.03 v2.1.4,如果你需要更舊的版本,可以按下 Change platform version,目前最舊提供到 PHP 5.3。
可惜目前還沒有 PHP 7.0。最新消息,目前已經支援 PHP 7.0。

下一步到了 Application Version,如前面的範例,這裡可以直接選擇要上傳的 zip 檔,或者也可以指定 s3 上的檔案。


如果 Environment Type 選擇了 Load balancing, auto scaling,這一頁還會有 Deployment Preferences 需要設定。


當你的 Application 有透過 auto scaling 運行多台 instance 時,你希望 Elastic Beanstalk 幫你無痛部署新版本的程式碼嗎?那就選擇 Rolling



想要了解更多這部分的內容,可以參考官方文件《Deployment Policies and Settings》

再來要設定 Environment Information,這包含了 URL。


如果你需要 DB Service,那在 Additional Resources 這一個步驟,記得要勾選 Create an RDS DB Instance with this environment


下個步驟 Configuration Details 可設定的項目比較多一點,對初次使用來說,大該先處理這三項即可:
  • Instance type - 你可以調整 instance 的規格,規格的選項即是 EC2 的選項,可以查看 EC2 Instance Types 來參考。
  • EC2 key pair - 如果你有打算 ssh 直接登入 instance 做些事情,那就設定一組 key pair。
  • Root Volume size - 如果需要大一點的 storage,可以在此調整。
來到 Environment Tags,如果有特別需求,你可以給 environment 額外的 Tag,
若沒需求就直接下一步。


因為有勾選 Create an RDS DB Instance with this environment,會多一個 RDS Configuration 的步驟。


可以設定的選項與 RDS 的 Web Console 是一致的。

(抓個 RDS 的圖提供對照參考。)

緊接著要設定 Permissions,這是因為 Elastic Beanstalk 需要足夠的權限來幫你代管主機,幫你處理許多事情,而這裡就是讓你選擇要套用哪一個 Role。

但若是初次使用你也沒得選, Instance profileService role 都只能選擇預設值。


一般來說預設值所賦予的權限即綽綽有餘,如果覺得有所疑慮,當然也可以自己建立合適的 Role。在這份官方文件《Managing Elastic Beanstalk Service Roles》中就有簡單提到如何建立。

最後就再次 Review,確定都沒問題就 Launch 吧!


按下 Launch 之後,如果有問題發生,Web Console 也會顯示提示或警告。


若沒出現提示或警告,那就一樣去泡咖啡或上廁所吧!而且這一次因為有勾選 Create an RDS DB Instance with this environment,建立的時間又會更久一些,請耐心等待。


同樣的當 Environment 建立完成後,記得要調整 Software Configuration,將 Document root 改成 /public


另外這次我故意上傳了沒有 .env 的 code,於是噴錯了。


AWS Elastic Beanstalk 與 Azure 的 App service 一樣,也可以把 .env 的參數直接設定在 Web Console 裡,這樣就不用將 .env 一起推上去。

進到 Software Configuration 中,在 Environment Properties 設定即可。


沒意外補上 APP_KEY 之後,就一樣能看到 Laravel 預設的入口頁了。
以上就是 Web Console 的操作方式。

透過 aws cli 使用 Elastic Beanstalk (Create New Application)

接著要來透過 aws cli 來操作,在那之前有一些前置作業要完成。

前置作業

首先我們要預備一組 AWS 的 Access Key ID 及 Secret Access Key,它必須具備 Elastic Beanstalk 的權限。
你可以登入 AWS Web Console,在 IAM 中產生一組。不知道該怎麼產生,那就看看官方文件吧
記得要給予足夠的 Permissions,如果要用現成的 Policy,就先選用 AWSElasticBeanstalkFullAccess 吧。


接著設定 aws cli 的 configure。

aws configure

輸入指令後,就會引導你一一輸入 Access Key ID、Secret Access Key、Default region 及 Default output format。

另外如下圖,如果輸入錯誤或想要變更,你只要再次輸入指令即可。


其實 config 會被存放在 ~/.aws 底下的 configcredentials 這兩個檔案裡。因此你也可以自己直接修改這兩個檔案,這同時也意味著 credentials 很重要,因為這裡面就是你的 Secret Access Key。


建立不含 DB 的 Environment

首先要先建立一個 Application。

使用 aws cli 指令 aws elasticbeanstalk create-application

如下,建立一個名為 TryLaravel 的 Application

aws elasticbeanstalk create-application --application-name TryLaravel

第二步要上傳程式碼至 S3,並讓它與 Application 產生關聯,成為一個 Application Version。

如果你有照著文章前面的說明,已使用 Web Console 在 Elastic Beanstalk 創建過 Environment,那你的 S3 應該已經有一個類似 elasticbeanstalk-ap-northeast-1-123456789012 的 Bucket。

那是 Elastic Beanstalk 自動幫你建立的,它會用來儲存一些相關的檔案,所以可別亂刪了。

我們就把檔案上傳至這個自動建好的 Bucket。(你也可以存放在其他的 Bucket。)

aws s3 cp laravel-default.zip s3://elasticbeanstalk-ap-northeast-1-123456789012

上傳完畢後,要將此 zip 檔新增為一個 Application Version,這次要使用的指令是 create-application-version

有幾個必要的參數

  • --application-name 必填,不然它怎麼知道是哪個 Appliaction?
  • --version-label 必填,這個版本的 label,要記好後面還會用到它。
  • --source-bundle 必填,告訴他 zip 檔放在 S3 的哪個位置。

aws elasticbeanstalk create-application-version --application-name TryLaravel --version-label v1 --source-bundle S3Bucket="elasticbeanstalk-ap-northeast-1-123456789012",S3Key="laravel-default.zip"

接著是建立 Environment。

但在那之前我們要確認一下可用的 solution stack,透過 aws cli 指令 aws elasticbeanstalk list-available-solution-stacks 查閱。

aws elasticbeanstalk list-available-solution-stacks

其中跟 PHP 相關的如下。

可惜依然沒有 PHP 7.0。最新消息,已經支援 PHP 7.0。

使用 aws cli 指令 aws elasticbeanstalk create-environment 建立 Environment。

aws elasticbeanstalk create-environment --application-name TryLaravel --environment-name environment-cli --solution-stack-name "64bit Amazon Linux 2016.03 v2.1.4 running PHP 5.6" --cname-prefix trylaravelcli --version-label=v1
  • --application-name 必填,要將 Environment 建立在哪一個 Application 之中。
  • --environment-name 必填,預備新建立的 Environment 的名稱。
  • --solution-stack-name 必填,這決定環境是要用哪一個 AMI 來建立 instance,也決定要跑哪一種程式語言。(這與另一個參數 --template-name 是二選一,這部分後面會另外說明。)
  • --cname-prefix 建議要填,這就是 URL
  • --version-label 建議要填,就填剛才建立的 Application Version。
用上述的指令我們就可以建出一個基本的 Environment,但這不夠完美,還有許多 Configuration 需要一一補設定。例如:

  • Iam Instance Profile
  • Service Role
  • Rolling Update Enabled
  • Environment Variables
  • document_root

因此我們修改指令,盡可能一次就把多個設定搞定。這時我們要利用 --cli-input-json 這個參數,這可以讓我們用 json 格式來輸入我們想要設定的內容,因此指令就會變成下面的樣子,將所有的參數都放在一段 json 中。

aws elasticbeanstalk create-environment --cli-input-json '{
    "ApplicationName": "TryLaravel",
    "EnvironmentName": "environment-cli",
    "CNAMEPrefix": "trylaravelcli",
    "SolutionStackName": "64bit Amazon Linux 2016.03 v2.1.4 running PHP 5.6",
    "VersionLabel": "v1",
    "OptionSettings": [
        {
            "OptionName": "IamInstanceProfile",
            "ResourceName": "AWSEBAutoScalingLaunchConfiguration",
            "Namespace": "aws:autoscaling:launchconfiguration",
            "Value": "aws-elasticbeanstalk-ec2-role"
        },
        {
            "OptionName": "EnvironmentVariables",
            "Namespace": "aws:cloudformation:template:parameter",
            "Value": "APP_KEY=4uamrdVTqYODQ1wb0Tn17bCWLj4i6rHg,APP_DEBUG=true"
        },
        {
            "OptionName": "APP_DEBUG",
            "Namespace": "aws:elasticbeanstalk:application:environment",
            "Value": "true"
        },
        {
            "OptionName": "APP_KEY",
            "Namespace": "aws:elasticbeanstalk:application:environment",
            "Value": "4uamrdVTqYODQ1wb0Tn17bCWLj4i6rHg"
        },
        {
            "OptionName": "document_root",
            "Namespace": "aws:elasticbeanstalk:container:php:phpini",
            "Value": "/public"
        },
        {
            "OptionName": "ServiceRole",
            "Namespace": "aws:elasticbeanstalk:environment",
            "Value": "aws-elasticbeanstalk-service-role"
        }
    ]
}'

但這樣的指令太長也不太好使用,所以再做一點修改,我們將 json 單獨儲存成另外一個檔案 options.json,檔案內只存放以下內容。

{
    "ApplicationName": "TryLaravel",
    "EnvironmentName": "environment-cli",
    "CNAMEPrefix": "trylaravelcli",
    "SolutionStackName": "64bit Amazon Linux 2016.03 v2.1.4 running PHP 5.6",
    "VersionLabel": "v1",
    "OptionSettings": [
        {
            "OptionName": "IamInstanceProfile",
            "ResourceName": "AWSEBAutoScalingLaunchConfiguration",
            "Namespace": "aws:autoscaling:launchconfiguration",
            "Value": "aws-elasticbeanstalk-ec2-role"
        },
        {
            "OptionName": "EnvironmentVariables",
            "Namespace": "aws:cloudformation:template:parameter",
            "Value": "APP_KEY=4uamrdVTqYODQ1wb0Tn17bCWLj4i6rHg,APP_DEBUG=true"
        },
        {
            "OptionName": "APP_DEBUG",
            "Namespace": "aws:elasticbeanstalk:application:environment",
            "Value": "true"
        },
        {
            "OptionName": "APP_KEY",
            "Namespace": "aws:elasticbeanstalk:application:environment",
            "Value": "4uamrdVTqYODQ1wb0Tn17bCWLj4i6rHg"
        },
        {
            "OptionName": "document_root",
            "Namespace": "aws:elasticbeanstalk:container:php:phpini",
            "Value": "/public"
        },
        {
            "OptionName": "ServiceRole",
            "Namespace": "aws:elasticbeanstalk:environment",
            "Value": "aws-elasticbeanstalk-service-role"
        }
    ]
}

於是指令就能縮短如下。當然記得把 file://options.json 修改成正確的檔案路徑。

aws elasticbeanstalk create-environment --cli-input-json file://options.json

執行指令並且稍後再回到 Web Console 查看狀態,應該會是如下圖一樣,順利部署成功的狀態。


這裡補充一個其他內容,就是我如何能知道在指令 create-environment 中有哪一些 Options 可以設定?又怎麼設定?

最簡單的做法就是你先用 web Console 建出一個你理想中的環境,接著再用 describe-configuration-settings 查看它。

就用我們前面剛建立好的 Application 及 Environment 為例,指令如下:

aws elasticbeanstalk describe-configuration-settings --application-name TryLaravel --environment-name environment-cli

如此一來你就能得到一個很長的 json,裡面便記錄了這些 Option 的設定,你即可取你所需的複製使用。

利用 template 建立包含 DB 的 Environment

前面講了很多,但眼尖的你應該會發現,前面的環境並未包含 DB。因此接下來我們再換一個方式,一口氣用 aws cli 建出包含 DB 的 Environment。

這裡我們就會需要使用到 template,但 template 要從何處而來?

老樣子最簡單的方法u一樣是先利用 Web Console 建立出你理想的 Environment,再將它 save 為 template。

在 Dashboard 的 Actions 按鈕中,找到 Save Configuration 的選項,即可將 Environment 存為 template。



於是我們只要很簡單的一行指令,即可完成一切。

aws elasticbeanstalk create-environment --application-name TryLaravel --environment-name environment-cli --template-name deploy_success --version-label v1

透過 eb cli 使用 Elastic Beanstalk

最後來說明如何透過 aws eb cli 來使用 Elastic Beanstalk。
其實在 Elastic Beanstalk 的 Web Console 中,AWS 已經有一個簡單的 Get Started 介紹 eb cli 如何使用。


所以我們就先依樣畫葫蘆。

composer create-project --prefer-dist laravel/laravel trylaravel "5.1.*"
cd trylaravel
eb init -p PHP

在上述指令的過程中,若是首次使用 eb cli,輸入 eb init -p PHP 之後,會先詢問你 credentials。


credentials 一樣會存放在 ~/.aws/config 裡面,所以要注意安全,別隨便外洩了。

同時當執行了 eb init -p PHP 之後,eb cli 會幫你建立一個 .elasticbeanstalk 資料夾,並且新增一個 config.yml

這時先別急著執行下一個指令 eb create,先來檢查一下這個 config.yml

branch-defaults:
  default:
    environment: null
    group_suffix: null
global:
  application_name: trylaravel
  default_ec2_keyname: null
  default_platform: PHP
  default_region: us-west-2
  profile: eb-cli
  sc: null

eb cli 會根據 .elasticbeanstalk 資料夾裡面的 Configuration 檔案來控制該如何建制環境、設定配置並幫你部署程式碼。所以這些 Configuration 檔該如何設置便是能否活用 eb cli 及 Elastic Beanstalk 的重點了。

想要更靈活運用,當然只好請出官方文件了,不過老實說你可能要把《AWS Elastic Beanstalk Environment Configuration》整個章節都看完,才能搞懂所有細節。

因為文件是依據 Before、During、After Creation 三個階段來說明 Environment Configuration,它會同時介紹 Web Console、aws cli 及 eb cli 分別如何操作。

這裡就直接示範該如何修改,首先修改三個明顯的地方。
(或者你也可以再執行一次 eb init -i,它會用對話的方式幫助你完成幾個基本項目。)

  application_name: TryLaravel
  default_platform: PHP 5.6
  default_region: ap-northeast-1

application_name 改成目前已存在的 Application name,讓 eb cli 直接在既有的 Application 中建立 Environment 即可,不要再 Create New Application。並且指定要 PHP 5.6,以及 region 要在 ap-northeast-1 (Toyko)。

如此一來,再去執行 eb create 應該就能順利建立一個基本的 Environment,接著就能繼續用 eb cli 設定其他的細節。

看到這裡你可能會想說「等等!這樣也太麻煩了吧?難道不能利用一下我們前面已經做好的 template (Saved Configurations) 及已經上傳過的 Application Version (code) 嗎?」

當然可以,首先修改一下 config.yml,刪除我們不需要的部分,只需留下幾個項目即可。

global:
  application_name: TryLaravel
  default_platform: PHP 5.6
  default_region: ap-northeast-1
  profile: eb-cli

接著輸入指令。

eb create --cfg deploy_success --version v1 --timeout 30

--cfg 輸入已存放在此 Application 的 template (Saved Configurations) 名稱。

前面也有提到 Elastic Beanstalk 會自動幫你在 S3 上建立一個 Bucket。其實 template (Saved Configurations) 也會被存放在裡面。

存放路徑是 <Bucket>/resources/templates/<Application name>

例如:

elasticbeanstalk-ap-northeast-1-123456789012/resources/templates/TryLaravel

而使用 --cfg 不只可以指定雲端上的 template,也能指定使用存放在本機電腦上的 template,所以你可以將 S3 存放的 template 下載後拿去給其他專案,在建立新的 Application 時使用。
更多細節就不多說了,各位可以閱讀官方文件的這一段說明。


AWS Elastic Beanstalk 官方文件

多補上的 --timeout 是讓 Terminal 可以持續接收 Events,因為我們的 template 有包含建立 DB 的動作,需要比較久的時間,有時動作還沒做完 eb cli 已經 timeout 不再接收 Events。
當然 timeout 也不會有不倆影響,只是你無法在 Terminal 中看到 目前的 Events 而已,你還是可以前往 Web Console 查看。


沒意外當它跑完所有動作之後,我們一樣能順利看到 Laravel 預設的入口頁。

本文就到此結束,以上只能算是簡單的入門操作而已,Elastic Beanstalk 還有更多深入的內容,所以官方文件務必要仔細詳閱喔。



沒有留言:

張貼留言

不歡迎留言打廣告,所以有進行留言管理,敬請見諒。