Kubernetesに負荷をかけオートスケールを観察する
本番環境でKubernetesを使うためには、Kubernetesがどのように動作するか把握していないと安心して運用することができません。
まずはサービスを運用する上で重要になる、高負荷時の動きを確認してみたいと思います。
KubernetesにはHPAとCluster Autoscalerの二種類がありますが、両方の動きを見ていきます。
詳細な解説は他に譲りますが、
HPAは稼働中のPodを増加させることで高負荷に耐え、
Cluster AutoscalerはPodを増加させることができないときにKubernetesが扱えるリソースを追加するものです。
つまり、負荷が高まるとHPAがおこりPodが追加され、それでも負荷が高くHPAが続きKubernetesが管理しているリソースに空きがなくなったときにCluster AutoscalerによってVMが追加され、そこにPodが追加されます。
環境
- GKE 1.9.7-gke.0
実行するアプリケーション
できるだけ手軽に実験したいので、goでリクエストを受け付けて、少し負荷がかかる処理をした後にレスポンスを返すアプリケーションをKubernetesで実行してみます。
Kubernetesの構成は
Ingress -> Service -> Deployment
となっています。
実行するgoのAPIのソースはこのようにしました。
package main import ( "fmt" "net/http" "strconv" ) func handler(w http.ResponseWriter, r *http.Request) { n := 0 for i := 0; i < 1*1000*1000*1000; i++ { n += i } fmt.Fprintf(w, strconv.Itoa(n)+"\n") fmt.Fprintf(w, "my-api") } func main() { http.HandleFunc("/", handler) http.ListenAndServe(":80", nil) }
とても単純なものです。
これをDocker Imageにし、DockerのrunコマンドでAPIサーバーが起動するようにDockerfileを書きます。
FROM golang:1.9.2-alpine3.6 ADD ./server.go ./ RUN go build -o server CMD ["/go/server"]
Imageをアップロードしますが、せっかくGKEを使用するので同じGCP上にあるGoogle Container Registryにアップロードします。
$ docker build -t asia.gcr.io/{your-project-id}/my-api:v1 . $ gcloud docker -- push asia.gcr.io/{your-project-id}/my-api:v1
Kubernetesの設定ファイル
Kubernetesについては省略します。
今回は以下の設定ファイルを使用します。
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: test-ingress annotations: kubernetes.io/ingress.global-static-ip-name: "test-ip" spec: backend: serviceName: service-my-api servicePort: 80 --- apiVersion: v1 kind: Service metadata: name: service-my-api spec: type: NodePort ports: - protocol: TCP port: 80 targetPort: 80 name: http selector: app: my-api version: v1 --- apiVersion: extensions/v1beta1 kind: Deployment metadata: name: my-api spec: replicas: 2 template: metadata: labels: app: my-api version: v1 spec: containers: - name: myapi image: gcr.io/{your-project-id}/myapi:v1 resources: requests: cpu: "500m" limits: cpu: "1500m" ports: - containerPort: 80 --- apiVersion: autoscaling/v1 kind: HorizontalPodAutoscaler metadata: name: my-api namespace: default spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: my-api minReplicas: 2 maxReplicas: 6 targetCPUUtilizationPercentage: 70
オートスケールに関係のあるところだけ解説します。
今回負荷をかけるAPIがあるPodに対してはCPUを1.5個まで使用を許可しています。
このPodが初期値として2台稼働しており、閾値を70としています。
つまり、CPUの使用率が70%を超えたときにPodの追加が行われることになります。
また、公式ドキュメントのautoscaling-algorithmによると、10%の許容値があったり瞬間的に超えただけだとオートスケールしなかったりするようです。
負荷をかける
負荷をかけるツールはいろいろありますが、手軽に使えるhey
を使用します。
このツールで負荷をかけてみた結果、このようになりました。
PodのCPU使用率
ノードのCPU使用率
ピーク時はPodは6個に、ノードは3台にまで増えていますね。
HPAは追加にかかる時間が数秒なので、EC2とかのオートスケールと比べるとだいぶ早いですね。
これは便利そうです。