Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,18 @@
test
test
# Terraform
terraform/.terraform/
terraform/.terraform.lock.hcl
terraform/terraform.tfstate
terraform/terraform.tfstate.backup
terraform/*.tfvars

# Yandex Cloud SA key
.yc/

venv/
*/venv/
__pycache__/
.terraform/
.pulumi/
*.tfstate
*.tfstate.backup
2 changes: 2 additions & 0 deletions pulumi/lab04-yc/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.pyc
venv/
7 changes: 7 additions & 0 deletions pulumi/lab04-yc/Pulumi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
name: lab04-yc
description: A minimal Python Pulumi program
runtime: python
config:
pulumi:tags:
value:
pulumi:template: python
128 changes: 128 additions & 0 deletions pulumi/lab04-yc/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import os
import pathlib

import pulumi
import pulumi_yandex as yandex



ZONE = "ru-central1-a"


FOLDER_ID = "b1g1cmmbss046n25oln3"

SSH_PUBLIC_KEY_PATH = os.path.expanduser("~/.ssh/id_ed25519.pub")

SSH_USERNAME = "ubuntu"



def read_ssh_public_key(path: str) -> str:
p = pathlib.Path(path)
if not p.exists():
raise FileNotFoundError(f"SSH public key not found: {p}")
return p.read_text().strip()


ssh_pub = read_ssh_public_key(SSH_PUBLIC_KEY_PATH)



net = yandex.VpcNetwork(
"lab-network",
folder_id=FOLDER_ID,
)

subnet = yandex.VpcSubnet(
"lab-subnet",
folder_id=FOLDER_ID,
network_id=net.id,
zone=ZONE,
v4_cidr_blocks=["10.0.0.0/24"],
)



sg = yandex.VpcSecurityGroup(
"lab-sg",
folder_id=FOLDER_ID,
network_id=net.id,
description="Security group for lab04 VM (SSH, HTTP, app port)",
egresses=[
yandex.VpcSecurityGroupEgressArgs(
protocol="ANY",
description="Allow all outbound",
v4_cidr_blocks=["0.0.0.0/0"],
from_port=0,
to_port=65535,
)
],
ingresses=[
yandex.VpcSecurityGroupIngressArgs(
protocol="TCP",
description="SSH",
v4_cidr_blocks=["0.0.0.0/0"],
port=22,
),
yandex.VpcSecurityGroupIngressArgs(
protocol="TCP",
description="HTTP",
v4_cidr_blocks=["0.0.0.0/0"],
port=80,
),
yandex.VpcSecurityGroupIngressArgs(
protocol="TCP",
description="App port 5000",
v4_cidr_blocks=["0.0.0.0/0"],
port=5000,
),
],
)



image = yandex.get_compute_image(
family="ubuntu-2004-lts",
folder_id="standard-images",
)



vm = yandex.ComputeInstance(
"lab-vm",
folder_id=FOLDER_ID,
zone=ZONE,
platform_id="standard-v2",
resources=yandex.ComputeInstanceResourcesArgs(
cores=2,
memory=1,
core_fraction=20,
),
boot_disk=yandex.ComputeInstanceBootDiskArgs(
initialize_params=yandex.ComputeInstanceBootDiskInitializeParamsArgs(
image_id=image.id,
size=10,
type="network-hdd",
)
),
network_interfaces=[
yandex.ComputeInstanceNetworkInterfaceArgs(
subnet_id=subnet.id,
nat=True,
security_group_ids=[sg.id],
)
],
metadata={
"ssh-keys": f"{SSH_USERNAME}:{ssh_pub}",
},
labels={
"lab": "lab04",
"tool": "pulumi",
},
)


pulumi.export("external_ip", vm.network_interfaces[0].nat_ip_address)
pulumi.export("zone", vm.zone)
pulumi.export("subnet_id", subnet.id)
pulumi.export("security_group_id", sg.id)
1 change: 1 addition & 0 deletions pulumi/lab04-yc/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pulumi>=3.0.0,<4.0.0
212 changes: 212 additions & 0 deletions terraform/docs/LAB04.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
# LAB04 — Infrastructure as Code (Terraform & Pulumi)

## 1. Cloud Provider & Infrastructure

**Cloud Provider:** Yandex Cloud
**Folder ID:** b1g1cmmbss046n25oln3
**Region / Zone:** ru-central1-a
**Instance Type:** standard-v2 (2 vCPU with 20% core fraction, 1 GB RAM)
**Disk:** 10 GB HDD
**Operating System:** Ubuntu 24.04 LTS

The smallest available instance type compatible with Yandex Cloud free tier was selected to minimize cost.

### Security Configuration

The following ports are opened in the security group:

- TCP 22 — SSH (restricted access for remote management)
- TCP 80 — HTTP (future deployment)
- TCP 5000 — Application port (DevOps Info Service from previous labs)

### Created Resources

- VPC Network (`lab-network`)
- Subnet (`lab-subnet`)
- Security Group (`lab-sg`)
- Virtual Machine (`lab-vm`)
- Public IP Address

Estimated cost: **0 RUB** (free tier usage).
Terraform Version: 1.9.8
Pulumi Version: 3.222.0

---

## 2. Terraform Implementation

### Terraform Version
Terraform CLI 1.9.x (Ubuntu Linux)

### Project Structure

terraform/
├── main.tf
├── variables.tf
├── outputs.tf
└── docs/LAB04.md


### Authentication

Authentication was configured using a Yandex Cloud service account JSON key:
~/.yc/terraform-key.json


Provider configuration:

```hcl
provider "yandex" {
service_account_key_file = pathexpand("~/.yc/terraform-key.json")
folder_id = var.folder_id
zone = var.zone
}
```

### Workflow

```
terraform init
terraform fmt
terraform validate
terraform plan
terraform apply
```


Example output from terraform plan:
Plan: 3 to add, 0 to change, 0 to destroy.

Example output from terraform apply:
Apply complete! Resources: 3 added, 0 changed, 0 destroyed.

Outputs:

external_ip = "X.X.X.X"


SSH Verification
ssh ubuntu@<external_ip>


SSH connection was successful.

Cleanup

After verifying functionality, Terraform resources were destroyed:

terraform destroy


All resources created by Terraform were removed successfully to avoid duplication and unnecessary usage.

## 3. Pulumi Implementation
Pulumi Version

Pulumi CLI v3.222.0

Language

Python

Project Structure
pulumi/lab04-yc/
├── Pulumi.yaml
├── Pulumi.dev.yaml
├── requirements.txt
├── __main__.py
└── venv/

Authentication

Pulumi uses the same Yandex Cloud service account key:

export YC_SERVICE_ACCOUNT_KEY_FILE=/home/vboxuser/.yc/terraform-key.json

Resources Created

The same infrastructure was recreated using Pulumi:

VpcNetwork

VpcSubnet

VpcSecurityGroup

ComputeInstance

Public IP

Pulumi Commands
pulumi preview
pulumi up


Preview example:

+ yandex:index:VpcNetwork
+ yandex:index:VpcSubnet
+ yandex:index:VpcSecurityGroup
+ yandex:index:ComputeInstance


Apply output:

Outputs:
external_ip : "93.77.190.119"
zone : "ru-central1-a"

SSH Verification
ssh ubuntu@93.77.190.119


SSH access was successful.

## 4. Terraform vs Pulumi Comparison
Ease of Learning

Terraform was easier to start with due to extensive documentation and straightforward declarative syntax. Pulumi required more setup (virtual environments, Python dependencies).

Code Readability

Terraform configurations are compact and declarative, making them easy to read for simple infrastructure. Pulumi provides more flexibility but adds programming complexity.

Debugging

Terraform errors are generally clear during plan and apply. Pulumi provides Python stack traces, which can be more detailed but sometimes harder to interpret.

Documentation

Terraform has broader documentation and community examples. Pulumi documentation is solid but less extensive for Yandex Cloud specifically.

Use Case Preference

Terraform is preferable for straightforward infrastructure definitions.
Pulumi is more powerful when complex logic, loops, or programming constructs are required.

## 5. Lab 5 Preparation & Cleanup

For Lab 5 (Ansible), the VM created using Pulumi will be kept active.

Active VM:

IP Address: 93.77.190.119
Zone: ru-central1-a
User: ubuntu

Terraform resources were destroyed.
Pulumi-managed VM remains running for future configuration management tasks.

No secrets or state files were committed to Git.

Infrastructure can be recreated at any time using:

terraform apply


or

pulumi up

Terraform state was stored locally. The file terraform.tfstate was added to .gitignore and not committed to the repository.

Binary file added terraform/docs/screenshots/pulumi-up.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added terraform/docs/screenshots/terraform-apply.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added terraform/docs/screenshots/yc-vm-running.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading