add simple diagrams from the cluster and overall network architecture [ci skip]
This commit is contained in:
parent
9749bb8dde
commit
8225bd2294
4 changed files with 251 additions and 0 deletions
BIN
diagram/home_infra.png
Normal file
BIN
diagram/home_infra.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 MiB |
BIN
diagram/kubernetes_network.png
Normal file
BIN
diagram/kubernetes_network.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 MiB |
211
diagram/main.py
Normal file
211
diagram/main.py
Normal file
|
|
@ -0,0 +1,211 @@
|
|||
from unicodedata import name
|
||||
from diagrams import Diagram, Cluster, Edge, Node
|
||||
from diagrams.generic.compute import Rack
|
||||
from diagrams.aws.compute import EC2
|
||||
from diagrams.aws.database import RDS
|
||||
from diagrams.k8s.network import Service, Ingress
|
||||
from diagrams.k8s.compute import Pod
|
||||
from diagrams.aws.network import ELB
|
||||
from diagrams.onprem.network import Nginx, Pfsense
|
||||
from diagrams.generic.network import Firewall, Router, Switch, VPN
|
||||
from diagrams.generic.storage import Storage
|
||||
from diagrams.generic.os import Windows, Raspbian, IOS
|
||||
from diagrams.generic.device import Mobile
|
||||
from diagrams.onprem.client import Client, Users
|
||||
from diagrams.aws.iot import IotCamera, IotAnalyticsChannel
|
||||
from kubernetes import client, config
|
||||
|
||||
vpn_clients: dict[str, Node] = {}
|
||||
# namespaces_to_visualize = {
|
||||
# "website", "vaultwarden", "uptime", "technitium", "reverse-proxy",
|
||||
# "oauth2", "monitoring", "mailserver", "kms", "immich", "headscale",
|
||||
# "frigate", "f1-stream", "excalidraw", "dashy", "calibre", "audiobookshelf"
|
||||
# }
|
||||
namespaces_to_not_visualize = {
|
||||
"ytdlp", "wireguard", "webhook-handler", "url", "travel-blog", "registry",
|
||||
"redis", "openid-help-page", "localai", "kubernetes-dashboard",
|
||||
"headscale", "hackmd", "finance-app", "drone", "dbaas", "crowdsec",
|
||||
"cloudflared", "city-guesser"
|
||||
}
|
||||
|
||||
|
||||
def border_router(
|
||||
name: str,
|
||||
include_vpn_client: bool = False,
|
||||
) -> tuple[Firewall, Router]:
|
||||
with Cluster(name):
|
||||
tp_link_fw = Firewall()
|
||||
tp_link_router = Router()
|
||||
tp_link_fw >> tp_link_router
|
||||
if include_vpn_client:
|
||||
vpn_client = VPN(f"{name} Tailscale Client")
|
||||
vpn_clients[name] = vpn_client
|
||||
return tp_link_fw, tp_link_router
|
||||
|
||||
|
||||
def sofia():
|
||||
with Cluster("Sofia"):
|
||||
_, tp_link_router = border_router("Border Router")
|
||||
ext_switch = Switch('Extension Switch')
|
||||
tp_link_router >> ext_switch
|
||||
with Cluster('R730'):
|
||||
with Cluster("Pfsense"):
|
||||
pfsense = Pfsense('Firewall')
|
||||
vpn_client = VPN("Pfsense Tailscale Client")
|
||||
vpn_clients["pfsense"] = vpn_client
|
||||
|
||||
with Cluster('Kubernetes Network'):
|
||||
k8s_switch = Switch()
|
||||
|
||||
config.load_kube_config()
|
||||
v1 = client.CoreV1Api()
|
||||
network_api = client.NetworkingV1Api()
|
||||
for namespace in v1.list_namespace(watch=False).items:
|
||||
namespace_name = namespace.metadata.name
|
||||
# if namespace_name not in namespaces_to_visualize:
|
||||
# continue
|
||||
if namespace_name in namespaces_to_not_visualize:
|
||||
continue
|
||||
with Cluster(namespace_name):
|
||||
for ingress in network_api.list_namespaced_ingress(
|
||||
namespace_name).items:
|
||||
# for k8s_svc in v1.list_namespaced_service(
|
||||
# namespace_name).items:
|
||||
ingress = Ingress(ingress.spec.rules[0].host)
|
||||
# service = Service(k8s_svc.metadata.name)
|
||||
# k8s_switch >> service
|
||||
k8s_switch >> ingress
|
||||
|
||||
pfsense >> k8s_switch
|
||||
with Cluster('Management Network'):
|
||||
mgt_switch = Switch()
|
||||
# Truenas
|
||||
truenas = Storage("Truenas")
|
||||
# pxe server
|
||||
pxe_server = Rack("PXE Server")
|
||||
# HA
|
||||
home_assistant = Rack("Home Assistant")
|
||||
with Cluster("Devvm"):
|
||||
devvm = Rack("Devvm")
|
||||
devvm_vpn_client = VPN("Tailscale Client")
|
||||
vpn_clients["devvm"] = devvm_vpn_client
|
||||
|
||||
mgt_switch >> truenas
|
||||
mgt_switch >> pxe_server
|
||||
mgt_switch >> home_assistant
|
||||
mgt_switch >> devvm
|
||||
|
||||
pfsense >> mgt_switch
|
||||
|
||||
windows10 = Windows("Windows 10 Server")
|
||||
tp_link_router >> windows10
|
||||
|
||||
ext_switch >> pfsense
|
||||
|
||||
nas = Storage('Synology NAS')
|
||||
tp_link_router >> nas
|
||||
|
||||
|
||||
def london():
|
||||
with Cluster("London"):
|
||||
_, openwrt = border_router("London OpenWRT", include_vpn_client=True)
|
||||
rpi = Raspbian()
|
||||
# client = Mobile()
|
||||
# ios_client = IOS()
|
||||
ip_cam = IotCamera("IP Camera")
|
||||
users = Users()
|
||||
|
||||
openwrt >> rpi
|
||||
# openwrt >> client
|
||||
# openwrt >> ios_client
|
||||
openwrt >> users
|
||||
rpi >> Edge() << ip_cam
|
||||
|
||||
|
||||
def valchedrym():
|
||||
with Cluster("Valchedrym"):
|
||||
_, openwrt = border_router("Valchedrym OpenWRT",
|
||||
include_vpn_client=True)
|
||||
|
||||
users = Users()
|
||||
ip_cam = IotCamera("Surveillance System")
|
||||
alarm_system = IotAnalyticsChannel("Alarm System")
|
||||
|
||||
openwrt >> users
|
||||
openwrt >> ip_cam
|
||||
openwrt >> alarm_system
|
||||
|
||||
|
||||
def mladost3():
|
||||
with Cluster("Mladost 3"):
|
||||
_, tp_link = border_router("Mladost 3 Router ")
|
||||
laptop = Windows()
|
||||
tp_link >> laptop
|
||||
|
||||
|
||||
def outer_infra():
|
||||
with Diagram("Home Infra", show=False, outformat="png", direction="LR"):
|
||||
sofia()
|
||||
london()
|
||||
valchedrym()
|
||||
mladost3()
|
||||
with Cluster("Mobile VPN Clients"):
|
||||
mobile_vpn_clients = VPN()
|
||||
vpn_clients["mobile vpn users"] = mobile_vpn_clients
|
||||
mobile_vpn_users = Users("headscale.viktorbarzin.me/manager")
|
||||
mobile_vpn_clients >> mobile_vpn_users
|
||||
# link all vpn clients
|
||||
existing_links = set()
|
||||
for vpn_client in vpn_clients.values():
|
||||
for other_vpn_client in vpn_clients.values():
|
||||
if other_vpn_client == vpn_client:
|
||||
continue
|
||||
key = vpn_client.label + other_vpn_client.label
|
||||
reverse_key = other_vpn_client.label + vpn_client.label
|
||||
if key in existing_links or reverse_key in existing_links:
|
||||
continue
|
||||
vpn_client >> Edge(color="darkgreen") << other_vpn_client
|
||||
existing_links.add(key)
|
||||
|
||||
|
||||
def k8s_network():
|
||||
with Diagram("Kubernetes Network",
|
||||
show=False,
|
||||
outformat="png",
|
||||
direction="LR"):
|
||||
with Cluster("Kubernetes Network"):
|
||||
k8s_switch = Switch()
|
||||
config.load_kube_config()
|
||||
v1 = client.CoreV1Api()
|
||||
network_api = client.NetworkingV1Api()
|
||||
for namespace in v1.list_namespace(watch=False).items:
|
||||
namespace_name = namespace.metadata.name
|
||||
# if namespace_name not in namespaces_to_visualize:
|
||||
# continue
|
||||
if namespace_name in namespaces_to_not_visualize or namespace_name == "monitoring":
|
||||
continue
|
||||
with Cluster(namespace_name):
|
||||
for ingress in network_api.list_namespaced_ingress(
|
||||
namespace_name).items:
|
||||
ing = Ingress(ingress.spec.rules[0].host)
|
||||
rule = ingress.spec.rules[0]
|
||||
# for rule in ingress.spec.rules:
|
||||
path = rule.http.paths[0]
|
||||
# for path in rule.http.paths:
|
||||
k8s_svc = path.backend.service
|
||||
svc = Service(f"{k8s_svc.name}:{k8s_svc.port.number}")
|
||||
ing >> svc
|
||||
pods = v1.list_namespaced_pod(namespace_name)
|
||||
for k8s_pod in pods.items:
|
||||
if k8s_pod.status.phase != "Running":
|
||||
continue
|
||||
pod = Pod(k8s_pod.metadata.name)
|
||||
svc >> pod
|
||||
# service = Service(k8s_svc.metadata.name)
|
||||
# k8s_switch >> service
|
||||
k8s_switch >> ing
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
outer_infra()
|
||||
k8s_network()
|
||||
40
diagram/requirements.txt
Normal file
40
diagram/requirements.txt
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
asttokens==2.4.1
|
||||
cachetools==5.3.2
|
||||
certifi==2023.11.17
|
||||
charset-normalizer==3.3.2
|
||||
decorator==5.1.1
|
||||
diagrams==0.23.4
|
||||
exceptiongroup==1.2.0
|
||||
executing==2.0.1
|
||||
google-auth==2.26.1
|
||||
graphviz==0.20.1
|
||||
idna==3.6
|
||||
ipdb==0.13.13
|
||||
ipython==8.19.0
|
||||
jedi==0.19.1
|
||||
Jinja2==3.1.2
|
||||
kubernetes==28.1.0
|
||||
MarkupSafe==2.1.3
|
||||
matplotlib-inline==0.1.6
|
||||
oauthlib==3.2.2
|
||||
parso==0.8.3
|
||||
pexpect==4.9.0
|
||||
prompt-toolkit==3.0.43
|
||||
ptyprocess==0.7.0
|
||||
pure-eval==0.2.2
|
||||
pyasn1==0.5.1
|
||||
pyasn1-modules==0.3.0
|
||||
Pygments==2.17.2
|
||||
python-dateutil==2.8.2
|
||||
PyYAML==6.0.1
|
||||
requests==2.31.0
|
||||
requests-oauthlib==1.3.1
|
||||
rsa==4.9
|
||||
six==1.16.0
|
||||
stack-data==0.6.3
|
||||
tomli==2.0.1
|
||||
traitlets==5.14.1
|
||||
typed-ast==1.5.5
|
||||
urllib3==1.26.18
|
||||
wcwidth==0.2.13
|
||||
websocket-client==1.7.0
|
||||
Loading…
Add table
Add a link
Reference in a new issue