Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Ruby

Triển Khai Rails 6 Trên AWS Elastic Beanstalk & RDS: Hướng Dẫn Hoàn Chỉnh

Khi viết ứng dụng, một vấn đề lớn bạn phải suy nghĩ là cách ứng dụng sẽ được chia sẻ với thế giới.

Một cách phổ biến là triển khai trên Heroku. Nó dễ setup và fully managed. Nhưng cũng thường thấy teams bỏ Heroku sau. Khi traffic tăng, Heroku trở nên quá đắt và thiếu linh hoạt.

Điều gì nếu có thể deploy ứng dụng mới với sự dễ dàng như Heroku mà không hy sinh sự linh hoạt và tiết kiệm chi phí từ platform chung như AWS? Đó là có thể, dùng Elastic Beanstalk — dịch vụ từ AWS.

Trong bài này, tôi sẽ hướng dẫn setup Rails 6 app và chạy trên AWS dùng Elastic Beanstalk làm compute base và RDS (Relational Database Service) — cụ thể Postgres — làm data store.

Cuối tutorial, bạn sẽ có thể:

  1. Setup Rails 6 app với vài routes và chạy local.
  2. Tạo AWS account.
  3. Setup và deploy app lên Elastic Beanstalk dùng free-tier resources.

Hãy bắt đầu.

Elastic Beanstalk Và RDS Là Gì?

Để hiểu Elastic Beanstalk và vấn đề nó giải quyết, trước hãy nói về EC2 của Amazon.

EC2 là Elastic Compute Cloud 2. Dịch vụ này cho bạn provision VPCs, cơ bản là máy tính, chạy OS bạn chọn (ví dụ Ubuntu). App sẽ sống trong máy này và truy cập resources như file system, RAM để deliver tasks. Cuối cùng, app chạy giống như local, chỉ khác máy thuộc Amazon và accessible qua internet dùng infrastructure của Amazon.

Hãy tưởng tượng user Alice, đã provision instance trên EC2. Alice cần:

  • Setup security group cho phép requests đến app.
  • Setup load balancer.
  • SSH vào instance, setup app và environment secrets, v.v.

Điều này cho full control nhưng đôi khi bạn muốn focus vào app chứ không phải infrastructure. Đó là lúc Elastic Beanstalk xuất hiện.

Elastic Beanstalk cung cấp CLI làm dễ dàng mọi việc này và tự động hóa hầu hết: tạo security groups, load balancers. Infrastructure bên dưới vẫn là EC2, nhưng thêm layer abstraction với visual dashboard cho phép setup environment variables, databases, auto-scaling, lấy logs và các functions khác rất đơn giản.

Rails Là Gì?

Nhiều tools có thể đưa web app lên chạy. Thường library/framework bạn chọn phụ thuộc vào ngôn ngữ.

Nếu ngôn ngữ bạn chọn là Ruby, framework phổ biến là Rails (Ruby on Rails). Rails tạo ra tại Basecamp 2003, qua nhiều năm đã trở thành framework đầy đủ, mature, bao gồm gần như mọi thứ để build modern web app.

Với Rails bạn build từ personal blog đơn giản đến Airbnb, GitHub phức tạp. Chắc bạn biết hai công ty này, và đúng, chúng chạy trên Rails!

Dù bài này dùng ví dụ deploy Rails app lên AWS, hầu hết concepts chính giống nhau bất kể language/framework: Python/Django, PHP/Laravel.

Setup Rails

Lưu ý: commands dưới đây chạy out-of-the-box trên UNIX/Linux. Nếu dùng Windows, hãy dùng Windows Subsystem for Linux và/hoặc Microsoft Windows Terminal.

Trước hết, verify Ruby version:

ruby -v

Bất kỳ version 2.5.0 trở lên đều OK. Nếu không, vào đây lấy latest version. Tôi dùng 2.6.5.

Nếu Ruby OK, install Rails:

gem install rails

Sau đó confirm Rails version:

rails --version

Nếu thấy version trên 6.0.0, bạn ready cho tutorial.

Setup Postgres

Chúng ta dùng Postgres DB làm data store. Đây là guide tuyệt vời cài đặt trên mọi platform.

Thêm Và Chạy Code

Chúng ta build API đơn giản lưu movie data: name, release year, genre. API chỉ có 2 endpoints GET & POST cho demo.

Tạo Rails API app mới:

rails new movie-api --api --database=postgresql

Sau khi command chạy thành công, chắc chắn cd vào project folder trước khi chạy commands tiếp.

Generate model:

rails generate model Movie name:string year:integer genre:string

Setup database và run migrations:

rails db:setup
rails db:migrate

Nếu thành công, bạn thấy migration mới trong db/migrate giống như:

class CreateMovies < ActiveRecord::Migration[6.0]
  def change
    create_table :movies do |t|
      t.string :name
      t.integer :year
      t.string :genre
      t.timestamps
    end
  end
end

Thêm controller logic cho API endpoints:

rails g controller api/Movies

Thêm code vào app/controllers/movies_controller.rb:

class Api::MoviesController < ApplicationController
  # GET /movies
  def show
    @movies = Movie.all
    render json: @movies
  end

  # POST /movies
  def create
    @movie = Movie.new(movie_params)
    if @movie.save
      render json: @movie
    else
      render error: {error: 'Failed to add movie record'}, status: 400
    end
  end

  private

  def movie_params
    params.require(:movie).permit(:name, :year, :genre)
  end
end

Setup routes vào config/routes.rb:

Rails.application.routes.draw do
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
  namespace :api do
    resource :movies
  end
end

Sanity check với rails routes để verify mọi thứ OK. Output chứa tương tự:

Triển Khai Rails 6 Trên AWS Elastic Beanstalk & RDS: Hướng Dẫn Hoàn Chỉnh

Trước khi chạy server, thêm seed data vào db/seeds.rb:

# This file should contain all the record creation needed to seed the database with its default values.
# The data can then be loaded with the Rails db:seed command (or created alongside the database with db:setup).
movies = Movie.create([
  { name: 'Star Wars', year: 1977, genre: 'SCI-FI'},
  { name: 'Lord of the Rings', year: 2001, genre: 'Fantasy' }
])

Chạy command thêm data vào DB:

rails db:seed

Chạy API:

rails s

Truy cập https://127.0.0.1:3000/api/movies thấy seed data:

[
  {
    "id": 1,
    "name": "Star Wars",
    "year": 1977,
    "genre": "SCI-FI",
    "created_at": "2020-01-01T10:04:56.100Z",
    "updated_at": "2020-01-01T10:04:56.100Z"
  },
  {
    "id": 2,
    "name": "Lord of the Rings",
    "year": 2001,
    "genre": "Fantasy",
    "created_at": "2020-01-01T10:04:56.108Z",
    "updated_at": "2020-01-01T10:04:56.108Z"
  }
]

Tạo AWS Account

Vào website này. Nếu chưa có account hoặc chưa sign in từ browser, bạn thấy trang như sau:

Triển Khai Rails 6 Trên AWS Elastic Beanstalk & RDS: Hướng Dẫn Hoàn Chỉnh

Click nút cam Create an AWS Account góc trên phải (hoặc sign in nếu đã có). Điền signup form (chọn Account Type là Personal khi điền địa chỉ), bạn vào console. Đừng quên verify email!

Đừng lo nếu UI overwhelming. Nó đơn giản khi bạn biết đi đâu.

Setup IAM User

Tiếp theo setup IAM user. Cho access API keys để SSH và access resources từ ngoài AWS.

Cũng nên có IAM user riêng chỉ access resources cần thiết thay vì dùng admin credentials mặc định cho security.

Trang home, search IAM và navigate đến IAM home page.

Triển Khai Rails 6 Trên AWS Elastic Beanstalk & RDS: Hướng Dẫn Hoàn Chỉnh

Trên IAM homepage, dưới IAM Resources, click Users: 0.

Triển Khai Rails 6 Trên AWS Elastic Beanstalk & RDS: Hướng Dẫn Hoàn Chỉnh

Click Add User. Điền username, chọn checkbox Programmatic access.

Triển Khai Rails 6 Trên AWS Elastic Beanstalk & RDS: Hướng Dẫn Hoàn Chỉnh

Màn hình tiếp theo, chọn Attach existing policies directly, search AdministratorAccess.

Triển Khai Rails 6 Trên AWS Elastic Beanstalk & RDS: Hướng Dẫn Hoàn Chỉnh

Trang sau, thêm name tag để identify user sau:

Triển Khai Rails 6 Trên AWS Elastic Beanstalk & RDS: Hướng Dẫn Hoàn Chỉnh

Trang review, click Create User.

Trang sau, download CSV file chứa credentials. Cần cho phần sau.

Mở file credentials.csv trong spreadsheet app hoặc editor. Quan tâm nhất: Access key ID và Secret access key.

Cuối cùng, vào HOME folder, tạo folder .aws. Bên trong tạo file config (không extension). Full path như /Users/your-user/.aws/config.

Nếu không tạo được folder .aws và file config, có thể skip. Quan trọng là có CSV credentials cho sau.

Đặt vào file config:

[profile eb-cli]
region = us-east-1
aws_access_key_id = your-aws-access-key-id
aws_secret_access_key = your-aws-secret-access-key

AWS region tìm thấy góc trên phải AWS account page khi sign in.

Tạo RDS DB

Tạo Postgres DB để app communicate. Search RDS từ home page.

Trang RDS home, click Create database.

Triển Khai Rails 6 Trên AWS Elastic Beanstalk & RDS: Hướng Dẫn Hoàn Chỉnh

Chọn Standard Create; dưới Engine Options chọn PostgreSQL.

Triển Khai Rails 6 Trên AWS Elastic Beanstalk & RDS: Hướng Dẫn Hoàn Chỉnh

Kéo xuống, chọn Free tier dưới Templates, dưới Settings để DB instance identifier là movie-api. Master username để postgres, thêm password.

Triển Khai Rails 6 Trên AWS Elastic Beanstalk & RDS: Hướng Dẫn Hoàn Chỉnh

Bỏ qua DB instance size, Storage, Availability & durability. Dưới Connectivity, chọn Additional connectivity configuration, set Publicly accessible = Yes, VPC Security group = Create new.

Triển Khai Rails 6 Trên AWS Elastic Beanstalk & RDS: Hướng Dẫn Hoàn Chỉnh

Bỏ qua Database authentication. Dưới Additional configuration, thêm Initial database name; movie_api_db OK. Bỏ qua hết, click Create Database cuối trang.

Quay lại RDS dashboard, click default group dưới VPC Security groups cột phải:

Triển Khai Rails 6 Trên AWS Elastic Beanstalk & RDS: Hướng Dẫn Hoàn Chỉnh

Cuối trang, chọn Inbound edit rules như sau:

Triển Khai Rails 6 Trên AWS Elastic Beanstalk & RDS: Hướng Dẫn Hoàn Chỉnh

Đảm bảo Outbound rules như sau:

Triển Khai Rails 6 Trên AWS Elastic Beanstalk & RDS: Hướng Dẫn Hoàn Chỉnh

Tạo Elastic Beanstalk App

Navigate đến Elastic Beanstalk home, click Create New Application.

Triển Khai Rails 6 Trên AWS Elastic Beanstalk & RDS: Hướng Dẫn Hoàn Chỉnh

Điền form application.

Triển Khai Rails 6 Trên AWS Elastic Beanstalk & RDS: Hướng Dẫn Hoàn Chỉnh

Thấy message No environments currently exist for this application. Create one now. Click Create one now.

Chọn Web server environment.

Triển Khai Rails 6 Trên AWS Elastic Beanstalk & RDS: Hướng Dẫn Hoàn Chỉnh

Đổi Environment name thành production-env. Domain để trống. Dưới Base Configuration, chọn Preconfigured platform chọn Ruby. Application code để Sample application, click Create environment. Mất thời gian, kiên nhẫn.

Triển Khai Rails 6 Trên AWS Elastic Beanstalk & RDS: Hướng Dẫn Hoàn Chỉnh

Xong, thấy trang như sau:

Triển Khai Rails 6 Trên AWS Elastic Beanstalk & RDS: Hướng Dẫn Hoàn Chỉnh

Tìm URL sau environment ID. Click để xem default Ruby app trên Elastic Beanstalk. Sớm API bạn sẽ chạy trên URL đó.

Chuẩn Bị App Cho Deployment

Để app ready cho deployment, config web server trước.

Rails ship Puma — production-ready web server — làm default. Edit config tại config/puma.rb:

max_threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count }
threads min_threads_count, max_threads_count

# Specifies the `port` that Puma will listen on to receive requests; default is 3000.
# port ENV.fetch("PORT") { 3000 }

# Specifies the `environment` that Puma will run in.
# environment ENV.fetch("RAILS_ENV") { "development" }

# Specifies the `pidfile` that Puma will use.
pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" }

# Specifies the number of `workers` to boot in clustered mode.
# Workers are forked web server processes. If using threads and workers together,
# the concurrency of the application would be max `threads` * `workers.`
# Workers do not work on JRuby or Windows (both of which do not support
# processes).
# workers ENV.fetch("WEB_CONCURRENCY") { 2 } # <------ uncomment this line

# Use the `preload_app!` method when specifying a `workers` number.
# This directive tells Puma to first boot the application and load code
# before forking the application. This takes advantage of Copy On Write
# process behavior so workers use less memory.
# preload_app! # <------ uncomment this line

# Allow Puma to be restarted by the `Rails restart` command.
plugin :tmp_restart

Edit cuối config/database.yml, comment existing production config, dùng:

production:
  url: <%= ENV['DATABASE_URL'] %>

Vào Elastic Beanstalk console, chọn environment production-env, vào Configuration.

Màn hình configuration overview, click Modify cho Software:

Triển Khai Rails 6 Trên AWS Elastic Beanstalk & RDS: Hướng Dẫn Hoàn Chỉnh

Thêm DATABASE_URL và RAILS_ENV, click 'Apply':

Triển Khai Rails 6 Trên AWS Elastic Beanstalk & RDS: Hướng Dẫn Hoàn Chỉnh

DB URL dùng Endpoint từ RDS dashboard. Format: postgresql://postgres:YOURPASSWORD@ENDPOINT:5432/movie_api_db. Quên password? Đổi ở Modify section của DB RDS dashboard.

Manual Deployment

Đơn giản: tạo zip file app từ command line, upload lên Elastic Beanstalk console.

cd vào project folder. Tạo zip:

zip -r deploy_1.zip .

deploy_1.zip xuất hiện trong project directory. Xong? Vào AWS.

Từ Elastic Beanstalk Dashboard, click Upload and Deploy:

Triển Khai Rails 6 Trên AWS Elastic Beanstalk & RDS: Hướng Dẫn Hoàn Chỉnh

Đổi version label meaningful hơn:

Triển Khai Rails 6 Trên AWS Elastic Beanstalk & RDS: Hướng Dẫn Hoàn Chỉnh

Sau khi Elastic Beanstalk update environment xong, truy cập environment URL xem API running! Dùng free service để send requests populate DB trên AWS.

Deployment Với EB CLI

Elastic Beanstalk CLI làm dễ dàng hầu hết việc manual trên với vài commands. Setup và dùng trên project hiện tại. Phụ thuộc vào IAM user setup đúng, đảm bảo step đó OK hoặc có CSV credentials.

Hầu hết máy đã có Python. Install:

pip install awsebcli --user

MacOS cũng dùng:

brew install awsebcli

Đọc thêm về installation tại đây.

Sau install, cd project folder chạy eb init.

Follow prompts theo AWS environment. Chọn region bằng số:

Select a default region
1) us-east-1 : US East (N. Virginia)
2) us-west-1 : US West (N. California)
3) us-west-2 : US West (Oregon)
4) eu-west-1 : EU (Ireland)
5) eu-central-1 : EU (Frankfurt)
6) ap-south-1 : Asia Pacific (Mumbai)
7) ap-southeast-1 : Asia Pacific (Singapore)
8) ap-southeast-2 : Asia Pacific (Sydney)
9) ap-northeast-1 : Asia Pacific (Tokyo)
10) ap-northeast-2 : Asia Pacific (Seoul)
11) sa-east-1 : South America (Sao Paulo)
12) cn-north-1 : China (Beijing)
13) cn-northwest-1 : China (Ningxia)
14) us-east-2 : US East (Ohio)
15) ca-central-1 : Canada (Central)
16) eu-west-2 : EU (London)
17) eu-west-3 : EU (Paris)

Phần Ruby version, chọn version liên quan dùng Puma:

1) Ruby 2.6 (Passenger Standalone)
2) Ruby 2.6 (Puma)
3) Ruby 2.5 (Passenger Standalone)
4) Ruby 2.5 (Puma)
5) Ruby 2.4 (Passenger Standalone)
6) Ruby 2.4 (Puma)
7) Ruby 2.3 (Passenger Standalone)
8) Ruby 2.3 (Puma)
9) Ruby 2.2 (Passenger Standalone)
10) Ruby 2.2 (Puma)
11) Ruby 2.1 (Passenger Standalone)
12) Ruby 2.1 (Puma)
13) Ruby 2.0 (Passenger Standalone)
14) Ruby 2.0 (Puma)
15) Ruby 1.9.3

Tôi chọn 2.

Làm theo prompts còn lại, chọn 'no' cho CodeCommit và 'no' cho setup SSH.

Nếu không setup AWS config, CLI sẽ prompt AWS keys. Thêm như yêu cầu.

Xong, CLI exit. Chạy commands như eb status check status app deployed.

Environment details for: production-env
Application name: movie-api
Region: us-east-2
Deployed Version: Deploy 2-2
Environment ID: e-mab3kjy6pp
Platform: arn:aws:elasticbeanstalk:us-east-2::platform/Puma with Ruby 2.6 running on 64bit Amazon Linux/2.11.1
Tier: WebServer-Standard-1.0
CNAME: production-env.qnbznvpp2t.us-east-2.elasticbeanstalk.com
Updated: 2020-01-22 23:37:17.183000+00:00
Status: Ready
Health: Green

Deploy version mới, chạy eb deploy.

Xong! Đọc thêm CLI commands khác tại đây.

Tóm Tắt

Trong tutorial, chúng ta học setup Rails API đơn giản, setup AWS resources (Elastic Beanstalk, RDS), deploy app dùng chúng.

Cũng cover dùng Elastic Beanstalk CLI tự động hóa deployments. Bây giờ bạn biết cách từ app chạy local đến app shared với thế giới trên AWS.