Я пытаюсь обновить свой сервис с нулевым временем простоя. Пока я безуспешен. Балансировщик нагрузки направляет трафик на старые экземпляры, поскольку они отключаются, несмотря на то, что они неработоспособны в соответствии с проверкой работоспособности балансировщика нагрузки. Я использую терраформ и gcp. Фактическая служба, которая будет обновлена, должна завершить соединение TLS, поэтому эта служба должна использовать балансировщик сетевой нагрузки, целевой пул. Региональный менеджер группы экземпляров должен обеспечить избыточность в случае выхода зоны из строя.
Игрушечная версия terraform, в которой количество экземпляров уменьшено, но показывает проблему
variable "project" {
type = string
}
variable "region" {
type = string
default = "us-central1"
}
provider "google" {
project = var.project
region = var.region
}
resource "google_compute_region_instance_group_manager" "default" {
base_instance_name = "instance"
name = "default"
region = var.region
target_size = 3
target_pools = [
google_compute_target_pool.default.self_link,
]
update_policy {
minimal_action = "REPLACE"
type = "PROACTIVE"
max_surge_fixed = 3
max_unavailable_fixed = 0
min_ready_sec = 120
}
version {
instance_template = google_compute_instance_template.template-b.self_link
}
}
resource "google_compute_address" "default" {
name = "default"
}
resource "google_compute_target_pool" "default" {
name = "default"
region = var.region
instances = []
health_checks = [
google_compute_http_health_check.default.self_link
]
lifecycle {
ignore_changes = [
instances
]
}
}
resource "google_compute_http_health_check" "default" {
name = "default"
request_path = "/"
check_interval_sec = 1
timeout_sec = 1
healthy_threshold = 3
unhealthy_threshold = 1
}
resource "google_compute_forwarding_rule" "default" {
name = "default"
region = var.region
ip_protocol = "TCP"
port_range = "80"
target = google_compute_target_pool.default.self_link
ip_address = google_compute_address.default.address
}
data "google_compute_network" "default" {
name = "default"
}
resource "google_compute_instance_template" "template-b" {
name = "template-b1"
machine_type = "f1-micro"
disk {
boot = true
auto_delete = true
disk_size_gb = 100
disk_type = "pd-ssd"
source_image = data.google_compute_image.my_image.self_link
}
network_interface {
network = data.google_compute_network.default.self_link
}
metadata_startup_script = file("./startup-scripts/helloworld.sh")
metadata = {
instance-env = "SOFTWARE_VERSION=Version-B"
}
tags = [
"http-server"
]
lifecycle {
create_before_destroy = true
}
}
data "google_compute_image" "my_image" {
family = "ubuntu-1804-lts"
project = "ubuntu-os-cloud"
}
output "ip-address" {
value = google_compute_address.default.address
}
сценарий загрузки, который запускает сервер, работающий на каждом экземпляре. startup-scripts/helloworld.sh
#!/bin/bash -x
METADATA_BASE=http://metadata.google.internal/computeMetadata/v1
SOFTWARE_VERSION=$(curl -sfm5 -H "Metadata-Flavor: Google" ${METADATA_BASE}/instance/attributes/instance-env)
echo "Hello World! This is ${SOFTWARE_VERSION} from $(hostname -f)" > index.html
python3 -m http.server 80 &
Проблема, с которой я столкнулся, заключается в том, что при уменьшении количества экземпляров, скажем, с 6 до 3, я вижу, что некоторые экземпляры помечены как неработоспособные при проверке работоспособности, но целевой пул по-прежнему направляет трафик на эти экземпляры. Документация для этого подразумевает, что эти экземпляры не должны видеть никакого трафика.
во время изменения размера числа экземпляров с 6 до 3 я запустил два сценария оболочки и получил эти результаты while [[ 1 ]]; do echo -n "$(date +%s) "; curl -m5 http://${IP_ADDRESS} && sleep 1; done
no timeouts
...
1589838264 Hello World! This is SOFTWARE_VERSION=Version-B from instance-562f.c.my-project.internal
1589838265 Hello World! This is SOFTWARE_VERSION=Version-B from instance-42dm.c.my-project.internal
1589838267 curl: (52) Empty reply from server
1589838267 curl: (28) Connection timed out after 5004 milliseconds
1589838272 Hello World! This is SOFTWARE_VERSION=Version-B from instance-xss8.c.my-project.internal
1589838273 curl: (28) Connection timed out after 5004 milliseconds
1589838278 Hello World! This is SOFTWARE_VERSION=Version-B from instance-xss8.c.my-project.internal
1589838279 curl: (28) Connection timed out after 5004 milliseconds
1589838284 Hello World! This is SOFTWARE_VERSION=Version-B from instance-wh9v.c.my-project.internal
1589838285 curl: (28) Connection timed out after 5004 milliseconds
1589838290 Hello World! This is SOFTWARE_VERSION=Version-B from instance-w47x.c.my-project.internal
1589838292 curl: (28) Connection timed out after 5003 milliseconds
1589838297 curl: (28) Connection timed out after 5003 milliseconds
1589838302 Hello World! This is SOFTWARE_VERSION=Version-B from instance-xss8.c.my-project.internal
...
no time outs
while [[ 1 ]]; do echo -n "$(date +%s) "; gcloud compute target-pools get-health default --region us-central1 && sleep 1; done
all six instances are healthy
...
1589838263 ---
healthStatus:
- healthState: HEALTHY
instance: compute/v1/projects/my-project/zones/us-central1-f/instances/instance-xss8
ipAddress: <IP_ADDRESS>
kind: compute#targetPoolInstanceHealth
---
healthStatus:
- healthState: HEALTHY
instance: compute/v1/projects/my-project/zones/us-central1-c/instances/instance-w47x
ipAddress: <IP_ADDRESS>
kind: compute#targetPoolInstanceHealth
---
healthStatus:
- healthState: HEALTHY
instance: compute/v1/projects/my-project/zones/us-central1-b/instances/instance-wh9v
ipAddress: <IP_ADDRESS>
kind: compute#targetPoolInstanceHealth
---
healthStatus:
- healthState: UNHEALTHY
instance: compute/v1/projects/my-project/zones/us-central1-f/instances/instance-rvcl
kind: compute#targetPoolInstanceHealth
---
healthStatus:
- healthState: HEALTHY
instance: compute/v1/projects/my-project/zones/us-central1-b/instances/instance-562f
ipAddress: <IP_ADDRESS>
kind: compute#targetPoolInstanceHealth
---
healthStatus:
- healthState: UNHEALTHY
instance: compute/v1/projects/my-project/zones/us-central1-c/instances/instance-42dm
kind: compute#targetPoolInstanceHealth
1589838266 ---
healthStatus:
- healthState: HEALTHY
instance: compute/v1/projects/my-project/zones/us-central1-f/instances/instance-xss8
ipAddress: <IP_ADDRESS>
kind: compute#targetPoolInstanceHealth
---
healthStatus:
- healthState: HEALTHY
instance: compute/v1/projects/my-project/zones/us-central1-c/instances/instance-w47x
ipAddress: <IP_ADDRESS>
kind: compute#targetPoolInstanceHealth
---
healthStatus:
- healthState: HEALTHY
instance: compute/v1/projects/my-project/zones/us-central1-b/instances/instance-wh9v
ipAddress: <IP_ADDRESS>
kind: compute#targetPoolInstanceHealth
---
healthStatus:
- healthState: UNHEALTHY
instance: compute/v1/projects/my-project/zones/us-central1-f/instances/instance-rvcl
kind: compute#targetPoolInstanceHealth
---
healthStatus:
- healthState: UNHEALTHY
instance: compute/v1/projects/my-project/zones/us-central1-b/instances/instance-562f
kind: compute#targetPoolInstanceHealth
---
healthStatus:
- healthState: UNHEALTHY
instance: compute/v1/projects/my-project/zones/us-central1-c/instances/instance-42dm
kind: compute#targetPoolInstanceHealth
...
unhealthy for a bit
...
1589838312 ---
healthStatus:
- healthState: HEALTHY
instance: v1/projects/my-project/zones/us-central1-f/instances/instance-xss8
ipAddress: <IP_ADDRESS>
kind: compute#targetPoolInstanceHealth
---
healthStatus:
- healthState: HEALTHY
instance: compute/v1/projects/my-project/zones/us-central1-c/instances/instance-w47x
ipAddress: <IP_ADDRESS>
kind: compute#targetPoolInstanceHealth
---
healthStatus:
- healthState: HEALTHY
instance: compute/v1/projects/my-project/zones/us-central1-b/instances/instance-wh9v
ipAddress: <IP_ADDRESS>
kind: compute#targetPoolInstanceHealth
как вы можете видеть по отметкам времени из сценариев, неработоспособные экземпляры все еще получают трафик.
Этот же шаблон неработоспособных инстансов, получающих трафик, можно увидеть при замене шаблона инстанса для регионального менеджера группы инстансов в terraform на другой. это также можно увидеть при вызове второго регионального диспетчера группы экземпляров и добавлении его в целевой пул, ожидающем перехода трафика к этим новым экземплярам, а затем удалении более старого регионального диспетчера группы экземпляров из целевого пула. Я также попытался создать второй целевой пул с его собственным менеджером группы экземпляров, а затем изменить правило переадресации, но там я увидел более минуты простоя, когда трафик даже не направлялся ни в одну из региональных групп экземпляров.
Что я могу сделать, чтобы избежать этого простоя?