Google Compute Engineでアプリを起動してみました

最近GCPが気になっていまして、
以前 Google Compute Engine でインスタンスの作成までやったので、
今回はそのインスタンス上でアプリを起動させてみるところまでやってみました。





インスタンスの作成まではこちらの記事に書きました。



mtomitomi.hatenablog.com






やったこと









環境









Google Compute Engine(GCE)とは



GCPではGCEというIaaSを提供していて、AWSでいうとEC2にあたるサービスです。

時間あたりの課金で、Googleが実際に使用している運用環境をレンタルすることができます。
長く稼働するインスタンスに自動で値引きを適用したり、ストレージやCPUの性能が高いため、
他社に比べて性能あたりの単価が割安になるようです。





<補足>




  • IaaS(Infrastructure as a Service):仮想サーバなどのインフラを利用するサービス


  • PaaS(Platform as a Service):アプリケーションを稼働させるOSなどのプラットフォーム一式を利用できるサービス


  • SaaS(Software as a Service):ソフトウェアをインターネット経由で利用できるサービス(Gmailなど)








Google Cloud SDKのインストール



gcloudコマンドを使用するために、Google Cloud SDKをインストールします。

インストールには Python2.7系 が必要なのですが、私の環境は 3.6系 が入っていたので、
pyenvを使って2.7系をインストールして切り替えることにしました。

けれども、普通にpyenvコマンドを実行すると下記のエラーになりました。

MacでHighSierraにするとこの事象が発生するようです。



$ pyenv install 2.7.14
...

ERROR: The Python ssl extension was not compiled. Missing the OpenSSL lib?

Please consult to the Wiki page to fix the problem.
https://github.com/pyenv/pyenv/wiki/Common-build-problems


BUILD FAILED (OS X 10.13.2 using python-build 20160602)





エラーメッセージに書いてあるリンク先ページ通りに下記コマンドを実行すると、
インストールすることができました。




$ CFLAGS="-I$(brew --prefix openssl)/include" LDFLAGS="-L$(brew --prefix openssl)/lib" pyenv install -v 2.7.14
...

$ pyenv versions
* system (set by /Users/m-tominaga/.pyenv/version)
2.7.14
3.6.3





バージョンを2.7.14に切り替えます。



$ pyenv global 2.7.14

$ python -V
Python 2.7.14





このあと、公式手順ではパッケージ「google-cloud-sdk-180.0.0-darwin-x86_64.tar.gz」をダウンロードして
ローカルで展開してシェルを実行する方法が記載されているのですが、
その方法だとバージョンが古いようでインストールできませんでした。

なので別の手順を調べたところ、下記コマンドで正常にインストールすることができました。
コマンド実行後の質問は、全てYEnterで大丈夫でした。



$ curl https://sdk.cloud.google.com | bash





インストールが完了したら下記コマンドで.bashrcの変更を反映させます。

パスが通ってgcloudコマンドを実行できるようになります。



$ exec -l $SHELL

$ which gcloud





次に下記コマンドを実行してSDKを初期化します。

質問にYを入力するとブラウザが起動するので、Googleアカウントでログインして「許可する」をクリックします。



$ gcloud init





認証完了の画面が表示されます。



f:id:mtomitomi:20180217184152p:plain





コマンドプロンプトに戻ると使用するプロジェクトを聞かれるので、
使いたいプロジェクトを数字で選択します。




Pick cloud project to use:
[1] gcp-test
[2] pure-polymer
[3] Create a new project
Please enter numeric choice or text value (must exactly match list
item):
Please enter a value between 1 and 3, or a value present in the list:





ゾーンを聞かれます。

Yでゾーンを個別に選ぶことができますが、nでも大丈夫です。




Do you want to configure a default Compute Region and Zone? (Y/n)? Y





セットアップ完了のメッセージが表示されたら、認証アカウントの確認をしてみます。
下記コマンドを実行すると、ログインしているアカウントが表示されます。




$ gcloud auth list






ローカルリポジトリの作成



自分のリポジトリでもいいのですが、インスタンス内でアプリケーションを動作させたかったので、
下記手順にある hello-world のリポジトリをクローンさせて頂きました。



www.topgate.co.jp





クローンできたらhello_worldディレクトリだけをコピーし、gitの初期化をして最初のコミットをします。



$ git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git

$ cd python-docs-samples

$ cp -rf appengine/standard/flask/hello_world hello_world

$ cd hello_world

$ git init .

$ git add .

$ git commit -m "initial commit"






GCPリポジトリに登録



新しく作成したhello_worldリポジトリを、GCPリポジトリに登録します。

GCPメニュー画面の左側から「Source Repositories -> リポジトリ」を選択します。



f:id:mtomitomi:20180217183710p:plain





新しくリポジトリを作成したいので「開始」をクリックします。



f:id:mtomitomi:20180217183812p:plain





リポジトリ名を適当に入力して作成をクリックします。



f:id:mtomitomi:20180217183905p:plain





1番上のローカルGitレポジトリからCloudレポジトリへのコードのpush を選択します。



f:id:mtomitomi:20180217184112p:plain





右端にある矢印をクリックするとコマンドが表示されるので、その通りに実行します。
使うプロジェクトを聞かれるので任意のプロジェクトを選択、リージョンは特に指定しなくても良いのでnで大丈夫です。




$ gcloud init && git config credential.helper gcloud.sh

$ git remote add google \
> https://source.developers.google.com/p/gcp-test...../r/hello-world

$ git push --all google





GCPのコンソールからリポジトリが登録されていることを確認できました。



f:id:mtomitomi:20180217185211p:plain






VMインスタンス上でリポジトリをクローン



まずは、gcloudコマンドでインスタンスにログインします。

GCPメニュー画面の左にある「Compute Engine -> VMインスタンス」を選択します。

今回は、前に作成したインスタンスを使いました。

作成方法は下記の記事に書きました。



mtomitomi.hatenablog.com





作成したインスタンスの項目「接続」のSSHの横にある「▼」をクリックし、
「gcloudコマンドを表示」を選択します。



f:id:mtomitomi:20180217190123p:plain



f:id:mtomitomi:20180217190428p:plain





コマンドが表示されるので、コピーしてターミナルに貼り付けて実行します。

パスワードを入力すると、インスタンスにログインすることができます。




$ gcloud compute --project "gcp-test-...." ssh --zone "us-central1-a" "sample"

[m-tominaga@sample ~]$





先ほど作成したリポジトリインスタンス上でクローンします。

クローンするためにgitが必要なので、
このインスタンス内でgitのインストールをしておく必要がありました。




[m-tominaga@sample ~]$ sudo yum install git

[m-tominaga@sample ~]$ gcloud init

[m-tominaga@sample ~]$ gcloud source repos clone hello-world --project={プロジェクトID}





認証完了後に再度クローンを試みましたが、またエラーになりました。




ERROR: (gcloud.source.repos.clone) PERMISSION_DENIED: Request had insufficient authentication scopes.





リポジトリをクローンするための権限がないようなので設定します。







補足ですが、gcloud init の代わりにgcloud auth loginを使う方法もあります。






【補足】gcloud auth login での認証方法



下記コマンドを実行します。続行するか聞かれるのでYを入力します。




$ gcloud auth login



ターミナルにURLが表示され、Enter verification codeを入力するように求められます。

URLをブラウザで開くとコードが表示されているので、
この値をターミナルの Enter verification code に貼り付けて認証します。





認証完了後、下記コマンドを実行してプロジェクトIDを設定します。




$ gcloud config set project {PROJECT_ID}











インスタンスのアクセス権限を付与



GCPにはサービスアカウントというアプリケーションやVMに属するアカウントがあるのですが、
このアカウントにインスタンスのアクセス権限を付与する必要があるようです。





GCPメニューから「Compute Engine -> VMインスタンス」を選択します。

権限を変更するためにはインスタンスを停止させる必要があるので、
対象のVMインスタンスの右横にある...をクリックして「停止」を選択します。



f:id:mtomitomi:20180218120334p:plain





インスタンスが停止されたら、対象のVMインスタンス名をクリックします。



f:id:mtomitomi:20180218115501p:plain





下のほうに「Cloud API アクセススコープ デフォルトのアクセス権を許可」とあるので、
「詳細」をクリックしてアクセス権の一覧を表示させます。



f:id:mtomitomi:20180218115118p:plain





Cloud Source Repositoriesが無効になっていますが、
これを読み取れるよう権限を変更したいので、右上にある編集をクリックします。



f:id:mtomitomi:20180218115949p:plain





Cloud Source Repositoriesを「読み取りのみ」に変更します。

今回、書き込む予定はないので読み取りのみにしました。



f:id:mtomitomi:20180218120221p:plain





インスタンスを開始させたらインスタンスの権限変更は完了です。






IAMユーザに権限を付与



今度はIAMの権限を設定します。

GCPメニューから「IAMと管理 -> IAM」を選択し、「追加」をクリックします。



f:id:mtomitomi:20180218120752p:plain





今回使ったVMインスタンスのサービスアカウントはXXX-compute@developer.gserviceaccount.comなので、
メンバーにこのユーザーを追加し、役割は「Source -> Source Repository 読み取り」を追加します。



f:id:mtomitomi:20180218121145p:plain





追加をクリックしたら権限追加は完了です。



f:id:mtomitomi:20180218121223p:plain






認証の設定



再度クローンしてみましたが、また失敗しました。

今度は認証に失敗しているようです。




fatal: remote error:


Invalid authentication credentials.

Please generate a new identifier:
https://source.developers.google.com/auth/start?scopes=https://www.googleapis.com/auth/cloud-platform

ERROR: (gcloud.source.repos.clone) Command '['git', 'clone', u'https://source.developers.google.com/p/gcp-test-194303/r/hello-world', '/home/m-tominaga/hello-world']' returned non-zero exit status 128





表示されたエラーメッセージ通りに下記URLにアクセスすると、解決方法が記載されていました。
ちなみに自分のユーザー名とパスワードも記載されています。



https://source.developers.google.com/auth/start?scopes=https://www.googleapis.com/auth/cloud-platform





記載されていた通りに、ホームディレクトリに.netrcファイルを作成し、
machine source.developers.google.com login {ユーザー名} password {パスワード}の1行を追加しました。

ちなみに、ユーザー名とはEmailアドレス(XXX@gmail.com)のことです。





.netrcファイルの編集が終わったら、下記コマンドを実行します。




[m-tominaga@sample hello-world]$ git config http.cookiefile





再度クローンをしてみると正常にクローンできました。




[m-tominaga@sample hello-world]$ gcloud source repos clone hello-world --project=gcp-test-XXXXXX

[m-tominaga@sample hello-world]$ ls
hello-world






アプリケーションの起動



必要なライブラリをインストールし、クローンしてきたPythonアプリケーションを実行します。




[m-tominaga@sample hello-world]$ cd hello-world

[m-tominaga@sample hello-world]$ sudo yum -y install python-pip python-gunicorn

[m-tominaga@sample hello-world]$ sudo pip install --upgrade pip

[m-tominaga@sample hello-world]$ sudo pip install flask

[m-tominaga@sample hello-world]$ sudo gunicorn -b 0.0.0.0:80 main:app
2018-02-18 13:10:58 [10600] [INFO] Starting gunicorn 18.0
2018-02-18 13:10:58 [10600] [INFO] Listening at: http://0.0.0.0:80 (10600)
2018-02-18 13:10:58 [10600] [INFO] Using worker: sync
2018-02-18 13:10:58 [10605] [INFO] Booting worker with pid: 10605





起動できたようですが、ブラウザで確認する方法がわかりませんでした。。

Python環境の構築については、公式ドキュメントに記載されているようだったので、
正しい手順を理解するために別途やっておこうと思います。






やってみた所感



AWSよりもドキュメントが充実していない印象で、
エラーの解決方法を調べるのにとても時間がかりました。
また、ネットの情報も細かい手順をだいぶ省いてたりするので、
初心者のひとは入門書の書籍を買ってやったほうが、効率が良いかもしれないです。



仮想環境でaptコマンドが使えなくて別の手順を探すなどしていて、
この手順を一通りやるのに想定以上の時間がかかってしまいました。

GCPの機能では認証や権限といった部分にだいぶハマってしまいましたが、
後の操作でも重要になってくると思うので、良い経験になったと思っています。





インフラに疎いことを再認識することができたので、
GCPを使いながら理解を深めていきたいと思います。