GKEで半年運用してみた
Katsutoshi Nagaoka



gcp ja night #31 (2016/01/21) #gcpja
永岡 克利 (Katsutoshi Nagaoka)
• 2011年 CyberAgent 中途入社
• 社内向け基盤システムの開発・運用
• 現在、ライブ配信サービス「takusuta」を立ち上げ、運用中
• エンジニア
• #java #cassandra …
• #golang #node.js #mongodb #aws #gcp …
@na_ga
About me
Outline
• takusuta 紹介
• GKE ざっくり説明
• takusuta における GKE の活用例
• まとめ
takusuta 紹介
ライブ配信サービス takusuta
iOS & Android App

2015/07 ~
ライブ配信サービス takusuta
https://takusuta.com/ on GKE

2015/08 ~
iOS & Android App

2015/07 ~
• API
• EC2
• S3
• Web
• GKE
• S3
構成
AWS
Route53
CloudFront S3
EC2 MongoDBELB
BigQuery
GCP
GKEGCE-LB
Aerospike
GKE 採用に至るまで
• 2015/07
• iOS, Android アプリ公開
• S3 の Static Content でペライチな Web ページ
• nodejs + riot による SEO 対策した Web ページを作ることに
• ちょうど kubernetes v1.0.0 がリリースされた
• 近いうちに GKE も GA になりそうな
• どうせ作るなら… 一旦 Web だけワンチャン使ってみたい
• 2015/08
• GKE is Generally Available
• Web ページリニューアル
GKE について
GKE とは
• Kubernetes のフルマネージドサービス
• Docker コンテナの管理ツール
• GCE 上に Kubernetes Cluster を構築
• クラスタのリサイズ
• コンテナのグルーピング
• コンテナの自動配置
• コンテナのリサイズ
• コンテナの負荷分散
出典: http://kubernetes.io/
GKE の料金
• すごい安い
• Cluster の各 Node 料金は GCE 料金が適用
• Cluster の料金は Node 数によって異なる
• 5 Node までは無料
• 6 Node 以上で $0.15 hour / cluster
• $108 month / cluster
GKE の用語
• Pod
• コンテナのグループ
• 1コンテナ以上で作成
• Replication Controller (RC)
• Pod のレプリカ管理
• 管理下の Pod のリサイズを担当
Pod
GKE Node
Pod Pod
GKE Node
Pod Pod Pod
RC
Management Pod Replica
GKE の用語
• Pod
• コンテナのグループ
• 1コンテナ以上で作成
• Replication Controller (RC)
• Pod のレプリカ管理
• 管理下の Pod のリサイズを担当
• Service
• Pod に対する LB みたいなやつ
• iptables で DNAT → kube-proxy
Pod
GKE Node
Pod Pod
GKE Node
Pod Pod Pod
Service RC
Layer4 Load Balancer
GKE における構成
単体構成
• GKE
• tkst-service (type: LoadBalancer)

設定された Global IP で公開される

現状では Layer4 のみサポート
tkst-pod
GKE NODE GKE NODE
tkst-service tkst-rc
tkst-pod
User
Admin
https://takusuta.com
単体構成
• GKE
• tkst-service (type: LoadBalancer)

設定された Global IP で公開される

現状では Layer4 のみサポート

• Service に証明書を設定できない
tkst-pod
GKE NODE GKE NODE
tkst-service tkst-rc
tkst-pod
User
Admin
https://takusuta.com
単体構成
• GKE
• tkst-service (type: LoadBalancer)

設定された Global IP で公開される

現状では Layer4 のみサポート

• Service に証明書を設定できない
• 各 Pod に証明書を持たせる
tkst-pod
GKE NODE GKE NODE
tkst-service tkst-rc
tkst-pod
User
Admin
https://takusuta.com
単体構成
• GKE
• tkst-service (type: LoadBalancer)

設定された Global IP で公開される

現状では Layer4 のみサポート

• Service に証明書を設定できない
• 各 Pod に証明書を持たせる
• 非効率的なので避けたい
tkst-pod
GKE NODE GKE NODE
tkst-service tkst-rc
tkst-pod
User
Admin
https://takusuta.com
GCE-LB と組み合わせた構成
• GKE
• tkst-service (type: NodePort)

各 Node が Service に設定した

ポートでリクエストを受け付ける
tkst-pod
GKE NODE GKE NODE
tkst-service tkst-rc
tkst-pod
User
tkst-backend
tkst-url-map
GCE-HTTPS-LB
https://takusuta.com
Admin
GCE-LB と組み合わせた構成
• GKE
• tkst-service (type: NodePort)

各 Node が Service に設定した

ポートでリクエストを受け付ける

• GCE-LB に証明書を設定する
tkst-pod
GKE NODE GKE NODE
tkst-service tkst-rc
tkst-pod
User
tkst-backend
tkst-url-map
GCE-HTTPS-LB
https://takusuta.com
Admin
GCE-LB と組み合わせた構成
• GKE
• tkst-service (type: NodePort)

各 Node が Service に設定した

ポートでリクエストを受け付ける

• GCE-LB に証明書を設定する
• GKE の Instance Group と

ポートを Backend として指定する
tkst-pod
GKE NODE GKE NODE
tkst-service tkst-rc
tkst-pod
User
tkst-backend
tkst-url-map
GCE-HTTPS-LB
https://takusuta.com
Admin
Cross Region LB 構成
• 米国からは US Region
tkst-pod
GKE NODE GKE NODE
tkst-service tkst-rc
tkst-pod
User from US
tkst-backend-us
tkst-url-map
Cross-Region HTTPS-LB
https://takusuta.com
tkst-pod
GKE NODE GKE NODE
tkst-service tkst-rc
tkst-pod
tkst-backend-asia
Cross Region LB 構成
• 日本からは Asia Region
tkst-pod
GKE NODE GKE NODE
tkst-service tkst-rc
tkst-pod
User from Japan
tkst-backend-us
https://takusuta.com
tkst-pod
GKE NODE GKE NODE
tkst-service tkst-rc
tkst-pod
tkst-backend-asia
tkst-url-map
Cross-Region HTTPS-LB
Cross Region LB 構成
• 利用率や Rate で自動切り替え
• ex: CPU 80%
tkst-pod
GKE NODE GKE NODE
tkst-service tkst-rc
tkst-pod
User from Japan
tkst-backend-us
https://takusuta.com
tkst-pod
GKE NODE GKE NODE
tkst-service tkst-rc
tkst-pod
tkst-backend-asia
tkst-url-map
Cross-Region HTTPS-LB
Region/zone の選択
• Zone によって差異がある
• Haswell [2013 ]
• Ivy Bridge [2012 ]
• Sandy Bridge [2011 ]
• Asia Region は同じなので

気にしなくて ok
出典: https://cloud.google.com/compute/docs/zones
GKE の構築
Google Cloud SDK
• Google 社製の GCP 管理ツール群
• gcloud
• Cluster の作成/管理
• kubectl
• RC の作成/管理
• Service の作成/管理
Cluster の作成
# create cluster

$ gcloud container clusters create "tkst-asia-001" 

--num-nodes 3 
--zone "asia-east1-b" 
--machine-type "n1-highcpu-4" 

--scope "compute-rw","storage-ro","bigquery","logging-write","monitoring"



• cluster 作成時しか設定できない項目がある
• num-nodes は cluster 作成後もオンラインで変更できる
• 現時点では num-nodes 以外の項目は cluster 作成後に変更できない

• 特に scope は後々面倒になるので注意が必要
• GKE から Fluentd などで BigQuery に流し込む為には bigquery scope が必須
• 直近使う予定がなくても、とりあえず付けといた方が良い

Cluster の取得
# describe cluster

$ gcloud container clusters describe tkst-asia-001



currentNodeCount: 3
currentMasterVersion: 1.1.4
currentNodeVersion: 1.1.4
initialClusterVersion: 1.1.4
nodeConfig:
diskSizeGb: 100
machineType: n1-highcpu-4
oauthScopes:
- https://www.googleapis.com/auth/bigquery
- https://www.googleapis.com/auth/compute
- https://www.googleapis.com/auth/devstorage.read_only
- https://www.googleapis.com/auth/logging.write
- https://www.googleapis.com/auth/monitoring
nodeIpv4CidrSize: 24
status: RUNNING
zone: asia-east1-b
Image のアップロード
# build docker image

$ docker build .



# upload docker image to Google Container Registry (GCR)

$ docker tag -f tkst/tkst asia.gcr.io/xxxxx/tkst:1.9.3

$ gcloud docker push asia.gcr.io/xxxxx/tkst:1.9.3



• GCR はホスト名でアップロード先リージョンを指定できる
• asia.gcr.io: asia リージョン
• us.gcr.io: us リージョン
• eu.gcr.io: european リージョン
RC の作成
# create replication controller

$ cat << EOS > ./tkst-rc.json; kubectl create -f ./tkst-rc.json
{
"kind": "ReplicationController",
"apiVersion": "v1",
"metadata": { "name": "tkst-rc", "labels": { "name": "tkst-rc" } },
"spec": {
"replicas": 3,
"selector": { "name": "tkst-rc-pods" },
"template": {
"metadata": { "labels": { "name": "tkst-rc-pods" } },
"spec": {
"containers": [ {
"name": "tkst-container",
"image": "asia.gcr.io/xxxxx/tkst:1.9.3",
"ports": [ { "containerPort":3000, "protocol":"TCP" } ]
} ]
}
}
}
}
EOS
RC の取得
# get replication controller

$ kubectl get rc
CONTROLLER CONTAINER(S) IMAGE(S) SELECTOR REPLICAS
tkst-rc tkst asia.gcr.io/xxxxx/tkst:1.9.3 name=tkst-rc-pods 3 



# describe replication controller

$ kubectl describe rc tkst-rc
Name: tkst-rc
Namespace: default

Image(s): asia.gcr.io/xxxxx/tkst:1.9.3
Selector: name=tkst-rc-pods
Labels: name=tkst-rc
Replicas: 3 current / 3 desired
Pods Status: 3 Running / 0 Waiting / 0 Succeeded / 0 Failed
No volumes.

Events:
FirstSeen LastSeen Count Reason Message
───────── ──────── ───── ────── ───────
25m 25m 1 SuccessfulCreate Created pod: tkst-rc-5gghw
25m 25m 1 SuccessfulCreate Created pod: tkst-rc-b59cv

25m 25m 1 SuccessfulCreate Created pod: tkst-rc-qw4da
Pod の取得
# get pod

$ kubectl get pod
NAME READY STATUS RESTARTS AGE
tkst-rc-1tjlf 1/1 Running 0 25m
tkst-rc-5zogh 1/1 Running 0 25m
tkst-rc-kpujg 1/1 Running 0 25m



# describe pod

$ kubectl describe pod tkst-rc-1tjlf
Name: tkst-rc-1tjlf
Namespace: default
Image(s): asia.gcr.io/xxxxx/tkst:1.9.3
Node: gke-tkst-asia-001-a48fb14f-node-crjc/10.240.0.18
Start Time: Thu, 21 Jan 2016 06:03:50 +0900
Labels: name=tkst-rc-pods
Status: Running
IP: 10.184.2.3
Replication Controllers: tkst-rc (3/3 replicas created)
Pod への接続
# attach pod

$ kubectl attach pod tkst-rc-1tjlf


# get pod log

$ kubectl logs -f tkst-rc-1tjlf
# get pod log (with content name)
$ kubectl logs -f tkst-rc-1tjlf -c tkst-node-container
{"level":"info","message":"use memcached store [options={"hosts":["10.240.0.4:11211
{"level":"debug","message":"try to update site-maps cache.","label":"dev","timestamp":
{"level":"debug","message":"cache update scheduler started. key=sitemap","label":"dev"
{"level":"info","message":"[middleware_access_logger] setup with options {"tag":"ta
{"level":"info","message":"[WEB] Append route. path={"twitter":"/explore/auth/twitt
{"level":"info","message":"[WEB] Append route. path="/explore/logout"","label":"web_
{"level":"info","message":"[WEB] Append route. path="/ping"","label":"web_dev","time
{"level":"info","message":"[WEB] Append route. path="/"","label":"web_dev","timestam
...
Service の作成
# create service

$ cat << EOS > ./tkst-srv.json; kubectl create -f ./tkst-srv.json
{
"kind": "Service",
"apiVersion": "v1",
"metadata": { "name": "tkst-srv", "labels": { "name": "tkst-srv" } },
"spec": {
"type": "NodePort",
"ports": [ {
"port": 3000,
"targetPort": 3000,
"nodePort": 30000
} ],
"selector": {
"name": "tkst-rc-pods"
}
}
}
EOS
Service の取得
# get service

$ kubectl get service
NAME CLUSTER_IP EXTERNAL_IP PORT(S) SELECTOR
tkst-srv 10.119.246.120 nodes 3000/TCP name=tkst-rc-pods
kubernetes 10.119.240.1 <none> 443/TCP <none> 



# describe service

$ kubectl describe service tkst-srv
Name: tkst-srv
Namespace: default
Labels: name=tkst-srv
Selector: name=tkst-rc-pods
Type: NodePort
IP: 10.119.246.120
Port: 3000/TCP
NodePort: 30000/TCP
Endpoints: 10.116.0.3:3000,10.116.2.3:3000
Session Affinity: None
No events.
HTTPS-LB の作成
# create backend

$ gcloud beta compute backend-services create "tkst-backend" 

—-protocol HTTP --port-name "tkst-port" --http-health-check "tkst-check"



# add backend resource 

$ gcloud beta compute backend-services add-backend "tkst-backend" 
--instance-group "${GKE_INSTANCE_GROUP}"


# create url maps
$ gcloud beta compute url-maps create "tkst-https-lb" 

--default-service "tkst-backend"
# create target https proxy
$ gcloud beta compute target-https-proxies create "tkst-https-lb-proxy" 

--url-map "tkst-https-lb" 

--ssl-certificate "${SSL_CERTIFICATE}"



# create forwarding rule
$ gcloud beta compute forwarding-rules create "tkst-https-lb-forward" 

--global --address "${LB_GLOBAL_IP}" --port-range "443" 

--target-https-proxy "tkst-https-lb-proxy"
takusuta における GKE 活用例
用途によって Cluster を別ける
• 大きなクラスターは作らない
• 5 ノード以下は無料
• 最大ノード数は 250 まで(少し前は 100 までだった)
• 同じ Pod でまとめた方がキャパシティ制御しやすい
用途によって Cluster を別ける
• ennis-asia-app-001 cluster
• num-nodes: 5, machine-type: n1-highcpu-4
• service: ennis-asia-app-srv (type=NodeType, 30000),
• rc: ennis-asia-app-rc (replica=10 )

• ennis-asia-nginx-001 cluster
• num-nodes: 3, machine-type: n1-highcpu-2
• service: ennis-asia-nginx-srv (type=NodeType, 30080, 30443)
• rc: ennis-asia-nginx-rc (replica=3 )
Cluster の命名規則ぽい奴
• ennis-asia-app-001
• ennis: プロジェクトの chord name
• asia: 配置する region
• app: 稼働させる container の名称
• 001: ユニークにするための連番(なんでも良い)

• Cluster の machine-type をオンラインで変更はサポートされていない
• 現状だと新しく Cluster を作成して GCE-LB を切り替える
• 高い頻度で Cluster を再構築 (使い捨て) している
Cluster の命名規則ぽい奴
• ennis-asia-app-001
• ennis: プロジェクトの chord name
• asia: 配置する region
• app: 稼働させる container の名称
• 001: ユニークにするための連番(なんでも良い)

• Cluster の machine-type をオンラインで変更はサポートされていない
• 現状だと新しく Cluster を作成して GCE-LB を切り替える
• 高い頻度で Cluster を再構築 (使い捨て) している
• Instance Templates の更新 API が無い … (́・ω・`)
Multi Container Pod
• ennis-app pod
• 用途
• Web アプリケーションコンテナ
• 全てのログは 127.0.0.1:24224 を経由して BigQuery に投げている
• コンテナ
• API (ennis-node-con, TCP:3000, 3001)
• Fluentd (ennis-fluentd-con, TCP:24224)

Multi Container Pod
# get service list
$ kubectl get service
NAME CLUSTER_IP EXTERNAL_IP PORT(S) SELECTOR
ennis-app-srv 10.187.254.39 nodes 3000/TCP,3001/TCP name=ennis-app-rc-pods
kubernetes 10.187.240.1 <none> 443/TCP <none>
# get replication controller list

$ kubectl get rc
CONTROLLER CONTAINER(S) IMAGE(S)
ennis-app-rc-1453323827 ennis-node-con asia.gcr.io/xxxxx/ennis-node:1.9.5
ennis-fluentd-con asia.gcr.io/xxxxx/fluentd-aggregator:1.0.1
# get pod list
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
ennis-app-rc-1453323827-0ampm 2/2 Running 0 2h
ennis-app-rc-1453323827-5xvfk 2/2 Running 0 2h
ennis-app-rc-1453323827-gvr4z 2/2 Running 0 2h
Single Container Pod
• ennis-nginx pod 
• 用途
• GCE-LB の Default Backend として設定する
• url-maps に該当しないリクエストは nginx 経由で転送させる
• ex: http(s)://107.178.243.152/ → https://takusuta.com/
• コンテナ
• Nginx (ennis-nginx-proxy-con, TCP:80)

Single Container Pod
# get service list
$ kubectl get service
NAME CLUSTER_IP EXTERNAL_IP PORT(S) SELECTOR
ennis-nginx-srv 10.107.251.130 nodes 80/TCP name=ennis-nginx-rc-pods
kubernetes 10.107.240.1 <none> 443/TCP <none>
# get replication controller list

$ kubectl get rc
CONTROLLER CONTAINER(S) IMAGE(S)
ennis-nginx-rc ennis-nginx-proxy-con asia.gcr.io/xxxxx/nginx-proxy:1.0.2
# get pod list
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
ennis-nginx-rc-3byoj 1/1 Running 0 7h
ennis-nginx-rc-i6dbs 1/1 Running 0 7h
ennis-nginx-rc-sefai 1/1 Running 0 7h
Sample : Dockerfile
# nginx-proxy Dockerfile
$ cat ./nginx-proxy/Dockerfile
FROM takusuta/nginx-1.8.0
MAINTAINER Katsutoshi Nagaoka <katsutoshi.nagaoka@gmail.com>
USER root
ENV HOME /root
WORKDIR /root
# Define default command.
CMD ["bash"]
# Generate script.
ADD generate-nginx-proxy-conf.sh /usr/local/sbin/generate-nginx-proxy-conf.sh
# Staring nginx.
EXPOSE 80
CMD /usr/local/sbin/generate-nginx-proxy-conf.sh && nginx -g "daemon off;"
Sample : Dockerfile
# generate nginx-proxy config script
$ cat ./nginx-proxy/generate-nginx-proxy-conf.sh
#!/bin/sh
if [ "x${ENNIS_WEB_DOMAIN}" = "x" ] ; then
echo "Invalid parameter, ENNIS_WEB_DOMAIN is empty”; exit 1
fi
cat << EOS > /etc/nginx/conf.d/nginx-proxy.conf
server {
listen 80;
server_name _;
location ~^/ping$ {
access_log off;
return 200;
}
location / {
return 301 https://${ENNIS_WEB_DOMAIN}$request_uri;
}
}
EOS
Sample : RC
# create ennis-nginx replication controller

$ cat << EOS > ./${NGINX_RC_NAME}.json && kubectl create -f ./${NGINX_RC_NAME}.json
{
"kind": "ReplicationController",

"apiVersion": "v1",
"metadata": { "name": "${NGINX_RC_NAME}", "labels": { "name": "${NGINX_RC_NAME}" } },
"spec": {
"replicas": 3,
"selector": { "name": "${NGINX_POD_NAME}" },
"template": {
"metadata": { "labels": { "name": "${NGINX_POD_NAME}" } },
"spec": {
"containers": [
{
"name": “ennis-nginx-proxy-con",
"image": "${GCR_DOMAIN}/${PROJECT_ID}/nginx-proxy:${TAG}",
"env": [ { "name": "ENNIS_WEB_DOMAIN", "value": "${DOMAIN}" } ],
"ports": [ { "containerPort":80, "protocol":"TCP" } ]
}
...
EOS
Sample : Service
# create ennis-nginx service

$ cat << EOS > ./${NGINX_SRV_NAME}.json && kubectl create -f ./${NGINX_RC_NAME}.json
{
"kind": "Service",
"apiVersion": "v1",
"metadata": { "name": "${NGINX_SRV_NAME}", "labels": { "name": "${NGINX_SRV_NAME}" } },
"spec": {
"type": "NodePort",
"ports": [
{
"port": 80,
"targetPort": 80,
"nodePort": 30080,
"protocol": "TCP"
}
],
"selector": { "name": "${NGINX_POD_NAME}" }
}
}
EOS
GCR への最速アップロード
• GCE 上の Jenkins でイメージのビルド & アップロードをしている
• 同じ Google ネットワーク内のため最速で GCR にアップロード可能
• タグ切り → CI → Jenkins (build & upload & release) ← hubot
• GCR が落ちたなどの障害は今の所、経験なし
GCR への最速アップロード
• GCE 上の Jenkins でイメージのビルド & アップロードをしている
• 同じ Google ネットワーク内のため最速で GCR にアップロード可能
• タグ切り → CI → Jenkins (build & upload & release) ← hubot
• GCR が落ちたなどの障害は今の所、経験なし
• GCR 上にアップロードした古いイメージの削除に若干難あり
• そのうち改善されるはず…
RC の無停止アップデート
• kubectl rolling-update コマンドでリリース作業をしている
• 新旧 RC の各 Pod を一台ずつ inc/dec してくれる
• single container Pod は非常に簡単

kubectl rolling-update [old-rc-name] [new-image-url]

• multi container Pod は分かり難い
• kubectl rolling-update [old-rc-name] -f [new-rc-json]
• rc name に "-unixtime" などを追記し、

selector と metadata も同様に version: "unixtime" などを入れる
• ex: ennis-asia-app-rc → ennis-asia-app-rc-1453323016
RC の無停止アップデート
# create multi container pod schema JSON for rolling update

$ RC_NAME=tkst-rc
$ RC_CREATED=$(Date +'%s') 

$ RC_UNIQUE_NAME=${RC_NAME}-${RC_CREATED}


$ cat << EOS | kubectl rolling-update ${RC_CURRENT_NAME} -f -
{
"kind": "ReplicationController",
"metadata": { "name": "${RC_UNIQUE_NAME}", "labels": { "name": "${RC_UNIQUE_NAME}" }
},
"spec": {
"selector": { "name": "${RC_NAME}-pods", "version": "${RC_CREATED}" },
"template": {
"metadata": {
"labels": { "name": "${RC_NAME}-pods", "version": "${RC_CREATED}" }
},
"spec": {
"containers": [ { ... }, { ... }, ... ],
...
EOS
Cluster / RC のスケール
• gcloudコマンドで node を制御できる
• gcloud compute instance-groups managed 

resize [gke-cluster-instance-group] --size [num]
• kubectl scale コマンドで replica を制御できる
• kubectl scale rc [rc-name] --replicas=[num]
• RC のオートスケールも実装されたが、まだ使い道が浮かんでこない
Cloud Logging によるログ管理
• GKE は各 Pod の標準出力を Cloud Logging に投げている 
• ログの集約及び閲覧をリアルタイムに実現できる
• 最近 GKE フィルターが付いて益々便利になった
Cloud Logging によるログ管理
• GKE は各 Pod の標準出力を Cloud Logging に投げている 
• ログの集約及び閲覧をリアルタイムに実現できる
• 最近 GKE フィルターが付いて益々便利になった
• 標準機能だとノイズが多く若干不便
• app container から CL の REST API を直接叩いている (winston-gcl)
• ログ名、レベルによるフィルターも効くのでもっと便利に
• 負荷急騰時は、一旦 CL を見る体勢
Cloud Monitoring による死活監視
• イマなら StackDriver を無料で使える
• 元々AWS の死活監視に使用していたので違和感なし
• Alert 時は Slack とメールでの通知を行っている
Cloud Monitoring による死活監視
• イマなら StackDriver を無料で使える
• 元々AWS の死活監視に使用していたので違和感なし
• Alert 時は Slack とメールでの通知を行っている
• GKE Container リソースで取得可能な metrics が少ない
• 古い GKE Cluster の場合 StackDriver agent から取得できない
• GKE Cluster をアップデート (or 作り直し) で正常に取得できる
• 足りない箇所は各 container から custom metrics を送信している
Kubernetes dashboard
• 標準機能の簡易ダッシュボード
• そんなに信用してないし、あまり見ていない
• 使いにくい
https://xxx.xxx.xxx.xxx/api/v1/proxy/namespaces/kube-system/services/kube-ui
• 結構使える子
• https://github.com/kubernetes/kubedash
• Cloud Monitoring は重い…
• パッと確認するのに便利
• インストールも簡単
kubedash
https://xxx.xxx.xxx.xxx/api/v1/proxy/namespaces/kube-system/services/kubedash
まとめ
GKEで半年運用してみて…
• 簡単 & 安い & 期待
• 細かいところは幾つかあるが、本番環境で問題なく利用できてる
• ここ数ヶ月で Cloud Logging の GKE 連携改善など色々キテル
• GKE のドキュメントは少ないが、kubernetes docs で事足りる

• GKE によるコンテナ管理は非常に魅力的で、積極的に使っていきたい
• 出来るだけシンプルに使う・複雑な構成はしない
チートシート
# pod

$ kubectl get pod
$ kubectl describe pod [pod-name]
$ kubectl attach [pod-name]
$ kubectl logs [-f] [pod-name] [-c container-name]
# replication controller

$ kubectl get rc
$ kubectl describe rc [rc-name]
$ kubectl rolling-update [rc-name] [new-image-url]
$ kubectl rolling-update [rc-name] -f [new-rc-schema-json-file-path]
$ kubectl scale rc [rc-name] --replicas=[num]
# service

$ kubectl service service
$ kubectl describe service [service-name]
# cluster

$ kubectl cluster-info
$ gcloud compute instance-groups managed resize [gke-cluster-instance-group] --size [num]
ご静聴ありがとうございました

GKEで半年運用してみた

  • 1.
  • 2.
    永岡 克利 (KatsutoshiNagaoka) • 2011年 CyberAgent 中途入社 • 社内向け基盤システムの開発・運用 • 現在、ライブ配信サービス「takusuta」を立ち上げ、運用中 • エンジニア • #java #cassandra … • #golang #node.js #mongodb #aws #gcp … @na_ga About me
  • 3.
    Outline • takusuta 紹介 •GKE ざっくり説明 • takusuta における GKE の活用例 • まとめ
  • 4.
  • 5.
  • 6.
    ライブ配信サービス takusuta https://takusuta.com/ onGKE
 2015/08 ~ iOS & Android App
 2015/07 ~
  • 7.
    • API • EC2 •S3 • Web • GKE • S3 構成 AWS Route53 CloudFront S3 EC2 MongoDBELB BigQuery GCP GKEGCE-LB Aerospike
  • 8.
    GKE 採用に至るまで • 2015/07 •iOS, Android アプリ公開 • S3 の Static Content でペライチな Web ページ • nodejs + riot による SEO 対策した Web ページを作ることに • ちょうど kubernetes v1.0.0 がリリースされた • 近いうちに GKE も GA になりそうな • どうせ作るなら… 一旦 Web だけワンチャン使ってみたい • 2015/08 • GKE is Generally Available • Web ページリニューアル
  • 9.
  • 10.
    GKE とは • Kubernetesのフルマネージドサービス • Docker コンテナの管理ツール • GCE 上に Kubernetes Cluster を構築 • クラスタのリサイズ • コンテナのグルーピング • コンテナの自動配置 • コンテナのリサイズ • コンテナの負荷分散 出典: http://kubernetes.io/
  • 11.
    GKE の料金 • すごい安い •Cluster の各 Node 料金は GCE 料金が適用 • Cluster の料金は Node 数によって異なる • 5 Node までは無料 • 6 Node 以上で $0.15 hour / cluster • $108 month / cluster
  • 12.
    GKE の用語 • Pod •コンテナのグループ • 1コンテナ以上で作成 • Replication Controller (RC) • Pod のレプリカ管理 • 管理下の Pod のリサイズを担当 Pod GKE Node Pod Pod GKE Node Pod Pod Pod RC Management Pod Replica
  • 13.
    GKE の用語 • Pod •コンテナのグループ • 1コンテナ以上で作成 • Replication Controller (RC) • Pod のレプリカ管理 • 管理下の Pod のリサイズを担当 • Service • Pod に対する LB みたいなやつ • iptables で DNAT → kube-proxy Pod GKE Node Pod Pod GKE Node Pod Pod Pod Service RC Layer4 Load Balancer
  • 14.
  • 15.
    単体構成 • GKE • tkst-service(type: LoadBalancer)
 設定された Global IP で公開される
 現状では Layer4 のみサポート tkst-pod GKE NODE GKE NODE tkst-service tkst-rc tkst-pod User Admin https://takusuta.com
  • 16.
    単体構成 • GKE • tkst-service(type: LoadBalancer)
 設定された Global IP で公開される
 現状では Layer4 のみサポート
 • Service に証明書を設定できない tkst-pod GKE NODE GKE NODE tkst-service tkst-rc tkst-pod User Admin https://takusuta.com
  • 17.
    単体構成 • GKE • tkst-service(type: LoadBalancer)
 設定された Global IP で公開される
 現状では Layer4 のみサポート
 • Service に証明書を設定できない • 各 Pod に証明書を持たせる tkst-pod GKE NODE GKE NODE tkst-service tkst-rc tkst-pod User Admin https://takusuta.com
  • 18.
    単体構成 • GKE • tkst-service(type: LoadBalancer)
 設定された Global IP で公開される
 現状では Layer4 のみサポート
 • Service に証明書を設定できない • 各 Pod に証明書を持たせる • 非効率的なので避けたい tkst-pod GKE NODE GKE NODE tkst-service tkst-rc tkst-pod User Admin https://takusuta.com
  • 19.
    GCE-LB と組み合わせた構成 • GKE •tkst-service (type: NodePort)
 各 Node が Service に設定した
 ポートでリクエストを受け付ける tkst-pod GKE NODE GKE NODE tkst-service tkst-rc tkst-pod User tkst-backend tkst-url-map GCE-HTTPS-LB https://takusuta.com Admin
  • 20.
    GCE-LB と組み合わせた構成 • GKE •tkst-service (type: NodePort)
 各 Node が Service に設定した
 ポートでリクエストを受け付ける
 • GCE-LB に証明書を設定する tkst-pod GKE NODE GKE NODE tkst-service tkst-rc tkst-pod User tkst-backend tkst-url-map GCE-HTTPS-LB https://takusuta.com Admin
  • 21.
    GCE-LB と組み合わせた構成 • GKE •tkst-service (type: NodePort)
 各 Node が Service に設定した
 ポートでリクエストを受け付ける
 • GCE-LB に証明書を設定する • GKE の Instance Group と
 ポートを Backend として指定する tkst-pod GKE NODE GKE NODE tkst-service tkst-rc tkst-pod User tkst-backend tkst-url-map GCE-HTTPS-LB https://takusuta.com Admin
  • 22.
    Cross Region LB構成 • 米国からは US Region tkst-pod GKE NODE GKE NODE tkst-service tkst-rc tkst-pod User from US tkst-backend-us tkst-url-map Cross-Region HTTPS-LB https://takusuta.com tkst-pod GKE NODE GKE NODE tkst-service tkst-rc tkst-pod tkst-backend-asia
  • 23.
    Cross Region LB構成 • 日本からは Asia Region tkst-pod GKE NODE GKE NODE tkst-service tkst-rc tkst-pod User from Japan tkst-backend-us https://takusuta.com tkst-pod GKE NODE GKE NODE tkst-service tkst-rc tkst-pod tkst-backend-asia tkst-url-map Cross-Region HTTPS-LB
  • 24.
    Cross Region LB構成 • 利用率や Rate で自動切り替え • ex: CPU 80% tkst-pod GKE NODE GKE NODE tkst-service tkst-rc tkst-pod User from Japan tkst-backend-us https://takusuta.com tkst-pod GKE NODE GKE NODE tkst-service tkst-rc tkst-pod tkst-backend-asia tkst-url-map Cross-Region HTTPS-LB
  • 25.
    Region/zone の選択 • Zoneによって差異がある • Haswell [2013 ] • Ivy Bridge [2012 ] • Sandy Bridge [2011 ] • Asia Region は同じなので
 気にしなくて ok 出典: https://cloud.google.com/compute/docs/zones
  • 26.
  • 27.
    Google Cloud SDK •Google 社製の GCP 管理ツール群 • gcloud • Cluster の作成/管理 • kubectl • RC の作成/管理 • Service の作成/管理
  • 28.
    Cluster の作成 # createcluster
 $ gcloud container clusters create "tkst-asia-001" 
 --num-nodes 3 --zone "asia-east1-b" --machine-type "n1-highcpu-4" 
 --scope "compute-rw","storage-ro","bigquery","logging-write","monitoring"
 
 • cluster 作成時しか設定できない項目がある • num-nodes は cluster 作成後もオンラインで変更できる • 現時点では num-nodes 以外の項目は cluster 作成後に変更できない
 • 特に scope は後々面倒になるので注意が必要 • GKE から Fluentd などで BigQuery に流し込む為には bigquery scope が必須 • 直近使う予定がなくても、とりあえず付けといた方が良い

  • 29.
    Cluster の取得 # describecluster
 $ gcloud container clusters describe tkst-asia-001
 
 currentNodeCount: 3 currentMasterVersion: 1.1.4 currentNodeVersion: 1.1.4 initialClusterVersion: 1.1.4 nodeConfig: diskSizeGb: 100 machineType: n1-highcpu-4 oauthScopes: - https://www.googleapis.com/auth/bigquery - https://www.googleapis.com/auth/compute - https://www.googleapis.com/auth/devstorage.read_only - https://www.googleapis.com/auth/logging.write - https://www.googleapis.com/auth/monitoring nodeIpv4CidrSize: 24 status: RUNNING zone: asia-east1-b
  • 30.
    Image のアップロード # builddocker image
 $ docker build .
 
 # upload docker image to Google Container Registry (GCR)
 $ docker tag -f tkst/tkst asia.gcr.io/xxxxx/tkst:1.9.3
 $ gcloud docker push asia.gcr.io/xxxxx/tkst:1.9.3
 
 • GCR はホスト名でアップロード先リージョンを指定できる • asia.gcr.io: asia リージョン • us.gcr.io: us リージョン • eu.gcr.io: european リージョン
  • 31.
    RC の作成 # createreplication controller
 $ cat << EOS > ./tkst-rc.json; kubectl create -f ./tkst-rc.json { "kind": "ReplicationController", "apiVersion": "v1", "metadata": { "name": "tkst-rc", "labels": { "name": "tkst-rc" } }, "spec": { "replicas": 3, "selector": { "name": "tkst-rc-pods" }, "template": { "metadata": { "labels": { "name": "tkst-rc-pods" } }, "spec": { "containers": [ { "name": "tkst-container", "image": "asia.gcr.io/xxxxx/tkst:1.9.3", "ports": [ { "containerPort":3000, "protocol":"TCP" } ] } ] } } } } EOS
  • 32.
    RC の取得 # getreplication controller
 $ kubectl get rc CONTROLLER CONTAINER(S) IMAGE(S) SELECTOR REPLICAS tkst-rc tkst asia.gcr.io/xxxxx/tkst:1.9.3 name=tkst-rc-pods 3 
 
 # describe replication controller
 $ kubectl describe rc tkst-rc Name: tkst-rc Namespace: default
 Image(s): asia.gcr.io/xxxxx/tkst:1.9.3 Selector: name=tkst-rc-pods Labels: name=tkst-rc Replicas: 3 current / 3 desired Pods Status: 3 Running / 0 Waiting / 0 Succeeded / 0 Failed No volumes.
 Events: FirstSeen LastSeen Count Reason Message ───────── ──────── ───── ────── ─────── 25m 25m 1 SuccessfulCreate Created pod: tkst-rc-5gghw 25m 25m 1 SuccessfulCreate Created pod: tkst-rc-b59cv
 25m 25m 1 SuccessfulCreate Created pod: tkst-rc-qw4da
  • 33.
    Pod の取得 # getpod
 $ kubectl get pod NAME READY STATUS RESTARTS AGE tkst-rc-1tjlf 1/1 Running 0 25m tkst-rc-5zogh 1/1 Running 0 25m tkst-rc-kpujg 1/1 Running 0 25m
 
 # describe pod
 $ kubectl describe pod tkst-rc-1tjlf Name: tkst-rc-1tjlf Namespace: default Image(s): asia.gcr.io/xxxxx/tkst:1.9.3 Node: gke-tkst-asia-001-a48fb14f-node-crjc/10.240.0.18 Start Time: Thu, 21 Jan 2016 06:03:50 +0900 Labels: name=tkst-rc-pods Status: Running IP: 10.184.2.3 Replication Controllers: tkst-rc (3/3 replicas created)
  • 34.
    Pod への接続 # attachpod
 $ kubectl attach pod tkst-rc-1tjlf 
 # get pod log
 $ kubectl logs -f tkst-rc-1tjlf # get pod log (with content name) $ kubectl logs -f tkst-rc-1tjlf -c tkst-node-container {"level":"info","message":"use memcached store [options={"hosts":["10.240.0.4:11211 {"level":"debug","message":"try to update site-maps cache.","label":"dev","timestamp": {"level":"debug","message":"cache update scheduler started. key=sitemap","label":"dev" {"level":"info","message":"[middleware_access_logger] setup with options {"tag":"ta {"level":"info","message":"[WEB] Append route. path={"twitter":"/explore/auth/twitt {"level":"info","message":"[WEB] Append route. path="/explore/logout"","label":"web_ {"level":"info","message":"[WEB] Append route. path="/ping"","label":"web_dev","time {"level":"info","message":"[WEB] Append route. path="/"","label":"web_dev","timestam ...
  • 35.
    Service の作成 # createservice
 $ cat << EOS > ./tkst-srv.json; kubectl create -f ./tkst-srv.json { "kind": "Service", "apiVersion": "v1", "metadata": { "name": "tkst-srv", "labels": { "name": "tkst-srv" } }, "spec": { "type": "NodePort", "ports": [ { "port": 3000, "targetPort": 3000, "nodePort": 30000 } ], "selector": { "name": "tkst-rc-pods" } } } EOS
  • 36.
    Service の取得 # getservice
 $ kubectl get service NAME CLUSTER_IP EXTERNAL_IP PORT(S) SELECTOR tkst-srv 10.119.246.120 nodes 3000/TCP name=tkst-rc-pods kubernetes 10.119.240.1 <none> 443/TCP <none> 
 
 # describe service
 $ kubectl describe service tkst-srv Name: tkst-srv Namespace: default Labels: name=tkst-srv Selector: name=tkst-rc-pods Type: NodePort IP: 10.119.246.120 Port: 3000/TCP NodePort: 30000/TCP Endpoints: 10.116.0.3:3000,10.116.2.3:3000 Session Affinity: None No events.
  • 37.
    HTTPS-LB の作成 # createbackend
 $ gcloud beta compute backend-services create "tkst-backend" 
 —-protocol HTTP --port-name "tkst-port" --http-health-check "tkst-check"
 
 # add backend resource 
 $ gcloud beta compute backend-services add-backend "tkst-backend" --instance-group "${GKE_INSTANCE_GROUP}" 
 # create url maps $ gcloud beta compute url-maps create "tkst-https-lb" 
 --default-service "tkst-backend" # create target https proxy $ gcloud beta compute target-https-proxies create "tkst-https-lb-proxy" 
 --url-map "tkst-https-lb" 
 --ssl-certificate "${SSL_CERTIFICATE}"
 
 # create forwarding rule $ gcloud beta compute forwarding-rules create "tkst-https-lb-forward" 
 --global --address "${LB_GLOBAL_IP}" --port-range "443" 
 --target-https-proxy "tkst-https-lb-proxy"
  • 38.
  • 39.
    用途によって Cluster を別ける •大きなクラスターは作らない • 5 ノード以下は無料 • 最大ノード数は 250 まで(少し前は 100 までだった) • 同じ Pod でまとめた方がキャパシティ制御しやすい
  • 40.
    用途によって Cluster を別ける •ennis-asia-app-001 cluster • num-nodes: 5, machine-type: n1-highcpu-4 • service: ennis-asia-app-srv (type=NodeType, 30000), • rc: ennis-asia-app-rc (replica=10 )
 • ennis-asia-nginx-001 cluster • num-nodes: 3, machine-type: n1-highcpu-2 • service: ennis-asia-nginx-srv (type=NodeType, 30080, 30443) • rc: ennis-asia-nginx-rc (replica=3 )
  • 41.
    Cluster の命名規則ぽい奴 • ennis-asia-app-001 •ennis: プロジェクトの chord name • asia: 配置する region • app: 稼働させる container の名称 • 001: ユニークにするための連番(なんでも良い)
 • Cluster の machine-type をオンラインで変更はサポートされていない • 現状だと新しく Cluster を作成して GCE-LB を切り替える • 高い頻度で Cluster を再構築 (使い捨て) している
  • 42.
    Cluster の命名規則ぽい奴 • ennis-asia-app-001 •ennis: プロジェクトの chord name • asia: 配置する region • app: 稼働させる container の名称 • 001: ユニークにするための連番(なんでも良い)
 • Cluster の machine-type をオンラインで変更はサポートされていない • 現状だと新しく Cluster を作成して GCE-LB を切り替える • 高い頻度で Cluster を再構築 (使い捨て) している • Instance Templates の更新 API が無い … (́・ω・`)
  • 43.
    Multi Container Pod •ennis-app pod • 用途 • Web アプリケーションコンテナ • 全てのログは 127.0.0.1:24224 を経由して BigQuery に投げている • コンテナ • API (ennis-node-con, TCP:3000, 3001) • Fluentd (ennis-fluentd-con, TCP:24224)

  • 44.
    Multi Container Pod #get service list $ kubectl get service NAME CLUSTER_IP EXTERNAL_IP PORT(S) SELECTOR ennis-app-srv 10.187.254.39 nodes 3000/TCP,3001/TCP name=ennis-app-rc-pods kubernetes 10.187.240.1 <none> 443/TCP <none> # get replication controller list
 $ kubectl get rc CONTROLLER CONTAINER(S) IMAGE(S) ennis-app-rc-1453323827 ennis-node-con asia.gcr.io/xxxxx/ennis-node:1.9.5 ennis-fluentd-con asia.gcr.io/xxxxx/fluentd-aggregator:1.0.1 # get pod list $ kubectl get pod NAME READY STATUS RESTARTS AGE ennis-app-rc-1453323827-0ampm 2/2 Running 0 2h ennis-app-rc-1453323827-5xvfk 2/2 Running 0 2h ennis-app-rc-1453323827-gvr4z 2/2 Running 0 2h
  • 45.
    Single Container Pod •ennis-nginx pod  • 用途 • GCE-LB の Default Backend として設定する • url-maps に該当しないリクエストは nginx 経由で転送させる • ex: http(s)://107.178.243.152/ → https://takusuta.com/ • コンテナ • Nginx (ennis-nginx-proxy-con, TCP:80)

  • 46.
    Single Container Pod #get service list $ kubectl get service NAME CLUSTER_IP EXTERNAL_IP PORT(S) SELECTOR ennis-nginx-srv 10.107.251.130 nodes 80/TCP name=ennis-nginx-rc-pods kubernetes 10.107.240.1 <none> 443/TCP <none> # get replication controller list
 $ kubectl get rc CONTROLLER CONTAINER(S) IMAGE(S) ennis-nginx-rc ennis-nginx-proxy-con asia.gcr.io/xxxxx/nginx-proxy:1.0.2 # get pod list $ kubectl get pod NAME READY STATUS RESTARTS AGE ennis-nginx-rc-3byoj 1/1 Running 0 7h ennis-nginx-rc-i6dbs 1/1 Running 0 7h ennis-nginx-rc-sefai 1/1 Running 0 7h
  • 47.
    Sample : Dockerfile #nginx-proxy Dockerfile $ cat ./nginx-proxy/Dockerfile FROM takusuta/nginx-1.8.0 MAINTAINER Katsutoshi Nagaoka <katsutoshi.nagaoka@gmail.com> USER root ENV HOME /root WORKDIR /root # Define default command. CMD ["bash"] # Generate script. ADD generate-nginx-proxy-conf.sh /usr/local/sbin/generate-nginx-proxy-conf.sh # Staring nginx. EXPOSE 80 CMD /usr/local/sbin/generate-nginx-proxy-conf.sh && nginx -g "daemon off;"
  • 48.
    Sample : Dockerfile #generate nginx-proxy config script $ cat ./nginx-proxy/generate-nginx-proxy-conf.sh #!/bin/sh if [ "x${ENNIS_WEB_DOMAIN}" = "x" ] ; then echo "Invalid parameter, ENNIS_WEB_DOMAIN is empty”; exit 1 fi cat << EOS > /etc/nginx/conf.d/nginx-proxy.conf server { listen 80; server_name _; location ~^/ping$ { access_log off; return 200; } location / { return 301 https://${ENNIS_WEB_DOMAIN}$request_uri; } } EOS
  • 49.
    Sample : RC #create ennis-nginx replication controller
 $ cat << EOS > ./${NGINX_RC_NAME}.json && kubectl create -f ./${NGINX_RC_NAME}.json { "kind": "ReplicationController",
 "apiVersion": "v1", "metadata": { "name": "${NGINX_RC_NAME}", "labels": { "name": "${NGINX_RC_NAME}" } }, "spec": { "replicas": 3, "selector": { "name": "${NGINX_POD_NAME}" }, "template": { "metadata": { "labels": { "name": "${NGINX_POD_NAME}" } }, "spec": { "containers": [ { "name": “ennis-nginx-proxy-con", "image": "${GCR_DOMAIN}/${PROJECT_ID}/nginx-proxy:${TAG}", "env": [ { "name": "ENNIS_WEB_DOMAIN", "value": "${DOMAIN}" } ], "ports": [ { "containerPort":80, "protocol":"TCP" } ] } ... EOS
  • 50.
    Sample : Service #create ennis-nginx service
 $ cat << EOS > ./${NGINX_SRV_NAME}.json && kubectl create -f ./${NGINX_RC_NAME}.json { "kind": "Service", "apiVersion": "v1", "metadata": { "name": "${NGINX_SRV_NAME}", "labels": { "name": "${NGINX_SRV_NAME}" } }, "spec": { "type": "NodePort", "ports": [ { "port": 80, "targetPort": 80, "nodePort": 30080, "protocol": "TCP" } ], "selector": { "name": "${NGINX_POD_NAME}" } } } EOS
  • 51.
    GCR への最速アップロード • GCE上の Jenkins でイメージのビルド & アップロードをしている • 同じ Google ネットワーク内のため最速で GCR にアップロード可能 • タグ切り → CI → Jenkins (build & upload & release) ← hubot • GCR が落ちたなどの障害は今の所、経験なし
  • 52.
    GCR への最速アップロード • GCE上の Jenkins でイメージのビルド & アップロードをしている • 同じ Google ネットワーク内のため最速で GCR にアップロード可能 • タグ切り → CI → Jenkins (build & upload & release) ← hubot • GCR が落ちたなどの障害は今の所、経験なし • GCR 上にアップロードした古いイメージの削除に若干難あり • そのうち改善されるはず…
  • 53.
    RC の無停止アップデート • kubectlrolling-update コマンドでリリース作業をしている • 新旧 RC の各 Pod を一台ずつ inc/dec してくれる • single container Pod は非常に簡単
 kubectl rolling-update [old-rc-name] [new-image-url]
 • multi container Pod は分かり難い • kubectl rolling-update [old-rc-name] -f [new-rc-json] • rc name に "-unixtime" などを追記し、
 selector と metadata も同様に version: "unixtime" などを入れる • ex: ennis-asia-app-rc → ennis-asia-app-rc-1453323016
  • 54.
    RC の無停止アップデート # createmulti container pod schema JSON for rolling update
 $ RC_NAME=tkst-rc $ RC_CREATED=$(Date +'%s') 
 $ RC_UNIQUE_NAME=${RC_NAME}-${RC_CREATED} 
 $ cat << EOS | kubectl rolling-update ${RC_CURRENT_NAME} -f - { "kind": "ReplicationController", "metadata": { "name": "${RC_UNIQUE_NAME}", "labels": { "name": "${RC_UNIQUE_NAME}" } }, "spec": { "selector": { "name": "${RC_NAME}-pods", "version": "${RC_CREATED}" }, "template": { "metadata": { "labels": { "name": "${RC_NAME}-pods", "version": "${RC_CREATED}" } }, "spec": { "containers": [ { ... }, { ... }, ... ], ... EOS
  • 55.
    Cluster / RCのスケール • gcloudコマンドで node を制御できる • gcloud compute instance-groups managed 
 resize [gke-cluster-instance-group] --size [num] • kubectl scale コマンドで replica を制御できる • kubectl scale rc [rc-name] --replicas=[num] • RC のオートスケールも実装されたが、まだ使い道が浮かんでこない
  • 56.
    Cloud Logging によるログ管理 •GKE は各 Pod の標準出力を Cloud Logging に投げている  • ログの集約及び閲覧をリアルタイムに実現できる • 最近 GKE フィルターが付いて益々便利になった
  • 57.
    Cloud Logging によるログ管理 •GKE は各 Pod の標準出力を Cloud Logging に投げている  • ログの集約及び閲覧をリアルタイムに実現できる • 最近 GKE フィルターが付いて益々便利になった • 標準機能だとノイズが多く若干不便 • app container から CL の REST API を直接叩いている (winston-gcl) • ログ名、レベルによるフィルターも効くのでもっと便利に • 負荷急騰時は、一旦 CL を見る体勢
  • 58.
    Cloud Monitoring による死活監視 •イマなら StackDriver を無料で使える • 元々AWS の死活監視に使用していたので違和感なし • Alert 時は Slack とメールでの通知を行っている
  • 59.
    Cloud Monitoring による死活監視 •イマなら StackDriver を無料で使える • 元々AWS の死活監視に使用していたので違和感なし • Alert 時は Slack とメールでの通知を行っている • GKE Container リソースで取得可能な metrics が少ない • 古い GKE Cluster の場合 StackDriver agent から取得できない • GKE Cluster をアップデート (or 作り直し) で正常に取得できる • 足りない箇所は各 container から custom metrics を送信している
  • 60.
    Kubernetes dashboard • 標準機能の簡易ダッシュボード •そんなに信用してないし、あまり見ていない • 使いにくい https://xxx.xxx.xxx.xxx/api/v1/proxy/namespaces/kube-system/services/kube-ui
  • 61.
    • 結構使える子 • https://github.com/kubernetes/kubedash •Cloud Monitoring は重い… • パッと確認するのに便利 • インストールも簡単 kubedash https://xxx.xxx.xxx.xxx/api/v1/proxy/namespaces/kube-system/services/kubedash
  • 62.
  • 63.
    GKEで半年運用してみて… • 簡単 &安い & 期待 • 細かいところは幾つかあるが、本番環境で問題なく利用できてる • ここ数ヶ月で Cloud Logging の GKE 連携改善など色々キテル • GKE のドキュメントは少ないが、kubernetes docs で事足りる
 • GKE によるコンテナ管理は非常に魅力的で、積極的に使っていきたい • 出来るだけシンプルに使う・複雑な構成はしない
  • 64.
    チートシート # pod
 $ kubectlget pod $ kubectl describe pod [pod-name] $ kubectl attach [pod-name] $ kubectl logs [-f] [pod-name] [-c container-name] # replication controller
 $ kubectl get rc $ kubectl describe rc [rc-name] $ kubectl rolling-update [rc-name] [new-image-url] $ kubectl rolling-update [rc-name] -f [new-rc-schema-json-file-path] $ kubectl scale rc [rc-name] --replicas=[num] # service
 $ kubectl service service $ kubectl describe service [service-name] # cluster
 $ kubectl cluster-info $ gcloud compute instance-groups managed resize [gke-cluster-instance-group] --size [num]
  • 65.