---
title: "Create a cloud server, Managed Kubernetes cluster, and Managed Databases cluster in a private subnet using Terraform"
sidebar_label: "Create a server, Managed Kubernetes cluster, and Managed Databases cluster in a private subnet"
sidebar_position: 5
description: "How to create a cloud server, Managed Kubernetes cluster, and Managed Databases cluster in a private subnet"
---

import Formbricks from '@theme/MDXComponents/Formbricks'
import ConfigureProviders from '@site/i18n/en/docusaurus-plugin-content-docs-terraform/current/_partials/common/configure-providers.mdx'
import ConfigureProvidersConfig from '@site/i18n/en/docusaurus-plugin-content-docs-terraform/current/_partials/common/configure-providers-config.mdx'
import CreateNetworks from '@site/i18n/en/docusaurus-plugin-content-docs-terraform/current/_partials/cloud-networks/create-networks.mdx'
import CreateRouter from '@site/i18n/en/docusaurus-plugin-content-docs-terraform/current/_partials/cloud-networks/create-router.mdx'
import AddPublicSsh from '@site/i18n/en/docusaurus-plugin-content-docs-terraform/current/_partials/cloud-servers/add-public-ssh-key.mdx'
import CreatePort from '@site/i18n/en/docusaurus-plugin-content-docs-terraform/current/_partials/cloud-servers/create-port.mdx'
import GetImage from '@site/i18n/en/docusaurus-plugin-content-docs-terraform/current/_partials/cloud-servers/get-image.mdx'
import CreateBootVolume from '@site/i18n/en/docusaurus-plugin-content-docs-terraform/current/_partials/cloud-servers/create-boot-volume.mdx'
import CreatePublicFloatingIp from '@site/i18n/en/docusaurus-plugin-content-docs-terraform/current/_partials/cloud-networks/create-public-floating-ip.mdx'
import AssociateIp from '@site/i18n/en/docusaurus-plugin-content-docs-terraform/current/_partials/cloud-networks/associate-ip.mdx'
import CreateFixedServerBootNetwork from '@site/i18n/en/docusaurus-plugin-content-docs-terraform/current/_partials/cloud-servers/create-fixed-server-with-boot-network-volume.mdx'
import CreateResourcesAlert from '@site/i18n/en/docusaurus-plugin-content-docs-terraform/current/_partials/common/create-resources-alert.mdx'
import CreateDatabaseMySQL from '@site/i18n/en/docusaurus-plugin-content-docs-terraform/current/_partials/managed-databases/create-database-mysql.mdx'
import CreateUserMySQL from '@site/i18n/en/docusaurus-plugin-content-docs-terraform/current/_partials/managed-databases/create-user-mysql.mdx'
import GrantAccessMySQL from '@site/i18n/en/docusaurus-plugin-content-docs-terraform/current/_partials/managed-databases/grant-access-mysql.mdx'
import Tabs from '@theme/Tabs'
import TabItem from '@theme/TabItem'
import {TabItemLabel} from '@selectel/docux/components'

# Create a cloud server, Managed Kubernetes cluster, and Managed Database cluster in a private subnet using Terraform

This is an example of creating infrastructure that consists of:

* from a private subnet `192.168.199.0/24`;
* a cloud server of custom configuration with a bootable network volume and an additional network volume;
* a fault-tolerant Managed Kubernetes cluster with nodes of custom configuration;
* a MySQL semi-sync cluster of custom configuration.

<CreateResourcesAlert />

<br />

1. Optional: [configure the providers](#configure-providers).

2. [Add a public SSH key](#add-public-ssh-key).

3. [Create a private network and subnet](#create-networks).

4. [Create a cloud router connected to the internet](#create-router).

5. [Create a cloud server](#create-cloud-server).

6. [Create a Managed Kubernetes cluster](#create-mk-cluster).

7. [Create a Managed Database cluster](#create-db-cluster).

## Configuration files \{#config}

<details>
  <summary>Example file for configuring providers</summary>

  <ConfigureProvidersConfig />
</details>

<details>
  <summary>Example file for creating a cloud server of custom configuration with a bootable network volume and an additional network volume</summary>

  ```hcl
  resource "selectel_vpc_keypair_v2" "keypair_1" {
    name       = "keypair"
    public_key = file("~/.ssh/id_rsa.pub")
    user_id    = selectel_iam_serviceuser_v1.serviceuser_1.id
  }

  resource "openstack_compute_flavor_v2" "flavor_1" {
    name      = "custom-flavor-with-network-volume"
    vcpus     = 2
    ram       = 2048
    disk      = 0
    is_public = false

    lifecycle {
      create_before_destroy = true
    }

  }

  resource "openstack_networking_network_v2" "network_1" {
    name           = "private-network"
    admin_state_up = "true"
  }

  resource "openstack_networking_subnet_v2" "subnet_1" {
    network_id = openstack_networking_network_v2.network_1.id
    cidr       = "192.168.199.0/24"
  }

  data "openstack_networking_network_v2" "external_network_1" {
    external = true
  }

  resource "openstack_networking_router_v2" "router_1" {
    name                = "router"
    external_network_id = data.openstack_networking_network_v2.external_network_1.id
  }

  resource "openstack_networking_router_interface_v2" "router_interface_1" {
    router_id = openstack_networking_router_v2.router_1.id
    subnet_id = openstack_networking_subnet_v2.subnet_1.id
  }

  resource "openstack_networking_port_v2" "port_1" {
    name       = "port"
    network_id = openstack_networking_network_v2.network_1.id

    fixed_ip {
      subnet_id = openstack_networking_subnet_v2.subnet_1.id
    }
  }

  data "openstack_images_image_v2" "image_1" {
    name        = "Ubuntu 20.04 LTS 64-bit"
    most_recent = true
    visibility  = "public"
  }

  resource "openstack_blockstorage_volume_v3" "volume_1" {
    name                 = "boot-volume-for-server"
    size                 = "5"
    image_id             = data.openstack_images_image_v2.image_1.id
    volume_type          = "fast.ru-9a"
    availability_zone    = "ru-9a"
    enable_online_resize = true

    lifecycle {
      ignore_changes = [image_id]
    }

  }

  resource "openstack_blockstorage_volume_v3" "volume_2" {
    name                 = "additional-volume-for-server"
    size                 = "7"
    volume_type          = "universal.ru-9a"
    availability_zone    = "ru-9a"
    enable_online_resize = true
  }

  resource "openstack_compute_instance_v2" "server_1" {
    name              = "server"
    flavor_id         = openstack_compute_flavor_v2.flavor_1.id
    key_pair          = selectel_vpc_keypair_v2.keypair_1.name
    availability_zone = "ru-9a"

    network {
      port = openstack_networking_port_v2.port_1.id
    }

    lifecycle {
      ignore_changes = [image_id]
    }

    block_device {
      uuid             = openstack_blockstorage_volume_v3.volume_1.id
      source_type      = "volume"
      destination_type = "volume"
      boot_index       = 0
    }

    block_device {
      uuid             = openstack_blockstorage_volume_v3.volume_2.id
      source_type      = "volume"
      destination_type = "volume"
      boot_index       = -1
    }

    vendor_options {
      ignore_resize_confirmation = true
    }
  }

  resource "openstack_networking_floatingip_v2" "floatingip_1" {
    pool = "external-network"
  }

  resource "openstack_networking_floatingip_associate_v2" "association_1" {
    port_id     = openstack_networking_port_v2.port_1.id
    floating_ip = openstack_networking_floatingip_v2.floatingip_1.address
  }

  output "public_ip_address" {
    value = openstack_networking_floatingip_v2.floatingip_1.fixed_ip
  }
  ```
</details>

<details>
  <summary>Example file for creating a fault-tolerant Managed Kubernetes cluster with nodes of custom configuration</summary>

  ```hcl
  resource "openstack_networking_network_v2" "network_1" {
    name           = "private-network"
    admin_state_up = "true"
  }

  resource "openstack_networking_subnet_v2" "subnet_1" {
    name       = "private-subnet"
    network_id = openstack_networking_network_v2.network_1.id
    cidr       = "192.168.199.0/24"
  }

  data "openstack_networking_network_v2" "external_network_1" {
    external = true
  }

  resource "openstack_networking_router_v2" "router_1" {
    name                = "router"
    external_network_id = data.openstack_networking_network_v2.external_network_1.id
  }

  resource "openstack_networking_router_interface_v2" "router_interface_1" {
    router_id = openstack_networking_router_v2.router_1.id
    subnet_id = openstack_networking_subnet_v2.subnet_1.id
  }

  data "selectel_mks_kube_versions_v1" "versions" {
    project_id = selectel_vpc_project_v2.project_1.id
    region     = "ru-9"
  }

  resource "selectel_mks_cluster_v1" "cluster_1" {
    name                     = "high_availability_cluster"
    project_id               = selectel_vpc_project_v2.project_1.id
    region                   = "ru-9"
    kube_version             = data.selectel_mks_kube_versions_v1.versions.latest_version
    network_id               = openstack_networking_network_v2.network_1.id
    subnet_id                = openstack_networking_subnet_v2.subnet_1.id
    maintenance_window_start = "00:00:00"
  }

  resource "selectel_mks_nodegroup_v1" "nodegroup_1" {
    cluster_id                   = selectel_mks_cluster_v1.cluster_1.id
    project_id                   = selectel_mks_cluster_v1.cluster_1.project_id
    region                       = selectel_mks_cluster_v1.cluster_1.region
    availability_zone            = "ru-9a"
    nodes_count                  = "2"
    cpus                         = 2
    ram_mb                       = 4096
    volume_gb                    = 32
    volume_type                  = "fast.ru-9a"
    install_nvidia_device_plugin = false
    labels                       = {
      "label-key0": "label-value0",
      "label-key1": "label-value1",
      "label-key2": "label-value2",
    }
  }
  ```
</details>

<details>
  <summary>Example file for creating a MySQL semi-sync cluster of custom configuration</summary>

  ```hcl
  resource "openstack_networking_network_v2" "network_1" {
    name           = "private-network"
    admin_state_up = "true"
  }

  resource "openstack_networking_subnet_v2" "subnet_1" {
    network_id = openstack_networking_network_v2.network_1.id
    cidr       = "192.168.199.0/24"
  }

  data "selectel_dbaas_datastore_type_v1" "datastore_type_1" {
    project_id = selectel_vpc_project_v2.project_1.id
    region     = "ru-9"
    filter {
      engine  = "mysql_native"
      version = "8"
    }
  }

  resource "selectel_dbaas_mysql_datastore_v1" "datastore_1" {
    name       = "datastore-1"
    project_id = selectel_vpc_project_v2.project_1.id
    region     = "ru-9"
    type_id    = data.selectel_dbaas_datastore_type_v1.datastore_type_1.datastore_types[0].id
    subnet_id  = openstack_networking_subnet_v2.subnet_1.id
    node_count = 3
    flavor {
      vcpus = 1
      ram   = 4096
      disk  = 32
    }
  }

  resource "selectel_dbaas_user_v1" "user_1" {
    project_id   = selectel_vpc_project_v2.project_1.id
    region       = "ru-9"
    datastore_id = selectel_dbaas_mysql_datastore_v1.datastore_1.id
    name         = "user"
    password     = "secret"
  }

  resource "selectel_dbaas_mysql_database_v1" "database_1" {
    project_id   = selectel_vpc_project_v2.project_1.id
    region       = "ru-9"
    datastore_id = selectel_dbaas_mysql_datastore_v1.datastore_1.id
    name         = "database_1"
  }

  resource "selectel_dbaas_grant_v1" "grant_1" {
    project_id   = selectel_vpc_project_v2.project_1.id
    region       = "ru-9"
    datastore_id = selectel_dbaas_mysql_datastore_v1.datastore_1.id
    database_id  = selectel_dbaas_mysql_database_v1.database_1.id
    user_id      = selectel_dbaas_user_v1.user_1.id
  }

  ```
</details>

## 1. Optional: configure providers \{#configure-providers}

If you have [configured the Selectel and OpenStack providers](/terraform/configure-terraform-environment/#configure-providers), skip this step.

<ConfigureProviders />

## 2. Add a public SSH key \{#add-public-ssh-key}

<AddPublicSsh />

## 3. Create a private network and subnet \{#create-networks}

<CreateNetworks />

## 4. Create a cloud router connected to the internet \{#create-router}

<CreateRouter />

## 5. Create a cloud server \{#create-cloud-server}

1. [Create a port for the cloud server](#create-port).

2. [Get an image](#get-image).

3. [Create a boot volume](#create-boot-volume).

4. [Create a server](#create-server).

5. [Create a public floating IP address](#create-public-floating-ip).

6. [Assign an association between the public and private IP address of the cloud server](#associate-ip).

### 1. Create a port for the cloud server \{#create-port}

<CreatePort />

### 2. Get an image \{#get-image}

<GetImage />

### 3. Create a bootable network volume \{#create-boot-volume}

<CreateBootVolume />

### 4. Create a cloud server \{#create-server}

<CreateFixedServerBootNetwork />

### 5. Create a public floating IP address \{#create-public-floating-ip}

<CreatePublicFloatingIp />

### 6. Assign an association between the public and private IP address of the cloud server \{#associate-ip}

<AssociateIp />

## 6. Create a Managed Kubernetes cluster \{#create-mk-cluster}

1. [Create a fault-tolerant cluster](#create-high-availability-cluster).

2. [Create a node group of custom configuration with a network volume](#create-node-group).

### 1. Create a fault-tolerant cluster \{#create-high-availability-cluster}

```hcl
data "selectel_mks_kube_versions_v1" "versions" {
  project_id = selectel_vpc_project_v2.project_1.id
  region     = "ru-9"
}

resource "selectel_mks_cluster_v1" "cluster_1" {
  name                     = "high_availability_cluster"
  project_id               = selectel_vpc_project_v2.project_1.id
  region                   = "ru-9"
  kube_version             = data.selectel_mks_kube_versions_v1.versions.latest_version
  network_id               = openstack_networking_network_v2.network_1.id
  subnet_id                = openstack_networking_subnet_v2.subnet_1.id
  maintenance_window_start = "00:00:00"
}
```

Where `region` is a [pool](/infrastructure/locations/#pool) in which the cluster will be created, for example `ru-9`.

See the detailed description of the [selectel\_mks\_cluster\_v1](/terraform/selectel-provider-reference/resources/mks_cluster_v1/) resource.

### 2. Create a node group of custom configuration with a network volume \{#create-node-group}

```hcl
  resource "selectel_mks_nodegroup_v1" "nodegroup_1" {
    cluster_id                   = selectel_mks_cluster_v1.cluster_1.id
    project_id                   = selectel_mks_cluster_v1.cluster_1.project_id
    region                       = selectel_mks_cluster_v1.cluster_1.region
    availability_zone            = "ru-9a"
    nodes_count                  = "2"
    cpus                         = 2
    ram_mb                       = 4096
    volume_gb                    = 32
    volume_type                  = "fast.ru-9a"
    install_nvidia_device_plugin = false
    labels                       = {
      "label-key0": "label-value0",
      "label-key1": "label-value1",
      "label-key2": "label-value2",
    }
  }
```

Where:

* `availability_zone` is a [pool segment](/infrastructure/locations/#pool) where the node group will be located, for example `ru-9a`;

* `nodes_count` — the number of worker nodes in the node group. The maximum number of nodes is 15;

* `cpus` — the number of vCPUs for each node;

* `ram_mb` — the amount of RAM for each node in MB;

* `volume_gb` — the disk size in GB;

* `volume_type` — the disk type in the `<type>.<pool_segment>` format, for example `basic.ru-9a`:

  * `<type>` — `basic`, `universal` or `fast`;
  * `<pool_segment>` — a [pool segment](/infrastructure/locations/#pool) in which the network volume will be created, for example `ru-9a`;

* `install_nvidia_device_plugin` — confirms or cancels the installation of GPU drivers and NVIDIA® Device Plugin:

  * `true` — for GPU flavors, it confirms the installation of GPU drivers and NVIDIA® Device Plugin;
  * `false` — for flavors with and without GPU, disables the installation of GPU drivers and NVIDIA® Device Plugin. You can [manually install drivers for GPU node groups](/managed-kubernetes/node-groups/gpu-drivers/#install-gpu-drivers).

See the detailed description of the [selectel\_mks\_nodegroup\_v1](/terraform/selectel-provider-reference/resources/mks_nodegroup_v1/) resource.

## 7. Create a Managed Database cluster \{#create-db-cluster}

1. [Create a MySQL semi-sync cluster](#create-my-sql-cluster).

2. [Create a user](#create-user).

3. [Create a database](#create-database).

4. [Grant the user access to the database](#grant-access).

### 1. Create a MySQL semi-sync cluster of custom configuration \{#create-my-sql-cluster}

```hcl
  data "selectel_dbaas_datastore_type_v1" "datastore_type_1" {
    project_id = selectel_vpc_project_v2.project_1.id
    region     = "ru-9"
    filter {
      engine  = "mysql_native"
      version = "8"
    }
  }

  resource "selectel_dbaas_mysql_datastore_v1" "datastore_1" {
    name       = "datastore-1"
    project_id = selectel_vpc_project_v2.project_1.id
    region     = "ru-9"
    type_id    = data.selectel_dbaas_datastore_type_v1.datastore_type_1.datastore_types[0].id
    subnet_id  = openstack_networking_subnet_v2.subnet_1.id
    node_count = 3
    flavor {
      vcpus = 1
      ram   = 4096
      disk  = 32
    }
  }
```

Where:

* `region` — pool, for example `ru-9`. You can check the list of available pools in the [Product availability by location](/infrastructure/product-availability-by-location/#managed-databases);
* `filter` — a filter for Managed Database types:
  * `engine` — a Managed Database type. For a MySQL semi-sync cluster, specify `mysql_native`;
  * `version` — a Managed Database version. The list of available versions can be found in the [Versions and configurations](/managed-databases/mysql-semi-sync/configurations/) instructions;
* `nodes_count` — the number of nodes. The maximum number of nodes is 6;
* `flavor` — a custom cluster configuration. The available values of custom configurations can be found in the [Versions and configurations](/managed-databases/mysql-semi-sync/configurations/) instructions:
  * `vcpus` — the number of vCPUs;
  * `ram` — the amount of RAM in MB;
  * `disk` — the disk size in GB.

See the detailed description of data sources and resources:

* [selectel\_dbaas\_datastore\_type\_v1](/terraform/selectel-provider-reference/data-sources/dbaas_datastore_type_v1/);
* [selectel\_dbaas\_flavor\_v1](/terraform/selectel-provider-reference/data-sources/dbaas_flavor_v1/);
* [selectel\_dbaas\_mysql\_datastore\_v1](/terraform/selectel-provider-reference/resources/dbaas_mysql_datastore_v1/).

### 2. Create a user \{#create-user}

<CreateUserMySQL />

### 3. Create a database \{#create-database}

<CreateDatabaseMySQL />

### 4. Grant the user access to the database \{#grant-access}

<GrantAccessMySQL />

<Formbricks />
