☸️ How to deploy a secured OVH managed Kubernetes cluster using Terraform in 2023

This page summarizes the projects mentioned and recommended in the original post on dev.to

Our great sponsors
  • WorkOS - The modern identity platform for B2B SaaS
  • InfluxDB - Power Real-Time Data Analytics at Scale
  • SaaSHub - Software Alternatives and Reviews
  • public-cloud-roadmap

    Agile roadmap for OVHcloud Public Cloud services. Discover the features our product teams are working on, comment and influence our backlog.

  • resource "ovh_cloud_project_kube" "cluster" { service_name = var.project_id[terraform.workspace] name = "${terraform.workspace}-cluster" region = var.region private_network_id = openstack_networking_network_v2.private_network.id private_network_configuration { default_vrack_gateway = "192.168.12.1" private_network_routing_as_default = true } customization { apiserver { admissionplugins { enabled = ["NodeRestriction"] disabled = ["AlwaysPullImages"] # the long-awaited option <3, see https://github.com/ovh/public-cloud-roadmap/issues/70#issuecomment-1235364408 } } } } resource "ovh_cloud_project_kube_nodepool" "node_pool" { service_name = var.project_id[terraform.workspace] name = "${terraform.workspace}-pool" kube_id = ovh_cloud_project_kube.cluster.id flavor_name = "b2-15" ## TODO : configure using https://docs.ovh.com/us/en/kubernetes/configuring-cluster-autoscaler/, not available in terraform # autoscale = true desired_nodes = 3 max_nodes = 3 min_nodes = 3 timeouts { create = "1h" # default 20m ; OVH can be real slow on this one, and will consider a duplicate on next run } } resource "local_sensitive_file" "kubeconfig" { content = ovh_cloud_project_kube.cluster.kubeconfig filename = "${terraform.workspace}.kubeconfig" file_permission = "0644" depends_on = [ovh_cloud_project_kube.cluster, ovh_cloud_project_kube_nodepool.node_pool] }

  • public-cloud-examples

  • # Inspired by : https://github.com/ovh/public-cloud-examples/tree/main/databases/pgsql # This example is a bit different and older : https://github.com/ovh/public-cloud-databases-examples/tree/main/databases/postgresql/terraform/hello-world resource "ovh_cloud_project_database" "pg_database" { # depends_on = [openstack_networking_network_v2.private_network] service_name = var.project_id[terraform.workspace] description = "${terraform.workspace} PostGreSQL Cluster" engine = "postgresql" # one of [postgresql cassandra mysql kafka kafkaConnect] version = "14" plan = "business" # 2 nodes, read replicas planned : https://docs.ovh.com/gb/en/publiccloud/databases/postgresql/capabilities/#plans flavor = "db1-7" # https://docs.ovh.com/gb/en/publiccloud/databases/postgresql/capabilities/#hardware-resources_1 nodes { region = var.global_region network_id = openstack_networking_network_v2.private_network.id subnet_id = openstack_networking_subnet_v2.subnet.id } nodes { region = var.global_region network_id = openstack_networking_network_v2.private_network.id subnet_id = openstack_networking_subnet_v2.subnet.id } } resource "ovh_cloud_project_database_database" "auth-server" { service_name = ovh_cloud_project_database.pg_database.service_name engine = ovh_cloud_project_database.pg_database.engine cluster_id = ovh_cloud_project_database.pg_database.id name = "auth-server" } resource "ovh_cloud_project_database_database" "backend" { service_name = ovh_cloud_project_database.pg_database.service_name engine = ovh_cloud_project_database.pg_database.engine cluster_id = ovh_cloud_project_database.pg_database.id name = "backend" } resource "ovh_cloud_project_database_ip_restriction" "ip_restriction" { engine = "postgresql" cluster_id = ovh_cloud_project_database.pg_database.id service_name = ovh_cloud_project_database.pg_database.service_name ip = "192.168.12.0/24" } resource "ovh_cloud_project_database_postgresql_user" "backend" { service_name = ovh_cloud_project_database.pg_database.service_name cluster_id = ovh_cloud_project_database.pg_database.id name = "backend" # 'postgres' is a reserved user, detailed message taken from API https://eu.api.ovh.com/console/#/cloud/project/%7BserviceName%7D/database/postgresql/%7BclusterId%7D/user~POST roles = ["replication"] # Arbitrary string to change to trigger a password update. # Use 'terraform refresh' after 'terraform apply' to update the output with the new password. password_reset = "password-reset-on-18-01-2022" } resource "ovh_cloud_project_database_postgresql_user" "auth" { service_name = ovh_cloud_project_database.pg_database.service_name cluster_id = ovh_cloud_project_database.pg_database.id name = "auth" # 'postgres' is a reserved user, detailed message taken from API https://eu.api.ovh.com/console/#/cloud/project/%7BserviceName%7D/database/postgresql/%7BclusterId%7D/user~POST roles = ["replication"] # Arbitrary string to change to trigger a password update. # Use 'terraform refresh' after 'terraform apply' to update the output with the new password. password_reset = "password-reset-on-18-01-2022" }

  • WorkOS

    The modern identity platform for B2B SaaS. The APIs are flexible and easy-to-use, supporting authentication, user identity, and complex enterprise features like SSO and SCIM provisioning.

    WorkOS logo
  • public-cloud-databases-examples

    OVHcloud Public Cloud Databases Training examples

  • # Inspired by : https://github.com/ovh/public-cloud-examples/tree/main/databases/pgsql # This example is a bit different and older : https://github.com/ovh/public-cloud-databases-examples/tree/main/databases/postgresql/terraform/hello-world resource "ovh_cloud_project_database" "pg_database" { # depends_on = [openstack_networking_network_v2.private_network] service_name = var.project_id[terraform.workspace] description = "${terraform.workspace} PostGreSQL Cluster" engine = "postgresql" # one of [postgresql cassandra mysql kafka kafkaConnect] version = "14" plan = "business" # 2 nodes, read replicas planned : https://docs.ovh.com/gb/en/publiccloud/databases/postgresql/capabilities/#plans flavor = "db1-7" # https://docs.ovh.com/gb/en/publiccloud/databases/postgresql/capabilities/#hardware-resources_1 nodes { region = var.global_region network_id = openstack_networking_network_v2.private_network.id subnet_id = openstack_networking_subnet_v2.subnet.id } nodes { region = var.global_region network_id = openstack_networking_network_v2.private_network.id subnet_id = openstack_networking_subnet_v2.subnet.id } } resource "ovh_cloud_project_database_database" "auth-server" { service_name = ovh_cloud_project_database.pg_database.service_name engine = ovh_cloud_project_database.pg_database.engine cluster_id = ovh_cloud_project_database.pg_database.id name = "auth-server" } resource "ovh_cloud_project_database_database" "backend" { service_name = ovh_cloud_project_database.pg_database.service_name engine = ovh_cloud_project_database.pg_database.engine cluster_id = ovh_cloud_project_database.pg_database.id name = "backend" } resource "ovh_cloud_project_database_ip_restriction" "ip_restriction" { engine = "postgresql" cluster_id = ovh_cloud_project_database.pg_database.id service_name = ovh_cloud_project_database.pg_database.service_name ip = "192.168.12.0/24" } resource "ovh_cloud_project_database_postgresql_user" "backend" { service_name = ovh_cloud_project_database.pg_database.service_name cluster_id = ovh_cloud_project_database.pg_database.id name = "backend" # 'postgres' is a reserved user, detailed message taken from API https://eu.api.ovh.com/console/#/cloud/project/%7BserviceName%7D/database/postgresql/%7BclusterId%7D/user~POST roles = ["replication"] # Arbitrary string to change to trigger a password update. # Use 'terraform refresh' after 'terraform apply' to update the output with the new password. password_reset = "password-reset-on-18-01-2022" } resource "ovh_cloud_project_database_postgresql_user" "auth" { service_name = ovh_cloud_project_database.pg_database.service_name cluster_id = ovh_cloud_project_database.pg_database.id name = "auth" # 'postgres' is a reserved user, detailed message taken from API https://eu.api.ovh.com/console/#/cloud/project/%7BserviceName%7D/database/postgresql/%7BclusterId%7D/user~POST roles = ["replication"] # Arbitrary string to change to trigger a password update. # Use 'terraform refresh' after 'terraform apply' to update the output with the new password. password_reset = "password-reset-on-18-01-2022" }

  • terraform-provider-ovh

    Terraform OVH provider

  • # inspired by https://github.com/yomovh/tf-at-ovhcloud pointed by https://github.com/ovh/terraform-provider-ovh/issues/329 resource "ovh_cloud_project_user" "s3_admin" { service_name = var.project_id[terraform.workspace] description = "Used to create S3 buckets with Terraform" role_names = [ "objectstore_operator" ] } resource "ovh_cloud_project_user_s3_credential" "s3_admin_cred" { service_name = ovh_cloud_project_user.s3_admin.service_name user_id = ovh_cloud_project_user.s3_admin.id } resource "aws_s3_bucket" "backend" { # name should be unique because shared by all users on the system bucket = "my-app-clients-data-${terraform.workspace}" } resource "ovh_cloud_project_user" "backend" { service_name = var.project_id[terraform.workspace] # username is the user id, and is not customizable description = "my-app backend app user" role_names = [ "objectstore_operator" ] } resource "ovh_cloud_project_user_s3_credential" "backend" { service_name = ovh_cloud_project_user.backend.service_name user_id = ovh_cloud_project_user.backend.id } resource "ovh_cloud_project_user_s3_policy" "policy" { service_name = ovh_cloud_project_user.backend.service_name user_id = ovh_cloud_project_user.backend.id policy = jsonencode({ "Statement" : [{ "Sid" : "RWContainer", "Effect" : "Allow", "Action" : ["s3:GetObject", "s3:PutObject", "s3:DeleteObject", "s3:ListBucket", "s3:ListMultipartUploadParts", "s3:ListBucketMultipartUploads", "s3:AbortMultipartUpload", "s3:GetBucketLocation"], "Resource" : ["arn:aws:s3:::${aws_s3_bucket.backend.bucket}", "arn:aws:s3:::${aws_s3_bucket.backend.bucket}/*"] }] }) }

  • tf-at-ovhcloud

    My own terraform sample

  • # inspired by https://github.com/yomovh/tf-at-ovhcloud pointed by https://github.com/ovh/terraform-provider-ovh/issues/329 resource "ovh_cloud_project_user" "s3_admin" { service_name = var.project_id[terraform.workspace] description = "Used to create S3 buckets with Terraform" role_names = [ "objectstore_operator" ] } resource "ovh_cloud_project_user_s3_credential" "s3_admin_cred" { service_name = ovh_cloud_project_user.s3_admin.service_name user_id = ovh_cloud_project_user.s3_admin.id } resource "aws_s3_bucket" "backend" { # name should be unique because shared by all users on the system bucket = "my-app-clients-data-${terraform.workspace}" } resource "ovh_cloud_project_user" "backend" { service_name = var.project_id[terraform.workspace] # username is the user id, and is not customizable description = "my-app backend app user" role_names = [ "objectstore_operator" ] } resource "ovh_cloud_project_user_s3_credential" "backend" { service_name = ovh_cloud_project_user.backend.service_name user_id = ovh_cloud_project_user.backend.id } resource "ovh_cloud_project_user_s3_policy" "policy" { service_name = ovh_cloud_project_user.backend.service_name user_id = ovh_cloud_project_user.backend.id policy = jsonencode({ "Statement" : [{ "Sid" : "RWContainer", "Effect" : "Allow", "Action" : ["s3:GetObject", "s3:PutObject", "s3:DeleteObject", "s3:ListBucket", "s3:ListMultipartUploadParts", "s3:ListBucketMultipartUploads", "s3:AbortMultipartUpload", "s3:GetBucketLocation"], "Resource" : ["arn:aws:s3:::${aws_s3_bucket.backend.bucket}", "arn:aws:s3:::${aws_s3_bucket.backend.bucket}/*"] }] }) }

  • InfluxDB

    Power Real-Time Data Analytics at Scale. Get real-time insights from all types of time series data with InfluxDB. Ingest, query, and analyze billions of data points in real-time with unbounded cardinality.

    InfluxDB logo
NOTE: The number of mentions on this list indicates mentions on common posts plus user suggested alternatives. Hence, a higher number means a more popular project.

Suggest a related project

Related posts