In this tutorial, we will create a simple web service architecture documents.
To install ndiag command, please check the "Install" section.
STEP1: Represent the roles of the instance and the middlewares/apps on the instance using "Node" and "Component"
📌 Keyword: Node, Component, Node component
First, Create a YAML document as ndiag.yml like the following
---
name: Simple web service
docPath: docs/arch
nodes:
-
name: lb
components:
- NGINX
-
name: app
components:
- NGINX
- App
-
name: db
components:
- PostgreSQL Full version of ndiag.yml is here (click).
---
name: Simple web service
docPath: docs/arch
nodes:
-
name: lb
components:
- NGINX
-
name: app
components:
- NGINX
- App
-
name: db
components:
- PostgreSQLIn this ndiag.yml, the roles of the instances (lb, app, db) is represented by Node and the middlewares and applications on the instances are represented by Component.
Both Node and Component are elements that make up a system (architectural elements).
Then, run ndiag doc command.
$ ndiag doc -c ndiag.yml --rm-distIf the command is successful, two directories should be created as follows.
$ ls
docs ndiag.descriptions ndiag.yml
$ tree docs/
docs/
└── arch
├── README.md
├── node-app.md
├── node-app.svg
├── node-db.md
├── node-db.svg
├── node-lb.md
├── node-lb.svg
├── view-nodes.md
└── view-nodes.svg
1 directory, 9 files
$ tree ndiag.descriptions
ndiag.descriptions
├── _component-app_app.md
├── _component-app_nginx.md
├── _component-db_postgresql.md
├── _component-lb_nginx.md
├── _index.md
├── _node-app.md
├── _node-db.md
├── _node-lb.md
└── _view-nodes.md
0 directories, 9 files| Directory | |
|---|---|
docs/ |
Generated documents |
ndiad.descriptions |
Sub documents to set description of architecture elements ( It will be explained in STEP7 ) |
Open the file docs/arch/README.md. The documentation template is now complete.
A Component that belongs to Node is called Node component.
📌 Keyword: networks:, Global component
Data flow between components (HTTP requests/database access, etc.) is represented by adding networks: to ndiag.yml.
[...]
networks:
-
route:
- "internet"
- "vip"
-
route:
- "vip"
- "lb:nginx"
-
route:
- "lb:nginx"
- "app:nginx"
- "app:app"
[...] Full version of ndiag.yml is here (click).
---
name: Simple web service
docPath: docs/arch
nodes:
-
name: lb
components:
- NGINX
-
name: app
components:
- NGINX
- App
-
name: db
components:
- PostgreSQL
networks:
-
route:
- "internet"
- "vip"
-
route:
- "vip"
- "lb:nginx"
-
route:
- "lb:nginx"
- "app:nginx"
- "app:app"
-
route:
- "app:app"
- "Payment API"
-
route:
- "app:app"
- "db:postgresql"Then, run ndiag doc command as in STEP1.
$ ndiag doc -c ndiag.yml --rm-dist( After STEP2, execute ndiag doc command to generate the document. )
Node component is specified by joining "Node id (= Node name)" and "Component name" with :.
💡 Example: lb:nginx means "Component NGINX" that belongs to "Node lb"
A Component that does not belong to Node (or Cluster) is called "Global component" ( internet, vip, Payment API ). It is specified by only the Component name.
📌 Keyword: relations:
The relations between Components, other than the data flow, are expressed using relations: as shown below.
[...]
relations:
-
components:
- 'lb:Keepalived'
- "vip" Full version of ndiag.yml is here (click).
---
name: Simple web service
docPath: docs/arch
nodes:
-
name: lb
components:
- NGINX
-
name: app
components:
- NGINX
- App
-
name: db
components:
- PostgreSQL
networks:
-
route:
- "internet"
- "vip"
-
route:
- "vip"
- "lb:nginx"
-
route:
- "lb:nginx"
- "app:nginx"
- "app:app"
-
route:
- "app:app"
- "db:postgresql"
-
route:
- "app:app"
- "Payment API"
relations:
-
components:
- 'lb:Keepalived'
- "vip"Then, run ndiag doc command.
$ ndiag doc -c ndiag.yml --rm-distnetworks: is another expression for type: network in relations:. You can use either one.
💡 Example:
| networks: | relations: |
|---|---|
networks:
-
route:
- "internet"
- "vip"
|
relations:
-
type: network
components:
- "internet"
- "vip"
|
📌 Keyword: Cluster, Layer, Cluster component
Represent groups of Nodes and Components using clusters:.
[...]
-
name: db
components:
- PostgreSQL
clusters:
- 'consul:dc1'
networks:
-
route:
- "internet"
- "vip_group:lb:vip"
[...] Full version of ndiag.yml is here (click).
---
name: Simple web service
docPath: docs/arch
nodes:
-
name: lb
components:
- NGINX
clusters:
- 'Consul:dc1'
- 'vip_group:lb'
-
name: app
components:
- NGINX
- App
clusters:
- 'consul:dc1'
-
name: db
components:
- PostgreSQL
clusters:
- 'consul:dc1'
networks:
-
route:
- "internet"
- "vip_group:lb:vip"
-
route:
- "vip_group:lb:vip"
- "lb:nginx"
-
route:
- "lb:nginx"
- "app:nginx"
- "app:app"
-
route:
- "app:app"
- "db:postgresql"
-
route:
- "app:app"
- "Service:Payment:Payment API"
relations:
-
components:
- 'lb:Keepalived'
- "vip_group:lb:vip""Node" can belong to multiple Clusters.
💡 Example:
[...]
nodes:
-
name: instance
components:
- http-server
clusters:
- 'role:web'
- 'location:dc'
- 'os:ubuntu-focal'
[...]In ndiag, Nodes and Components can be grouped by an element called Cluster.
A Node can belong to multiple Clusters.
💡 Example:
[...]
nodes:
-
name: instance
components:
- http-server
clusters:
- 'role:web'
- 'location:dc'
- 'os:ubuntu-focal'
[...]"Cluster" always belongs to a "Layer". "Layer" can have multiple Clusters.
In the figure, Clusters that belong to the same Layer are represented by lines of the same color.
"Cluster" is specified by joining Layer id (= Layer name) and Cluster name with :.
💡 Example: Layer role has a Cluster role:web and a Cluster role:db with the same Layer id role.
Also, a Component that belongs to Cluster instead of Node is called Cluster component.
Cluster component is specified by joining Cluster id and Component name with :.
💡 Example: vip_group:lb:vip means "Component vip" that belongs to "Cluster vip_group:lb"
📌 Keyword: icon
🚧
[...]
-
name: db
components:
- PostgreSQL?icon=db
clusters:
- 'consul:dc1'
networks:
-
route:
- "internet?icon=cloud"
- "vip_group:lb:vip"
[...] Full version of ndiag.yml is here (click).
---
name: Simple web service
docPath: docs/arch
nodes:
-
name: lb
components:
- NGINX?icon=lb-l7
clusters:
- 'Consul:dc1'
- 'vip_group:lb'
-
name: app
components:
- NGINX?icon=proxy
- App?icon=cube4
clusters:
- 'consul:dc1'
-
name: db
components:
- PostgreSQL?icon=db
clusters:
- 'consul:dc1'
networks:
-
route:
- "internet?icon=cloud"
- "vip_group:lb:vip"
-
route:
- "vip_group:lb:vip"
- "lb:nginx"
-
route:
- "lb:nginx"
- "app:nginx"
- "app:app"
-
route:
- "app:app"
- "db:postgresql"
-
route:
- "app:app"
- "Service:Payment:Payment API"
relations:
-
components:
- 'lb:Keepalived?icon=keepalived'
- "vip_group:lb:vip"
customIcons:
-
key: keepalived
lines:
- b1 b5 f9 j5 j1 f1 b1
- d2 d6
- h2 d4
- e4 h6📌 Keyword: views:, Label
🚧
[...]
views:
-
name: overview
layers: ["consul", "vip_group", "service"]
[...] Full version of ndiag.yml is here (click).
---
name: Simple web service
docPath: docs/arch
views:
-
name: overview
layers: ["consul", "vip_group", "service"]
-
name: http access
layers: ["vip_group"]
labels: ["http"]
-
name: app
layers: ["vip_group", "service"]
labels: ["app"]
nodes:
-
name: lb
components:
- NGINX?icon=lb-l7
clusters:
- 'Consul:dc1'
- 'vip_group:lb'
-
name: app
components:
- NGINX?icon=proxy
- App?icon=cube4&label=lang:ruby
clusters:
- 'consul:dc1'
-
name: db
components:
- PostgreSQL?icon=db
clusters:
- 'consul:dc1'
networks:
-
labels:
- http
route:
- "internet?icon=cloud"
- "vip_group:lb:vip"
-
labels:
- http
route:
- "vip_group:lb:vip"
- "lb:nginx"
-
labels:
- http
- app
route:
- "lb:nginx"
- "app:nginx"
- "app:app"
-
labels:
- app
route:
- "app:app"
- "db:postgresql"
-
labels:
- app
route:
- "app:app"
- "Service:Payment:Payment API"
relations:
-
labels:
- http
components:
- 'lb:Keepalived?icon=keepalived'
- "vip_group:lb:vip"
customIcons:
-
key: keepalived
lines:
- b1 b5 f9 j5 j1 f1 b1
- d2 d6
- h2 d4
- e4 h6🚧
🚧