def k8s(name): with Cluster(name): with Cluster('ns: onepanel'): svc_core = Service('core') pd_core = Pod('core-*') dep_core = Deployment('core') dep_core >> pd_core svc_core >> pd_core svc_core_ui = Service('core-ui') pd_core_ui = Pod('core-ui-*') dep_core_ui = Deployment('core-ui') dep_core_ui >> pd_core_ui svc_core_ui >> pd_core_ui with Cluster('ns: istio-system'): ing = Ingress('istio-ingressgateway') # cert = Secret('TLS') with Cluster('ns: my-project'): with Cluster('Workspace'): svc_workspace = Service('jupyterlab') pd_workspace = Pod('jupyterlab-*') pv_workspace = PV('jupyterlab-data-0') sts_workspace = StatefulSet('jupyterlab') sts_workspace >> pd_workspace pd_workspace - pv_workspace svc_workspace >> pd_workspace # with Cluster('ns: cert-manager'): # certmanager = Pod('cert-manager') # certmanager >> cert ing >> [svc_core, svc_core_ui, svc_workspace] node_1 = Node('node-1') node_2 = Node('node-2') node_3 = Node('node-2') pd_core - node_1 pd_core - node_2 pd_core_ui - node_1 pd_core_ui - node_2 pd_workspace - node_3 return node_1, node_2, node_3, ing, pd_core, pv_workspace
graph_attr = {"pad": "0.5"} with Diagram(filename="jitsi_sharding", direction='TB', show=False, outformat='png', graph_attr=graph_attr): with Cluster("Conference 1"): users_1 = [Custom("user", globe_img) for _ in range(3)] with Cluster("Conference 2"): users_2 = [Custom("user", globe_img) for _ in range(2)] with Cluster("Kubernetes Cluster"): ingress = Ingress("jitsi.beyondcloud.com.br") with Cluster("HAProxy"): n_haproxy = 2 haproxy_pods = [Pod(f"haproxy-{i}") for i in range(n_haproxy)] edge_conference_1 = Edge(color="red") edge_conference_2 = Edge(color="green") shard_0 = Custom("shard-0", jitsi_img) shard_1 = Custom("shard-1", jitsi_img) users_1 >> edge_conference_1 >> ingress users_2 >> edge_conference_2 >> ingress for haproxy in haproxy_pods: ingress >> haproxy for i in range(len(users_1)):
from diagrams import Diagram, Cluster from diagrams.k8s.rbac import ClusterRole, ClusterRoleBinding, Group, RoleBinding, Role, ServiceAccount, User from diagrams.k8s.infra import ETCD, Master, Node from diagrams.k8s.podconfig import ConfigMap, Secret from diagrams.k8s.group import Namespace from diagrams.k8s.network import Endpoint, Ingress, NetworkPolicy, Service from diagrams.k8s.others import CRD, PSP from diagrams.k8s.storage import PersistnetVolume, PersistentVolumeClaim, StorageClass, Volume from diagrams.k8s.clusterconfig import HorizontalPodAutoscaler, LimitRange, Quota from diagrams.k8s.controlplane import APIServer, CCM, ControllerManager, KubeProxy, Kubelet, Scheduler from diagrams.k8s.compute import Cronjob, Deployment, DaemonSet, Job, Pod, ReplicaSet, StatefulSet with Diagram("test-diagram", show=False): ingress = Ingress("in-as-mob") with Cluster("as-mob.ambevdevs.com.br"): with Cluster("/nonprod/asmob-empregado(/|$)(.*)"): ingress >> Service("autenticacao") >> Pod("teste") with Cluster("/nonprod/asmob-a(/|$)(.*)"): ingress >> Service("autenticacao") >> Pod("teste")
from __future__ import absolute_import from diagrams import Diagram, Cluster from diagrams.k8s.network import Ingress from diagrams.onprem.client import Client from diagrams.onprem.container import Docker from diagrams.generic.database import SQL NUM_CLIENTS = 3 NUM_SECURE_SERVICES = 2 with Diagram("JWThenticator Direct Validation Example Architecture"): with Cluster("Service Runtime"): ingress = Ingress("ingress") services = [] jwthenticator = Docker("jwthenticator") jwthenticator_db = SQL("jwthenticator-db") with Cluster("Secured Endpoints"): for i in range(NUM_SECURE_SERVICES): services.append(Docker(f"service-{i}")) # General initial flow for i in range(NUM_CLIENTS): Client(f"client-{i}") >> ingress # pylint: disable=expression-not-assigned for i in range(NUM_SECURE_SERVICES): ingress >> services[i] >> jwthenticator
# kubernetes-diagram.py # run the cmd: python3 cyri-lan-archi-diagram.py to generate the png file. from diagrams import Cluster, Diagram from diagrams.generic.network import Switch, Router from diagrams.generic.storage import Storage from diagrams.k8s.compute import Pod from diagrams.k8s.network import Ingress, Service from diagrams.k8s.storage import PV, PVC, StorageClass from diagrams.elastic.elasticsearch import Elasticsearch, Logstash, Kibana from diagrams.oci.connectivity import DNS from diagrams.onprem.compute import Server, Nomad with Diagram("Kubernetes Diagram", show=False): synology = DNS("reverse DNS") with Cluster("RaspberryPi4 + K3S"): ingress = Ingress("cyri.intra") svc = Service("services") pvc = PVC("pv claim") with Cluster("apps"): logstash = Logstash("logstash-oss") elasticsearch = Elasticsearch("elasticsearch") squid = Server("squid") elk = [elasticsearch - logstash - Kibana("kibana")] with Cluster("local-storage"): pv = [StorageClass("storage class") >> PV("persistent volume")] k8s = ingress >> svc k8s >> squid >> pvc << pv k8s >> logstash >> pvc << pv synology << ingress
from diagrams import Cluster, Diagram, Edge from diagrams.k8s.network import Service from diagrams.k8s.compute import Pod from diagrams.onprem.network import Internet from diagrams.onprem.network import Internet from diagrams.k8s.compute import Deploy from diagrams.k8s.network import Ingress from diagrams.k8s.podconfig import Secret from diagrams.k8s.podconfig import ConfigMap with Diagram("kubernetes deployment nodejs postgresql ingress", show=False): with Cluster("Kubernetes Components"): with Cluster("Services"): service_internal_node = Service("Internal Node Service") service_internal_postgres = Service("Internal Postgres Service") with Cluster("Ingress"): ingress = Ingress("Ingress") with Cluster("Pods"): postgresql = Pod("Postgresql") nodejs = Pod("Nodejs") with Cluster("configuration"): deployment = Deploy("Deployment") configmap = ConfigMap("ConfigMap") secret = Secret("Secret") deployment >> secret deployment >> configmap deployment >> Edge(label="defines") >> service_internal_node deployment >> Edge(label="defines") >> service_internal_postgres nodejs >> service_internal_postgres >> postgresql inet = Internet("Internet") inet >> ingress >> service_internal_node >> nodejs
graph_attr=graph_attr): with Cluster("Conference 1"): users_1 = [Custom("user", globe_img) for _ in range(3)] with Cluster("Conference 2"): users_2 = [Custom("user", globe_img) for _ in range(2)] all_users = Custom("all users", globe_img) with Cluster("Namespace 'jitsi'"): n_shards = 2 n_haproxy = 2 haproxy_sts = StatefulSet("haproxy") haproxy_pods = [Pod(f"haproxy-{j}") for j in range(n_haproxy)] haproxy_sts >> haproxy_pods web_service = Service("web") ingress = Ingress("jitsi.messenger.schule") ingress >> Service("haproxy") >> haproxy_pods >> web_service for k in range(n_shards): with Cluster(f"Shard-{k}"): web_pod = Pod(f"shard-{k}-web") prosody_pod = Pod(f"shard-{k}-prosody") jicofo_pod = Pod(f"shard-{k}-jicofo") Deployment(f"shard-{k}-prosody") >> prosody_pod Deployment(f"shard-{k}-jicofo") >> jicofo_pod web_service >> web_pod prosody_service = Service(f"shard-{k}-prosody") prosody_service >> prosody_pod prosody_service << web_pod prosody_service << jicofo_pod
from diagrams.k8s.compute import Pod from diagrams.k8s.network import Ingress from diagrams.generic.blank import Blank graph_attr = { # "splines": "curved" } with Diagram("OCP4 Default Ingress", show=False, direction="LR", graph_attr=graph_attr): dns = DNS("*.apps.dta.my.lab") lbint = LoadBalancing("HAProxy") with Cluster("OpenShift Cluster"): routerext = Ingress("default") with Cluster("Workers"): with Cluster("Projects"): with Cluster("proj-app-01"): workersint = [Pod("myApp")] with Cluster("proj-app-02"): workersext = [Pod("myApp")] dns >> lbint lbint >> routerext routerext >> workersint routerext >> workersext
from diagrams import Diagram from diagrams.k8s.clusterconfig import HPA from diagrams.k8s.compute import Deployment, Pod, ReplicaSet from diagrams.k8s.network import Ingress, Service with Diagram("Exposed Pod with 3 Replicas", show=False): net = Ingress("domain.com") >> Service("svc") net >> [Pod("pod1"), Pod("pod2"), Pod("pod3") ] << ReplicaSet("rs") << Deployment("dp") << HPA("hpa")
graph_attr=graph_attr): with Cluster("Conference 1"): users_1 = [Custom("user", globe_img) for _ in range(3)] with Cluster("Conference 2"): users_2 = [Custom("user", globe_img) for _ in range(2)] all_users = Custom("all users", globe_img) with Cluster("Namespace 'jitsi'"): n_shards = 2 n_haproxy = 2 haproxy_sts = StatefulSet("haproxy") haproxy_pods = [Pod(f"haproxy-{j}") for j in range(n_haproxy)] haproxy_sts >> haproxy_pods web_service = Service("web") ingress = Ingress("jitsi.messenger.lyon") ingress >> Service("haproxy") >> haproxy_pods >> web_service for k in range(n_shards): with Cluster(f"Shard-{k}"): web_pod = Pod(f"shard-{k}-web") prosody_pod = Pod(f"shard-{k}-prosody") jicofo_pod = Pod(f"shard-{k}-jicofo") Deployment(f"shard-{k}-prosody") >> prosody_pod Deployment(f"shard-{k}-jicofo") >> jicofo_pod web_service >> web_pod prosody_service = Service(f"shard-{k}-prosody") prosody_service >> prosody_pod prosody_service << web_pod prosody_service << jicofo_pod
from diagrams import Diagram from diagrams.k8s.clusterconfig import HPA from diagrams.k8s.compute import Deployment, Pod, ReplicaSet from diagrams.k8s.network import Ingress, Service with Diagram("Research", show=False, filename="research"): net = Ingress("research.cashcowpro.com") >> Service("svc") pods = [ Pod("api-1"), Pod("api-2"), Pod("api-3"), Pod("worker-1"), Pod("worker-2"), Pod("worker-3") ] net >> pods << ReplicaSet("rs") << Deployment("dp") << HPA("hpa")
from diagrams import Diagram, Cluster from diagrams.gcp.database import Firestore from diagrams.onprem.network import Envoy from diagrams.onprem.compute import Server from diagrams.oci.network import Internetgateway from diagrams.k8s.compute import Pod from diagrams.k8s.network import Ingress, Service with Diagram("Gran - API System - Design", show=False): igw = Internetgateway("Gateway") with Cluster("Google Cloud Platform"): with Cluster("Google Kubernetes Engine"): net = Ingress("calmato.work") pods = [ Pod("user service"), Pod("group service"), Pod("todo service") ] net >> Service("svc") >> Envoy("lb") >> pods with Cluster("Firebase"): auth = Server("firebase authentication") firestore = Firestore("firestore") pods >> auth pods >> firestore igw >> net
from diagrams.gcp.network import Router, LoadBalancing, DNS from diagrams.k8s.compute import Pod from diagrams.k8s.network import Ingress from diagrams.generic.blank import Blank graph_attr = { "splines": "curved" } with Diagram("OCP4 Route Sharding ", show=False, direction="LR", graph_attr=graph_attr): dnsint = DNS("*.apps.dta.my.lab") dnsext = DNS("*.apps.uat.my.lab") lbint = LoadBalancing("HAProxy") with Cluster("OpenShift Cluster"): routerext = Ingress("router-default") routerint = Ingress("router-external") with Cluster("Workers"): with Cluster("Projects"): with Cluster("proj-ext-app-01"): workersint = [Pod("myApp")] with Cluster("proj-int-app-01"): workersext = [Pod("myApp")] dnsint >> lbint dnsext >> lbint lbint >> routerint >> workersint lbint >> routerext >> workersext
tektonIconURL = "https://cd.foundation/wp-content/uploads/sites/78/2020/04/tekton-icon-color-1.png" tektonIcon = "tekton.png" urlretrieve(tektonIconURL, tektonIcon) with Cluster("Remote Git"): github = Github("github") gitlab = Gitlab("gitlab") gits = [ github, gitlab] with Cluster("K8s cluster"): ic = CRD("IntegrationConfig") ij = CRD("IntegrationJob") ing = Ingress() with Cluster("CI/CD Operator"): webhookServer = Pod("Webhook server") github - Edge(label="PullRequest/Push/Tag") >> ing >> webhookServer webhookServer - Edge(label="Queued") >> ij pr = Custom("PipelineRun", tektonIcon) ij - Edge(label="Scheduled") >> pr tr1 = Custom("TaskRun-1", tektonIcon) tr2 = Custom("TaskRun-2", tektonIcon) tr3 = Custom("TaskRun-3", tektonIcon) pr >> tr3 >> Pod()
graph_attr=graph_attr): with Cluster("Conference 1"): users_1 = [Custom("user", globe_img) for _ in range(3)] with Cluster("Conference 2"): users_2 = [Custom("user", globe_img) for _ in range(2)] all_users = Custom("all users", globe_img) with Cluster("Namespace 'jitsi'"): n_shards = 1 n_haproxy = 2 haproxy_sts = StatefulSet("haproxy") haproxy_pods = [Pod(f"haproxy-{j}") for j in range(n_haproxy)] haproxy_sts >> haproxy_pods web_service = Service("web") ingress = Ingress("edulane.info") ingress >> Service("haproxy") >> haproxy_pods >> web_service for k in range(n_shards): with Cluster(f"Shard-{k}"): web_pod = Pod(f"shard-{k}-web") prosody_pod = Pod(f"shard-{k}-prosody") jicofo_pod = Pod(f"shard-{k}-jicofo") Deployment(f"shard-{k}-prosody") >> prosody_pod Deployment(f"shard-{k}-jicofo") >> jicofo_pod web_service >> web_pod prosody_service = Service(f"shard-{k}-prosody") prosody_service >> prosody_pod prosody_service << web_pod prosody_service << jicofo_pod
graph_attr = {"pad": "0.5"} with Diagram(filename="jitsi_sharding", direction='TB', show=False, outformat='png', graph_attr=graph_attr): with Cluster("Conference 1"): users_1 = [Custom("user", globe_img) for _ in range(3)] with Cluster("Conference 2"): users_2 = [Custom("user", globe_img) for _ in range(2)] with Cluster("Kubernetes Cluster"): ingress = Ingress("edurusma.adalet.gov.tr") with Cluster("HAProxy"): n_haproxy = 2 haproxy_pods = [Pod(f"haproxy-{i}") for i in range(n_haproxy)] edge_conference_1 = Edge(color="red") edge_conference_2 = Edge(color="green") shard_0 = Custom("shard-0", jitsi_img) shard_1 = Custom("shard-1", jitsi_img) users_1 >> edge_conference_1 >> ingress users_2 >> edge_conference_2 >> ingress for haproxy in haproxy_pods: ingress >> haproxy for i in range(len(users_1)):
def main(): parser = argparse.ArgumentParser(description='Create Kubernetes diagrams') parser.add_argument('-n', required=True, type=str, action='store', dest='namespace', help='Kubernetes namespace to get objects from') args = parser.parse_args() command = "kubectl -n " + args.namespace + " get ingress -o json" commandOutput = subprocess.run(command.split(), stdout=subprocess.PIPE) commandJson = commandOutput.stdout.decode('utf-8') ingressList = json.loads(commandJson) if len(ingressList["items"]) == 0: print("No ingress found. Aboring.") sys.exit() diagramMap = {} diagramMap["ingress"] = [] for ingress in ingressList["items"]: ingressMap = {} ingressMap["name"] = ingress["metadata"]["name"] ingressMap["items"] = [] for rule in ingress["spec"]["rules"]: hostMap = {} hostMap["name"] = rule["host"] hostMap["items"] = [] for path in rule["http"]["paths"]: pathMap = {} pathMap["name"] = path["path"] srvName = path["backend"]["serviceName"] pathMap["serviceName"] = srvName pathMap["items"] = [] command = "kubectl -n " + args.namespace + " get service " + srvName + " -o json" print("Running: " + command) commandOutput = subprocess.run(command.split(), stdout=subprocess.PIPE) commandJson = commandOutput.stdout.decode('utf-8') srvObj = json.loads(commandJson) #kubectl get pods -l environment=production,tier=frontend filter = "" for selector in srvObj["spec"]["selector"]: if filter != "": filter = "," + filter filter = selector + "=" + srvObj["spec"]["selector"][ selector] command = "kubectl -n " + args.namespace + " get pods -l " + filter + " -o json" print("Running: " + command) commandOutput = subprocess.run(command.split(), stdout=subprocess.PIPE) commandJson = commandOutput.stdout.decode('utf-8') podsList = json.loads(commandJson) for pod in podsList["items"]: podMap = {} podMap["name"] = pod["metadata"]["name"] pathMap["items"].append(podMap) hostMap["items"].append(pathMap) ingressMap["items"].append(hostMap) diagramMap["ingress"].append(ingressMap) for ingress in diagramMap["ingress"]: print(ingress["name"]) with Diagram("auto_" + ingress["name"], show=False): dIngress = Ingress(ingress["name"]) for host in ingress["items"]: print(host["name"]) with Cluster(host["name"]): for path in host["items"]: print(path["name"]) print(path["serviceName"]) with Cluster(path["name"]): dSrv = Service(path["serviceName"]) for pod in path["items"]: dSrv >> Pod(pod["name"]) dIngress >> dSrv sys.exit()
with Cluster("Private network"): private_subnets = [ PrivateSubnet("Subnet zone a"), PrivateSubnet("Subnet zone b"), PrivateSubnet("Subnet zone c"), PrivateSubnet("Subnet zone d"), ] with Cluster("Kubernetes cluster"): autoscaling_group = AutoScaling("Autoscaling group") autoscaling_group_instances = [ EC2("K8s worker zone a"), EC2("K8s worker zone b"), EC2("K8s worker zone c"), EC2("K8s worker zone d"), ] ingress = Ingress("Ingress gateway") services = Service("Services") pods = Pod("Container pods") ci_pipeline = GitlabCI("CI pipeline") terraform_repo = Terraform("Infra as code") remote_state = S3("Remote state") ssl_certificate - dns_name dns_name - load_balancer load_balancer - public_subnets public_subnets - nat_gateway nat_gateway - private_subnets private_subnets - autoscaling_group autoscaling_group - autoscaling_group_instances autoscaling_group_instances - ingress
from diagrams import Diagram, Cluster from diagrams.k8s.clusterconfig import HPA from diagrams.k8s.compute import Deployment, Pod, ReplicaSet from diagrams.k8s.network import Ingress, Service with Diagram("Exposed Pod with 4 Replicas", show=True): net = Ingress("releasemanagement.org") with Cluster("Kube Cluster"): net >> Service("svc") >> [Pod("pod1"), Pod("pod2"), Pod("pod3"), Pod("Pod4")] << ReplicaSet("rs") << Deployment("dp") << HPA("hpa") ›
# kubeflow architecture diagram from diagrams import Cluster, Diagram, Edge from diagrams.onprem.client import Users from diagrams.k8s.network import Ingress, Service with Diagram("Kubeflow Networking Architecture", show=False): user = Users("Users") with Cluster("API gateway"): ingress_gateway = Ingress("Ingress") user >> Edge(color="darkgreen") >> ingress_gateway ingress_gateway >> [ Service("Central Dashboard Virtual Service"), Service("Notebooks App Virtual Service") ]
#(png, jpg, svg, and pdf) are allowed. with Diagram(name="OCP3_Ingress_Egress", show=False, outformat="png"): #metrics = Prometheus("metric") #metrics << Edge(color="firebrick", style="dashed") << Grafana("monitoring") #helm = Helm("deploy1") #deploy1 = Deploy("deploy1") serverExtA = Server("DB Server") #serverExtB = Server("DB Server") with Cluster("Ingress Router ZONE A"): haproxy_ingressA = Ingress("app1.example.com") #with Cluster("Ingress Router ZONE B"): # haproxy_ingressB = Ingress("haroxy") with Cluster("Egress Router Namespace A"): haproxy_egressA = Ingress("haproxy") #with Cluster("Egress Router Namespace B"): # haproxy_egressB= Ingress("haproxy") with Cluster("Namespace A"): #POD1 = Pod("frontend") PODF = [Pod("frontend"), Pod("frontend"), Pod("frontend")] PODB = [Pod("backend"), Pod("backend"), Pod("backend")] haproxy_ingressA >> Edge(color="brown") >> Service(
with Diagram("Setup a blog on k3s", show=False, graph_attr=graph_attr, node_attr=node_attr, direction="TB"): users = Users("Users") with Cluster("LetsEncrypt API Servers", graph_attr=graph_attr): letsencrypt = LetsEncrypt("LE SSL Certificate") with Cluster("BareMetal Server", graph_attr=graph_attr): with Cluster("K8S Cluster", graph_attr=graph_attr): with Cluster("NS Cert-Manager", graph_attr=graph_attr): certificate_request = CertManager("mywebsite.com") with Cluster("NS www", graph_attr=graph_attr): website_secret = Secret("mywebsite.com") with Cluster("Ingress", graph_attr=graph_attr): ingress = Ingress("https") with Cluster("Pods", graph_attr=graph_attr): pod = Pod('website') with Cluster("Deployment", graph_attr=graph_attr): pod_deploy = Deployment("website") with Cluster("RS", graph_attr=graph_attr): pod_rs = RS("website") letsencrypt >> website_secret >> ingress certificate_request >> letsencrypt users >> ingress >> pod pod_rs >> pod pod_deploy >> pod
from diagrams import Diagram from diagrams.k8s.compute import DaemonSet, Deployment, Pod, ReplicaSet from diagrams.k8s.network import Ingress, Service from diagrams.k8s.podconfig import ConfigMap from diagrams.k8s.group import Namespace with Diagram("JupyterHub Kubernetes Architecture", show=False): nublado_ns = Namespace("nublado") pp_net = Ingress("/pp") nb_net = Ingress("/nb") pp_svc = Service("Prepuller") pp_deploy = Deployment("Prepuller") pp_pod = Pod("Prepuller") pp_ds = DaemonSet("Single image puller") hub_config = ConfigMap("Hub Config YAML") hub_svc = Service("JupyterHub") hub_deploy = Deployment("JupyterHub") hub_pod = Pod("JupyterHub") proxy_svc = Service("JupyterHubProxy") proxy_deploy = Deployment("JupyterHubProxy") proxy_pod = Pod("JupyterHubProxy") user_ns = Namespace("nublado-lsptestuser01") user_lab_pod = Pod("JupyterLab pod") user_config = ConfigMap("Lab Config YAML + Token") nublado_ns >> nb_net >> proxy_svc >> proxy_deploy >> proxy_pod >> hub_svc
fe = Pod("trow-frontend") fe >> be1 with Cluster("Node 2"): be2 = Pod("trow-backend-2") with Cluster("Node 3"): be3 = Pod("trow-backend-3") with Cluster("Node 4"): be4 = Pod("trow-backend-4") with Cluster("Node 5"): be5 = Pod("trow-backend-5") be1 - be2 be1 - be3 be1 - be4 be1 - be5 be2 - be3 be2 - be4 be2 - be5 be3 - be4 be3 - be5 be4 - be5 ing = Ingress("trow.io") svc = Service("trow-svc") ing >> svc svc >> fe
"""Notional system architecture.""" from diagrams import Cluster, Diagram from diagrams.gcp.network import FirewallRules, LoadBalancing from diagrams.k8s.compute import Deployment, Pod, ReplicaSet, StatefulSet from diagrams.k8s.podconfig import Secret from diagrams.k8s.network import Ingress, Service from diagrams.k8s.storage import PersistentVolume, PersistentVolumeClaim, StorageClass from diagrams.onprem.client import Client with Diagram("TRM Exercise Detail", show=False): with Cluster("GCP"): # Resources app_lb_ext = LoadBalancing("App LB (HTTP/external)") app_lb_int = LoadBalancing("App LB (TCP/internal)") app_ingress_ext = Ingress("App Ingress (external)") app_fw = FirewallRules("Firewall") with Cluster("GKE"): with Cluster("App Namespace"): # Resources app_dep = Deployment("App Deployment") app_rs = ReplicaSet("App ReplicaSet") app_replica_set_count = 3 app_pods = [ Pod("App Pod") for pod in range(0, app_replica_set_count, 1) ] app_secret = Secret( "App Secret\n(contains DB credentials & host)") app_svc_ext = Service("App Service (external)")