GKEにHelloとだけ言わせたい — Google Kubernetes Engineに無をデプロイする

gorlemkun
16 min readDec 20, 2018

--

「GKE?ああ、あれですよね、GoogleのKubernetesのマネージドサービスですよねー」

「どう思う?」

「どうって?」

「いや、使ってみてさあ、どういう感想だった?(ゴゴゴ)」

「・・・

GKE使ってサービス公開すらできません!!!やったことありません!!!><」

な状態から卒業したいので、ブラウザでアクセスするとHelloとだけ表示されるほぼ無なアプリケーションをGKEにデプロイして、GKEでサービス公開したということだけは周りの人に言えるようにする。

※ローカル作業はMac向けです。

対象

というか自分

  • コンテナはわかるかもしれない(わからなくてもいい)
  • でも初めて触って以来音沙汰なくて忘れかけてる
  • Google Cloudはじめて
  • Kubernetesはじめて

Hello! と言うだけのアプリをローカルに構築する

「Hello! と言うだけのアプリ」これすらもコンテナに不慣れとかだと作るのがしんどい。

といってもそんな簡素で無意味なアプリ公式で出しているところそんなに無いでしょ・・・と思いきやGoogle先生が出している。これを使う。

まず自分のpcでどんなアプリか確認する。

docker container run -p 9000:8080 gcr.io/google-samples/hello-app:1.0

と唱えると、http://localhost:9000/ にアクセスした結果、 Hello, world! とブラウザに表示されているはず。

人の作ったコンテナイメージ使うとなにもしなくてよい。楽。

そしてこれをGKEに乗っけたい。

Dockerインストールまだな方

上記が唱えられなかったひとはここからインストールしましょう。

(2018/11/25の執筆時点では、docker storeにsign inしないとDownload出来なくなっているっぽい?)

寄り道:Helloアプリのソースコードが気になる人は

goで書かれてます。これがソースコードです。わたしはgoがよめません。

GKE下準備

デプロイのためにプロジェクトを作成し、kubectlとgcloudのコマンドが打てるようにする。

GCPプロジェクト作成

これに沿う。が、基本管理画面に入って、プロジェクトの作成をクリックして、作成するだけ。管理画面のリンクはリンク先にある。

あ、請求関係の話が出てきてビビるかもしれないが、GCP登録後は300ドルくらいのクレジットが貰えるので急に破産したりはしない。問題ない。どれくらい期限が先になるかは登録時期に左右されるようで、人によって60日だったり1年だったりするんだとか。ちなみに自分の場合は1年だった。2018/11/25の執筆時点ではまだクレジットが残っている。

複数のGoogleアカウント管理している人はちゃんと意図したアカウントに作成しているか確認しましょう。間違えて会社や学校のアカウントとかでやらないように。

kubectl

Homebrew使います。まだ入れていない人はbrewコマンドを打つためにこれを打ちましょう。

/usr/bin/ruby -e "$(curl -fsSL <https://raw.githubusercontent.com/Homebrew/install/master/install>)"

そしてbrewコマンドでインストール

brew install kubernetes-cli

参考:

gcloud

これに沿う。

対話型インストーラを起動

curl <https://sdk.cloud.google.com> | bash

なんか色々聞かれるので好みに合わせて答えていく。ちなみに自分の場合は

  • インストールディレクトリはホームディレクトリ下
  • usage reportは送信しない
  • shell command completionは設定
  • ホームディレクトリ下の .bash_profile を上書き

そしてシェルを再起動

exec -l $SHELL

gcloud環境を初期化

gcloud init
  • ログインしろと言われる。 Y をtypeするとブラウザが起動するのでログインする
  • プロジェクトの一覧が出てくるので、先程作成したプロジェクトを選ぶ。
  • リージョン設定したいか?と聞かれる。なんかグローバルですごそうな理由が無い限りは東京から変更することはないと思うので、東京に設定する。
  • asia-northeast1-a と入力すると東京になる。
  • それ以外はこんな感じ。

initで色々設定して覚えきれない!忘れた!とたちまち思うが、それらはいつでも

gcloud config list

で確認できる。安心。

ちなみに会社と個人で設定を分けたいというとき、再び

gcloud init

すれば新しい設定を作れるし、

gcloud config configurations list

で、作った設定の一覧を表示できる。今自分が何の設定なのかも知れる。

そして一覧から設定の名前を選び、activateの後に置くと、設定を変更可能。

gcloud config configurations activate CONFIGURATION_NAME

空のクラスタを作成

準備が整ったのでKubernetesクラスタをつくる。クラスタをつくるとか響きがかっこいい。

gcloud container clusters create hello --machine-type=n1-standard-1 --num-nodes=3 --cluster-version=1.10.9-gke.5

ノードの数が複数無いとクラスタっぽくないのでとりあえず3つ立てている( --num-nodes=3 )。ケチりたい人は3の部分を1にすればOK。

マシンは n1-standard-1 。standardのうち一番しょぼいの。一覧はこちらからどうぞ。

クラスタのバージョン --cluster-version=1.10.9-gke.5は指定しないと古めのものが使われて、新しめの機能を使おうとする時に予期しないバグに遭遇しやすい。現在使えるバージョンをリストアップして、新しめのものを指定しましょう。

バージョンのリストは

gcloud container get-server-config

で確認できる。 validMasterVersions で示されているものから選ぶとgood.

さて、コマンドを打つとクラスタが作成されるが、クラスタの作成にはちょっと時間がかかるので待ちましょう。

作成できたらクラスタの情報を確認。なんかいっぱい出るはず。それならちゃんとクラスタがあるということ。

gcloud container clusters describe hello

また、GKEのコンソールでもクラスタの情報を表示できる。GCPのコンソールの左上ハンバーガー→GKE→クラスタ から確認できるはず。

ここからアプリケーションを扱うには kubectl を使う。どうやらGKE特有のリソース(上記のクラスタなど)の確保にはgcloudコマンドを使うが、kubernetesの文脈で扱えることは基本的にkubectlを使うっぽい。

kubectlを使う下準備として、gcloudコマンド経由でkubectlに認証情報を渡す。こうすることで、あたかもローカルでKubernetesを扱うようにGKEをコントロールできる。

gcloud container clusters get-credentials hello

こうして、kubectl上ではGKEのhelloクラスタが操作対象に設定された。こういう操作対象のことをコンテキストと呼ぶらしく、現在kubectl上で扱えるコンテキストの一覧は

kubectl config get-contexts

で取得できる。コンテキストの切り替えは

kubectl config use-context CONTEXT_NAME

で可能。

さて、kubectl上でクラスタを扱えるようになったので、クラスタのノード(物理的なサーバーのこと)の一覧を取得する。

kubectl get nodes

GKE上に作成したクラスタのノード一覧が表示されれば成功!3つのノードがリストになって出てくるはず。これで kubectl で操作したことは即座にGKE上に反映されるようになる。Googleのクラウド技術すごい。

ここで「会社のリソースを使ってうっかり秘密でクラスタを構築してしまった!」という場合でもgcloudコマンドからいつでもクラスタを消せるので問題ない。

gcloud container clusters delete hello

また、Kubernetesは「全部やり直せばそのバグ出ないようになります」みたいな状況になることもよくあるので、そういう時にも有効です。

Hello! と言うだけのアプリをGKEに構築する

さあ、さっきローカルで

docker container run -p 9000:8080 gcr.io/google-samples/hello-app:1.0

と唱え、http://localhost:9000/ にアクセスし、 Hello, world! とブラウザに表示したはず。

これをGKE上でやる。

Kubernetesだと、ローカルでDocker立ち上げてポート直で覗きに行くようにはいかなくて、ちゃんと用意しなくちゃいけないものがある。

  • Ingress
  • Service
  • Deployment

の3つ。これからこの3つをyamlファイルで表現して、アプリケーションをGKEにデプロイする。これら3つをそれぞれ詳細まで説明するとひどく長くなるので、すごいざっくり説明する。

基本的にこの3つは外部からアクセスが来ると

Ingress→Service→Deployment

と連携される。Hello! と言うのはDeploymentで、それがまたServiceを伝わり、Ingressを伝わり、Hello! がブラウザに表示される。つまりアプリケーションの本体はDeployment。Hello! を表示するhello-appコンテナイメージはDeploymentを表現するyamlファイルに記述する。

残りのIngressとServiceはなんなのかというと、

Ingressはロードバランサーで、外部からのトラフィックを一番始めに受けるところ。Kubernetesでアプリケーションを構築すると大体先頭にこいつを配置することになる。まだIngressの詳細な動きはよく調べてないが、ロードバランサー的にトラフィックを分配してくれるんだと思う。(Ingressという名前はめっちゃ有名な位置情報ゲームと全く同じなので最初は面食らった。どっちもGoogle発だし。)

Serviceはリソースに名前つける君。こいつに関しては既存のなにかに置き換えて説明するのが難しい。

例えばDeploymentは通常GKEの中にはいっぱい立っている。Serviceはそいつらに名前をつけてあげて、Deployment同士をつなげるのにその名前を使えるようにしたり、IngressからDeploymentをその名前で参照できるようにしてくれる。Serviceという概念があることで、各物理的なマシンにつなげるためにいちいち仮想的なipアドレスやらをコピペしてマッピングして…などせずに、シンプルに名付けで管理できるようになる。もうちょい具体的には、好きなホスト名が簡単につけられたりする。

それぞれ見直すと

  • Ingress(ロードバランサー)
  • Service(名付け君)
  • Deployment(アプリ本体)

という感じ。これから順につくっていく。

HelloなDeploymentを用意

まずはアプリ本体から。触れたことのあるものから順に扱ったほうがわかりやすそうな気がしたのでこの順番。

ここからファイルを作る必要があるので、どこかに置くためのディレクトリを作成しましょう。そこに作ったyamlファイルを置いていきます。

まずDeploymentのyamlファイルから。

hello-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-deploy
labels:
app: hello
spec:
replicas: 3
selector:
matchLabels:
app: hello
template:
metadata:
labels:
app: hello
spec:
containers:
- name: hello
image: gcr.io/google-samples/hello-app:1.0
ports:
- containerPort: 8080

kind: Deployment 指定でDeploymentについて記述したファイルであることを明示。spec/templete/spec配下にアプリケーションの内容を記述。 image: 部分でhello-appのコンテナイメージを指定し、ポート番号8080を公開した。

HelloなDeploymentに名付けするServiceを用意

そしてアプリ本体につなぐための名前をつけるServiceをつくる。

hello-service.yaml

apiVersion: v1
kind: Service
metadata:
name: hello-svc
spec:
type: NodePort
selector:
app: hello
ports:
- name: http
port: 80
targetPort: 8080

ここでも kind: Service でServiceであることを明示。そしてspec配下での selector: app: hello 指定で app: hello とラベル付けされたDeploymentへのヒモ付けであることを明示している。

また、 ports: 指定で受け口 port: 80 と、Deploymentへ流す口 targetPort: 8080 を設定することでポート番号を80から8080にリレーしている。

Helloを世の中に公開するIngressを用意

最後にアプリ本体を公開するIngressをつくる。

hello-ingress.yaml

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: hello-ingress
spec:
rules:
- http:
paths:
- backend:
serviceName: hello-svc
servicePort: 80

kind: Ingress なのは言わずもがな。そして backend: serviceName: hello-svc に注目。ここでhello-svcという名前のServiceに接続することを明示している。

Serviceで指定した受け口80番も servicePort: 80 できちんとつなげてあげる。

さあ、やっとGKEにデプロイ

3つのファイルが配置されたディレクトリに移動し、用意したリソースをそれぞれkubectlで適用していく。ちなみに-fのオプションはファイルネーム指定の時に使うもの。今回すべてのリソースをyamlで指定しているので全部に-fがつく。

kubectl apply -f hello-deployment.yaml
kubectl apply -f hello-service.yaml
kubectl apply -f hello-ingress.yaml

全部(特にingressは)作成し終わるのに1分?ほどかかる。全部終わるとグローバルIPアドレスが振られるのでアクセスできるようになる。IPアドレスは

kubectl get ingress

で調べられる。見えたIPアドレスをブラウザに入力すると、最初試したように Hello! とブラウザが言ってくれるはず。かくしてGKEにちゃんとデプロイできました。世の中にちゃんと公開されてます。イェイ!

後処理

作成したリソースはdeleteで消せる。

kubectl delete -f hello-deployment.yaml
kubectl delete -f hello-service.yaml
kubectl delete -f hello-ingress.yaml

クラスタはこう消す。

gcloud container clusters delete hello

これでもう課金されないはず。(先にクラスタを消してしまうと消しのこしが発生するらしく、課金継続してしまうらしいので注意!)

心配になったら、作成したプロジェクトも消しておくと確実に課金されない。

--

--