在 Compute Engine 上运行 Ruby Bookshelf 应用

本教程介绍了如何在 Compute Engine 上运行 Ruby Bookshelf 示例应用。您可以按照本教程中的说明将现有 Ruby 网页应用部署到 Compute Engine。建议您完整阅读适用于 App Engine 标准环境的教程中的 Bookshelf 应用文档。

目标

  • 将 Bookshelf 示例应用部署到单个 Compute Engine 实例。
  • 通过使用托管实例组横向扩缩该应用。
  • 通过 HTTP 负载平衡来处理流量。
  • 通过自动扩缩来应对流量变化。

费用

本教程使用 Google Cloud Platform 的以下收费组件:

您可使用价格计算器根据您的预计使用情况来估算费用。GCP 新用户可能有资格免费试用

完成本教程后,您可以删除所创建的资源以避免继续计费。如需了解详情,请参阅清理

准备工作

  1. 登录您的 Google 帐号。

    如果您还没有 Google 帐号,请注册新帐号

  2. 在 GCP Console 的项目选择器页面上,选择或创建 GCP 项目。

    转到项目选择器页面

  3. 确保您的 Google Cloud Platform 项目已启用结算功能。 了解如何确认您的项目已启用结算功能

  4. 启用Cloud Datastore API、Cloud Storage API 和 Cloud Pub/Sub API API。

    启用 API

  5. 安装并初始化 Cloud SDK
  6. 安装 Ruby 2.3 或更高版本Ruby on Rails。您还需要 Ruby 中包含的 Ruby Gem

初始化 Cloud Datastore

Bookshelf 示例应用使用 Cloud Datastore 存储图书。要在您的项目中首次初始化 Cloud Datastore,请执行以下操作:

  1. 在 Google Cloud Platform Console 中打开 Cloud Datastore。

    打开 Cloud Datastore

  2. 为您的数据存储区选择一个区域,然后点击继续

    当您到达创建实体页面时,请关闭窗口。Bookshelf 应用已准备好在 Cloud Datastore 上创建实体。

创建 Cloud Storage 存储分区

以下说明介绍如何创建 Cloud Storage 存储分区。存储分区是 Cloud Storage 中用于存放数据的基本容器。

  1. 在终端窗口中,输入以下命令:

    gsutil mb gs://[YOUR-BUCKET-NAME]

    [YOUR-BUCKET-NAME] 表示 Cloud Storage 存储分区的名称。

  2. 要在 Bookshelf 应用中查看上传的图片,请将存储分区的默认访问控制列表 (ACL) 设置为 public-read

    gsutil defacl set public-read gs://[YOUR-BUCKET-NAME]

克隆示例应用

示例应用可在 GitHub 上的 GoogleCloudPlatform/getting-started-ruby 下找到。

  1. 克隆代码库。

    git clone https://github.com/GoogleCloudPlatform/getting-started-ruby.git
    
  2. 转到示例目录。

    cd getting-started-ruby/7-compute-engine
    

配置应用

  1. 安装依赖项。

    bundle install
    
  2. 通过复制提供的示例来创建配置文件。这些配置文件的路径包含在 .gitignore 中,因此不受版本控制系统的约束。

    cp config/database.example.yml config/database.yml
    cp config/settings.example.yml config/settings.yml
    
  3. 打开 config/settings.yml 进行修改并替换以下值:

    • @@PROJECT_ID@@ 替换为您的项目 ID。
    • @@BUCKET_NAME@@ 替换为您在上一步中创建的存储分区的名称。
    • @@CLIENT_ID@@ 替换为您的 OAuth 客户端 ID。
    • @@CLIENT_SECRET@@ 替换为您的 OAuth 客户端密钥。
  4. 保存并关闭 settings.yml

  5. 打开 config/database.yml 进行修改,并将 @@PROJECT_ID@@ 替换为您的项目 ID。

  6. 保存并关闭 database.yml

在本地计算机上运行应用

  1. 启动本地网络服务器。

    rails server
    
  2. 在网络浏览器中,输入 http://localhost:3000

    要停止本地网络服务器,请按 Control+C

在本地计算机上运行工作器

工作器使用 Resque 队列服务。Resque 由 Redis 支持,因此您需要一个在端口 6379 上本地运行的 Redis 服务器,以用于连接工作器。要开始使用 Redis,请参阅《Redis 快速入门》。

Redis 运行后,在新命令窗口中输入以下命令:

TERM_CHILD=1 QUEUE=* rake environment resque:work

现在将一些图书添加到 Bookshelf 应用。如果您的应用和工作器实例均在本地运行,则可以观察到工作器在后台更新图书信息。

Resque 的界面配置为可通过以下地址访问,您可使用该地址来检查工作器的状态:

http://localhost:3000/resque

将应用部署到单个实例

单实例部署

此部分逐步介绍了如何在 Compute Engine 上运行应用的单个实例。

将代码推送到代码库

您可以使用 Cloud Source Repositories 在项目中创建 Git 代码库,并将应用代码上传到其中。然后,您的实例可以在启动过程中从代码库中拉取应用代码的最新版本。这样,当您更新应用时,就不需要配置新映像或实例;您只需重启现有实例或创建一个新实例,因此使用 Git 代码库非常方便。

如果这是您第一次使用 Git,请使用 git config --global 设置您的身份

  1. 在 GCP Console 中,创建代码库:

    创建代码库

  2. 将应用的代码推送到项目的代码库中:

    git commit -am "Updating configuration"
    git config credential.helper gcloud.sh
    git remote add cloud https://source.developers.google.com/p/[YOUR_PROJECT_ID]/r/[YOUR_REPO]
    git push cloud master
    

    其中,[YOUR_PROJECT_ID] 是您的项目 ID,[YOUR_REPO] 是代码库的名称。

使用启动脚本初始化实例

现在,Compute Engine 实例可以访问您的代码,您需要一种方法来指示实例下载并运行这些代码。实例可以有一个每当其启动或重新启动时都会运行的启动脚本。

下面是 Bookshelf 示例应用中包含的启动脚本:

set -e

# Talk to the metadata server to get the project id
PROJECTID=$(curl -s "http://metadata.google.internal/computeMetadata/v1/project/project-id" -H "Metadata-Flavor: Google")
REPO_NAME="[YOUR_REPO_NAME]"

# Get the source code
export HOME=/root
git config --global credential.helper gcloud.sh
# Change branch from master if not using master
git clone https://source.developers.google.com/p/$PROJECTID/r/$REPO_NAME /opt/app -b master

pushd /opt/app/7-compute-engine

pushd config

cp database.example.yml database.yml
chmod go-rwx database.yml
cp settings.example.yml settings.yml
chmod go-rwx settings.yml

# Add your GCP project ID here
sed -i -e 's/@@PROJECT_ID@@/[YOUR_PROJECT_ID]/' settings.yml
sed -i -e 's/@@PROJECT_ID@@/[YOUR_PROJECT_ID]/' database.yml

# Add your cloud storage config here
sed -i -e 's/@@BUCKET_NAME@@/[YOUR_BUCKET_NAME]/' settings.yml

# Add your OAuth config here
sed -i -e 's/@@CLIENT_ID@@/[YOUR_CLIENT_ID]/' settings.yml
sed -i -e 's/@@CLIENT_SECRET@@/[YOUR_CLIENT_SECRET]/' settings.yml
popd # config

./gce/configure.sh

popd # /opt/app
set -e

curl -s "https://storage.googleapis.com/signals-agents/logging/google-fluentd-install.sh" | bash
cat >/etc/google-fluentd/config.d/railsapp.conf << EOF
<source>
  type tail
  format none
  path /opt/app/7-compute-engine/log/*.log
  pos_file /var/tmp/fluentd.railsapp.pos
  read_from_head true
  tag railsapp
</source>
EOF
service google-fluentd restart &

# Install dependencies from apt
apt-get update
apt-get install -y git ruby ruby-dev build-essential libxml2-dev zlib1g-dev nginx libmysqlclient-dev libsqlite3-dev redis-server

gem install bundler --no-ri --no-rdoc

useradd -m railsapp
chown -R railsapp:railsapp /opt/app

mkdir /opt/gem
chown -R railsapp:railsapp /opt/gem

sudo -u railsapp -H bundle install --path /opt/gem
sudo -u railsapp -H bundle exec rake assets:precompile

systemctl enable redis-server.service
systemctl start redis-server.service

cat gce/default-nginx > /etc/nginx/sites-available/default
systemctl restart nginx.service

cat gce/railsapp.service > /lib/systemd/system/railsapp.service
systemctl enable railsapp.service
systemctl start railsapp.service

cat gce/resqworker.service > /lib/systemd/system/resqworker.service
systemctl enable resqworker.service
systemctl start resqworker.service

该启动脚本执行以下任务:

  1. 从 Cloud Source Repositories 代码库克隆应用的源代码,并使用您的密钥设置配置文件。

  2. 安装 Logging 代理,并将其配置为监控应用的日志。这意味着,您在上一教程里配置的日志仍将上传到 GCP Console 的日志记录部分,就像是您在使用 App Engine 一样。

  3. 安装并配置 Ruby、Rails 和 NGINX。

自定义启动脚本

示例应用提供了一个启动脚本模板;您可以修改此模板,以便将您的密钥添加到其中。请注意,不得将密钥签入源代码控制系统。

  1. 将启动脚本模板复制到一个您将修改但不会签入的文件中:

    cp gce/startup-script.sh gce/my-startup.sh
    
  2. 修改 my-startup.sh 文件。

    为数据库和 Cloud Storage 添加密钥。这些密钥与您之前添加到 database.ymlsettings.yml 的密钥相同。将 [YOUR_* 占位符替换为您的值。

    示例如下:

    # Add your GCP project ID here
    sed -i -e 's/PROJECT_ID/your-project-id/' settings.yml
    sed -i -e 's/PROJECT_ID/your-project-id/' database.yml
    
    # Add your Cloud Storage config here
    sed -i -e 's/BUCKET_NAME/your-bucket-name/' settings.yml
    
    # Add your OAuth config here
    sed -i -e 's/CLIENT_ID/1234/' settings.yml
    sed -i -e 's/CLIENT_SECRET/1234/' settings.yml
    

创建和配置 Compute Engine 实例

  1. 创建 Compute Engine 实例。

    以下命令可创建实例,允许其访问 GCP 服务,并运行启动脚本。实例名称是 my-app-instance

    Linux/macOS

    gcloud compute instances create my-app-instance \
        --machine-type=g1-small \
        --scopes logging-write,storage-rw,datastore,https://www.googleapis.com/auth/projecthosting \
        --metadata-from-file startup-script=gce/my-startup.sh \
        --zone us-central1-f \
        --tags http-server \
        --image-family ubuntu-1604-lts \
        --image-project ubuntu-os-cloud
    

    Windows

    gcloud compute instances create my-app-instance ^
        --machine-type=g1-small ^
        --scopes logging-write,storage-rw,datastore,https://www.googleapis.com/auth/projecthosting ^
        --metadata-from-file startup-script=gce/my-startup.sh ^
        --zone us-central1-f ^
        --tags http-server ^
        --image-family ubuntu-1604-lts ^
        --image-project ubuntu-os-cloud
    

  2. 检查实例创建的进度。

    gcloud compute instances get-serial-port-output my-app-instance --zone us-central1-f
    

    如果启动脚本已完成,您会在命令输出末尾附近看到 Finished running startup script

  3. 创建一条防火墙规则以允许流量进入您的实例。

    Linux/macOS

    gcloud compute firewall-rules create default-allow-http-80 \
        --allow tcp:80 \
        --source-ranges 0.0.0.0/0 \
        --target-tags http-server \
        --description "Allow port 80 access to http-server"
    

    Windows

    gcloud compute firewall-rules create default-allow-http-80 ^
        --allow tcp:80 ^
        --source-ranges 0.0.0.0/0 ^
        --target-tags http-server ^
        --description "Allow port 80 access to http-server"
    

  4. 获取您的实例的外部 IP 地址。

    gcloud compute instances list
    
  5. 要查看应用是否正在运行,请转到 http://[YOUR_INSTANCE_IP]

    其中 [YOUR_INSTANCE_IP] 是您的实例的外部 IP 地址。

管理和监控实例

您可以使用 GCP Console 来监控和管理您的实例。

  • 要查看正在运行的实例并使用 ssh 连接到该实例,请从 GCP Console 转到虚拟机实例页面。

    转到“虚拟机实例”页面

  • 要查看 Compute Engine 资源生成的所有日志,请从 GCP Console 转到日志页面。

    转到“日志”页面

    Logging 会自动配置为从各种常用服务(包括 syslog)收集日志。

使用多个实例实现横向调节

使用托管实例的多实例部署

Compute Engine 可进行横向调节。通过使用托管实例组和 Compute Engine 自动调节程序,Compute Engine 可以在需要时自动创建应用的实例,并在需求较低时关停实例。您可以设置 HTTP 负载平衡器,以将流量分配给托管实例组中的实例。

部署脚本

示例应用包含一个自动执行以下部署步骤的脚本。名为 deploy.sh 的脚本会对自动执行调节和负载平衡的完整应用部署资源,如使用多个实例实现横向调节中所述。

您可以自行完成以下各个步骤,或者从 gce 目录运行 gce/deploy.sh

创建托管实例组

托管实例组是基于同一实例模板的一组同构实例。实例模板可定义实例的配置,包括源映像、磁盘大小、范围和元数据(包括启动脚本)。

  1. 创建模板。

    gcloud compute instance-templates create my-app-tmpl \
        --machine-type=g1-small \
        --scopes logging-write,storage-rw,datastore,https://www.googleapis.com/auth/projecthosting \
        --metadata-from-file startup-script=gce/my-startup.sh \
        --image-family ubuntu-1604-lts \
        --image-project ubuntu-os-cloud \
        --tags http-server
    
  2. 创建实例组。

    gcloud compute instance-groups managed create my-app-group \
        --base-instance-name my-app \
        --size 2 \
        --template my-app-tmpl \
        --zone us-central1-f
    

    --size 参数用于指定组中实例的数量。在所有实例都已运行完启动脚本后,您可以使用其外部 IP 地址和端口 8080 分别访问这些实例。要查找这些实例的外部 IP 地址,请输入 gcloud compute instances list。托管实例的名称以您在 --base-instance-name 参数中指定的同一前缀 my-app 开头。

创建负载平衡器

单个实例可用于测试或调试,但要处理网络流量,最好使用负载平衡器将流量自动引导至可用实例。要创建负载平衡器,请按照以下步骤操作。

  1. 创建运行状况检查。

    负载平衡器会使用运行状况检查来确定哪些实例能够处理流量。

    gcloud compute http-health-checks create bookshelf-health-check \
        --request-path / \
        --port 8080
    
  2. 创建一个已命名的端口:

    HTTP 负载平衡器会查找 http 服务以了解将流量引导至哪个端口。在现有实例组中,为端口 8080 指定名称 http

    gcloud compute instance-groups managed set-named-ports my-app-group \
        --named-ports http:8080 \
        --zone us-central1-f
    
  3. 创建后端服务。

    后端服务是经过负载平衡后的流量的目标。它定义了将流量引导至哪个实例组,以及要使用哪种运行状况检查。

    gcloud compute backend-services create my-app-service \
        --http-health-check bookshelf-health-check
    
  4. 添加后端服务。

    gcloud compute backend-services add-backend my-app-service \
        --group my-app-group \
        --zone us-central1-f
    
  5. 创建一个网址映射和代理。

    网址映射定义了将哪些网址引导至哪些后端服务。在此示例中,所有流量都由一个后端服务处理。如果您想对多个区域或组之间的请求执行负载平衡,则可以创建多个后端服务。代理会接收流量并使用网址映射将其转发到后端服务。

    1. 创建网址映射。

      gcloud compute url-maps create my-app-service-map \
          --default-service my-app-service
      
    2. 创建代理。

      gcloud compute target-http-proxies create my-app-service-proxy \
          --url-map my-app-service-map
      
  6. 创建全局转发规则。全局转发规则会将公共 IP 地址和端口绑定到代理。

    gcloud compute forwarding-rules create my-app-service-http-rule \
        --global \
        --target-http-proxy my-app-service-proxy \
        --port-range 80
    

配置自动调节程序

负载平衡器可确保流量分配给所有正常运行的实例。但如果您的实例需要处理的流量过多,该怎么办?您可以手动添加更多实例,但更好的解决方案是配置 Compute Engine 自动调节程序,以根据流量需求自动创建和删除实例。

  1. 创建自动调节程序。

    gcloud compute instance-groups managed set-autoscaling my-app-group \
        --max-num-replicas 10 \
        --target-load-balancing-utilization 0.5 \
        --zone us-central1-f
    

    以上命令会在托管实例组(可自动扩大至最多 10 个实例)上创建一个自动调节程序。系统会在负载平衡器的利用率高于 50% 时添加实例,并在利用率低于 50% 时移除实例。

  2. 检查进度,直到至少有一个实例显示 HEALTHY 为止。

    gcloud compute backend-services get-health frontend-web-service --global
    

查看您的应用

  1. 获取负载平衡器的转发 IP 地址。

    gcloud compute forwarding-rules list --global
    

    您的转发规则 IP 地址位于 IP_ADDRESS 列中。

  2. 在浏览器中,输入列表中的 IP 地址。

    现在,您的应用已经过了负载平衡和自动调节,正在 Google Compute Engine 上运行。

管理和监控您的部署

您可以使用 GCP Console 监控负载平衡、自动扩缩和托管实例组。

清理

为避免因本教程中使用的资源而导致系统向您的 Google Cloud Platform 帐号收取费用,请执行以下操作:

运行收尾清理脚本

如果您运行了 deploy.sh 脚本,请运行 teardown.sh 脚本以移除 deploy.sh 脚本创建的所有资源。这会将您的项目恢复为运行 deploy.sh 脚本之前的状态,还有助于避免继续产生费用。要移除在本教程开头部分创建的单个实例和存储分区,请按照下一部分中的说明进行操作。

手动删除资源

如果您手动执行本教程中的步骤,则可以手动删除您创建的云资源。

删除负载平衡器

  1. 在 GCP Console 中,转到负载平衡页面。

    转到“负载平衡”页面

  2. 选中要删除的负载平衡器旁边的复选框,然后点击删除delete

  3. 删除负载平衡器对话框中,选择关联的后端服务和运行状况检查资源,然后点击删除delete。该负载平衡器及其关联资源将被删除。

删除 Compute Engine 托管实例组

要删除 Compute Engine 实例组,请运行以下命令:

  1. 在 GCP Console 中,转到实例组页面。

    转到“实例组”页面

  2. 点击要删除的实例组。
  3. 点击删除 delete 以删除实例组。

删除单个 Compute Engine 实例

要删除 Compute Engine 实例,请运行以下命令:

  1. 在 GCP Console 中,转到虚拟机实例页面。

    转到“虚拟机实例”页面

  2. 点击您要删除的实例。
  3. 点击删除 delete 以删除映像。

删除您的 Cloud Storage 存储分区

要删除 Cloud Storage 存储分区,请执行以下操作:

  1. 在 GCP Console 中,转到 Cloud Storage 浏览器页面。

    转到“Cloud Storage 浏览器”页面

  2. 点击要删除的存储分区对应的复选框。
  3. 点击删除 以删除存储分区。

后续步骤