From 0299bfec27f2cce76e2a213d77de1a125e2b3b50 Mon Sep 17 00:00:00 2001 From: rs1986x <33729460+rs1986x@users.noreply.github.com> Date: Fri, 4 Aug 2023 06:30:18 +0200 Subject: [PATCH] feat: add support for liveness and readiness probes (#101) Co-authored-by: Prabhu <18209477+prabhu34@users.noreply.github.com> Co-authored-by: Amanda Karina Lopes de Oliveira Co-authored-by: Andrew Peabody Co-authored-by: Grant Sorbo --- README.md | 2 ++ main.tf | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++ variables.tf | 54 ++++++++++++++++++++++++++++++++++++++++++ versions.tf | 2 +- 4 files changed, 123 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 82c9fbbd..625c39ed 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,7 @@ module "cloud_run" { | generate\_revision\_name | Option to enable revision name generation | `bool` | `true` | no | | image | GCR hosted image URL to deploy | `string` | n/a | yes | | limits | Resource limits to the container | `map(string)` | `null` | no | +| liveness\_probe | Periodic probe of container liveness. Container will be restarted if the probe fails.
More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes |
object({
failure_threshold = optional(number, null)
initial_delay_seconds = optional(number, null)
timeout_seconds = optional(number, null)
period_seconds = optional(number, null)
http_get = optional(object({
path = optional(string)
http_headers = optional(list(object({
name = string
value = string
})), null)
}), null)
grpc = optional(object({
port = optional(number)
service = optional(string)
}), null)
})
| `null` | no | | location | Cloud Run service deployment location | `string` | n/a | yes | | members | Users/SAs to be given invoker access to the service | `list(string)` | `[]` | no | | ports | Port which the container listens to (http1 or h2c) |
object({
name = string
port = number
})
|
{
"name": "http1",
"port": 8080
}
| no | @@ -72,6 +73,7 @@ module "cloud_run" { | service\_annotations | Annotations to the service. Acceptable values all, internal, internal-and-cloud-load-balancing | `map(string)` |
{
"run.googleapis.com/ingress": "all"
}
| no | | service\_labels | A set of key/value label pairs to assign to the service | `map(string)` | `{}` | no | | service\_name | The name of the Cloud Run service to create | `string` | n/a | yes | +| startup\_probe | Startup probe of application within the container.
All other probes are disabled if a startup probe is provided, until it succeeds.
Container will not be added to service endpoints if the probe fails.
More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes |
object({
failure_threshold = optional(number, null)
initial_delay_seconds = optional(number, null)
timeout_seconds = optional(number, null)
period_seconds = optional(number, null)
http_get = optional(object({
path = optional(string)
http_headers = optional(list(object({
name = string
value = string
})), null)
}), null)
tcp_socket = optional(object({
port = optional(number)
}), null)
grpc = optional(object({
port = optional(number)
service = optional(string)
}), null)
})
| `null` | no | | template\_annotations | Annotations to the container metadata including VPC Connector and SQL. See [more details](https://cloud.google.com/run/docs/reference/rpc/google.cloud.run.v1#revisiontemplate) | `map(string)` |
{
"autoscaling.knative.dev/maxScale": 2,
"autoscaling.knative.dev/minScale": 1,
"generated-by": "terraform",
"run.googleapis.com/client-name": "terraform"
}
| no | | template\_labels | A set of key/value label pairs to assign to the container metadata | `map(string)` | `{}` | no | | timeout\_seconds | Timeout for each request | `number` | `120` | no | diff --git a/main.tf b/main.tf index 6fac2b56..23948c6d 100644 --- a/main.tf +++ b/main.tf @@ -48,6 +48,72 @@ resource "google_cloud_run_service" "main" { requests = var.requests } + dynamic "startup_probe" { + for_each = var.startup_probe != null ? [1] : [] + content { + failure_threshold = var.startup_probe.failure_threshold + initial_delay_seconds = var.startup_probe.initial_delay_seconds + timeout_seconds = var.startup_probe.timeout_seconds + period_seconds = var.startup_probe.period_seconds + dynamic "http_get" { + for_each = var.startup_probe.http_get != null ? [1] : [] + content { + path = var.startup_probe.http_get.path + dynamic "http_headers" { + for_each = var.startup_probe.http_get.http_headers != null ? var.startup_probe.http_get.http_headers : [] + content { + name = http_headers.value["name"] + value = http_headers.value["value"] + } + } + } + } + dynamic "tcp_socket" { + for_each = var.startup_probe.tcp_socket != null ? [1] : [] + content { + port = var.startup_probe.tcp_socket.port + } + } + dynamic "grpc" { + for_each = var.startup_probe.grpc != null ? [1] : [] + content { + port = var.startup_probe.grpc.port + service = var.startup_probe.grpc.service + } + } + } + } + + dynamic "liveness_probe" { + for_each = var.liveness_probe != null ? [1] : [] + content { + failure_threshold = var.liveness_probe.failure_threshold + initial_delay_seconds = var.liveness_probe.initial_delay_seconds + timeout_seconds = var.liveness_probe.timeout_seconds + period_seconds = var.liveness_probe.period_seconds + dynamic "http_get" { + for_each = var.liveness_probe.http_get != null ? [1] : [] + content { + path = var.liveness_probe.http_get.path + dynamic "http_headers" { + for_each = var.liveness_probe.http_get.http_headers != null ? var.liveness_probe.http_get.http_headers : [] + content { + name = http_headers.value["name"] + value = http_headers.value["value"] + } + } + } + } + dynamic "grpc" { + for_each = var.liveness_probe.grpc != null ? [1] : [] + content { + port = var.liveness_probe.grpc.port + service = var.liveness_probe.grpc.service + } + } + } + } + dynamic "env" { for_each = var.env_vars content { diff --git a/variables.tf b/variables.tf index ec71c374..d6f3f758 100644 --- a/variables.tf +++ b/variables.tf @@ -165,6 +165,60 @@ variable "container_command" { default = [] } +variable "startup_probe" { + type = object({ + failure_threshold = optional(number, null) + initial_delay_seconds = optional(number, null) + timeout_seconds = optional(number, null) + period_seconds = optional(number, null) + http_get = optional(object({ + path = optional(string) + http_headers = optional(list(object({ + name = string + value = string + })), null) + }), null) + tcp_socket = optional(object({ + port = optional(number) + }), null) + grpc = optional(object({ + port = optional(number) + service = optional(string) + }), null) + }) + default = null + description = <<-EOF + Startup probe of application within the container. + All other probes are disabled if a startup probe is provided, until it succeeds. + Container will not be added to service endpoints if the probe fails. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + EOF +} + +variable "liveness_probe" { + type = object({ + failure_threshold = optional(number, null) + initial_delay_seconds = optional(number, null) + timeout_seconds = optional(number, null) + period_seconds = optional(number, null) + http_get = optional(object({ + path = optional(string) + http_headers = optional(list(object({ + name = string + value = string + })), null) + }), null) + grpc = optional(object({ + port = optional(number) + service = optional(string) + }), null) + }) + default = null + description = <<-EOF + Periodic probe of container liveness. Container will be restarted if the probe fails. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + EOF +} variable "env_vars" { type = list(object({ value = string diff --git a/versions.tf b/versions.tf index 15f9a8d7..60b1d3c0 100644 --- a/versions.tf +++ b/versions.tf @@ -15,7 +15,7 @@ */ terraform { - required_version = ">= 0.13" + required_version = ">= 1.3" required_providers { google = {