[{"data":1,"prerenderedAt":328},["ShallowReactive",2],{"project-auto-discover-vms":3},{"id":4,"title":5,"body":6,"description":306,"duration":307,"extension":308,"featured":309,"github":310,"image":311,"live":312,"meta":313,"navigation":314,"order":226,"path":315,"role":312,"seo":316,"status":317,"stem":318,"team_size":312,"tech":319,"type":325,"year":326,"__hash__":327},"projects\u002Fproject\u002Fauto-discover-vms.md","Azure Auto Discover VMs",{"type":7,"value":8,"toc":298},"minimark",[9,14,18,22,25,68,72,77,85,107,111,116,122,157,161,164,294],[10,11,13],"h2",{"id":12},"the-problem","The Problem",[15,16,17],"p",{},"In standard cloud deployments, scaling backend servers or replacing unhealthy instances requires manually updating load balancer configurations or hardcoding static IPs. This manual intervention introduces configuration drift, increases the risk of human error, and causes latency or dropped connections during proxy configuration reloads. In a dynamic, auto-scaling environment, infrastructure must be self-aware and autonomous.",[10,19,21],{"id":20},"my-solution","My Solution",[15,23,24],{},"I engineered a custom Service Mesh architecture for Azure that eliminates manual IP tracking and static load balancer configuration.",[26,27,28,39,47,60],"ul",{},[29,30,31,35,38],"li",{},[32,33,34],"strong",{},"Custom Control Plane",[36,37],"br",{},"\nBuilt a lightweight, highly concurrent Go service using the Azure SDK to automatically discover backend Virtual Machines based on metadata.",[29,40,41,44,46],{},[32,42,43],{},"Dynamic Configuration (xDS)",[36,45],{},"\nIntegrated Envoy Proxy as the edge gateway. It receives real-time configuration via gRPC and updates routing instantly without requiring restarts.",[29,48,49,52,54,55,59],{},[32,50,51],{},"Infrastructure as Code",[36,53],{},"\nOrchestrated the environment using modular Terraform. Infrastructure is bootstrapped automatically using ",[56,57,58],"code",{},"cloud-init",".",[29,61,62,65,67],{},[32,63,64],{},"Real-Time Observability",[36,66],{},"\nImplemented a REST API in the Control Plane to expose discovery status, health metrics, and system state.",[10,69,71],{"id":70},"technical-deep-dive","Technical Deep Dive",[73,74,76],"h3",{"id":75},"architecture-decisions","Architecture Decisions",[15,78,79,82,84],{},[32,80,81],{},"Why Envoy Proxy over Nginx\u002FHAProxy?",[36,83],{},"\nTraditional reverse proxies require reloads to apply upstream changes, which can drop active connections. Envoy supports dynamic configuration via the xDS API, allowing in-memory updates with zero downtime.",[15,86,87,90,92,93,96,97,96,100,96,103,106],{},[32,88,89],{},"Why Terraform Modularity?",[36,91],{},"\nThe infrastructure is separated into independent modules (",[56,94,95],{},"network",", ",[56,98,99],{},"backend-vms",[56,101,102],{},"control-plane",[56,104,105],{},"envoy-lb","). This ensures backend changes do not impact core networking or load balancing layers.",[73,108,110],{"id":109},"key-features","Key Features",[112,113,115],"h4",{"id":114},"_1-automated-iac-provisioning-and-injection","1. Automated IaC Provisioning and Injection",[15,117,118,119,121],{},"Terraform dynamically injects the Control Plane IP into Envoy’s bootstrap configuration using ",[56,120,58],{},", enabling immediate gRPC connectivity on startup.",[123,124,129],"pre",{"className":125,"code":126,"language":127,"meta":128,"style":128},"language-hcl shiki shiki-themes github-light github-dark","# Inject Control Plane IP into Envoy bootstrap config\ncustom_data = base64encode(templatefile(\"${path.module}\u002Fcloud-init.yml\", {\n  control_plane_host = var.control_plane_host\n}))\n","hcl","",[56,130,131,139,145,151],{"__ignoreMap":128},[132,133,136],"span",{"class":134,"line":135},"line",1,[132,137,138],{},"# Inject Control Plane IP into Envoy bootstrap config\n",[132,140,142],{"class":134,"line":141},2,[132,143,144],{},"custom_data = base64encode(templatefile(\"${path.module}\u002Fcloud-init.yml\", {\n",[132,146,148],{"class":134,"line":147},3,[132,149,150],{},"  control_plane_host = var.control_plane_host\n",[132,152,154],{"class":134,"line":153},4,[132,155,156],{},"}))\n",[112,158,160],{"id":159},"_2-rest-api-for-mesh-observability","2. REST API for Mesh Observability",[15,162,163],{},"A REST API was built alongside the gRPC server to provide real-time visibility into the system state.",[123,165,169],{"className":166,"code":167,"language":168,"meta":128,"style":128},"language-json shiki shiki-themes github-light github-dark","\u002F\u002F GET \u002Fapi\u002Fvms\n{\n  \"last_update\": \"2025-02-04T10:00:00Z\",\n  \"total_vms\": 2,\n  \"snapshot_version\": 15,\n  \"vms\": [\n    {\n      \"name\": \"auto-discover-vms-app-0\",\n      \"public_ip\": \"20.120.10.1\",\n      \"private_ip\": \"10.1.1.4\"\n    }\n  ]\n}\n","json",[56,170,171,177,183,199,211,224,233,239,252,265,276,282,288],{"__ignoreMap":128},[132,172,173],{"class":134,"line":135},[132,174,176],{"class":175},"sJ8bj","\u002F\u002F GET \u002Fapi\u002Fvms\n",[132,178,179],{"class":134,"line":141},[132,180,182],{"class":181},"sVt8B","{\n",[132,184,185,189,192,196],{"class":134,"line":147},[132,186,188],{"class":187},"sj4cs","  \"last_update\"",[132,190,191],{"class":181},": ",[132,193,195],{"class":194},"sZZnC","\"2025-02-04T10:00:00Z\"",[132,197,198],{"class":181},",\n",[132,200,201,204,206,209],{"class":134,"line":153},[132,202,203],{"class":187},"  \"total_vms\"",[132,205,191],{"class":181},[132,207,208],{"class":187},"2",[132,210,198],{"class":181},[132,212,214,217,219,222],{"class":134,"line":213},5,[132,215,216],{"class":187},"  \"snapshot_version\"",[132,218,191],{"class":181},[132,220,221],{"class":187},"15",[132,223,198],{"class":181},[132,225,227,230],{"class":134,"line":226},6,[132,228,229],{"class":187},"  \"vms\"",[132,231,232],{"class":181},": [\n",[132,234,236],{"class":134,"line":235},7,[132,237,238],{"class":181},"    {\n",[132,240,242,245,247,250],{"class":134,"line":241},8,[132,243,244],{"class":187},"      \"name\"",[132,246,191],{"class":181},[132,248,249],{"class":194},"\"auto-discover-vms-app-0\"",[132,251,198],{"class":181},[132,253,255,258,260,263],{"class":134,"line":254},9,[132,256,257],{"class":187},"      \"public_ip\"",[132,259,191],{"class":181},[132,261,262],{"class":194},"\"20.120.10.1\"",[132,264,198],{"class":181},[132,266,268,271,273],{"class":134,"line":267},10,[132,269,270],{"class":187},"      \"private_ip\"",[132,272,191],{"class":181},[132,274,275],{"class":194},"\"10.1.1.4\"\n",[132,277,279],{"class":134,"line":278},11,[132,280,281],{"class":181},"    }\n",[132,283,285],{"class":134,"line":284},12,[132,286,287],{"class":181},"  ]\n",[132,289,291],{"class":134,"line":290},13,[132,292,293],{"class":181},"}\n",[295,296,297],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}",{"title":128,"searchDepth":141,"depth":141,"links":299},[300,301,302],{"id":12,"depth":141,"text":13},{"id":20,"depth":141,"text":21},{"id":70,"depth":141,"text":71,"children":303},[304,305],{"id":75,"depth":147,"text":76},{"id":109,"depth":147,"text":110},"A dynamic Service Mesh utilizing Envoy Proxy and a custom Go Control Plane to automatically discover and load balance Azure Virtual Machines with zero downtime.","3 weeks","md",false,"https:\u002F\u002Fgithub.com\u002Fszuryuu\u002Fauto-discover-vms","\u002Fimages\u002Fprojects\u002Fterraform.png",null,{},true,"\u002Fproject\u002Fauto-discover-vms",{"title":5,"description":306},"Completed","project\u002Fauto-discover-vms",[320,321,322,323,324],"Go","Envoy Proxy","Terraform","Azure","Cloud-init","Solo Project","2026","Xj35xEp8AGPgIVTcPjHOaTmCzo-JJ6at_tJJsymA7Es",1776582962961]