この記事は Google Cloud Platform(1) Advent Calendar 2016 の15日目の記事です。
普段は golang をやってるアプリケーションの人っぽい感じになっていますが、他にも色々とやっています。(と、いうアピールをたまにしておかないと) さて、今回は GKE + golang のデプロイ話でもしましょう。結局、golang が絡んでいますね。
準備
Docker をインストールしておき、使用できるようにしましょう。
コンテナイメージの作成・プッシュ
プロジェクト構成は下記のようにし、docker ビルドしたイメージを Container Registry にプッシュするようにします。
helloworld/ ├── deployment.yaml ├── Dockerfile ├── main.go └── service.yaml
main.go
アプリケーションコードはとてもシンプルに、8080番ポートで構えるサーバーを用意し、アクセスがあったときに "Hello world!" と表示するアプリケーションを用意します。
package main import ( "fmt" "log" "net/http" ) func main() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello world!") }) log.Fatal(http.ListenAndServe(":8080", nil)) }
動作確認するには go run してビルド・起動し、 curl などで叩いてみてください。
# 実行 $ go run main.go # 確認 $ curl -XGET localhost:8080 Hello world!
Dockerfile
golang をビルドするイメージが公開されているので、そのイメージを使用します。
FROM golang:1.7.4-onbuild
Docker ビルド・実行
main.go と Dockerfile が用意できたら実際にイメージをビルド・実行してみます。
# ビルド $ docker build -t hello-container . # 実行 $ docker run -p 8080:8080 hello-container # 確認 $ curl -XGET localhost:8080 Hello world!
ビルドや実行で使用している hello-container
はコンテナイメージへのタグです。
Container Registry にプッシュ
先ほど作成したコンテナイメージを Google Container Registry にプッシュします。先ほど作成したタグにエイリアスを張っておきます。
$ docker tag hello-container asia.gcr.io/[YOUR_PROJECT_ID]/helloworld
asia.gcr.io の部分はホスト先を指定することが可能です。
Registry Host | Region |
---|---|
us.gcr.io | US |
es.gcr.io | EU |
asia.gcr.io | ASIA |
gcr.io | US (unfixed) |
あと、わざわざエイリアスを張らずに、直接レジストリの命名でタグを作成しても大丈夫です。 Google Container Registry 用にエイリアス・タグを作成したらプッシュします。
$ gcloud docker push asia.gcr.io/[YOUR_PROJECT_ID]/helloworld
※ [YOUR_PROJECT_ID]
は GCP の Project ID を指定するようにしてください。
ここまで作成できたらコンテナイメージ作成については完了です。
Container Engine クラスタの作成
デプロイ先となるクラスタの作成を行います。コンソールから作成もできますし、コマンドからも作成が可能です。 お試しで試してみるなら Cloud Shell をオススメします。
クラスタ作成
今回は gcloud コマンドから作成します。
$ gcloud container clusters create helloworld --zone asia-northeast1-c \ --scopes cloud-platform \ --num-nodes 2
scopes オプションはアプリケーションの必要に応じて datastore や bigquery のスコープも --scopes cloud-platform,datastore,bigquery
のように増やしてください。
クラスタの認証
gcloud コマンドで認証を行うために、作成したクラスタの認証から行います。
$ gcloud container clusters get-credentials helloworld --zone asia-northeast1-c
Fetching cluster endpoint and auth data. kubeconfig entry generated for helloworld.
が出力されればOK。
クラスタの確認
問題なく作成されたか確認してみます。
$ kubectl cluster-info Kubernetes master is running at https://xxx.xxx.xxx.xxx GLBCDefaultBackend is running at https://xxx.xxx.xxx.xxx/api/v1/proxy/namespaces/kube-system/services/default-http-backend Heapster is running at https://xxx.xxx.xxx.xxx/api/v1/proxy/namespaces/kube-system/services/heapster KubeDNS is running at https://xxx.xxx.xxx.xxx/api/v1/proxy/namespaces/kube-system/services/kube-dns kubernetes-dashboard is running at https://xxx.xxx.xxx.xxx/api/v1/proxy/namespaces/kube-system/services/kubernetes-dashboard
デプロイ
コンテナイメージ化されたアプリケーションをデプロイするためクラスタのレプリカセットとサービスの作成を行います。
Deployment
deployment.yaml という命名で下記のような Yaml ファイルを用意し、 kubectl コマンドを使用してレプリカセットを作成します。
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: helloworld labels: app: helloworld spec: replicas: 3 template: metadata: labels: app: helloworld spec: containers: - name: helloworld-app image: us.gcr.io/[YOUR_PROJECT_ID]/hello-golang:latest imagePullPolicy: Always ports: - name: http-server containerPort: 8080
continers.image には先ほどプッシュしたコンテナイメージの Registry Host を指定します。ここまでできたら kubectl コマンドを使用します。
$ kubectl create -f deployment.yaml
レプリカセットの進捗状況は下記で確認がとれます。
$ kubectl get deployments NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE helloworld 3 3 3 3 42m
Service
今度は service.yaml という命名で下記のような Yaml ファイルを用意します。サービスはレプリカセットと一緒に作成されたポッドにアクセスするための定義になります。
apiVersion: v1 kind: Service metadata: name: helloworld labels: app: helloworld spec: type: LoadBalancer ports: - port: 80 targetPort: http-server selector: app: helloworld
$ kubectl create -f service.yaml
サービスの作成進捗は下記を叩くことでわかりますし、 LoadBalancer Ingress
の IP が公開された IP アドレスとなるので、LoadBalancer 作成後、この IP にアクセスすることによって "Hello world!" が表示されるはずです。
$ kubectl describe service helloworld Name: helloworld Namespace: default Labels: app=helloworld Selector: app=helloworld Type: LoadBalancer IP: xxx.xxx.xxx.xxx LoadBalancer Ingress: xxx.xxx.xxx.xxx. Port: <unset> 80/TCP NodePort: <unset> 31510/TCP Endpoints: xxx.xxx.xxx.xxx:8080,xxx.xxx.xxx.xxx:8080,xxx.xxx.xxx.xxx:8080 Session Affinity: None Events: FirstSeen LastSeen Count From SubobjectPath Type Reason Message --------- -------- ----- ---- ------------- -------- ------ ------- 43m 43m 1 {service-controller } Normal CreatingLoadBalancer Creating load balancer 42m 42m 1 {service-controller } Normal CreatedLoadBalancer Created load balancer
動作検証
ここまでできたら、先ほどの LoadBalancer Ingress
にある IP にアクセスして "Hello world!" が表示されることを確認してみましょう。
停止方法
クラスタを削除することによって、ポッドやロードバランサーもあわせて削除されます。超楽。
$ gcloud container clusters delete helloworld --zone asia-northeast1-c The following clusters will be deleted. - [helloworld] in [asia-northeast1-c]