在Sinatra上尝试使用Google App Engine / Ruby
好的,在2016年的GCP Next大会上有个重要的公告,就是Google App Engine现在支持Ruby语言了。
- [速報]Google App EngineがRubyとNode.jsのサポートを発表。GCP Next 2016
我简单地试了一下,跟你分享一下。
准备Google Cloud平台的项目。
把App Engine的区域设置为美国。
目前看来,似乎必须选择美国。欧洲不行。默认应该是us-central,所以应该没问题。

启用计费
这个价格相当便宜,几乎处于创建账户初始阶段提供的优惠范围内,但若不激活付款功能就无法试用。
谷歌应用引擎弹性环境实际上是一个“套用以8080端口处理HTTP请求的Docker容器作为<应用程序>的自动扩展、Docker Engine、负载均衡器和性能分析器的设置”。Docker引擎通常在计算引擎实例上运行。因此,基本上需要支付一个计算引擎实例的费用。
在本地安装Google Cloud SDK。
按照官方网站提供的指南进行安装。
$ curl https://sdk.cloud.google.com | bash
$ exec -l $SHELL
$ gcloud init
如果已經安裝了,為了安全起見,請更新組件。
$ gcloud components update
Your current Cloud SDK version is: 99.0.0
You will be upgraded to version: 102.0.0
┌─────────────────────────────────────────────────────┐
│ These components will be updated. │
├──────────────────────────────┬────────────┬─────────┤
│ Name │ Version │ Size │
├──────────────────────────────┼────────────┼─────────┤
│ BigQuery Command Line Tool │ 2.0.24 │ < 1 MiB │
│ Cloud SDK Core Libraries │ 2016.03.22 │ 3.9 MiB │
│ gcloud app Python Extensions │ 1.9.34 │ 7.2 MiB │
└──────────────────────────────┴────────────┴─────────┘
...... 略 .....
Update done!
应用程序开发
创建一个app.yaml文件
创建一个类似以下内容的 app.yaml 文件。app.yaml 是App Engine 的定义文件。与传统的“.yml”不同,它的扩展名惯例上是“.yaml”。
runtime: ruby
vm: true
entrypoint: bundle exec rackup -p 8080 -E production config.ru
resources:
cpu: .5
memory_gb: 1.3
disk_size_gb: 10
automatic_scaling:
min_num_instances: 1
max_num_instances: 5
cool_down_period_sec: 60
cpu_utilization:
target_utilization: 0.5
顺便提一下,如果在没有 app.yaml 文件的情况下尝试使用 gcloud preview app deploy 命令,它会根据该目录的状态自动创建 app.yaml 文件。根据我的测试经验,如果存在 Gemfile 和 config.ru文件,那么会自动判断是不是 Ruby 项目,并且生成相应的 app.yaml 文件。
Gemfile是一个包含Ruby项目所需gem依赖的文件,而bundle install则是一个用于安装这些依赖的命令。
在这里,我们将创建一个非常简单的Sinatra应用程序,为此,请准备以下Gemfile。
source 'https://rubygems.org'
gem 'sinatra'
进行安装。
bundle install
请创建一个名为 config.ru 的文件。
为了简单起见,在config.ru文件中直接创建应用程序。
require 'sinatra/base'
class App < Sinatra::Base
get '/' do
"hello sinatra"
end
end
run App.new
文件布局
$ tree
.
├── Gemfile
├── Gemfile.lock
├── app.yaml
└── config.ru
现状就是这样。
部署
在具有 app.yaml 文件的目录中运行 gcloud preview app deploy 命令即可进行部署。
如果没有设置特定选项,这个命令将…
-
- 部署新版本
-
- 将请求分配给新版本
- 在所有流量指向新版本应用程序后,废弃旧版本实例
该操作可以通过使用 –promote 或者 –no-promote 选项来进行更改。请参考 gcloud preview app deploy –help 获取更多详情。
尝试部署
初始出现的警告是关于使用预览状态命令的提醒,但如果不仔细阅读文档是不行的,请忽略这里。
$ gcloud preview app deploy
WARNING: The `gcloud preview app` surface is rapidly improving. Look out for
changing flags and new commands before the transition out of the `preview`
component. These changes will be documented in the Cloud SDK release notes
<https://goo.gl/X8apDJ> and via deprecation notices for changing commands.
If you would like to avoid changing behavior, please pin to a fixed version of
the Google Cloud SDK as described under the "Alternative Methods" section of the
Cloud SDK web site: <https://cloud.google.com/sdk/#alternative>.
You are about to deploy the following modules:
- hogehoge-funfun/default (from [/Users/ma2saka/tech-dev/default/app.yaml])
Deployed URL: [https://hogehoge-funfun.appspot.com]
Do you want to continue (Y/n)? Y
当初的部署情况下,
If this is your first deployment, this may take a while...-
我们将需要等待很长时间。因为要设置App Engine的负载均衡器,设置Docker Engine等等,所以会花费很多时间。让我们耐心等待吧。
过了一会儿,建构日志就会像下面这样显示出来。
... 略 ...
Verifying that Managed VMs are enabled and ready.
Building and pushing image for module [default]
Started cloud build [55XXa2XX-fXXXX-XX-XXXXX-7XXcbXXXXXX4].
To see logs in the Cloud Console: https://console.developers.google.com/logs?project=hogehoge-funfun&service=cloudbuild.googleapis.com&key1=55XXa2XX-fXXXX-XX-XXXXX-7XXcbXXXXXX4&logName=projects/hogehoge-funfun/logs/cloudbuild
----------------------------- REMOTE BUILD OUTPUT -----------------------------
starting build "55XXa2XX-fXXXX-XX-XXXXX-7XXcbXXXXXX4"
FETCHSOURCE
Fetching storage object: gs://staging.hogehoge-funfun.appspot.com/hogehoge-funfun.default.20160326t114542#1458960451575000
Copying gs://staging.hogehoge-funfun.appspot.com/hogehoge-funfun.default.20160326t114542#1458960451575000...
Downloading file:///tmp/source-archive.tgz: 0 B/1.23 KiB Downloading file:///tmp/source-archive.tgz: 1.23 KiB/1.23 KiB
FETCHBUILDER
Using default tag: latest
... 略 ...
我正在构建Docker镜像,我能看出它是在使用Google Cloud Container Builder进行执行。与将镜像从本地带来构建和上传的方式相比,这种方式对通信网络更友好,这对于网络流量有限的用户来说非常令人高兴,尤其是作为一个依赖移动网络的人来说。
33ea738d3459: Image successfully pushed
50f67d2b5587: Pushing
50f67d2b5587: Image successfully pushed
f76fbdd2abab: Pushing
f76fbdd2abab: Image successfully pushed
Pushing tag for rev [f76fbdd2abab] on {https://appengine.gcr.io/v1/repositories/gcloud/hogehoge-funfun.default.20160326t114542/tags/latest}
DONE
-------------------------------------------------------------------------------
Updating module [default]...done.
Deployed module [default] to [https://hogehoge-funfun.appspot.com]
部署已经完成。最终,Docker 容器镜像已上传到 gcr.io。
确认行动
显示出用于最后访问的URL后,让我们点击试试看。
$ curl -i https://hogehoge-funfun.appspot.com
HTTP/1.1 200 OK
Content-Type: text/html;charset=utf-8
X-Xss-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Via: inde199:14908
Date: Sat, 26 Mar 2016 03:00:38 GMT
Server: Google Frontend
Content-Length: 13
Alternate-Protocol: 443:quic,p=1
Alt-Svc: quic=":443"; ma=2592000; v="31,30,29,28,27,26,25"
hello sinatra
我动了!
Sinatra可以运行的话,Rails大概也可以运行。实际上,Ruby官方的入门教程示例应用程序就是一个常规的Rails应用程序。
- https://github.com/GoogleCloudPlatform/getting-started-ruby
请修正代码并重新上传。
尝试进行状态更新和环境变量确认。
git diff
diff --git a/config.ru b/config.ru
index e042580..a2486fc 100644
--- a/config.ru
+++ b/config.ru
@@ -3,7 +3,7 @@ require 'sinatra/base'
class App < Sinatra::Base
get '/' do
- "hello sinatra"
+ ENV.collect {|x| "#{x[0]} = #{x[1]}"} .join("\n")
end
end
我們只需部署,然後觀察動作即可。
$ gcloud preview app deploy
所以,最后的结果是。
$ curl -s https://hogehoge-funfun.appspot.com
RBENV_VERSION = 2.3.0
APPENGINE_LOADBALANCER =
MEMCACHE_PORT_11211_TCP_PROTO = tcp
HOSTNAME = 9647520bdc61
NOKOGIRI_USE_SYSTEM_LIBRARIES = 1
GAE_APPENGINE_HOSTNAME = hogehoge-funfun.appspot.com
PREINSTALLED_RUBY_VERSIONS = 2.1.8 2.2.4 2.3.0
MEMCACHE_NAME = /gaeapp/memcache
MEMCACHE_PORT_11211_TCP_ADDR = 172.17.X.X
GAE_MODULE_NAME = default
GAE_AFFINITY = true
FOREMAN_VERSION = 0.78.0
RBENV_ROOT = /rbenv
GAE_LONG_APP_ID = hogehoge-funfun
RACK_ENV = production
GAE_MODULE_VERSION = 20160326t120623
RBENV_HOOK_PATH = /rbenv/rbenv.d:/usr/local/etc/rbenv.d:/etc/rbenv.d:/usr/lib/rbenv/hooks
MEMCACHE_PORT_11211_TCP_PORT = 11211
GAE_MODULE_INSTANCE = 0
APPENGINE_LOADBALANCER_IP =
PATH = /rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/bin:/rbenv/versions/2.3.0/bin:/rbenv/libexec:/rbenv/plugins/ruby-build/bin:/rbenv/shims:/rbenv/bin:/nodejs/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
RUBY_CONFIGURE_OPTS = --disable-install-doc
GAE_MINOR_VERSION = 391637041054208257
PWD = /app
MEMCACHE_PORT = tcp://172.17.X.X:11211
MODULE_YAML_PATH = app.yaml
SHLVL = 0
HOME = /root
MEMCACHE_PORT_11211_TCP = tcp://172.17.X.X:11211
USE_MVM_AGENT = true
RBENV_DIR = /app
SERVER_SOFTWARE = Google App Engine/1.9.35
GAE_VM = true
DEBIAN_FRONTEND = noninteractive
PORT = 8080
MEMCACHE_ENV_PORT = 8080
MEMCACHE_ENV_DEBIAN_FRONTEND = noninteractive
RUBYLIB = /rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/bundler-1.11.2/lib:/rbenv/rbenv.d/exec/gem-rehash
GAE_PARTITION = s
BUNDLER_VERSION = 1.11.2
RUBYOPT = -rbundler/setup
GEM_PATH = /rbenv/versions/2.3.0/lib/ruby/gems/2.3.0:/root/.gem/ruby/2.3.0
GEM_HOME = /rbenv/versions/2.3.0/lib/ruby/gems/2.3.0
BUNDLE_BIN_PATH = /rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/bundler-1.11.2/exe/bundle
BUNDLE_GEMFILE = /app/Gemfile
你可以看到对方也在使用rbenv,应用程序位于/app目录下,rbenv位于/rbenv目录下,Ruby默认版本为2.3.0,提供了memcached。
确认实例正在运行并检查仪表盘。
当你通过浏览器进入开发者控制台时,可以看到 App Engine 的仪表板以及 Compute Engine 上有一个实例正在运行。
$ gcloud compute instances list
NAME ZONE MACHINE_TYPE PREEMPTIBLE INTERNAL_IP EXTERNAL_IP STATUS
gae-default-20160326t120623-1r0h us-central1-f g1-small 10.128.X.X 104.197.XXX.XX RUNNING

在仪表盘上,有链接指向访问分析之类的。
查看日志
如果能够上传应用程序,之后只需要确认日志。
所有日志等都由名为Stackdriver的系统进行集中管理。在GCP内部,被简洁地标记为”日志”。
由于Stackdriver是一项新服务,所以预计这里所写的内容会很快过时,但总的来说,包括Flexible Environment在内的所有内容都还在测试阶段,所以没关系。虽然有点难理解,但Stackdriver作为一个独立的服务也存在,同时也有整合到Google Cloud Platform的Stackdriver系统。
-
- Google、競合のAWSもモニタリングできる「Google Stackdriver」公開
- Stackdriver
Stackdriver可以将App Engine的请求以及更广泛的范围内的日志聚合起来。

通过使用Google Cloud Platform,整体的活动日志以及运行App Engine的主机的syslog日志、容器输出等都被汇总聚合。
禁用应用程序
当验证完成后,我想停止应用程序,但即使关闭容器主机,Google也会自动重新启动它。这种情况下,我们应选择App Engine的“设置”中的“禁用应用程序”选项。

用这个,Compute Engine 的容器也会自动消失。
总结
我认为作为一个打包完成的运行环境非常完整。虽然我还没有在上面尝试过,但可以使用gen-config生成Dockerfile并在本地的Docker环境中创建完全相同的容器来运行,因此非常适合作为开发环境使用。
我觉得对于Heroku的免费套餐来说,使用Cloud SQL和App Engine / Ruby可能需要花费大约16美元/月左右,所以这是需要考虑的问题。我确实认为GCP在可扩展性和环境灵活性方面绝对是首选,但是否还应该使用GAE来使用Cloud Datastore呢?
此外,例如考虑将其用作Rails应用程序的容器时,我会担心迁移等执行的时间安排。或许可以将其加入任务队列并执行吧。这方面会作为今后的确认问题之一。