From 47baecaecab34fa29c3269f38bdad1880491bf44 Mon Sep 17 00:00:00 2001 From: usrbinkat Date: Wed, 8 Jan 2025 14:15:39 -0800 Subject: [PATCH] update k8s support to 1.32 + Cilium L2 Announcement rfe --- .DS_Store | Bin 0 -> 6148 bytes docs/.DS_Store | Bin 0 -> 6148 bytes docs/developer_guide/.DS_Store | Bin 0 -> 6148 bytes .../networking/GlobalArchitectureSample.md | 380 ++++++++++++++++++ ...workDiagrams_AdvancedEnterpriseDiagrams.md | 290 +++++++++++++ .../MermaidNetworkDiagrams_GetStarted.md | 219 ++++++++++ ...dNetworkDiagrams_RealWorldDocumentation.md | 268 ++++++++++++ docs/hack/u.yml | 169 ++++++++ docs/hack/u2.yml | 192 +++++++++ pulumi/src/hostpath_provisioner/deploy.py | 129 +++--- pulumi/src/kubevirt/deploy.py | 156 +++++-- pulumi/src/multus/deploy.py | 189 ++++++--- pulumi/src/prometheus/deploy.py | 136 +++---- pulumi/src/vm/ubuntu.py | 93 +++-- pulumi/stacks/Pulumi.optiplexprime.yaml | 15 +- 15 files changed, 1929 insertions(+), 307 deletions(-) create mode 100644 .DS_Store create mode 100644 docs/.DS_Store create mode 100644 docs/developer_guide/.DS_Store create mode 100644 docs/developer_guide/networking/GlobalArchitectureSample.md create mode 100644 docs/developer_guide/networking/MermaidNetworkDiagrams_AdvancedEnterpriseDiagrams.md create mode 100644 docs/developer_guide/networking/MermaidNetworkDiagrams_GetStarted.md create mode 100644 docs/developer_guide/networking/MermaidNetworkDiagrams_RealWorldDocumentation.md create mode 100644 docs/hack/u.yml create mode 100644 docs/hack/u2.yml diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..8a3d316db31c8150a2547bb8ae74fa7ba52dae4a GIT binary patch literal 6148 zcmeHK%}T>S5Z-O0Nhm@NiXIod7EFs!#Y?F51&ruHr6#6mFlI~B+CwSisxRc5_&m<+ zZp32FB6bFLzxmzGevtiPjPd>~=`iLo#vEvf9F-bDcWtO)k`XzM5zmWpoXHsMcN6>T zfZuMhgh_VKitpbakF&Ix`u+!RG_8$I+ji}ieH%W?c{q)xv!WkOuF<-XGK(uciZ9dA zeCTbT%6uB7`DmgF(qsfFH&UNl*Kdnn z_h`9vot^!Ilk?$I_MFRC%_j%Cm24TT;0=_o<-CNGJd^nY_^SLWkB}H328aP-V2v3t zhl0~uV-9HP!~ii+&j9WZ0vcjqu+*rw4(RaujByJQ1$2B%APR$l!BQhcK)5ai)TP`! zF}N-Vzc6`$!BV3xXI#w;bO81@&bdUMjQqG RsvM9m0*Vmoh=E^V;1gr-N)!M9 literal 0 HcmV?d00001 diff --git a/docs/.DS_Store b/docs/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..e3ca0c642459b1b963827b56ffeed9d0cb73070b GIT binary patch literal 6148 zcmeHK%}N6?5T3Nv?oz}(D0&QdE!Y;JikGF<7jQ)nDz(d&y0~siw?Btc*sH#fZ{qVf zlcZv);z1B8GcfrklbMA1vLqV-5Up`k2k-#EK_x7>*nA;0PP!rm>md|+jsz48pa(MqN+sdK?uJ)!Z`$#8&Qv<;#%XV;6XK|cA-C6Y8mVbZjngR8xq%sQ zUB~Tsd$U=+D(gqJ=DaFrCyiQFHXFzDx$Ep69G+fu9+Rh3JsV~PeuP@KEH2;$jUS4f z1j95@X&)mOvn;Y1nE_^i8CW|8>_O*L)~+%xh#6o8e#-!z4-%Eox0oB$M+Y|a`$*#@ zLK3v;EkP(P`WAD8ID#TfDxygh_K6`(I{KxJ^DX8EO*#m@GR|XH7WRcA^y=uBIvj*= zkXvSe8CYhZXu2NV|L5Po|Cf`v#|$t7YsG*lwS#sGOR{(CN^x}8O4NH)5{kvM?llS4Kwhk47>vg7g4YP literal 0 HcmV?d00001 diff --git a/docs/developer_guide/.DS_Store b/docs/developer_guide/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..ddbc2dad4671a72d5378943a48b0712b981c50e3 GIT binary patch literal 6148 zcmeHK!Ab)$5S_Hub}d2=iXH=A3vP>0#miFb54fTSmD**CE?qaJ-MWWT*sK1Kf8zHz zlcZv4J$MnZGcb9R$;^g%3CRWkM0*l80BQhGK_x6W*sKs5CtZ?)^$-gE4Fw|@Km-Xq zEJd^9FET)Dw}tD~hZHjSvVK7}9tN=raQrP8#?d%+-FHzamNquaWv5&%-}#R!^V42B z8Mk|*8|qyu6$f*>7hFaCtXtbTQ%Ty3lKx01L}4F8Zm**xR9Rb1l5nhZeKX)V6{lO< zn@$^b**J1rv$~v~G~K#vHIHXAr?Pu+czV$t#7~KOF? Cloud_Native + Global_Edge --> Edge_Computing + Cloud_Native <--> Enterprise_Core + Edge_Computing <--> Enterprise_Core +``` + +### Physical Infrastructure Components + +```mermaid +flowchart TB + subgraph DC ["Data Center Physical Layer"] + direction TB + + subgraph Network ["Network Infrastructure"] + Core["Core - Cisco 9500"] + Spine["Spine - Nexus 9364C"] + Leaf["Leaf - Nexus 93180YC-EX"] + ToR["ToR - Nexus 9300"] + end + + subgraph Compute ["Compute Infrastructure"] + Blade["Blade Chassis"] + HCI["HCI Clusters"] + GPU["GPU Clusters"] + end + + subgraph Storage ["Storage Infrastructure"] + SAN["SAN Fabric"] + NAS["NAS Arrays"] + Object["Object Storage"] + end + + subgraph Interconnect ["Interconnection"] + DCI["DCI Links"] + IXP["IXP Connectivity"] + DWDM["DWDM Systems"] + end + end + + Core --> Spine + Spine --> Leaf + Leaf --> ToR +``` + +## Network Segmentation & Security + +### Zero Trust Security Architecture + +```mermaid +flowchart TB + subgraph Security ["Security Framework"] + direction TB + + subgraph Access ["Access Control"] + IdP["Identity Provider"] + MFA["MFA Service"] + PAM["Privileged Access"] + end + + subgraph Perimeter ["Perimeter Security"] + NGFW["Next-Gen Firewall"] + IPS["IPS/IDS"] + WAF["Web App Firewall"] + end + + subgraph Micro ["Microsegmentation"] + NSX["NSX Security"] + Calico["Calico Policy"] + VPC["VPC Security"] + end + + subgraph Crypto ["Cryptography"] + KMS["Key Management"] + HSM["Hardware Security"] + PKI["PKI Infrastructure"] + end + end + + Access --> Perimeter + Perimeter --> Micro + Micro --> Crypto +``` + +## Manufacturing & OT Networks + +### Industrial Network Architecture + +```mermaid +flowchart TB + subgraph Industrial ["Industrial Network"] + direction TB + + subgraph L5 ["Enterprise Network - L5"] + ERP["ERP Systems"] + MES["MES Systems"] + end + + subgraph L4 ["Site Operations - L4"] + SCADA["SCADA Systems"] + Historian["Historians"] + end + + subgraph L3 ["Area Control - L3"] + PLC["PLC Control"] + HMI["HMI Systems"] + end + + subgraph L2_1 ["Process Network - L2/1"] + Sensors["Sensors"] + Actuators["Actuators"] + IO["I/O Systems"] + end + + DMZ["Industrial DMZ"] + end + + L5 --- DMZ + DMZ --- L4 + L4 --- L3 + L3 --- L2_1 +``` + +## Network Operations & Automation + +### DevOps Workflow + +```mermaid +flowchart LR + subgraph Automation ["Network Automation"] + direction TB + + subgraph IaC ["Infrastructure as Code"] + Terraform["Terraform"] + Ansible["Ansible"] + Puppet["Puppet"] + end + + subgraph CI_CD ["CI/CD Pipeline"] + Git["Git Repos"] + Jenkins["Jenkins"] + ArgoCD["ArgoCD"] + end + + subgraph Testing ["Network Testing"] + Unit["Unit Tests"] + Int["Integration Tests"] + E2E["E2E Tests"] + end + end + + IaC --> CI_CD + CI_CD --> Testing +``` + +## Observability & Monitoring + +### Monitoring Stack + +```mermaid +flowchart TB + subgraph Observability ["Observability Platform"] + direction TB + + subgraph Metrics ["Metrics Collection"] + Prometheus["Prometheus"] + SNMP["SNMP Collection"] + Telemetry["Streaming Telemetry"] + end + + subgraph Logs ["Log Management"] + ELK["ELK Stack"] + Splunk["Splunk"] + Loki["Loki"] + end + + subgraph Tracing ["Distributed Tracing"] + Jaeger["Jaeger"] + Zipkin["Zipkin"] + OpenTelemetry["OpenTelemetry"] + end + + subgraph Visualization ["Dashboards"] + Grafana["Grafana"] + Kibana["Kibana"] + Custom["Custom Dashboards"] + end + end + + Metrics --> Visualization + Logs --> Visualization + Tracing --> Visualization +``` + +## Wireless & Mobile Infrastructure + +### 5G and WiFi Integration + +```mermaid +flowchart TB + subgraph Wireless ["Wireless Infrastructure"] + direction TB + + subgraph WiFi ["Enterprise WiFi"] + WiFi6E["WiFi 6E APs"] + WLC["Wireless Controllers"] + WIPS["Wireless IPS"] + end + + subgraph FiveG ["5G Infrastructure"] + RAN["5G RAN"] + Core["5G Core"] + MEC["Mobile Edge Computing"] + end + + subgraph IoT ["IoT Connectivity"] + LoRa["LoRaWAN"] + BLE["Bluetooth LE"] + Zigbee["Zigbee"] + end + end + + WiFi --- FiveG + FiveG --- IoT +``` + +## Disaster Recovery & Business Continuity + +### Recovery Architecture + +```mermaid +flowchart TB + subgraph DR ["Disaster Recovery"] + direction TB + + subgraph Primary ["Primary Site"] + P_Net["Network"] + P_Compute["Compute"] + P_Data["Data"] + end + + subgraph Secondary ["Secondary Site"] + S_Net["Network"] + S_Compute["Compute"] + S_Data["Data"] + end + + subgraph Cloud_DR ["Cloud DR"] + C_VPC["Cloud VPC"] + C_Storage["Cloud Storage"] + C_Compute["Cloud Compute"] + end + end + + Primary <-->|"Sync"| Secondary + Primary -.->|"Backup"| Cloud_DR + Secondary -.->|"Backup"| Cloud_DR +``` + +## Implementation Guidelines + +### Prerequisites +- Network engineering expertise (CCNA/CCNP/CCIE) +- Cloud platform experience +- Security certification (CISSP/CCSP) +- Automation skills (Python/Ansible) +- Infrastructure as Code experience + +### Documentation +- [Network Architecture Guide](docs/architecture.md) +- [Security Implementation](docs/security.md) +- [Automation Framework](docs/automation.md) +- [Operations Playbook](docs/operations.md) + +## Compliance Framework + +### Standards Implementation +- SOC 2 Type II Controls +- ISO 27001 Framework +- HIPAA Security Rule +- PCI DSS Requirements +- NIST Cybersecurity Framework +- GDPR Data Protection + +### Automated Compliance +- Continuous compliance monitoring +- Automated control validation +- Real-time compliance reporting +- Policy enforcement automation +- Audit trail logging + +## Support & Operations + +### Resources +- [Network Operations Center](https://noc.enterprise.com) +- [Security Operations Center](https://soc.enterprise.com) +- [Engineering Wiki](https://wiki.enterprise.com) +- [API Documentation](https://api.enterprise.com) + +### Teams +- Network Engineering +- Security Operations +- Cloud Platform +- Automation & DevOps +- Compliance & Governance + +## License + +This architecture is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details. + +--- + +*Maintained by Enterprise Network Architecture Team* diff --git a/docs/developer_guide/networking/MermaidNetworkDiagrams_AdvancedEnterpriseDiagrams.md b/docs/developer_guide/networking/MermaidNetworkDiagrams_AdvancedEnterpriseDiagrams.md new file mode 100644 index 0000000..6e6f6ae --- /dev/null +++ b/docs/developer_guide/networking/MermaidNetworkDiagrams_AdvancedEnterpriseDiagrams.md @@ -0,0 +1,290 @@ +# Network Engineering Documentation with Mermaid - Part 2: Advanced Network Diagramming + +## Enterprise Network Diagrams + +### Campus Network Layout + +```mermaid +flowchart TB + subgraph Core ["Core Layer"] + C1["Core Switch 1
N9K-C9336C-FX2"] + C2["Core Switch 2
N9K-C9336C-FX2"] + C1 <==> C2 + end + + subgraph Distribution ["Distribution Layer"] + D1["Dist Switch 1
C9500-48Y4C"] + D2["Dist Switch 2
C9500-48Y4C"] + D1 <==> D2 + end + + subgraph Access ["Access Layer"] + A1["Access Switch 1
C9300-48U"] + A2["Access Switch 2
C9300-48U"] + A3["Access Switch 3
C9300-48U"] + A4["Access Switch 4
C9300-48U"] + end + + C1 --- D1 & D2 + C2 --- D1 & D2 + D1 --- A1 & A2 + D2 --- A3 & A4 +``` + +### Data Center Topology + +```mermaid +flowchart TB + subgraph DC1 ["Primary Data Center"] + subgraph Spine ["Spine Layer"] + S1["Spine 1"] + S2["Spine 2"] + end + + subgraph Leaf ["Leaf Layer"] + L1["Leaf 1"] + L2["Leaf 2"] + L3["Leaf 3"] + end + + subgraph Servers ["Server Farm"] + SRV1["Web Servers"] + SRV2["App Servers"] + SRV3["DB Servers"] + end + + S1 --- L1 & L2 & L3 + S2 --- L1 & L2 & L3 + L1 --- SRV1 + L2 --- SRV2 + L3 --- SRV3 + end +``` + +### SD-WAN Architecture + +```mermaid +flowchart LR + subgraph DC ["Data Center"] + vManage["vManage
Management"] + vSmart["vSmart
Controller"] + vBond["vBond
Orchestrator"] + vEdgeDC["vEdge Router"] + end + + subgraph Branch1 ["Branch Office 1"] + vEdge1["vEdge Router"] + SW1["Branch Switch"] + end + + subgraph Branch2 ["Branch Office 2"] + vEdge2["vEdge Router"] + SW2["Branch Switch"] + end + + Internet((Internet)) + MPLS((MPLS)) + + vManage --- vSmart & vBond + vEdgeDC --- Internet & MPLS + vEdge1 --- Internet & MPLS + vEdge2 --- Internet & MPLS + vEdge1 --- SW1 + vEdge2 --- SW2 +``` + +## Protocol and Service Flows + +### BGP Route Advertisement + +```mermaid +sequenceDiagram + participant AS1 as AS 65001 + participant AS2 as AS 65002 + participant AS3 as AS 65003 + + AS1->>AS2: BGP Update (Prefix: 10.0.0.0/8) + AS2->>AS1: BGP Update ACK + AS2->>AS3: BGP Update (Prefix: 10.0.0.0/8) + AS3->>AS2: BGP Update ACK + Note over AS1,AS3: Route Propagation Complete +``` + +### High Availability Failover + +```mermaid +stateDiagram-v2 + [*] --> Active: System Boot + Active --> Standby: Failure Detected + Standby --> Active: Primary Restored + Active --> [*]: System Shutdown + Standby --> [*]: System Shutdown + + note right of Active + - Processing Traffic + - Primary Control Plane + - Active HSRP State + end note + + note left of Standby + - Monitoring Status + - Backup Control Plane + - Standby HSRP State + end note +``` + +### Load Balancer Configuration + +```mermaid +flowchart TB + subgraph LB ["F5 Load Balancer"] + VIP["Virtual IP
10.0.1.100"] + LB1["LTM 1"] + LB2["LTM 2"] + end + + subgraph WEB ["Web Server Pool"] + W1["Web Server 1
10.0.1.11"] + W2["Web Server 2
10.0.1.12"] + W3["Web Server 3
10.0.1.13"] + end + + Client["Client"] + Client --> VIP + VIP --> LB1 & LB2 + LB1 --> W1 & W2 & W3 + LB2 --> W1 & W2 & W3 +``` + +## Network Security Implementation + +### Security Zones and Policy + +```mermaid +flowchart TB + subgraph Internet_Zone ["Internet Zone"] + INT["Internet"] + end + + subgraph DMZ ["DMZ Zone"] + WEB["Web Servers"] + MAIL["Mail Servers"] + DNS["DNS Servers"] + end + + subgraph Internal ["Internal Zone"] + subgraph Protected ["Protected Resources"] + AD["Active Directory"] + DB["Databases"] + APP["Applications"] + end + end + + INT <--> FW1{"Firewall
Policy Engine"} + FW1 <--> DMZ + FW1 <--> Internal +``` + +### VPN Tunnel Configuration + +```mermaid +flowchart LR + subgraph Site_A ["Site A"] + RouterA["Router A
ASA 5506-X"] + NetworkA["10.1.0.0/16"] + end + + subgraph Site_B ["Site B"] + RouterB["Router B
ASA 5506-X"] + NetworkB["10.2.0.0/16"] + end + + RouterA <==>|"IPsec Tunnel
IKEv2 + AES256"| RouterB + NetworkA --- RouterA + RouterB --- NetworkB +``` + +### Zero Trust Architecture + +```mermaid +flowchart TB + subgraph Access_Layer ["Access Layer"] + Client["Client Device"] + NAC["NAC System"] + MFA["MFA Service"] + end + + subgraph Security_Services ["Security Services"] + NGFW["Next-Gen Firewall"] + IPS["IPS/IDS"] + CASB["CASB"] + end + + subgraph Resources ["Protected Resources"] + Apps["Applications"] + Data["Data Storage"] + Services["Cloud Services"] + end + + Client --> NAC + NAC --> MFA + MFA --> NGFW + NGFW --> IPS + IPS --> CASB + CASB --> Apps & Data & Services +``` + +### DMZ Implementation + +```mermaid +flowchart TB + Internet((Internet)) + + subgraph External_FW ["External Firewall"] + FW1["ASA 1"] + FW2["ASA 2"] + end + + subgraph DMZ ["DMZ Segment"] + direction LR + WAF["Web Application
Firewall"] + ReverseProxy["Reverse Proxy"] + WebServers["Web Servers"] + end + + subgraph Internal_FW ["Internal Firewall"] + FW3["ASA 3"] + FW4["ASA 4"] + end + + subgraph Internal ["Internal Network"] + AppServers["Application
Servers"] + DBServers["Database
Servers"] + end + + Internet <--> External_FW + External_FW <--> DMZ + DMZ <--> Internal_FW + Internal_FW <--> Internal +``` + +## Advanced Configuration Examples + +### EVPN VXLAN Fabric + +```mermaid +flowchart TB + subgraph Overlay ["EVPN Overlay"] + direction TB + Spine1["Spine 1"] <--> Spine2["Spine 2"] + + subgraph Leaf_Layer ["Leaf Layer"] + Leaf1["Leaf 1
VTEP 1"] + Leaf2["Leaf 2
VTEP 2"] + Leaf3["Leaf 3
VTEP 3"] + end + + Spine1 <--> Leaf1 & Leaf2 & Leaf3 + Spine2 <--> Leaf1 & Leaf2 & Leaf3 + end +``` diff --git a/docs/developer_guide/networking/MermaidNetworkDiagrams_GetStarted.md b/docs/developer_guide/networking/MermaidNetworkDiagrams_GetStarted.md new file mode 100644 index 0000000..525ac4a --- /dev/null +++ b/docs/developer_guide/networking/MermaidNetworkDiagrams_GetStarted.md @@ -0,0 +1,219 @@ +# Network Engineering Documentation with Mermaid - Part 1: Getting Started with Network Diagrams + +## Introduction + +Mermaid enables network engineers to create and maintain network documentation directly in code, making it version-control friendly and easily maintainable. Network diagrams stay synchronized with infrastructure changes through simple text updates rather than complex visual editor manipulations. + +### Installation + +```bash +# NPM installation +npm install -g @mermaid-js/mermaid-cli + +# Include in HTML + +``` + +Initialize Mermaid in your documentation: + +```javascript +mermaid.initialize({ + startOnLoad: true, + theme: 'default', + flowchart: { + useMaxWidth: false, + htmlLabels: true + } +}); +``` + +## Core Network Diagram Types + +### 1. Network Topology Flowcharts + +Basic network topology using flowchart syntax: + +```mermaid +flowchart LR + Internet((Internet)) + FW[Firewall] + R1[Core Router] + SW1[Distribution Switch] + AP1[Access Point] + + Internet --- FW + FW --- R1 + R1 --- SW1 + SW1 --- AP1 +``` + +Adding subnets and VLANs: + +```mermaid +flowchart TB + subgraph DMZ [DMZ Network 172.16.1.0/24] + WEB[Web Server] + MAIL[Mail Server] + end + + subgraph Internal [Internal Network 10.0.0.0/8] + AD[Active Directory] + FS[File Server] + end + + FW{Firewall} --> DMZ + FW --> Internal +``` + +### 2. Protocol Interactions + +Using sequence diagrams for network protocols: + +```mermaid +sequenceDiagram + participant C as Client + participant R as Router + participant D as DHCP Server + + C->>R: DHCP Discover + R->>D: DHCP Discover + D->>R: DHCP Offer + R->>C: DHCP Offer + C->>R: DHCP Request + R->>D: DHCP Request + D->>R: DHCP ACK + R->>C: DHCP ACK +``` + +### 3. Device State Diagrams + +Network interface states using state diagrams: + +```mermaid +stateDiagram-v2 + [*] --> Down + Down --> Init: Cable Connected + Init --> Up: Interface Configuration OK + Up --> Down: Cable Disconnected + Up --> Error: Link Errors + Error --> Down: Reset Interface +``` + +### 4. Packet Analysis + +TCP/IP packet structure: + +```mermaid +packet-beta + title TCP/IP Packet Structure + 0-31: "IP Header" + 32-63: "TCP Header" + 64-95: "TCP Options (Optional)" + 96-255: "Data Payload" +``` + +## Basic Network Components + +### Network Device Representation + +Standard network device symbols: + +```mermaid +flowchart TB + classDef router fill:#f96,stroke:#333 + classDef switch fill:#69f,stroke:#333 + classDef firewall fill:#f66,stroke:#333 + + R1[Router]:::router + SW1[L3 Switch]:::switch + FW1[Firewall]:::firewall + + R1 --- FW1 + FW1 --- SW1 +``` + +### Complex Enterprise Example + +```mermaid +flowchart TB + subgraph DC [Data Center] + FW1[ASA Firewall] + CR1[Nexus 9000] + CR2[Nexus 9000] + DS1[Catalyst 9300] + DS2[Catalyst 9300] + end + + subgraph Branch [Branch Office] + BR1[ISR 4451] + BSW1[Catalyst 2960] + end + + Internet((Internet)) --- FW1 + FW1 --- CR1 & CR2 + CR1 --- DS1 & DS2 + CR2 --- DS1 & DS2 + + FW1 --- BR1 + BR1 --- BSW1 +``` + +### Network Links and Connections + +Different connection types: + +```mermaid +flowchart LR + R1[Router 1] -- 1Gbps Ethernet --- R2[Router 2] + R1 -. OSPF Adjacency .- R2 + R1 == BGP Session === R2 + R1 -- "10.0.0.0/30" --- R2 +``` + +### VLAN Configuration + +```mermaid +flowchart TB + subgraph VLAN10 [VLAN 10 - Management] + M1[Management Server] + M2[NMS] + end + + subgraph VLAN20 [VLAN 20 - Users] + U1[User Workstation] + U2[User Laptop] + end + + subgraph VLAN30 [VLAN 30 - Servers] + S1[Application Server] + S2[Database Server] + end + + SW1[Core Switch] --- VLAN10 + SW1 --- VLAN20 + SW1 --- VLAN30 +``` + +## Best Practices + +1. Use consistent naming conventions + - Devices: R1, SW1, FW1 + - Networks: NET1, VLAN10, DMZ + - Interfaces: Gi0/1, Te1/1 + +2. Include relevant network information + - IP addresses and subnets + - Interface designations + - Protocol information + - VLAN assignments + +3. Maintain diagram hierarchy + - Top-level overview + - Detailed subnet views + - Protocol-specific diagrams + +4. Use appropriate diagram types + - Flowcharts for topology + - Sequence diagrams for protocols + - State diagrams for status + - Packet diagrams for data flow diff --git a/docs/developer_guide/networking/MermaidNetworkDiagrams_RealWorldDocumentation.md b/docs/developer_guide/networking/MermaidNetworkDiagrams_RealWorldDocumentation.md new file mode 100644 index 0000000..18873fd --- /dev/null +++ b/docs/developer_guide/networking/MermaidNetworkDiagrams_RealWorldDocumentation.md @@ -0,0 +1,268 @@ +# Network Engineering Documentation with Mermaid - Part 3: Real-World Network Documentation + +## Network Documentation Templates + +### Physical Network Topology Template + +```mermaid +flowchart TB + subgraph WAN ["WAN Connectivity"] + ISP1["ISP1 - AT&T
1Gbps"] + ISP2["ISP2 - Verizon
1Gbps"] + end + + subgraph DC ["Primary Data Center - DAL01"] + direction TB + subgraph Edge ["Edge Layer"] + RTR1["RTR-DAL01-ED01
ASR1002-X"] + RTR2["RTR-DAL01-ED02
ASR1002-X"] + end + + subgraph Core ["Core Layer"] + COR1["COR-DAL01-01
Nexus 9504"] + COR2["COR-DAL01-02
Nexus 9504"] + end + + subgraph Distribution ["Distribution Layer"] + DST1["DST-DAL01-01
Catalyst 9500"] + DST2["DST-DAL01-02
Catalyst 9500"] + end + + subgraph Access ["Access Layer"] + ACC1["ACC-DAL01-01
Catalyst 9300"] + ACC2["ACC-DAL01-02
Catalyst 9300"] + ACC3["ACC-DAL01-03
Catalyst 9300"] + ACC4["ACC-DAL01-04
Catalyst 9300"] + end + end + + ISP1 --- RTR1 + ISP2 --- RTR2 + RTR1 & RTR2 --- COR1 & COR2 + COR1 & COR2 --- DST1 & DST2 + DST1 --- ACC1 & ACC2 + DST2 --- ACC3 & ACC4 +``` + +### Logical Network Layout + +```mermaid +flowchart TB + subgraph Network_Zones ["Network Segmentation"] + subgraph External ["External Zone - 172.16.0.0/16"] + DMZ["DMZ Services
VLAN 100"] + Partners["Partner Access
VLAN 110"] + end + + subgraph Internal ["Internal Zone - 10.0.0.0/8"] + Corp["Corporate
VLAN 200-299"] + Production["Production
VLAN 300-399"] + Management["Management
VLAN 999"] + end + + subgraph Restricted ["Restricted Zone - 192.168.0.0/16"] + Finance["Financial Services
VLAN 400"] + HR["HR Systems
VLAN 410"] + end + end +``` + +### Service Dependencies Map + +```mermaid +flowchart LR + subgraph Frontend ["Frontend Services"] + Web["Web Servers
VLAN 100"] + CDN["CDN Services
VLAN 101"] + end + + subgraph Application ["Application Layer"] + API["API Gateway
VLAN 200"] + Cache["Redis Cache
VLAN 201"] + Queue["Message Queue
VLAN 202"] + end + + subgraph Backend ["Backend Services"] + DB["Database Cluster
VLAN 300"] + Storage["Storage Array
VLAN 301"] + end + + Web --> API + API --> Cache & Queue + API & Queue --> DB + DB --> Storage +``` + +## Case Studies + +### Enterprise Campus Network Implementation + +```mermaid +flowchart TB + subgraph Internet_Edge ["Internet Edge"] + FW1["FW-EDGE-01
Palo Alto 5260"] + FW2["FW-EDGE-02
Palo Alto 5260"] + end + + subgraph Campus_Core ["Campus Core"] + direction LR + Core1["CORE-01
Nexus 9504"] + Core2["CORE-02
Nexus 9504"] + Core1 <==>|"vPC Peer Link"| Core2 + end + + subgraph Building_A ["Building A"] + DST_A1["DST-A-01"] + DST_A2["DST-A-02"] + ACC_A1["ACC-A-01"] + ACC_A2["ACC-A-02"] + end + + subgraph Building_B ["Building B"] + DST_B1["DST-B-01"] + DST_B2["DST-B-02"] + ACC_B1["ACC-B-01"] + ACC_B2["ACC-B-02"] + end + + FW1 & FW2 --- Core1 & Core2 + Core1 & Core2 --- DST_A1 & DST_A2 + Core1 & Core2 --- DST_B1 & DST_B2 + DST_A1 & DST_A2 --- ACC_A1 & ACC_A2 + DST_B1 & DST_B2 --- ACC_B1 & ACC_B2 +``` + +### Multi-Site Data Center Connectivity + +```mermaid +flowchart TB + subgraph DC1 ["Primary DC - DAL01"] + Core1["Core Layer"] + Fabric1["VXLAN Fabric"] + end + + subgraph DC2 ["Secondary DC - PHX01"] + Core2["Core Layer"] + Fabric2["VXLAN Fabric"] + end + + subgraph DCI ["Data Center Interconnect"] + direction LR + DWDM1["DWDM-DAL01"] + DWDM2["DWDM-PHX01"] + end + + Core1 --- DWDM1 + Core2 --- DWDM2 + DWDM1 ===|"100G Lambda"| DWDM2 +``` + +### Industrial Network Segmentation + +```mermaid +flowchart TB + subgraph Enterprise ["Enterprise Network"] + Corp["Corporate Network"] + IT["IT Systems"] + end + + subgraph Industrial ["Industrial Zone"] + direction TB + FW_IND["Industrial Firewall"] + + subgraph Level3 ["Level 3 - Site Operations"] + MES["MES"] + Historian["Historian"] + end + + subgraph Level2 ["Level 2 - Process Network"] + HMI["HMI"] + SCADA["SCADA"] + end + + subgraph Level1 ["Level 1 - Control Network"] + PLC["PLCs"] + RTU["RTUs"] + end + + subgraph Level0 ["Level 0 - Field Network"] + Sensors["Sensors"] + Actuators["Actuators"] + end + end + + Corp --- FW_IND + FW_IND --- Level3 + Level3 --- Level2 + Level2 --- Level1 + Level1 --- Level0 +``` + +## Documentation Standards and Best Practices + +### Naming Convention Standards + +```mermaid +flowchart LR + subgraph Naming_Convention ["Device Naming Standard"] + direction TB + Format["FORMAT:
TYPE-SITE-ROLE-NUM"] + + Examples["EXAMPLES:
RTR-DAL01-CORE-01
SW-PHX02-ACC-04
FW-NYC03-DMZ-02"] + end +``` + +### Version Control Integration + +```mermaid +flowchart LR + subgraph Version_Control ["Documentation Workflow"] + direction TB + Edit["Local Edit"] + Review["Peer Review"] + Merge["Merge to Main"] + Deploy["Auto Deploy"] + end + + Edit --> Review + Review --> Merge + Merge --> Deploy +``` + +### Documentation Style Guidelines + +1. Diagram Hierarchy + - L1: Network Overview + - L2: Site-Specific Details + - L3: Component Details + +2. Color Coding Standards + ```mermaid + flowchart LR + classDef production fill:#e6ffe6,stroke:#006600 + classDef staging fill:#e6f3ff,stroke:#0066cc + classDef development fill:#ffe6e6,stroke:#cc0000 + + P[Production]:::production + S[Staging]:::staging + D[Development]:::development + ``` + +3. Link Type Representation + ```mermaid + flowchart LR + A[Device A] === B[Device B] + C[Device C] --- D[Device D] + E[Device E] -.- F[Device F] + + Note["=== High Speed Link
--- Standard Link
-.- Backup Link"] + ``` + +4. Required Documentation Elements + - Device Information + - IP Addressing + - VLAN Assignments + - Physical Connections + - Logical Topology + - Security Zones + - Change History diff --git a/docs/hack/u.yml b/docs/hack/u.yml new file mode 100644 index 0000000..a0e101f --- /dev/null +++ b/docs/hack/u.yml @@ -0,0 +1,169 @@ +# Create a secret for SSH key +# kubectl create secret generic kc2-pubkey --from-file=key1=$HOME/.ssh/id_rsa.pub --dry-run=client -o yaml | kubectl apply -f - +--- +apiVersion: v1 +kind: Service +metadata: + name: ubuntu-ssh +spec: + type: NodePort + ports: + - nodePort: 30590 + port: 30590 + protocol: TCP + targetPort: 22 + selector: + kc2.ccio.io/instance: ubuntu +--- +apiVersion: kubevirt.io/v1 +kind: VirtualMachine +metadata: + name: ubuntu + namespace: default + labels: + app: kc2 + annotations: + kubevirt.io/allow-pod-bridge-network-live-migration: "true" # Enable live migration for bridge interfaces + kubevirt.io/provisionOnNodeChange: "true" # Ensure provisioning after node changes +spec: + runStrategy: RerunOnFailure + dataVolumeTemplates: + - metadata: + name: ubuntu-root-disk + namespace: default + spec: + pvc: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 64Gi + storageClassName: ssd + source: + registry: + url: docker://docker.io/containercraft/ubuntu:22.04 + template: + metadata: + labels: + app: kc2 + kc2.ccio.io/instance: ubuntu + annotations: + kubevirt.io/allow-pod-bridge-network-live-migration: "true" # Annotation applied for live migration + spec: + hostname: ubuntu + domain: + clock: + utc: {} + timer: {} + cpu: + cores: 2 + sockets: 1 + threads: 2 + model: host-passthrough + dedicatedCpuPlacement: false + memory: + guest: 8Gi + resources: + limits: + memory: 8Gi + requests: + memory: 8Gi + machine: + type: q35 + devices: + rng: {} + autoattachPodInterface: true + autoattachSerialConsole: true + autoattachGraphicsDevice: true + networkInterfaceMultiqueue: true + disks: + - name: containerdisk + bootOrder: 1 + disk: + bus: virtio + - name: cloudinitdisk + disk: + bus: virtio + interfaces: + - name: enp1s0 # Primary interface + model: virtio + masquerade: {} # Default pod network + macAddress: "de:ad:be:ef:00:01" # Example MAC address + - name: enp2s0 # Secondary interface + bridge: {} # Bridge interface + macAddress: "de:ad:be:ef:00:02" # Example MAC address + features: + acpi: + enabled: true + smm: + enabled: true + firmware: + bootloader: + efi: + secureBoot: false + networks: + - name: enp1s0 + pod: {} # Default pod network + - name: enp2s0 + multus: + networkName: br0 # Multus NetworkAttachmentDefinition + terminationGracePeriodSeconds: 0 + accessCredentials: + - sshPublicKey: + source: + secret: + secretName: kc2-pubkey + propagationMethod: + qemuGuestAgent: + users: + - "kc2" + volumes: + - name: containerdisk + dataVolume: + name: ubuntu-root-disk + - name: cloudinitdisk + cloudInitNoCloud: + networkData: | + version: 2 + ethernets: + enp1s0: + dhcp4: true + dhcp6: false + dhcp-identifier: mac + enp2s0: + dhcp4: true + dhcp6: false + dhcp-identifier: mac + userData: | + #cloud-config + ssh_pwauth: true + chpasswd: + list: | + kc2:kc2 + expire: False + users: + - name: kc2 + sudo: ['ALL=(ALL) NOPASSWD:ALL'] + groups: sudo,xrdp,ssl-cert,docker + shell: /bin/bash + lock_passwd: false + hostname: ubuntu + update: true + packages: + - xrdp + - docker.io + - python3 + - python3-pip + - ubuntu-desktop + - gnome-tweak-tool + - neofetch + runcmd: + - "systemctl enable --now sshd" + - "systemctl restart sshd" + - "apt-get update" + - "apt-get install --install-recommends -y xrdp docker.io python3 python3-pip gnome-tweak-tool ubuntu-desktop neofetch" + - "lxd init --auto" + - "mkdir -p /home/kc2/.kube" + - "chown -R kc2:kc2 /home/kc2" + - "apt-get -y upgrade" + - "neofetch" diff --git a/docs/hack/u2.yml b/docs/hack/u2.yml new file mode 100644 index 0000000..d487f77 --- /dev/null +++ b/docs/hack/u2.yml @@ -0,0 +1,192 @@ +# Create a secret for SSH key +# kubectl create secret generic kc2-pubkey --from-file=key1=$HOME/.ssh/id_rsa.pub --dry-run=client -o yaml | kubectl apply -f - +--- +apiVersion: v1 +kind: Service +metadata: + name: ubuntu-ssh +spec: + type: NodePort + ports: + - nodePort: 30590 + port: 30590 + protocol: TCP + targetPort: 22 + selector: + kc2.ccio.io/instance: ubuntu +--- +apiVersion: kubevirt.io/v1 +kind: VirtualMachine +metadata: + name: ubuntu + namespace: default + labels: + app: kc2 + annotations: + kubevirt.io/allow-pod-bridge-network-live-migration: "true" # Enable live migration for bridge interfaces + kubevirt.io/provisionOnNodeChange: "true" # Ensure provisioning after node changes +spec: + runStrategy: RerunOnFailure + template: + metadata: + labels: + app: kc2 + kc2.ccio.io/instance: ubuntu + annotations: + kubevirt.io/allow-pod-bridge-network-live-migration: "true" # Annotation applied for live migration + spec: + hostname: ubuntu + domain: + clock: + utc: {} + timer: {} + cpu: + cores: 2 + sockets: 1 + threads: 2 + model: host-passthrough + dedicatedCpuPlacement: false + memory: + guest: 8Gi + resources: + limits: + memory: 8Gi + requests: + memory: 8Gi + machine: + type: q35 + devices: + rng: {} + autoattachPodInterface: false + autoattachSerialConsole: true + autoattachGraphicsDevice: true + networkInterfaceMultiqueue: true + disks: + - name: containerdisk + bootOrder: 1 + disk: + bus: virtio + - name: cloudinitdisk + disk: + bus: virtio + interfaces: + - name: enp1s0 # Secondary interface + bridge: {} # Bridge interface + macAddress: "de:ad:be:ef:00:02" # Example MAC address + # name: enp2s0 # Primary interface + # model: virtio + # masquerade: {} # Default pod network + # macAddress: "de:ad:be:ef:00:01" # Example MAC address + features: + acpi: + enabled: true + smm: + enabled: true + firmware: + bootloader: + efi: + secureBoot: false + networks: + - name: enp1s0 + multus: + networkName: br0 # Multus NetworkAttachmentDefinition + # name: enp1s0 + # pod: {} # Default pod network + terminationGracePeriodSeconds: 0 + accessCredentials: + - sshPublicKey: + source: + secret: + secretName: kc2-pubkey + propagationMethod: + qemuGuestAgent: + users: + - "kc2" + volumes: + - name: containerdisk + containerDisk: + image: docker.io/containercraft/ubuntu:22.04 + imagePullPolicy: Always + - name: cloudinitdisk + cloudInitNoCloud: + networkData: | + version: 2 + ethernets: + enp1s0: + dhcp4: true + dhcp6: false + dhcp-identifier: mac + enp2s0: + dhcp4: true + dhcp6: false + dhcp-identifier: mac + userData: | + #cloud-config + ssh_pwauth: true + chpasswd: + list: | + kc2:kc2 + expire: False + users: + - name: kc2 + sudo: ['ALL=(ALL) NOPASSWD:ALL'] + groups: sudo,xrdp,ssl-cert,docker,kvm + shell: /bin/bash + lock_passwd: false + hostname: ubuntu + update: true + packages: + - xrdp + - docker.io + - python3 + - python3-pip + - ubuntu-desktop + - gnome-tweak-tool + - neofetch + - qemu-kvm + - libvirt-daemon-system + - libvirt-clients + - bridge-utils + - virt-manager + - libguestfs-tools + - qemu-utils + - virt-top + - libosinfo-bin + - cloud-image-utils + - ovmf + - genisoimage + - spice-vdagent + - spice-client-gtk + - virt-viewer + - debootstrap + - lvm2 + - parted + - net-tools + - dnsmasq-base + - python3-libvirt + - python3-guestfs + - guestmount + - cpu-checker + - qemu-system-x86 + - qemu-system-arm + - qemu-system-ppc + - qemu-system-mips + - qemu-system-sparc + - qemu-system-aarch64 + - qemu-system-misc + - libvirt-daemon-driver-qemu + - libvirt-daemon-driver-lxc + - virtinst + - virt-v2v + runcmd: + - "systemctl enable --now sshd" + - "systemctl restart sshd" + - "apt-get update" + - "apt-get -y upgrade" + - "lxd init --auto" + - "mkdir -p /home/kc2/.kube" + - "chown -R kc2:kc2 /home/kc2" + - "apt-get update" + - "apt-get -y upgrade" + - "neofetch" + diff --git a/pulumi/src/hostpath_provisioner/deploy.py b/pulumi/src/hostpath_provisioner/deploy.py index 3b27c0d..b148fca 100644 --- a/pulumi/src/hostpath_provisioner/deploy.py +++ b/pulumi/src/hostpath_provisioner/deploy.py @@ -7,22 +7,27 @@ from pulumi_kubernetes.storage.v1 import StorageClass from src.lib.namespace import create_namespace + def deploy( - depends: pulumi.Output[list], - version: str, - ns_name: str, - hostpath: str, - default: bool, - k8s_provider: k8s.Provider, - ): + depends: pulumi.Output[list], + version: str, + ns_name: str, + hostpath: str, + default: bool, + k8s_provider: k8s.Provider, +): # If version is not supplied, fetch the latest stable version if version is None: - tag_url = 'https://github.com/kubevirt/hostpath-provisioner-operator/releases/latest' - tag = requests.get(tag_url, allow_redirects=False).headers.get('location') - version = tag.split('/')[-1] if tag else '0.17.0' - version = version.lstrip('v') - pulumi.log.info(f"Setting helm release version to latest stable: hostpath-provisioner/{version}") + tag_url = ( + "https://github.com/kubevirt/hostpath-provisioner-operator/releases/latest" + ) + tag = requests.get(tag_url, allow_redirects=False).headers.get("location") + version = tag.split("/")[-1] if tag else "0.17.0" + version = version.lstrip("v") + pulumi.log.info( + f"Setting helm release version to latest stable: hostpath-provisioner/{version}" + ) else: pulumi.log.info(f"Using helm release version: hostpath-provisioner/{version}") @@ -33,39 +38,33 @@ def deploy( ns_labels = { "kubevirt.io": "", "kubernetes.io/metadata.name": ns_name, - "pod-security.kubernetes.io/enforce": "privileged" + "pod-security.kubernetes.io/enforce": "privileged", } namespace = create_namespace( - depends, - ns_name, - ns_retain, - ns_protect, - k8s_provider, - ns_labels, - ns_annotations + depends, ns_name, ns_retain, ns_protect, k8s_provider, ns_labels, ns_annotations ) # Function to add namespace to resource if not set def add_namespace(args): obj = args.props - if 'metadata' in obj: - if isinstance(obj['metadata'], ObjectMetaArgs): - if not obj['metadata'].namespace: - obj['metadata'].namespace = ns_name + if "metadata" in obj: + if isinstance(obj["metadata"], ObjectMetaArgs): + if not obj["metadata"].namespace: + obj["metadata"].namespace = ns_name else: - if obj['metadata'] is None: - obj['metadata'] = {} - if not obj['metadata'].get('namespace'): - obj['metadata']['namespace'] = ns_name + if obj["metadata"] is None: + obj["metadata"] = {} + if not obj["metadata"].get("namespace"): + obj["metadata"]["namespace"] = ns_name else: - obj['metadata'] = {'namespace': ns_name} + obj["metadata"] = {"namespace": ns_name} # Return the modified object wrapped in ResourceTransformationResult return pulumi.ResourceTransformationResult(props=obj, opts=args.opts) # Deploy the webhook - url_webhook = f'https://github.com/kubevirt/hostpath-provisioner-operator/releases/download/v{version}/webhook.yaml' + url_webhook = f"https://github.com/kubevirt/hostpath-provisioner-operator/releases/download/v{version}/webhook.yaml" webhook = k8s.yaml.ConfigFile( "hostpath-provisioner-webhook", file=url_webhook, @@ -75,15 +74,13 @@ def add_namespace(args): provider=k8s_provider, transformations=[add_namespace], custom_timeouts=pulumi.CustomTimeouts( - create="1m", - update="1m", - delete="1m" - ) - ) + create="1m", update="1m", delete="1m" + ), + ), ) # Deploy the operator with a namespace transformation - url_operator = f'https://github.com/kubevirt/hostpath-provisioner-operator/releases/download/v{version}/operator.yaml' + url_operator = f"https://github.com/kubevirt/hostpath-provisioner-operator/releases/download/v{version}/operator.yaml" operator = k8s.yaml.ConfigFile( "hostpath-provisioner-operator", file=url_operator, @@ -93,11 +90,9 @@ def add_namespace(args): provider=k8s_provider, transformations=[add_namespace], custom_timeouts=pulumi.CustomTimeouts( - create="8m", - update="8m", - delete="2m" - ) - ) + create="8m", update="8m", delete="2m" + ), + ), ) # Ensure the CRDs are created before the HostPathProvisioner resource @@ -110,11 +105,9 @@ def add_namespace(args): depends_on=depends, provider=k8s_provider, custom_timeouts=pulumi.CustomTimeouts( - create="9m", - update="9m", - delete="2m" - ) - ) + create="9m", update="9m", delete="2m" + ), + ), ) # Create a HostPathProvisioner resource @@ -122,21 +115,11 @@ def add_namespace(args): "hostpath-provisioner-hpp", api_version="hostpathprovisioner.kubevirt.io/v1beta1", kind="HostPathProvisioner", - metadata={ - "name": "hostpath-provisioner-class-ssd", - "namespace": ns_name - }, + metadata={"name": "hostpath-provisioner-class-ssd", "namespace": ns_name}, spec={ "imagePullPolicy": "IfNotPresent", - "storagePools": [{ - "name": "ssd", - "path": hostpath - }], - "workload": { - "nodeSelector": { - "kubernetes.io/os": "linux" - } - } + "storagePools": [{"name": "ssd", "path": hostpath}], + "workload": {"nodeSelector": {"kubernetes.io/os": "linux"}}, }, opts=pulumi.ResourceOptions( parent=operator, @@ -144,11 +127,9 @@ def add_namespace(args): provider=k8s_provider, ignore_changes=["status"], custom_timeouts=pulumi.CustomTimeouts( - create="8m", - update="8m", - delete="2m" - ) - ) + create="8m", update="8m", delete="2m" + ), + ), ) # Define the StorageClass @@ -157,25 +138,25 @@ def add_namespace(args): metadata=ObjectMetaArgs( name="ssd", annotations={ - "storageclass.kubernetes.io/is-default-class": "true" if default else "false" - } + "storageclass.kubernetes.io/is-default-class": ( + "true" if default else "false" + ) + }, ), reclaim_policy="Delete", provisioner="kubevirt.io.hostpath-provisioner", - volume_binding_mode="WaitForFirstConsumer", + volume_binding_mode="Immediate", parameters={ "storagePool": "ssd", }, opts=ResourceOptions( parent=hostpath_provisioner, - #depends_on=hostpath_provisioner, + # depends_on=hostpath_provisioner, provider=k8s_provider, custom_timeouts=pulumi.CustomTimeouts( - create="8m", - update="8m", - delete="2m" - ) - ) + create="8m", update="8m", delete="2m" + ), + ), ) - return version, webhook # operator + return version, webhook # operator diff --git a/pulumi/src/kubevirt/deploy.py b/pulumi/src/kubevirt/deploy.py index fc2f0a3..9379e13 100644 --- a/pulumi/src/kubevirt/deploy.py +++ b/pulumi/src/kubevirt/deploy.py @@ -3,21 +3,39 @@ import tempfile import os import pulumi +from typing import List import pulumi_kubernetes as k8s from pulumi_kubernetes.apiextensions.CustomResource import CustomResource from pulumi_kubernetes.meta.v1 import ObjectMetaArgs from src.lib.namespace import create_namespace + def deploy_kubevirt( - depends, - ns_name: str, - version: str, - use_emulation: bool, - k8s_provider: k8s.Provider, - kubernetes_distribution: str - ): - - # Create namespace + depends: List[pulumi.Resource], + ns_name: str, + version: str, + use_emulation: bool, + k8s_provider: k8s.Provider, + kubernetes_distribution: str, +): + """ + Deploy KubeVirt with Talos-specific configuration and SELinux workaround + + Args: + depends: List of resources this deployment depends on + ns_name: Namespace to deploy KubeVirt into + version: Version of KubeVirt to deploy + use_emulation: Whether to use emulation mode + k8s_provider: Kubernetes provider instance + kubernetes_distribution: Type of k8s distribution (kind, talos) + + Returns: + Tuple containing: + - KubeVirt version deployed + - KubeVirt operator deployment + """ + + # Create namespace with required labels for KubeVirt ns_retain = True ns_protect = False ns_annotations = {} @@ -25,7 +43,7 @@ def deploy_kubevirt( "kubevirt.io": "", "kubernetes.io/metadata.name": ns_name, "openshift.io/cluster-monitoring": "true", - "pod-security.kubernetes.io/enforce": "privileged" + "pod-security.kubernetes.io/enforce": "privileged", } namespace = create_namespace( depends, @@ -34,64 +52,64 @@ def deploy_kubevirt( ns_protect, k8s_provider, custom_labels=ns_labels, - custom_annotations=ns_annotations + custom_annotations=ns_annotations, ) - # Fetch the latest stable version of KubeVirt + # Fetch the latest stable version of KubeVirt if not specified if version is None: - kubevirt_stable_version_url = 'https://storage.googleapis.com/kubevirt-prow/release/kubevirt/kubevirt/stable.txt' + kubevirt_stable_version_url = "https://storage.googleapis.com/kubevirt-prow/release/kubevirt/kubevirt/stable.txt" version = requests.get(kubevirt_stable_version_url).text.strip() version = version.lstrip("v") pulumi.log.info(f"Setting version to latest stable: kubevirt/{version}") else: - # Log the version override pulumi.log.info(f"Using helm release version: kubevirt/{version}") # Download the KubeVirt operator YAML - kubevirt_operator_url = f'https://github.com/kubevirt/kubevirt/releases/download/v{version}/kubevirt-operator.yaml' + kubevirt_operator_url = f"https://github.com/kubevirt/kubevirt/releases/download/v{version}/kubevirt-operator.yaml" response = requests.get(kubevirt_operator_url) kubevirt_yaml = yaml.safe_load_all(response.text) - # Edit the YAML in memory to remove the Namespace and adjust other resources + # Transform YAML to set namespace and remove namespace resource transformed_yaml = [] for resource in kubevirt_yaml: - if resource and resource.get('kind') == 'Namespace': - pulumi.log.debug(f"Transforming Namespace resource: {resource['metadata']['name']}") - continue # Skip adding this namespace to the edited YAML - if resource and 'metadata' in resource: - resource['metadata']['namespace'] = ns_name + if resource and resource.get("kind") == "Namespace": + pulumi.log.debug( + f"Transforming Namespace resource: {resource['metadata']['name']}" + ) + continue + if resource and "metadata" in resource: + resource["metadata"]["namespace"] = ns_name pulumi.log.debug(f"Setting namespace for {resource['kind']} to {ns_name}") transformed_yaml.append(resource) - # Write the edited YAML to a temporary file - with tempfile.NamedTemporaryFile(delete=False, mode='w') as temp_file: + # Write transformed YAML to temp file + with tempfile.NamedTemporaryFile(delete=False, mode="w") as temp_file: yaml.dump_all(transformed_yaml, temp_file) temp_file_path = temp_file.name - #pulumi.log.info(f"Deploying KubeVirt from local file path: {temp_file_path}") - # Ensure the tempfile is closed before passing it to ConfigFile + # Close temp file before passing to ConfigFile temp_file.close() - # Pass the edited YAML directly to ConfigFile + # Deploy KubeVirt operator from modified YAML operator = k8s.yaml.ConfigFile( - 'kubevirt-operator', + "kubevirt-operator", file=temp_file_path, opts=pulumi.ResourceOptions( parent=namespace, depends_on=depends, provider=k8s_provider, - ) + ), ) - # Ensure the temporary file is deleted after Pulumi uses it + # Cleanup temp file after use pulumi.Output.all().apply(lambda _: os.unlink(temp_file_path)) - # Determine useEmulation based on the kubernetes_distribution + # Set emulation mode based on kubernetes distribution use_emulation = True if kubernetes_distribution == "kind" else use_emulation if use_emulation: pulumi.log.info("KVM Emulation configured for KubeVirt in development.") - # Create the KubeVirt custom resource object + # Create the KubeVirt custom resource with configuration kubevirt_custom_resource_spec = { "customizeComponents": {}, "workloadUpdateStrategy": {}, @@ -103,24 +121,33 @@ def deploy_kubevirt( "version": version, "manufacturer": "ContainerCraft", "product": "Kargo", - "family": "CCIO" + "family": "CCIO", }, "developerConfiguration": { "useEmulation": use_emulation, "featureGates": [ "HostDevices", "ExpandDisks", - "AutoResourceLimitsGate" - ] + "AutoResourceLimitsGate", + "NetworkBindingPlugins", + "LiveMigration", + ], + # Log verbosity levels for KubeVirt components + # 1-Error, 2-Warn, 3-Info, 4-Debug, 5-Trace + # 6-TraceAll, 7-DebugAll, 8-InfoAll, 9-WarnAll, 10-ErrorAll + "logVerbosity": { + "virtLauncher": 2, + "virtHandler": 3, + "virtController": 4, + "virtAPI": 5, + "virtOperator": 6, + }, }, - "permittedHostDevices": { - "pciHostDevices": [ - ] - } - } + "permittedHostDevices": {"pciHostDevices": []}, + }, } - # Create the KubeVirt custom resource + # Deploy KubeVirt CR kubevirt = CustomResource( "kubevirt", api_version="kubevirt.io/v1", @@ -133,8 +160,53 @@ def deploy_kubevirt( opts=pulumi.ResourceOptions( provider=k8s_provider, parent=operator, - depends_on=depends - ) + depends_on=depends, + ), + ) + + # Deploy SELinux workaround DaemonSet for Talos + selinux_ds = k8s.apps.v1.DaemonSet( + "disable-selinux", + metadata={ + "name": "disable-selinux", + "namespace": ns_name, + "labels": {"app": "disable-selinux"}, + }, + spec={ + "selector": {"matchLabels": {"app": "disable-selinux"}}, + "template": { + "metadata": {"labels": {"app": "disable-selinux"}}, + "spec": { + "containers": [ + { + "name": "mount", + "image": "docker.io/library/alpine", + "command": [ + "sh", + "-exc", + "test -f /host/sys/fs/selinux/enforce && mount -t tmpfs tmpfs /host/sys/fs/selinux; sleep infinity", + ], + "securityContext": {"privileged": True}, + "volumeMounts": [ + { + "name": "host-root", + "mountPath": "/host", + "mountPropagation": "Bidirectional", + } + ], + } + ], + "volumes": [{"name": "host-root", "hostPath": {"path": "/"}}], + "hostIPC": True, + "hostNetwork": True, + "hostPID": True, + "tolerations": [{"operator": "Exists"}], + }, + }, + }, + opts=pulumi.ResourceOptions( + provider=k8s_provider, parent=namespace, depends_on=[operator] + ), ) return version, operator diff --git a/pulumi/src/multus/deploy.py b/pulumi/src/multus/deploy.py index 014786d..8bbc92c 100644 --- a/pulumi/src/multus/deploy.py +++ b/pulumi/src/multus/deploy.py @@ -1,74 +1,152 @@ import pulumi import pulumi_kubernetes as k8s -def transform_host_path(args): - # Get the object from the arguments - obj = args.props +def transform_resources(obj): + """ + Transform Kubernetes resource objects: + - Update hostPath mounts for netns + - Set standardized resource requests/limits + - Add clean exit for multus-shim copy command + + Args: + obj: The kubernetes resource object to transform + + Returns: + Modified resource object + """ pulumi.log.debug(f"Object keys: {list(obj.keys())}") - # Transform DaemonSet named 'kube-multus-ds' - if obj.get('kind', '') == 'DaemonSet' and obj.get('metadata', {}).get('name', '') == 'kube-multus-ds': - # Ensure spec is present - if 'spec' in obj: - # Transform paths in containers - containers = obj['spec']['template']['spec'].get('containers', []) - for container in containers: - volume_mounts = container.get('volumeMounts', []) - for vm in volume_mounts: - # Normalize path before checking to handle potential trailing slash - current_path = vm.get('mountPath', '').rstrip('/') - if current_path == '/run/netns': - vm['mountPath'] = '/var/run/netns' - - # Transform paths in volumes - volumes = obj['spec']['template']['spec'].get('volumes', []) - for vol in volumes: - if 'hostPath' in vol: - # Normalize path before checking to handle potential trailing slash - current_path = vol['hostPath'].get('path', '').rstrip('/') - if current_path == '/run/netns': - vol['hostPath']['path'] = '/var/run/netns' - - # Return the modified object - return pulumi.ResourceTransformationResult(props=obj, opts=args.opts) - -def deploy_multus( - depends: pulumi.Input[list], - version: str, - bridge_name: str, - k8s_provider: k8s.Provider + if ( + obj.get("kind", "") == "DaemonSet" + and obj.get("metadata", {}).get("name", "") == "kube-multus-ds" ): + if "spec" in obj: + pod_spec = obj["spec"]["template"]["spec"] + + # Transform main container (kube-multus) + for container in pod_spec.get("containers", []): + if container.get("name") == "kube-multus": + if "resources" not in container: + container["resources"] = {} + + # Set standardized resource limits/requests + container["resources"] = { + "requests": {"cpu": "10m", "memory": "60Mi"}, + "limits": {"cpu": "500m", "memory": "3Gi"}, + } + + # Transform init containers + init_containers = pod_spec.get("initContainers", []) + for init_container in init_containers: + # Set resources for install-multus-binary container + if init_container.get("name") == "install-multus-binary": + # Update resource limits/requests + init_container["resources"] = { + "requests": {"cpu": "10m", "memory": "60Mi"}, + "limits": {"cpu": "500m", "memory": "3Gi"}, + } + + # Add clean exit for multus-shim copy command + # Workaround: Adding '| true' ensures clean container exit even if copy fails + # This is temporary until upstream provides more robust shim installation + init_container["command"] = [ + "sh", + "-c", + "cp -f /usr/src/multus-cni/bin/multus-shim /host/opt/cni/bin/multus-shim || true", + ] + + # Set resources for install-cni container + elif init_container.get("name") == "install-cni": + init_container["resources"] = { + "requests": {"cpu": "10m", "memory": "60Mi"}, + "limits": {"cpu": "500m", "memory": "3Gi"}, + } + + # Transform volume paths + volumes = pod_spec.get("volumes", []) + for vol in volumes: + if "hostPath" in vol: + current_path = vol["hostPath"].get("path", "").rstrip("/") + if current_path == "/run/netns": + vol["hostPath"]["path"] = "/var/run/netns" + + return obj + +def deploy_multus(depends, version, bridge_name, k8s_provider): + """ + Deploy Multus CNI with Talos-specific configuration + + Args: + depends: List of resources this deployment depends on + version: Multus CNI version to deploy + bridge_name: Name of bridge interface to configure + k8s_provider: Kubernetes provider instance + + Returns: + Tuple containing: + - Multus version deployed + - Multus deployment resources + """ resource_name = f"k8snetworkplumbingwg-multus-daemonset-thick" manifest_url = f"https://raw.githubusercontent.com/k8snetworkplumbingwg/multus-cni/{version}/deployments/multus-daemonset-thick.yml" + daemonset_patch = { + "apiVersion": "apps/v1", + "kind": "DaemonSet", + "metadata": {"name": "kube-multus-ds", "namespace": "kube-system"}, + "spec": { + "template": { + "spec": { + "initContainers": [ + { + "name": "install-cni", + "image": "ghcr.io/siderolabs/install-cni:v1.9.0", + "command": ["/install-cni.sh"], + "securityContext": {"privileged": True}, + "volumeMounts": [ + { + "name": "cnibin", + "mountPath": "/host/opt/cni/bin", + "mountPropagation": "Bidirectional", + } + ], + } + ] + } + } + }, + } + multus = k8s.yaml.ConfigFile( resource_name, file=manifest_url, + transformations=[transform_resources], opts=pulumi.ResourceOptions( provider=k8s_provider, depends_on=depends, - transformations=[transform_host_path], custom_timeouts=pulumi.CustomTimeouts( - create="8m", - update="8m", - delete="2m" - ) - ) + create="8m", update="8m", delete="2m" + ), + ), + ) + + k8s.apps.v1.DaemonSetPatch( + "multus-daemonset-patch", + metadata={"name": "kube-multus-ds", "namespace": "kube-system"}, + spec=daemonset_patch["spec"], + opts=pulumi.ResourceOptions(depends_on=[multus]), ) - # Pulumi Kubernetes resource for NetworkAttachmentDefinition network_attachment_definition = k8s.apiextensions.CustomResource( "kargo-net-attach-def", api_version="k8s.cni.cncf.io/v1", kind="NetworkAttachmentDefinition", - metadata={ - "name": f"{bridge_name}", - "namespace": "default" - }, + metadata={"name": f"{bridge_name}", "namespace": "default"}, spec={ - "config": pulumi.Output.all(bridge_name, bridge_name).apply(lambda args: f''' + "config": pulumi.Output.all(bridge_name, bridge_name).apply( + lambda args: f""" {{ "cniVersion": "0.3.1", "name": "{bridge_name}", @@ -82,19 +160,20 @@ def deploy_multus( "type": "tuning" }} ] - }}''') + }}""" + ) }, opts=pulumi.ResourceOptions( depends_on=multus, provider=k8s_provider, custom_timeouts=pulumi.CustomTimeouts( - create="5m", - update="5m", - delete="5m" - ) - )) - - # Export the name of the resource - pulumi.export('network_attachment_definition', network_attachment_definition.metadata['name']) + create="5m", update="5m", delete="5m" + ), + ), + ) + + pulumi.export( + "network_attachment_definition", network_attachment_definition.metadata["name"] + ) return "master", multus diff --git a/pulumi/src/prometheus/deploy.py b/pulumi/src/prometheus/deploy.py index c2becac..e594b8f 100644 --- a/pulumi/src/prometheus/deploy.py +++ b/pulumi/src/prometheus/deploy.py @@ -3,13 +3,14 @@ from src.lib.namespace import create_namespace from src.lib.helm_chart_versions import get_latest_helm_chart_version + def deploy_prometheus( - depends: pulumi.Input[list], - ns_name: str, - version: str, - k8s_provider: k8s.Provider, - openunison_enabled: bool - ): + depends: pulumi.Input[list], + ns_name: str, + version: str, + k8s_provider: k8s.Provider, + openunison_enabled: bool, +): # Create the monitoring Namespace ns_retain = True @@ -19,16 +20,10 @@ def deploy_prometheus( "kubevirt.io": "", "kubernetes.io/metadata.name": ns_name, "openshift.io/cluster-monitoring": "true", - "pod-security.kubernetes.io/enforce": "privileged" + "pod-security.kubernetes.io/enforce": "privileged", } namespace = create_namespace( - depends, - ns_name, - ns_retain, - ns_protect, - k8s_provider, - ns_labels, - ns_annotations + depends, ns_name, ns_retain, ns_protect, k8s_provider, ns_labels, ns_annotations ) prometheus_helm_values = {} @@ -39,14 +34,14 @@ def deploy_prometheus( "users": { "allow_sign_up": False, "auto_assign_org": True, - "auto_assign_org_role": "Admin" + "auto_assign_org_role": "Admin", }, "auth.proxy": { "enabled": True, "header_name": "X-WEBAUTH-USER", "auto_sign_up": True, - "headers": "Groups:X-WEBAUTH-GROUPS" - } + "headers": "Groups:X-WEBAUTH-GROUPS", + }, } } } @@ -58,136 +53,107 @@ def deploy_prometheus( if version is None: chart_index_url = f"{chart_url}/{chart_index_path}" version = get_latest_helm_chart_version(chart_index_url, chart_name) - pulumi.log.info(f"Setting helm release version to latest stable: {chart_name}/{version}") + pulumi.log.info( + f"Setting helm release version to latest stable: {chart_name}/{version}" + ) else: pulumi.log.info(f"Using helm release version: {chart_name}/{version}") release = k8s.helm.v3.Release( - 'helm-release-prometheus', + "helm-release-prometheus", k8s.helm.v3.ReleaseArgs( chart=chart_name, version=version, values=prometheus_helm_values, - namespace='monitoring', + namespace="monitoring", skip_await=False, - repository_opts= k8s.helm.v3.RepositoryOptsArgs( - repo=chart_url - ), + repository_opts=k8s.helm.v3.RepositoryOptsArgs(repo=chart_url), ), opts=pulumi.ResourceOptions( - provider = k8s_provider, + provider=k8s_provider, parent=namespace, depends_on=depends, custom_timeouts=pulumi.CustomTimeouts( - create="30m", - update="30m", - delete="30m" - ) - ) + create="30m", update="30m", delete="30m" + ), + ), ) depends.append(release) # create services with predictable names service_grafana = k8s.core.v1.Service( "service-grafana", - metadata=k8s.meta.v1.ObjectMetaArgs( - name="grafana", - namespace=ns_name - ), + metadata=k8s.meta.v1.ObjectMetaArgs(name="grafana", namespace=ns_name), spec={ - "type":"ClusterIP", - "ports":[ - { - "name":"http-web", - "port": 80, - "protocol": "TCP", - "targetPort": 3000 - - } + "type": "ClusterIP", + "ports": [ + {"name": "http-web", "port": 80, "protocol": "TCP", "targetPort": 3000} ], - "selector":{ - "app.kubernetes.io/name":"grafana" - } + "selector": {"app.kubernetes.io/name": "grafana"}, }, opts=pulumi.ResourceOptions( parent=namespace, depends_on=depends, retain_on_delete=False, - provider = k8s_provider, + provider=k8s_provider, custom_timeouts=pulumi.CustomTimeouts( - create="3m", - update="3m", - delete="3m" - ) - ) + create="3m", update="3m", delete="3m" + ), + ), ) service_alertmanager = k8s.core.v1.Service( "service-alertmanager", metadata=k8s.meta.v1.ObjectMetaArgs( - name="alertmanager", - namespace="monitoring" + name="alertmanager", namespace="monitoring" ), spec={ - "type":"ClusterIP", - "ports":[ + "type": "ClusterIP", + "ports": [ { - "name":"http-web", + "name": "http-web", "port": 9093, "protocol": "TCP", - "targetPort": 9093 - + "targetPort": 9093, } ], - "selector":{ - "app.kubernetes.io/name":"alertmanager" - } + "selector": {"app.kubernetes.io/name": "alertmanager"}, }, opts=pulumi.ResourceOptions( parent=namespace, depends_on=depends, - provider = k8s_provider, + provider=k8s_provider, retain_on_delete=False, custom_timeouts=pulumi.CustomTimeouts( - create="3m", - update="3m", - delete="3m" - ) - ) + create="3m", update="3m", delete="3m" + ), + ), ) service_prometheus = k8s.core.v1.Service( "service-prometheus", - metadata=k8s.meta.v1.ObjectMetaArgs( - name="prometheus", - namespace="monitoring" - ), + metadata=k8s.meta.v1.ObjectMetaArgs(name="prometheus", namespace="monitoring"), spec={ - "type":"ClusterIP", - "ports":[ + "type": "ClusterIP", + "ports": [ { - "name":"http-web", + "name": "http-web", "port": 9090, "protocol": "TCP", - "targetPort": 9090 - + "targetPort": 9090, } ], - "selector":{ - "app.kubernetes.io/name":"prometheus" - } + "selector": {"app.kubernetes.io/name": "prometheus"}, }, opts=pulumi.ResourceOptions( parent=namespace, depends_on=depends, - provider = k8s_provider, + provider=k8s_provider, retain_on_delete=False, custom_timeouts=pulumi.CustomTimeouts( - create="3m", - update="3m", - delete="3m" - ) - ) + create="3m", update="3m", delete="3m" + ), + ), ) return version, release diff --git a/pulumi/src/vm/ubuntu.py b/pulumi/src/vm/ubuntu.py index 13db98e..b45f082 100644 --- a/pulumi/src/vm/ubuntu.py +++ b/pulumi/src/vm/ubuntu.py @@ -2,11 +2,8 @@ import pulumi import pulumi_kubernetes as k8s -def deploy_ubuntu_vm( - config_vm, - k8s_provider: k8s.Provider, - depends_on: list = [] - ): + +def deploy_ubuntu_vm(config_vm, k8s_provider: k8s.Provider, depends_on: list = []): # Extract configuration values from config_vm namespace = config_vm.get("namespace", "default") instance_name = config_vm.get("instance_name", "ubuntu") @@ -28,7 +25,7 @@ def deploy_ubuntu_vm( string_data={ "key1": ssh_pub_key, }, - opts=pulumi.ResourceOptions(provider=k8s_provider, depends_on=depends_on) + opts=pulumi.ResourceOptions(provider=k8s_provider, depends_on=depends_on), ) # Define the Service @@ -40,17 +37,19 @@ def deploy_ubuntu_vm( ), spec=k8s.core.v1.ServiceSpecArgs( type="NodePort", - ports=[k8s.core.v1.ServicePortArgs( - node_port=node_port, - port=node_port, - protocol="TCP", - target_port=22, - )], + ports=[ + k8s.core.v1.ServicePortArgs( + node_port=node_port, + port=node_port, + protocol="TCP", + target_port=22, + ) + ], selector={ f"{app_name}.ccio.io/instance": instance_name, }, ), - opts=pulumi.ResourceOptions(provider=k8s_provider, depends_on=depends_on) + opts=pulumi.ResourceOptions(provider=k8s_provider, depends_on=depends_on), ) # Cloud-init user data for VM configuration @@ -116,15 +115,9 @@ def deploy_ubuntu_vm( "cpu": { "model": "host-passthrough", "dedicatedCpuPlacement": False, - "isolateEmulatorThread": False - }, - "memory": {"guest": "4096M"}, - "resources": { - "limits": { - "memory": "4Gi", - "cpu": 2 - } + "isolateEmulatorThread": False, }, + "resources": {"limits": {"memory": "4Gi", "cpu": 2}}, "devices": { "rng": {}, "autoattachPodInterface": False, @@ -132,39 +125,55 @@ def deploy_ubuntu_vm( "autoattachGraphicsDevice": True, "networkInterfaceMultiqueue": False, "disks": [ - {"name": "containerdisk", "bootOrder": 1, "disk": {"bus": "virtio"}}, - {"name": "cloudinitdisk", "disk": {"bus": "virtio"}} + { + "name": "containerdisk", + "bootOrder": 1, + "disk": {"bus": "virtio"}, + }, + {"name": "cloudinitdisk", "disk": {"bus": "virtio"}}, ], "interfaces": [ {"name": "enp1s0", "model": "virtio", "bridge": {}} ], }, - "machine": {"type": "q35"} + "machine": {"type": "q35"}, }, "networks": [{"name": "enp1s0", "pod": {}}], "terminationGracePeriodSeconds": 0, - "accessCredentials": [{ - "sshPublicKey": { - "source": { - "secret": {"secretName": kc2_pubkey_secret.metadata["name"]} - }, - "propagationMethod": { - "qemuGuestAgent": {"users": [ssh_user]} + "accessCredentials": [ + { + "sshPublicKey": { + "source": { + "secret": { + "secretName": kc2_pubkey_secret.metadata["name"] + } + }, + "propagationMethod": { + "qemuGuestAgent": {"users": [ssh_user]} + }, } } - }], + ], "volumes": [ - {"name": "containerdisk", - "containerDisk": {"image": image_name, "imagePullPolicy": "Always"}}, - {"name": "cloudinitdisk", "cloudInitNoCloud": { - "networkData": network_data, - "userData": user_data, - }} - ] - } - } + { + "name": "containerdisk", + "containerDisk": { + "image": image_name, + "imagePullPolicy": "Always", + }, + }, + { + "name": "cloudinitdisk", + "cloudInitNoCloud": { + "networkData": network_data, + "userData": user_data, + }, + }, + ], + }, + }, }, - opts=pulumi.ResourceOptions(provider=k8s_provider, depends_on=depends_on) + opts=pulumi.ResourceOptions(provider=k8s_provider, depends_on=depends_on), ) # Export the Service URL and VM name as outputs diff --git a/pulumi/stacks/Pulumi.optiplexprime.yaml b/pulumi/stacks/Pulumi.optiplexprime.yaml index c234e96..d32dc81 100644 --- a/pulumi/stacks/Pulumi.optiplexprime.yaml +++ b/pulumi/stacks/Pulumi.optiplexprime.yaml @@ -21,9 +21,9 @@ config: replicas: 2 # Worker replicas, set 0 to disable workers vmpool root_disk_size: "64" # Root disk size in GiB kargo:vm: # Ubuntu VM deployment configuration - enabled: false # Disable VM deployment (set to true if needed) + enabled: true # Disable VM deployment (set to true if needed) kargo:cdi: - enabled: false + enabled: true kargo:cert_manager: enabled: true kargo:cilium: @@ -36,14 +36,11 @@ config: kargo:kubernetes_dashboard: enabled: false kargo:kubevirt: - enabled: false + enabled: true + version: 1.5.0-alpha.0 kargo:multus: - enabled: false + enabled: true kargo:prometheus: - enabled: false + enabled: true kargo:kubevirt_manager: enabled: false - kargo:kubevirt-manager: - enabled: false - kargo:cert-manager: - enabled: true