Skip to content

Commit dc38cc0

Browse files
committed
lab04
1 parent 127ad16 commit dc38cc0

9 files changed

Lines changed: 270 additions & 0 deletions

File tree

pulumi/.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
*.pyc
2+
venv/
3+
__pycache__
4+
Pulumi.dev.yaml

pulumi/Pulumi.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
name: devops-vm
2+
description: VM for DevOps lab
3+
runtime:
4+
name: python
5+
options:
6+
toolchain: pip
7+
virtualenv: venv
8+
config:
9+
pulumi:tags:
10+
value:
11+
pulumi:template: python

pulumi/__main__.py

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import pulumi
2+
import pulumi_yandex as yandex
3+
4+
# Read configuration (set via pulumi config)
5+
config = pulumi.Config()
6+
cloud_id = config.require("cloud_id")
7+
folder_id = config.require("folder_id")
8+
zone = config.get("zone") or "ru-central1-a"
9+
public_key_path = config.get("public_key_path") or "~/.ssh/id_rsa.pub"
10+
11+
# Read SSH public key file
12+
with open(public_key_path, "r") as f:
13+
ssh_public_key = f.read().strip()
14+
15+
# Get Ubuntu image
16+
image = yandex.get_compute_image(family="ubuntu-2404-lts-oslogin")
17+
18+
# Create VPC network
19+
network = yandex.VpcNetwork("lab-network")
20+
21+
# Create subnet
22+
subnet = yandex.VpcSubnet("lab-subnet",
23+
zone=zone,
24+
network_id=network.id,
25+
v4_cidr_blocks=["192.168.10.0/24"])
26+
27+
# Create security group
28+
security_group = yandex.VpcSecurityGroup("lab-sg",
29+
network_id=network.id,
30+
description="Allow SSH, HTTP, and app port 5000",
31+
ingress=[
32+
yandex.VpcSecurityGroupIngressArgs(
33+
protocol="TCP",
34+
description="SSH",
35+
port=22,
36+
v4_cidr_blocks=["0.0.0.0/0"],
37+
),
38+
yandex.VpcSecurityGroupIngressArgs(
39+
protocol="TCP",
40+
description="HTTP",
41+
port=80,
42+
v4_cidr_blocks=["0.0.0.0/0"],
43+
),
44+
yandex.VpcSecurityGroupIngressArgs(
45+
protocol="TCP",
46+
description="App port 5000",
47+
port=5000,
48+
v4_cidr_blocks=["0.0.0.0/0"],
49+
),
50+
],
51+
egress=[yandex.VpcSecurityGroupEgressArgs(
52+
protocol="ANY",
53+
description="Allow all outbound",
54+
v4_cidr_blocks=["0.0.0.0/0"],
55+
)])
56+
57+
# Create VM instance
58+
vm = yandex.ComputeInstance("lab-vm",
59+
zone=zone,
60+
platform_id="standard-v2",
61+
resources=yandex.ComputeInstanceResourcesArgs(
62+
cores=2,
63+
memory=1,
64+
core_fraction=20,
65+
),
66+
boot_disk=yandex.ComputeInstanceBootDiskArgs(
67+
initialize_params=yandex.ComputeInstanceBootDiskInitializeParamsArgs(
68+
image_id=image.id,
69+
size=10,
70+
type="network-hdd",
71+
),
72+
),
73+
network_interfaces=[yandex.ComputeInstanceNetworkInterfaceArgs(
74+
subnet_id=subnet.id,
75+
security_group_ids=[security_group.id],
76+
nat=True,
77+
)],
78+
metadata={
79+
"ssh-keys": f"ubuntu:{ssh_public_key}",
80+
})
81+
82+
# Export public IP
83+
pulumi.export("vm_public_ip", vm.network_interfaces[0].nat_ip_address)
84+
pulumi.export("ssh_command", pulumi.Output.concat("ssh ubuntu@", vm.network_interfaces[0].nat_ip_address))

pulumi/requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pulumi>=3.0.0,<4.0.0

terraform/.gitignore

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Terraform
2+
*.tfstate
3+
*.tfstate.*
4+
.terraform/
5+
terraform.tfvars
6+
*.tfvars
7+
.terraform.lock.hcl
8+
9+
# Secrets
10+
*.json
11+
*.pem
12+
*.key

terraform/docs/LAB04.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
## Lab 4 — Infrastructure as Code (Terraform & Pulumi)
2+
3+
### 1. Cloud Provider & Infrastructure
4+
- **Provider:** Yandex Cloud (reason: accessible in Russia, free tier).
5+
- **Instance Type:** 2 vCPU (20% core fraction), 1 GB RAM (free tier).
6+
- **Region:** ru-central1-a.
7+
- **Cost:** $0 (free tier).
8+
- **Resources Created:** VPC network, subnet, security group, VM with public IP.
9+
10+
### 2. Terraform Implementation
11+
- **Version:** 1.9.x
12+
- **Project Structure:** main.tf, variables.tf, outputs.tf, terraform.tfvars (gitignored).
13+
- **Key Decisions:** Used ephemeral public IP for simplicity; security group allows SSH, HTTP, port 5000.
14+
- **Challenges:** Had to adjust Yandex provider authentication; resolved by using service account key file.
15+
16+
### 3. Pulumi Implementation
17+
- **Version:** 3.x
18+
- **Language:** Python 3.13
19+
- **How Code Differs:** Imperative style; used Python to read SSH key file; configuration via `pulumi config`.
20+
- **Advantages:** Could use Python logic (file reading), better IDE support.
21+
- **Challenges:** Had to install provider package manually; resolved by adding to requirements.txt.
22+
23+
### 4. Terraform vs Pulumi Comparison
24+
- **Ease of Learning:** Terraform HCL is simpler for basic cases, but Pulumi is natural for developers.
25+
- **Code Readability:** Terraform is declarative and concise; Pulumi code is more verbose but allows complex logic.
26+
- **Debugging:** Pulumi's Python stack traces are familiar; Terraform's error messages can be cryptic.
27+
- **Documentation:** Both have excellent docs, but Pulumi's examples are more varied due to multiple languages.
28+
- **Use Case:** Terraform is great for pure infrastructure, Pulumi when you need to integrate with application code or reuse logic.
29+

terraform/main.tf

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
terraform {
2+
required_providers {
3+
yandex = {
4+
source = "yandex-cloud/yandex"
5+
}
6+
}
7+
required_version = ">= 0.13"
8+
}
9+
10+
11+
provider "yandex" {
12+
service_account_key_file = var.service_account_key_file
13+
cloud_id = var.cloud_id
14+
folder_id = var.folder_id
15+
zone = var.zone
16+
}
17+
18+
data "yandex_compute_image" "ubuntu" {
19+
family = "ubuntu-2404-lts-oslogin"
20+
}
21+
22+
resource "yandex_vpc_network" "lab_network" {
23+
name = "lab-network"
24+
}
25+
26+
resource "yandex_vpc_subnet" "lab_subnet" {
27+
name = "lab-subnet"
28+
zone = var.zone
29+
network_id = yandex_vpc_network.lab_network.id
30+
v4_cidr_blocks = ["192.168.10.0/24"]
31+
}
32+
33+
resource "yandex_vpc_security_group" "lab_sg" {
34+
name = "lab-security-group"
35+
description = "Allow SSH, HTTP, and app port 5000"
36+
network_id = yandex_vpc_network.lab_network.id
37+
38+
ingress {
39+
protocol = "TCP"
40+
description = "SSH"
41+
port = 22
42+
v4_cidr_blocks = ["0.0.0.0/0"]
43+
}
44+
45+
ingress {
46+
protocol = "TCP"
47+
description = "HTTP"
48+
port = 80
49+
v4_cidr_blocks = ["0.0.0.0/0"]
50+
}
51+
52+
ingress {
53+
protocol = "TCP"
54+
description = "App port 5000"
55+
port = 5000
56+
v4_cidr_blocks = ["0.0.0.0/0"]
57+
}
58+
59+
egress {
60+
protocol = "ANY"
61+
description = "Allow all outbound"
62+
v4_cidr_blocks = ["0.0.0.0/0"]
63+
}
64+
}
65+
66+
resource "yandex_compute_instance" "lab_vm" {
67+
name = "lab-vm"
68+
platform_id = "standard-v2"
69+
zone = var.zone
70+
71+
resources {
72+
cores = 2
73+
memory = 1
74+
core_fraction = 20
75+
}
76+
77+
boot_disk {
78+
initialize_params {
79+
image_id = data.yandex_compute_image.ubuntu.id
80+
size = 10
81+
type = "network-hdd"
82+
}
83+
}
84+
85+
network_interface {
86+
subnet_id = yandex_vpc_subnet.lab_subnet.id
87+
security_group_ids = [yandex_vpc_security_group.lab_sg.id]
88+
nat = true # Ephemeral public IP
89+
}
90+
91+
metadata = {
92+
ssh-keys = "ubuntu:${file(var.public_key_path)}"
93+
}
94+
}

terraform/outputs.tf

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
output "vm_public_ip" {
2+
description = "Public IP address of the VM"
3+
value = yandex_compute_instance.lab_vm.network_interface[0].nat_ip_address
4+
}
5+
6+
output "ssh_command" {
7+
description = "SSH command to connect to the VM"
8+
value = "ssh ubuntu@${yandex_compute_instance.lab_vm.network_interface[0].nat_ip_address}"
9+
}

terraform/variables.tf

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
variable "service_account_key_file" {
2+
description = "Path to the service account JSON key file"
3+
type = string
4+
}
5+
6+
variable "cloud_id" {
7+
description = "Yandex Cloud ID"
8+
type = string
9+
}
10+
11+
variable "folder_id" {
12+
description = "Yandex Folder ID"
13+
type = string
14+
}
15+
16+
variable "zone" {
17+
description = "Yandex Cloud zone"
18+
type = string
19+
default = "ru-central1-a"
20+
}
21+
22+
variable "public_key_path" {
23+
description = "Path to SSH public key"
24+
type = string
25+
default = "~/.ssh/id_rsa.pub"
26+
}

0 commit comments

Comments
 (0)