これは Google Cloud Platform Advent Calendar 2017 - Qiita の19日目のエントリです。otiai10です。
背景
ということで、k8sでやってみるかということになりました。GKEはその昔1度だけ触ったことがある*1けど、だいぶ記憶が無い。
k8s(Kubernetes)とは
クバネテス、って僕はよんでます。コンテナを実行する物理ホストないしそのクラスタを抽象化し、コンテナの死活監視やスケールを管理するコンテナオーケストレーションミドルウェア、だと理解しました。
docker-swarmと何がちがうの?
って思ったので、ちょっとググった。「似ているものとどう違うか」を知ることは、それを知るのに非常に有用です。
- How is Docker Swarm different than Kubernetes? - Stack Overflow
- 2016
- Kubernetes vs. Swarm: Which Container Orchestrator is Best for You? - Container JournalContainer Journal
swarmでは、Dockerの標準の機能が生で使えるし、セットアップも各プラットフォームでそんなに差異が無い
- まあKubernetes自分で立てるみたいなのは今んとこやるつもりないしいいけど
https://platform9.com/blog/compare-kubernetes-vs-docker-swarm/- 下記にplatform9によるupdateあり
- Hands on orchestration: Docker 1.12 Swarm vs Kubernetes - Torusware
- 両者の、具体的な、ローカルでのクラスタの構築ハンズオン。両者の雰囲気がよくわかる。
- Docker Swarm vs. Kubernetes: Comparison of the Two Giants
Kubernetesは、複数pod間でデータボリュームを共有するためのデータボリュームマネージャがある
- 最後にPros/Consもまとまってて参考になる
- Kubernetes vs. Swarm: Which Container Orchestrator is Best for You? - Container JournalContainer Journal
- 2017
- https://platform9.com/blog/kubernetes-docker-swarm-compared/
ストレージのバックエンド(nfs、AWS EBS、etc)を各々指定できる。なおかつ、ストレージの要求に対して、別々のバックエンドを持ち合わせて達成することもできる。
- Volumes | Kubernetes
- これはすごい
- Kubernetes Vs Docker Swarm - A Comparison of Containerization Platform
Kubernetesでアプリケーションを動かす場合は、pods, deployments, そして servicesについて知る必要がある。対して、Docker Swarmは、docker-composeとまったく同じように、servicesだけを意識すればよい。
- https://platform9.com/blog/kubernetes-docker-swarm-compared/
自分なりにまとめると
- 解決する問題とそのレイヤーはほぼ同じ
- Kubernetesはクラウド上のマネージドサービスとして使うのがよさそう。自分で立てるなら、Docker Swarmのほうが簡単だよ。
- 概念はKubernetesのほうが多いから、Dockerから来た場合は、ちょいちょい学習コストはありそうだよ。
- でも、やっぱりいろいろ複雑なことはKubernetesのほうができそう
- とくにvolumesまわりは、とっても気になるよ
GKEとは
で、いよいよGKE
- docker - What is the difference between kubernetes and GKE? - Stack Overflow
GKE(Google Kubernetes Engine)は、Kubernetesのマネージドサービスです
- Google Cloud Platform Blog: Google Container Engine - Kubernetes 1.8 takes advantage of the cloud built for containers
https://cloud.google.com/container-engine/
は、/kubernetes-engine
にリダイレクトされるので、言葉の定義として、もはやContainerEngineとは呼ばず、KubernetesEngineと呼ぶっぽい
- Google Kubernetes Engine | Google Cloud Platform
- Google Cloud Computing compares GCE, GAE and GKE
- GCP内の、GCEやGAEとの違いをおおまかに理解するのによい
- Node Pools | Kubernetes Engine | Google Cloud Platform
- 物理マシン(と言っても仮想ですが、マシンと言う意味で)のプールについて
- Pricing | Kubernetes Engine | Google Cloud Platform
- 料金。
- node poolをつくると、そこにlaunchされているGCEの分だけ課金が発生するっぽい。Nodeを小さめに作っておき、auto-scalingをうまいこと使えばよいかもしれない
要件の整理
- Job on Kubernetesの確認
- GKEのCluster Scalingの評価
- GKE上に小さいクラスタを立てる
- 重めのJobを複数サブミットする
- nodeが増えることを確認
- Jobが終わったらnodeが最初のサイズに戻れば勝ち
実装例
0. kubectlのインストール
% gcloud components install kubectl
% which kubectl
/Users/otiai10/.google-cloud-sdk/bin/kubectl
% kubectl --help
1-a: クラスタ立てる
ふむ
1-b. ジョブの実行
% mkdir /tmp/gke-workspace
% cd /tmp/gke-workspace
apiVersion: batch/v1 kind: Job metadata: name: my-first-batch-job spec: template: metadata: name: my-first-batch-job-tpl spec: containers: - name: my-fbj-container-01 image: perl command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"] restartPolicy: Never backoffLimit: 4
% kubectl create -f ./my-job.yaml W1219 14:24:30.058767 46656 factory_object_mapping.go:423] Failed to download OpenAPI (Get http://localhost:8080/swagger-2.0.0.pb-v1: dial tcp [::1]:8080: getsockopt: connection refused), falling back to swagger The connection to the server localhost:8080 was refused - did you specify the right host or port?
んなぁ〜、まあそうだよな、現状、ローカルのkubectl
は、GCPコンソールでつくったクラスタの存在なんて知らないわけだから。
コレに従って、gcloud
経由でクラスタ作ってたら、こうはならなかったと思われる。まあしかたないので、kubectl
に、GCPコンソールでつくったクラスタに向いてもらう。
% kubectl --help % kubectl cluster-info % kubectl config get-clusters % kubectl config view
--project
をいちいち指定するのがめんどいので、変える- gcloud config set | Cloud SDK | Google Cloud Platform
% gcloud projects list
% gcloud config set project gke-batch-test
- GCPから既存のクラスタのcredentialsをfetchする
- gcloud container clusters get-credentials | Cloud SDK | Google Cloud Platform
% gcloud container clusters list NAME ZONE MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS my-tiny-cluster asia-northeast1-a 1.7.8-gke.0 35.200.66.24 n1-standard-1 1.7.8-gke.0 1 RUNNING % gcloud container clusters get-credentials my-tiny-cluster Fetching cluster endpoint and auth data. kubeconfig entry generated for my-tiny-cluster.
そうすると、
% kubectl cluster-info Kubernetes master is running at https://35.200.66.24 GLBCDefaultBackend is running at https://35.200.66.24/api/v1/namespaces/kube-system/services/default-http-backend/proxy Heapster is running at https://35.200.66.24/api/v1/namespaces/kube-system/services/heapster/proxy KubeDNS is running at https://35.200.66.24/api/v1/namespaces/kube-system/services/kube-dns/proxy kubernetes-dashboard is running at https://35.200.66.24/api/v1/namespaces/kube-system/services/kubernetes-dashboard/proxy To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'. %
となる。いい感じに、kubectl
が、今まで知りえなかったGCP上のkubernetesクラスタの情報を持っている状態になった。ので、
1-c. ジョブ実行と成果確認
% kubectl create -f ./my-job.yaml error: error validating "./my-job.yaml": error validating data: [ValidationError(Job): ValidationError(Job.spec): unknown field "backoffLimit" in io.k8s.kubernetes.pkg.apis.batch.v1.JobSpec]; if you choose to ignore these errors, turn validation off with --validate=false
んなぁ〜、backoffLimit
って公式のquickstartにあるやつだぞ?しかたがないのでmy-job.yaml
におけるbackoffLimit
をコメントアウトした。
% kubectl create -f ./my-job.yaml job "my-first-batch-job" created
お
% kubectl describe jobs/my-first-batch-job Name: my-first-batch-job Namespace: default Selector: controller-uid=19e50d15-e484-11e7-acda-42010a920fe9 Labels: controller-uid=19e50d15-e484-11e7-acda-42010a920fe9 job-name=my-first-batch-job Annotations: <none> Parallelism: 1 Completions: 1 Start Time: Tue, 19 Dec 2017 15:16:07 +0900 Pods Statuses: 0 Running / 1 Succeeded / 0 Failed Pod Template: Labels: controller-uid=19e50d15-e484-11e7-acda-42010a920fe9 job-name=my-first-batch-job Containers: my-fbj-container-01: Image: perl Port: <none> Command: perl -Mbignum=bpi -wle print bpi(2000) Environment: <none> Mounts: <none> Volumes: <none> Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal SuccessfulCreate 1m job-controller Created pod: my-first-batch-job-qmmrn %
いい感じ。さらに、GCEのCPU使用率のグラフが
いい感じ。
2-a. クラスタ立てる
使いまわすので割愛。
2-b. 重めのジョブを複数投げる
円周率2000桁で、CPU使用率が30%ぐらいだったので、まー適当に2万桁ぐらい行ってみますか!
apiVersion: batch/v1 kind: Job metadata: - name: my-first-batch-job + name: heavy-job spec: template: metadata: - name: my-first-batch-job-tpl + name: heavy-job-tpl spec: containers: - - name: my-fbj-container-01 + name: heavy-job-container image: perl - command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"] + command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(20000)"] restartPolicy: Never # backoffLimit: 4
2-c.d.
metadata.name
をユニークにする必要があったので、ここを変えつつ、
% kubectl create -f ./my-job.yaml # ちょっと時間たって % kubectl create -f ./my-job.yaml # ちょっと時間たって % kubectl create -f ./my-job.yaml
とした。
サイズが増えとる。
ちょっと手間取って、スケールダウンのほうは確認できなかったけど、まあ重いジョブを投げて自動的にスケールアップするのは確認できた。
今後の検証事項
- 投げるジョブがおもすぎて
kubectl job delete {NAME}
してしまって、自動スケールダウンが確認できなかった - 明示的に
kubectl job delete {NAME}
すると、system podの管理を外れて、オートスケールダウンが発火しなくなるのか? - GCPコンソールでGCEを消しても、Kubernetesクラスタのクラスタサイズの表記が2のままだったのも、同じ性質の問題か?
- 「計算リソースも、任意の量が要求されうる」という要件があったのだけれど、どうやらこれに関しては、ある程度見積もれるジョブが来ることが期待されているっぽいので、あるクラスタにおいて1つのジョブが実行されるpodのリソースは、クラスタ定義における「マシンタイプ」を超えないようだ。これに関しては、別のソリューションを考える必要があるっぽい
あとかたづけ
雑感
- GCPアドベントカレンダー、GKEの話が多いきがする
- 先日、美容師さんに勧められた毛生え薬使い始めたんですが、進捗なかなかいいです
現場からは以上です。皆さん良いお年を!
DRYな備忘録として