在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,所以应该没问题。

スクリーンショット 2016-03-26 11.33.56.png

启用计费

这个价格相当便宜,几乎处于创建账户初始阶段提供的优惠范围内,但若不激活付款功能就无法试用。

谷歌应用引擎弹性环境实际上是一个“套用以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 命令即可进行部署。

如果没有设置特定选项,这个命令将…

    1. 部署新版本

 

    1. 将请求分配给新版本

 

    在所有流量指向新版本应用程序后,废弃旧版本实例

该操作可以通过使用 –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
スクリーンショット_2016-03-26_12_17_06.png

在仪表盘上,有链接指向访问分析之类的。

查看日志

如果能够上传应用程序,之后只需要确认日志。

所有日志等都由名为Stackdriver的系统进行集中管理。在GCP内部,被简洁地标记为”日志”。

由于Stackdriver是一项新服务,所以预计这里所写的内容会很快过时,但总的来说,包括Flexible Environment在内的所有内容都还在测试阶段,所以没关系。虽然有点难理解,但Stackdriver作为一个独立的服务也存在,同时也有整合到Google Cloud Platform的Stackdriver系统。

    • Google、競合のAWSもモニタリングできる「Google Stackdriver」公開

 

    Stackdriver

Stackdriver可以将App Engine的请求以及更广泛的范围内的日志聚合起来。

スクリーンショット_2016-03-26_12_23_01.png

通过使用Google Cloud Platform,整体的活动日志以及运行App Engine的主机的syslog日志、容器输出等都被汇总聚合。

禁用应用程序

当验证完成后,我想停止应用程序,但即使关闭容器主机,Google也会自动重新启动它。这种情况下,我们应选择App Engine的“设置”中的“禁用应用程序”选项。

スクリーンショット_2016-03-26_12_28_35.png

用这个,Compute Engine 的容器也会自动消失。

总结

我认为作为一个打包完成的运行环境非常完整。虽然我还没有在上面尝试过,但可以使用gen-config生成Dockerfile并在本地的Docker环境中创建完全相同的容器来运行,因此非常适合作为开发环境使用。

我觉得对于Heroku的免费套餐来说,使用Cloud SQL和App Engine / Ruby可能需要花费大约16美元/月左右,所以这是需要考虑的问题。我确实认为GCP在可扩展性和环境灵活性方面绝对是首选,但是否还应该使用GAE来使用Cloud Datastore呢?

此外,例如考虑将其用作Rails应用程序的容器时,我会担心迁移等执行的时间安排。或许可以将其加入任务队列并执行吧。这方面会作为今后的确认问题之一。

bannerAds