「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
これでもう課金されないはず。(先にクラスタを消してしまうと消しのこしが発生するらしく、課金継続してしまうらしいので注意!)
心配になったら、作成したプロジェクトも消しておくと確実に課金されない。