ゆるふわカウンターアタック

Qiitaっぽい時はQiitaで、slideshareっぽい時はslideshareで、preziっぽい時はpreziで、ブログっぽい時はここで

GCP Autoscalerで遊ぶ

日曜は犬と留守番をしていたので、時間をもてあましたので犬とオートスケールで遊ぶことにした

f:id:pioho:20160201185421p:plain

GCPのオートスケール機能Autoscalerの正式版は去年の9月ころ出たようです。

www.publickey1.jp

ウォームアップ不要ってところがAWSとの差別化ですね。5分以内に1000台一気に増やせるってすごくて怖い・・w
SSL終端できないとかもありますがが
まだマネコンにメニューもなくAPIのみの提供で、AWSの最初の頃のAutoscaleみたいな感じ、、って思ってたらインスタンスグループなるところにあった!

AWSのAutoscalingGroupのような感じですねきっと。

HTTPロードバランサを使ったAutoscalerで設定するものは以下

  • Global IP(HTTPロードバランサで使う場合タイプをグローバルにする)
  • Image File(オートスケールする際の作られるサーバーの元イメージ、これをもとにサーバーが増えていく)
  • Instance Template(マシンタイプ、Image File、ディスクタイプ、ディスクサイズ、所属ネットワークなどのインスタンスにまつわる情報をまとめたもの)
  • Instance Group(Instance Template、ゾーン、オートスケールのオンオフや閾値設定)

※この下はどちらかというとHTTPロードバランサの構成要素

  • Health Check(URLパス、ポート、間隔、タイムアウト)
  • Target Proxy(URLマップ、プロキシタイプ)
  • Global Transfer Rule(外部IP、プロトコル、Target Proxy)
  • Backend Service(リッスンプロトコルタイムアウト値、バックエンドとなるInstance Group、Health Check)
  • HTTP Load Balancer(Backend Service、Global Transfer Rule)

項目多いし文字だとわかりづらいので図にしてみる、が、やっぱわかりはずらい。。 ただこういう機能なんでこんなもんかと

f:id:pioho:20160131203954p:plain

ぽちぽちは大変なので、Terraformでやってみる
(テンプレは↓の方に張ったので変数を変えてよしなに試してみてもらえるとうれしい)

グローバルIPを作る場合、画面からだと以下のようにタイプを地域かGlobalかを選ぶところがある(どちらもグローバルIPではあるが、HTTPロードバランサにはグローバル指定のIPしか使えない)
※多分リージョン跨ぎのロードバランシングの為だと思うが今回は割愛
Terraformで使うResourceは地域IPの場合"google_compute_address"でグローバルIPの場合"google_compute_global_address"と分かれていて最初オプションで指定するものと勝手に思ってたから迷った><

f:id:pioho:20160201155653p:plain

AutoScalerどうだったか?

あたりまえだがAutoScaleしたw

インスタンス台数の最小値、最大値は設定できます。
とりあえず最小値4台、最大値16台、チェックはCPU50%とかで
InstanceGroup単位でCPU使用率を見ますが、4台のうち2台を100%にしました。
予想は行っても60%くらいかと思いきやグラフは一瞬80%くらい行きました。

結果的に無事インスタンスがAutoでScaleしましたがInsntance Groupのメトリクスがどういう計算になってるのか

最初の4台状態↓

f:id:pioho:20160201180729p:plain

CPU負荷かけて増えた状態。
10台に増えた。

AWSだと1度の増加台数を決めれるけどGCPはよしなに増やすっぽい。
だからスパイクにも強いってことだろう。最大数は決めれるけど

10台に増えてる↓

f:id:pioho:20160201180846p:plain



Instance Groupにある初期遅延時間(最初のヘルスチェックまでの時間)がデフォは300秒だけどTerraformだと変えられないっぽい?(いやどっかにある気がするがInstanceGroupとAutoscalerにはなかった。。)

なので多分ですが初期遅延時間(300s)+Cool Down(180s)の8分とインターバルのタイミングなので8分強。

CPU負荷を止めて、ぼーっとF5押しながらストップウォッチ見てたら10分弱くらいで減っていった↓

f:id:pioho:20160201180910p:plain



Cooldown値はあるのですが、AWSでは出来た一度に増設する台数とかきめ細かい設定はGCPはない(?)っぽいですね。
あと、LBのメトリクスがそもそも少ないw
あと、MultiZoneのAutoScaleはできない??これもAWSではできたけどもしできないなら痛い、

ほんとに出来ないかは不明、、Zoneの最小単位となるBackendを同じパス(/とか)で複数選択出来ればいいのだが、"URL MAP"設定でBackendを複数指定する場合、同じパス名でマップすると怒られる。なので同じパスにBackendを複数設定が出来なそうと思ったが違うかなぁ、、来週GCPUGおじゃまするので聞いてみよ。

※自己解決しました。HTTPLBのバランシング範囲はRegionでNWLBのバランシング範囲はZoneなのですね。

eventdots.jp

ちなみにTerraformのVarsとTemplateはこちら

構成としては

GCPのCredentialファイルは各自環境のものをカレントに置いといてね

### GCP
project_name = "test-project01"
region_asia = "asia-east1"
zone_asia1 = "asia-east1-a"
zone_asia2 = "asia-east1-b"

### GCE
server_name = "test-op01"
machine_type = "f1-micro"
image_name = "image-1"

### NW
http_port = "80"
ssh_port = "22"
any_port = "0.0.0.0/0"
kyoten_ip = "xx.xx.xx.xx"
ip_op = "test-opip01"
ip_lb = "test-lbip01"
fw_name = "test-allow-web"
## vars
variable "project_name" {}
variable "region_asia" {}
variable "zone_asia1" {}
variable "zone_asia2" {}
variable "server_name" {}
variable "machine_type" {}
variable "image_name" {}
variable "any_port" {}
variable "http_port" {}
variable "ssh_port" {}
variable "kyoten_ip" {}
variable "ip_op" {}
variable "fw_name" {}
variable "ip_lb" {}


provider "google" {
    credentials = "${file("account.json")}"
    project = "${var.project_name}"
    region = "${var.region_asia}"
}


## Global IP Address

resource "google_compute_address" "default1" {
    name = "${var.ip_op}"
    }

resource "google_compute_global_address" "default1" {
    name = "${var.ip_lb}"
    }


## Instance

resource "google_compute_instance" "default1" {
    name = "${var.server_name}"
    machine_type = "${var.machine_type}"
    zone = "${var.zone_asia1}"
    disk {
        image = "${var.image_name}"
    }
    network_interface {
        network = "${google_compute_network.default.name}"
        access_config {
            nat_ip = "${google_compute_address.default1.address}"
        }
    }
}


## Firewall

resource "google_compute_firewall" "default1" {
    name = "${var.fw_name}"
    network = "${google_compute_network.default.name}"
    allow {
        protocol = "tcp"
        ports = ["${var.http_port}"]
    }
    source_ranges = ["${var.any_port}"]
    source_tags = ["test-any"]
}

resource "google_compute_firewall" "default2" {
    name = "test-allow-ssh1"
    network = "${google_compute_network.default.name}"
    allow {
        protocol = "tcp"
        ports = ["${var.ssh_port}"]
    }
    source_ranges = ["10.10.0.0/16"]
    source_tags = ["op01"]

}

resource "google_compute_firewall" "default3" {
    name = "test-allow-ssh2"
    network = "${google_compute_network.default.name}"
    allow {
        protocol = "tcp"
        ports = ["${var.ssh_port}"]
    }
   source_ranges = ["${var.kyoten_ip}"]
    source_tags = ["test-office"]

}


## Network Address

resource "google_compute_network" "default" {
    name = "test-nw"
    ipv4_range = "10.10.0.0/16"
}

### LB
## HTTP Health Check

resource "google_compute_http_health_check" "default" {
    name = "test-check"
    request_path = "/"
    check_interval_sec = 5
    timeout_sec = 5
}

## TargetPool

resource "google_compute_target_pool" "default" {
    name = "test-pool"
    health_checks = ["${google_compute_http_health_check.default.name}"]
    region = "${var.region_asia}"
}


### AutoScaler
## Instance Template
resource "google_compute_instance_template" "default" {
    name = "test-template"
    machine_type = "f1-micro"
    disk {
        source_image = "image-1"
    }
    network_interface {
        network = "${google_compute_network.default.name}"
    }
}


## Instance Group

resource "google_compute_instance_group_manager" "default1" {
    name = "test-instansgrp1"
    instance_template = "${google_compute_instance_template.default.self_link}"
    target_pools = ["${google_compute_target_pool.default.self_link}"]
    base_instance_name = "test-svr"
    zone = "${var.zone_asia1}"
}


## Autoscaler

resource "google_compute_autoscaler" "default1" {
    name = "test-as1"
    zone = "${var.zone_asia1}"
    target = "${google_compute_instance_group_manager.default1.self_link}"
    autoscaling_policy = {
        max_replicas = 16
        min_replicas = 4
        cooldown_period = 180
        cpu_utilization = {
            target = 0.5
        }
    }
}


resource "google_compute_backend_service" "default1" {
    name = "test-backend1"
    description = "Hello World 1234"
    port_name = "http"
    protocol = "HTTP"
    timeout_sec = 10
    region = "${var.region_asia}"
    backend {
        group = "${google_compute_instance_group_manager.default1.instance_group}"
    }
    health_checks = ["${google_compute_http_health_check.default.self_link}"]
}


### LB

resource "google_compute_target_http_proxy" "default" {
    name = "test-proxy"
    description = "a description"
    url_map = "${google_compute_url_map.default.self_link}"
}


resource "google_compute_url_map" "default" {
    name = "test-urlmap"
    description = "a description"
    default_service = "${google_compute_backend_service.default1.self_link}"
    host_rule {
        hosts = ["mysite.com"]
        path_matcher = "allpaths"
    }
    path_matcher {
        default_service = "${google_compute_backend_service.default1.self_link}"
        name = "allpaths"
        path_rule {
            paths = ["/*"]
            service = "${google_compute_backend_service.default1.self_link}"
        }
    }
}

## Forwarding Rule

resource "google_compute_global_forwarding_rule" "default" {
    name = "test-forward"
    target = "${google_compute_target_http_proxy.default.self_link}"
    ip_address = "${google_compute_global_address.default1.address}"
    port_range = "${var.http_port}"
}

ちなみにAWSでオートスケール

AWS側のイメージとしては以下は多少参考になるかも。本番実装までしたので。ってか3年前かぁ、、古すぎる・・

www.slideshare.net