Skip to content

Repository files navigation

Virtuozzo IaaS Demo Terraform Project

This Terraform project demonstrates deploying infrastructure on Virtuozzo Hybrid Infrastructure (OpenStack-compatible) including:

  • Kubernetes Cluster: Managed HA Kubernetes cluster (3 masters, 3 workers)
  • PostgreSQL Cluster: 3 VMs for PostgreSQL cluster (infrastructure only)
  • Jumphost: Bastion host with public IP for secure access
  • Private Network: Internal network for secure inter-VM communication

Architecture

Internet
    |
    | (Floating IP)
    v
Jumphost (Ubuntu 24.04)
    |
    | SSH Tunnel / Private Network
    v
Private Network (172.16.10.0/24)
    |
    +-- PostgreSQL-1 (172.16.10.x)
    +-- PostgreSQL-2 (172.16.10.x)
    +-- PostgreSQL-3 (172.16.10.x)
    +-- Kubernetes Cluster (HA)
        +-- 3 Master Nodes
        +-- 3 Worker Nodes

Remote State & CI/CD

This project uses GitLab CI/CD with GitLab-managed Terraform state for automation and remote state storage.

GitLab Managed State Backend

State files are stored in GitLab's infrastructure using HTTP backend:

  • Secure state storage with encryption at rest and in transit
  • Automatic state locking via HTTP POST/DELETE
  • State versioning and history
  • Built-in integration with GitLab CI/CD
  • No external dependencies or S3 compatibility issues
  • Free unlimited state storage

GitLab CI/CD Pipeline

Automated pipeline with three stages:

  1. Validate Stage (on MR and main branch)

    • terraform fmt -check: Check formatting
    • terraform validate: Validate configuration
  2. Plan Stage (on MR and main branch)

    • terraform plan: Generate execution plan
    • Saves plan artifact for apply stage
    • Plan output visible in pipeline logs
  3. Apply Stage (on main branch only)

    • terraform apply: Execute changes
    • Requires manual approval in GitLab UI
    • Uses saved plan from plan stage

Setup Instructions

  1. Push Repository to GitLab

    • Create new project on GitLab
    • Add GitLab as remote: git remote add gitlab <gitlab-url>
    • Push code: git push gitlab main
  2. Configure CI/CD Variables

    • In GitLab project, go to Settings > CI/CD > Variables
    • Add OpenStack credentials (mark as Protected and Masked):
      • TF_VAR_auth_url
      • TF_VAR_user_name
      • TF_VAR_password
      • TF_VAR_domain_name
      • TF_VAR_tenant_name
      • TF_VAR_region
    • Add SSH public key:
      • TF_VAR_public_key (content of ~/.ssh/id_rsa.pub)
    • Add GitLab token:
      • GITLAB_ACCESS_TOKEN (Personal Access Token with api scope)
    • See Configure Terraform Variables and GITLAB_SETUP.md for details
  3. Enable Terraform State in GitLab

    • GitLab automatically manages Terraform state
    • No additional configuration required
    • State visible at: Infrastructure > Terraform states
  4. Local Development Setup

    • Get your GitLab project ID (visible in project overview)
    • Create GitLab Personal Access Token (Scopes: api, read_api)
    • Initialize with backend config (see CLAUDE.md)

Prerequisites

  1. Virtuozzo Cloud Management Platform Access

    • Account with appropriate permissions
    • OpenStack API credentials
  2. Tools

    • Terraform >= 1.0.0
    • OpenStack CLI (optional, for verification)
    • SSH key pair
    • Git
  3. GitLab Account (for CI/CD and remote state)

    • Free tier includes unlimited state storage
    • 400 CI/CD minutes per month
    • See Remote State & CI/CD above
  4. Knowledge Required

    • Basic Terraform understanding
    • SSH and networking concepts
    • Kubernetes basics (for cluster usage)
    • Git and GitLab CI/CD basics

Quick Start

1. Generate OpenStack Credentials

  1. Log in to Virtuozzo Cloud Management Platform
  2. Navigate to My Account > OpenStack Credentials tab
  3. Click Generate Application Credentials
  4. Save the following values:
    • Auth URL (Keystone endpoint)
    • Application Credential ID
    • Application Credential Secret

2. Query Available Resources

Before deploying, check what resources are available in your Virtuozzo environment:

# Set environment variables (optional, for OpenStack CLI)
export OS_AUTH_URL="https://your-endpoint:5000/v3"
export OS_APPLICATION_CREDENTIAL_ID="your-id"
export OS_APPLICATION_CREDENTIAL_SECRET="your-secret"

# Check available flavors (VM sizes)
openstack flavor list

# Check available images
openstack image list

# Check Kubernetes cluster templates
openstack coe cluster template list

# Check external network name
openstack network list --external

3. Configure Terraform Variables

Copy the example configuration and update with your values:

cp terraform.tfvars.example terraform.tfvars

Edit terraform.tfvars with your actual values:

# Required: OpenStack credentials
auth_url                      = "https://your-virtuozzo-endpoint:5000/v3"
application_credential_id     = "your-application-credential-id"
application_credential_secret = "your-application-credential-secret"

# Update these based on your environment
k8s_template_name = "kubernetes-v1.28.2"  # From: openstack coe cluster template list
external_network_name = "public"          # From: openstack network list --external
image_name = "Ubuntu 24.04"               # From: openstack image list

4. Deploy Infrastructure

# Initialize Terraform
terraform init

# Review the execution plan
terraform plan

# Apply the configuration
terraform apply

# Confirm with 'yes' when prompted

The deployment will take approximately 15-30 minutes, primarily for the Kubernetes cluster creation.

5. Access Your Infrastructure

After successful deployment, Terraform will output connection information:

# View outputs
terraform output

# Get jumphost public IP
terraform output jumphost_public_ip

# Get summary
terraform output deployment_summary

Usage Examples

SSH to Jumphost

# Get the public IP
JUMPHOST_IP=$(terraform output -raw jumphost_public_ip)

# SSH to jumphost
ssh ubuntu@$JUMPHOST_IP

Access PostgreSQL VMs

# From your local machine (via jumphost)
JUMPHOST_IP=$(terraform output -raw jumphost_public_ip)
POSTGRES_IP="172.16.10.10"  # Replace with actual IP from outputs

ssh -J ubuntu@$JUMPHOST_IP ubuntu@$POSTGRES_IP

# Or use ProxyJump in one command
ssh -o ProxyJump=ubuntu@$JUMPHOST_IP ubuntu@$POSTGRES_IP

Access Kubernetes Cluster

# Download kubeconfig (requires OpenStack CLI)
openstack coe cluster config demo-k8s-cluster

# Set KUBECONFIG environment variable
export KUBECONFIG=./config

# Verify cluster access
kubectl get nodes

# Check cluster info
kubectl cluster-info

Setup SSH Config for Easy Access

Add to ~/.ssh/config:

Host virtuozzo-jumphost
    HostName <jumphost-public-ip>
    User ubuntu
    IdentityFile ~/.ssh/id_rsa

Host postgres-*
    User ubuntu
    ProxyJump virtuozzo-jumphost
    IdentityFile ~/.ssh/id_rsa

Host postgres-1
    HostName 172.16.10.10

Host postgres-2
    HostName 172.16.10.11

Host postgres-3
    HostName 172.16.10.12

Then simply use:

ssh virtuozzo-jumphost
ssh postgres-1

Infrastructure Details

Network Configuration

  • Private Network: 172.16.10.0/24
  • DNS Nameservers: 8.8.8.8, 8.8.4.4
  • Router: Connected to external network for internet access
  • Security Groups:
    • Jumphost: SSH (22) from anywhere (configurable)
    • PostgreSQL: SSH (22) from private network, PostgreSQL (5432) within cluster

Compute Resources

Resource Flavor Count Purpose
Jumphost m1.small 1 Bastion host with public access
PostgreSQL m1.medium 3 PostgreSQL cluster nodes
K8s Masters m1.medium 3 Kubernetes control plane (HA)
K8s Workers m1.medium 3 Kubernetes worker nodes

Security Groups

Jumphost Security Group:

  • Inbound: SSH (22/tcp) from allowed CIDR
  • Inbound: ICMP (ping)
  • Outbound: All traffic

PostgreSQL Security Group:

  • Inbound: SSH (22/tcp) from private network
  • Inbound: PostgreSQL (5432/tcp) from same security group
  • Inbound: ICMP (ping)
  • Outbound: All traffic

Customization

Adjust VM Count

Edit terraform.tfvars:

# PostgreSQL cluster (must be odd number >= 3)
postgres_count = 5

# Kubernetes cluster
k8s_master_count = 3  # Odd number for HA
k8s_node_count = 5    # Any number >= 1

Change VM Sizes

jumphost_flavor = "m1.small"
postgres_flavor = "m1.large"
k8s_master_flavor = "m1.large"
k8s_worker_flavor = "m1.medium"

Restrict SSH Access

For better security, limit SSH access to your IP:

allowed_ssh_cidr = "203.0.113.100/32"  # Your public IP

Use Different Network Range

private_subnet_cidr = "10.0.1.0/24"

Advanced Configuration

Using Environment Variables

Instead of terraform.tfvars, you can use environment variables:

export TF_VAR_auth_url="https://your-endpoint:5000/v3"
export TF_VAR_application_credential_id="your-id"
export TF_VAR_application_credential_secret="your-secret"

Remote State Storage

For team collaboration, configure remote state:

# backend.tf
terraform {
  backend "s3" {
    bucket = "my-terraform-state"
    key    = "virtuozzo/demo/terraform.tfstate"
    region = "us-east-1"
  }
}

Add Volumes to PostgreSQL VMs

Add to main.tf:

resource "openstack_blockstorage_volume_v3" "postgres_data" {
  count = var.postgres_count
  name  = "${var.project_name}-postgres-${count.index + 1}-data"
  size  = 100  # GB
}

resource "openstack_compute_volume_attach_v2" "postgres_data" {
  count       = var.postgres_count
  instance_id = openstack_compute_instance_v2.postgres[count.index].id
  volume_id   = openstack_blockstorage_volume_v3.postgres_data[count.index].id
}

Troubleshooting

Cluster Creation Takes Long Time

Kubernetes cluster creation can take 15-30 minutes. Monitor progress:

# Watch Terraform output
terraform apply

# Or check via OpenStack CLI
openstack coe cluster list
openstack coe cluster show demo-k8s-cluster

SSH Connection Issues

# Verify jumphost is running
terraform output jumphost_public_ip

# Test connectivity
ping $(terraform output -raw jumphost_public_ip)

# Check security group rules
openstack security group list
openstack security group rule list <jumphost-sg-id>

# Verify SSH key
ssh-add -l

Image or Flavor Not Found

# List available images
openstack image list | grep -i ubuntu

# List available flavors
openstack flavor list

# Update terraform.tfvars with correct names

Kubernetes Template Not Found

# List available templates
openstack coe cluster template list

# Update k8s_template_name in terraform.tfvars

Outputs

After deployment, you can view various outputs:

# All outputs
terraform output

# Specific outputs
terraform output jumphost_public_ip
terraform output postgres_private_ips
terraform output k8s_api_address
terraform output deployment_summary

# JSON format
terraform output -json

Cleanup

To destroy all created resources:

# Preview what will be destroyed
terraform plan -destroy

# Destroy infrastructure
terraform destroy

# Confirm with 'yes' when prompted

Warning: This will permanently delete:

  • All VMs (jumphost, PostgreSQL nodes)
  • Kubernetes cluster
  • Networks and routers
  • Security groups
  • Floating IPs

Project Structure

.
├── main.tf                      # Root module - orchestrates all modules
├── providers.tf                 # OpenStack provider configuration
├── variables.tf                 # Root module variable definitions
├── outputs.tf                   # Root module outputs
├── versions.tf                  # Terraform version constraints
├── terraform.tfvars.example     # Example configuration
├── .gitignore                   # Git ignore rules
├── README.md                    # This file
│
└── modules/                     # Reusable Terraform modules
    ├── network/                 # Network infrastructure module
    │   ├── main.tf             # Networks, subnets, routers, security groups
    │   ├── variables.tf        # Network module variables
    │   └── outputs.tf          # Network module outputs
    │
    ├── compute/                 # Compute resources module
    │   ├── main.tf             # VMs, keypairs, floating IPs
    │   ├── variables.tf        # Compute module variables
    │   └── outputs.tf          # Compute module outputs
    │
    └── kubernetes/              # Kubernetes cluster module
        ├── main.tf             # K8s cluster via Magnum
        ├── variables.tf        # Kubernetes module variables
        └── outputs.tf          # Kubernetes module outputs

Module Organization

The project is organized into three main modules:

  1. Network Module (modules/network/)

    • Creates private network and subnet
    • Configures router with external gateway
    • Sets up security groups for jumphost and PostgreSQL
    • Manages network isolation and connectivity
  2. Compute Module (modules/compute/)

    • Creates and manages SSH keypairs
    • Deploys jumphost VM with floating IP
    • Deploys PostgreSQL cluster VMs
    • Handles instance configuration and metadata
  3. Kubernetes Module (modules/kubernetes/)

    • Creates managed Kubernetes cluster via Magnum
    • Configures HA setup with multiple masters and workers
    • Manages cluster lifecycle and configuration

Benefits of Modular Architecture

  • Reusability: Modules can be reused across different environments or projects
  • Maintainability: Each module has a clear, focused responsibility
  • Testability: Modules can be tested independently
  • Scalability: Easy to add, remove, or modify specific components
  • Separation of Concerns: Network, compute, and Kubernetes logic are isolated
  • Team Collaboration: Different teams can work on different modules

Using Modules in Other Projects

You can use these modules in other Terraform projects:

# Example: Use just the network module in another project
module "my_network" {
  source = "git::https://your-repo.com/terraform-virtuozzo.git//modules/network"

  project_name          = "my-project"
  environment           = "production"
  external_network_name = "public"
  private_subnet_cidr   = "10.0.1.0/24"
  dns_nameservers       = ["8.8.8.8"]
  allowed_ssh_cidr      = "203.0.113.0/24"
}

Next Steps

After deploying the infrastructure:

  1. Setup PostgreSQL Cluster:

    • Install PostgreSQL on the 3 VMs
    • Configure streaming replication
    • Setup connection pooling (pgBouncer)
    • Configure failover (Patroni/etcd)
  2. Kubernetes Workloads:

    • Deploy applications to K8s cluster
    • Setup ingress controller
    • Configure persistent volumes
    • Deploy monitoring (Prometheus/Grafana)
  3. Security Hardening:

    • Rotate SSH keys regularly
    • Enable firewall on VMs
    • Setup VPN for jumphost access
    • Configure audit logging
  4. Monitoring & Backup:

    • Setup monitoring (Zabbix, Prometheus)
    • Configure automated backups
    • Setup alerting
    • Document disaster recovery procedures

Resources

License

This demo project is provided as-is for educational and demonstration purposes.

Support

For issues related to:

  • Virtuozzo Platform: Contact Virtuozzo support
  • This Terraform Code: Open an issue in the repository
  • OpenStack Provider: Check provider documentation

About

Example terraform project for virtuozzo

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages