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:
- PostgreSQL
In 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-dist
If 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-dist
networks:
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
🚧
🚧