Homework 4
USING NOSQL TOOLS ON CRASHES DATASET
GROUP-5
Anisha Rao
Edward Montoya
Lina Devakumar Louis
Himanshee
Nilisha Makam Prashantha
Contents
- MongoDB
i. Goal
ii.About the Dataset
iii.Innovations
iv.Installation of MongoDB
v.Cluster Creation & Database Setup Cluster
v.Sharding
vi.Visualizations
vii.Aggregation Pipelines to Answer Questions
vii.Building Correlations from Aggregations
2. Neo4j
i.Goal
ii.About the Dataset
iii.Installation of Neo4j
iv.Establishing nodes and relationships
v.Analysis done using Cypher
3. MongoDB vs Neo4j
i.Takeaways
4. Docker
i.Workflow
ii.Installation of Docker desktop
iii.Dockerize Notebook
iv.Dockerize MongoDB
5.Kubernetes
i. Setting up of Kubernetes Cluster
1.MongoDB
MongoDB is a NoSQL document database that stores JSON-like documents in BSON format.It supports rich data structure and geospatial data .
GOAL
The purpose of this project is to upload the “crashdata2011-2020.csv” into MongoDB and perform meaningful analysis on it through aggregation pipelines and finding correlations among the various fields present in it to gain meaningful insights that are relevant to the concerned stakeholders who can then use these insights to prevent future accidents that could arise due to similar conditions existing in this historical dataset. Visualizations for the insights will also be used to provide a better understanding.
ABOUT THE DATASET
This dataset is taken from the sanjoseca.gov website. The dataset comprises all the crashes reported in San Jose from the year 2011-2020. It includes details such as injury types, distance from an intersection, crash date and time, weather conditions, road surface conditions, traffic controls and much more. Click here to view the dataset on the official website.
INNOVATION
We decided to approach our problem from the perspective of using intuitive assumptions, and then we tested our assumptions with the data. This can be highlighted in our granular testing of why there was an influx of crashes for the year 2016. For this we had several assumptions, and tried to use the data to support or disprove our hypothesis.
CLUSTER CREATION & DB SETUP IN CLUSTER
Step1: Create a Cluster
Step 2: Connect to cluster
SHARDING:
Step 1: Select Cluster -> Edit Configuration
Step 2: Select Dedicated as Sharding is possible for only tiers above M30.
Step 3: Select M30 or above tier.
*Since this tier comes with a cost we stopped there.
Step 4: In advanced settings choose Sharding.
*If we had upgraded to M30 cluster we could have turned sharding on for this cluster.
VISUALIZATIONS
The visualizations were done by using MongoDB Charts. We had to first deploy a shared cloud database on Atlas. Once this was done we had to create a cluster, and set the database access, and network access. Once this was done we could connect to the cluster using MongoDB Compass.
Using MongoDB Compass we could connect to the shared cloud on Atlas, and upload our Crashes dataset. Once the dataset is uploaded, then we could open up MongoDB Charts and begin using its features. In Charts, we had to select the datasource for our visualizations.
When the datasource is connected, then we can go back to our dashboard and begin building our dashboard and visualizations. This was done by “add chart,” then mapping to the correct datasource and using our aggregations to perform proper analysis to produce our desired visualizations.
In this menu we were able to build our visualizations, which resulted in 10 visualizations.
(Note: Visualizations are depicted in each aggregation pipeline respectively)
AGGREGATION PIPELINES TO ANSWER QUESTIONS WITH CHARTS FROM MONGO ATLAS
In this section we are trying to answer substantial questions from the dataset that could essentially provide meaningful insights through the usage of aggregation pipelines. We have used PyMongo to do our analysis and connect to MongoDB.
- Does RoadSurface have an effect on the type of injury?
In this aggregation we are calculating the minor injury vs major injury percentage for each RoadSurface category.
Aggregation pipeline and output:
[
{“$group”: {
“_id”: {“RoadwaySurface”: “$RoadwaySurface”},
“sum_minor”: {“$sum” : “$MinorInjuries”},
“sum_major”: {“$sum”: {“$add” : [“$ModerateInjuries”,”$SevereInjuries”,”$FatalInjuries”]}},
“total” : {“$sum”: {“$add” : [“$MinorInjuries”,”$ModerateInjuries”,”$SevereInjuries”,”$FatalInjuries”]}}
}},
{“$project”: {
“RoadwaySurface”: “$RoadwaySurface”,
“Minor_%” : {“$multiply”:[{“$divide”:[“$sum_minor”,”$total”]},100]},
“Major_%” : {“$multiply”:[{“$divide”:[“$sum_major”,”$total”]},100]}
}}]
Conclusion:
- From this output it is observed that “Snowy – Icy” road surface conditions could cause major injuries.
- It is also observed that “Slippery” road surface conditions have a higher chance of major injuries.
- Other road surface conditions seem to have a lower chance of major injuries.
- How has the number of crashes changed over the span of years from 2011 to 2020?
In this aggregation we are calculating the no: of crashes for every year by using substr to extract .
Aggregation pipeline and output:
[
{“$group”: {
“_id”: {“year”: { “$substr”: [ “$CrashDateTime”, {“$add” :
[{ “$indexOfCP”: [ “$CrashDateTime”, “/”,3 ] },1]}, 4 ] }
}
,
“count”: {“$sum” : 1} }},
{“$project”:{
“year”:”$_id.year”,
“count”:”$count”
}},
{ “$sort” : { “year” : 1 } }
]
Conclusion:
- From the bar graph we can observe a significant decrease in crashes over the years.
- There was a spike in 2016, which we can explore more in this project.
- What weather conditions majorly influence the occurrence of crashes?
In this we aggregate the count of crashes at Weather level and sort it from lowest to highest.
Aggregation pipeline and output:
[{“$group”: {
“_id”: {“Weather”: “$Weather”},
“count”: {“$sum” : 1}
}},
{“$project”: {
“Weather”:”$_id.Weather”,”count”:”$count”}
},
{
“$unset”: [“_id”]
},
{ “$sort” : { “count” : 1 } } ]
Conclusion:
- From this analysis we can observe that most crashes happened in normal weather conditions. But also we need to note that the majority of the times we do have normal weather conditions.
- Some percentage of crashes did happen during rain and cloudy weather which should indicate a good impact owing to the prevailing common clear conditions.
- Does the weather conditions have an affect on the type of injuries?
Aggregation Pipeline and Output:
[{ “$group”: {
“_id”: {“Weather”: “$Weather”},
“minor_injuries”: {“$sum”: “$MinorInjuries”},
“major_injuries”: {“$sum”: {“$add”: [“$ModerateInjuries”, “$SevereInjuries”, “$FatalInjuries”]}},
“total_injuries”: {“$sum”: {“$add”: [“$MinorInjuries”, “$ModerateInjuries”, “$SevereInjuries”, “$FatalInjuries”]}}
}},
{“$project”: {
“Weather”: “$Weather”,
“minor%”:{“$multiply”: [{“$divide”: [“$minor_injuries”,”$total_injuries”]},100]},
“major%”:{“$multiply”: [{“$divide”: [“$major_injuries”,”$total_injuries”]},100]}
}}
]
Conclusion:
- From this Output we can analyze that majorly injured accidents are higher in windy conditions.
- And most of the minor accidents occur in snow, rain and foggy conditions.
- We might think the percent of accidents in clear weather might be slightly lesser, but looking at the data we can conclude that there is equal no. of risk of accidents in clear weather as well.
- What is the Peak time for accidents?
Extracting the time from the CrashDateTime column and categorizing them in ranges that belong to “Early Morning”, “Morning”, “Afternoon”, etc using ‘if-else’ in aggregation pipeline and finding no: of crashes.
Aggregation Pipeline and output:
[{“$project”: {
“time_of_day”: {“$toInt”:{“$replaceAll” : { “input” : { “$substr”: [ “$CrashDateTime”, {“$add” :
[{ “$indexOfCP”: [ “$CrashDateTime”, ” “,3 ] },1]}, 2 ] },”find”:’:’,”replacement”:”}}
}
}
},
{“$project”: {
“Daytime”:
{“$cond”: {“if” : { “$and”: [ { “$gte”: [ “$time_of_day”, 3 ] },
{ “$lte”: [ “$time_of_day”, 7 ] } ] },”then”: ‘Early Morning’,
“else”: {“$cond”:{“if” : { “$and”: [ { “$gt”: [ “$time_of_day”, 7 ] },
{ “$lte”: [ “$time_of_day”, 10 ] } ] },”then”: ‘Morning’,
“else”: {“$cond”:{“if” : { “$and”: [ { “$gt”: [ “$time_of_day”, 10 ] },
{ “$lte”: [ “$time_of_day”, 15 ] } ] },”then”: ‘Afternoon’,
“else”:
{“$cond”:{“if” : { “$and”: [ { “$gt”: [ “$time_of_day”, 15 ] },
{ “$lte”: [ “$time_of_day”, 18 ] } ] },”then”: ‘Evening’,
“else”: {“$cond”:{“if” : { “$and”: [ { “$gt”: [ “$time_of_day”, 18 ] },
{ “$lte”: [ “$time_of_day”, 23 ] } ] },”then”: ‘Night’,
“else”: {“$cond”:{“if” : { “$and”: [ { “$gte”: [ “$time_of_day”, 0 ] },
{ “$lte”: [ “$time_of_day”, 0 ] } ] },”then”: ‘Midnight’,
“else”: ‘Late Night’}}}}}}}}}}}}}},
{“$group”: {
“_id”: {“Daytime”: “$Daytime”},
“count”: {“$sum” : 1}
}
},
{“$project”: {
“Daytime”:”$_id.Daytime”,”count”:”$count”}
},
{
“$unset”: [“_id”]
}]
Conclusion:
- From this output we can observe that afternoon hours is a peak time followed by night and evening hours.
- Midnight and late night hours seem to relatively have a much lower case of crashes.
- Does RoadSurface have an effect on the type of injury?
In this aggregation we are calculating the minor injury vs major injury percentage for different PedestrianActions.
Aggregation Pipeline and output:
[ {“$group”: {
“_id”: {“PedestrianAction”: “$PedestrianAction”},
“sum_minor”: {“$sum” : “$MinorInjuries”},
“sum_major”: {“$sum”: {“$add” : [“$ModerateInjuries”,”$SevereInjuries”,”$FatalInjuries”]}},
“total” : {“$sum”: {“$add” : [“$MinorInjuries”,”$ModerateInjuries”,”$SevereInjuries”,”$FatalInjuries”]}}
}},
{“$project”: {
“PedestrianAction”: “$_id.PedestrianAction”,
“Minor_%” : {“$multiply”:[{“$divide”:[“$sum_minor”,”$total”]},100]},
“Major_%” : {“$multiply”:[{“$divide”:[“$sum_major”,”$total”]},100]}
}},
{
“$unset”: [“_id”]
}
]
Conclusion:
- From this output we can observe that Pedestrians who did not cross in the crosswalk had major injuries.
- Crossing in crosswalk not at the intersection has more percentage compared to at the intersection.
- Walking pedestrians have a 50-50 major vs minor injury probability.
- Why did the year – 2016 have a spike in Crash Cases?
In this section we are exploring the data to find any possible conditions that stand out indicating a spike in accident cases. This analysis is carried out within the scope of this dataset only.
- Assumption 1: Unusual Roadway conditions caused more crashes in 2016 as compared to other years.
Leaving out the RoadwayCondition ‘No Unusual Conditions”, a total count was found for each year.
Aggregation Pipeline and output:
[
{“$group”: {
“_id”: {“year”: { “$substr”: [ “$CrashDateTime”, {“$add” :
[{ “$indexOfCP”: [ “$CrashDateTime”, “/”,3 ] },1]}, 4 ] }
}
,
“count”: {“$sum” : {“$cond”:{“if”:{“$eq”: [“$RoadwayCondition” , ‘No Unusual Conditions’]}, “then” : 0,
“else” : 1}}}}},
{“$project”:{
“year”:”$_id.year”,
“count”:”$count”
}},
{ “$sort” : { “year” : 1 } },
{
“$unset”: [“_id”]
}
]
Conclusion: This analysis had a Positive Outcome proving our assumption.
- Assumption 2: Functioning traffic controls were the lowest in 2016 as compared to other years.
Leaving out the other traffic control conditions and finding a total count of “Controls Functioning’ category for each year.
Aggregation Pipeline and output:
[
{“$group”: {
“_id”: {“year”: { “$substr”: [ “$CrashDateTime”, {“$add” :
[{ “$indexOfCP”: [ “$CrashDateTime”, “/”,3 ] },1]}, 4 ] }
}
,
“count”: {“$sum” : {“$cond”:{“if”:{“$eq”: [“$TrafficControl” , ‘Controls Functioning’]}, “then” : 1,
“else” : 0}}}}},
{“$project”:{
“year”:”$_id.year”,
“count”:”$count”
}},
{ “$sort” : { “year” : 1 } },
{
“$unset”: [“_id”]
}
]
Conclusion: This analysis had a Negative Outcome proving our assumption wrong.
- Assumption 3: There were more violations by drivers in 2016 as compared to other years.
Taking “Violation Driver 1” and “Violation Driver 2” categories and finding the sum of crashes for each year.
Aggregation Pipeline and output:
[{“$group”: {
“_id”: {“year”: { “$substr”: [ “$CrashDateTime”, {“$add” :
[{ “$indexOfCP”: [ “$CrashDateTime”, “/”,3 ] },1]}, 4 ] }
}
,
“count”: {“$sum” : {“$cond”:{“if”: {“$or”:[{“$eq”: [“$PrimaryCollisionFactor” , ‘Violation Driver 1’]},
{“$eq”: [“$PrimaryCollisionFactor” , ‘Violation Driver 2’]}]},
“then” : 1,
“else” : 0}}}}},
{“$project”:{
“year”:”$_id.year”,
“count”:”$count”
}},
{ “$sort” : { “count” : 1 } },
{
“$unset”: [“_id”]
}
]
Conclusion: This analysis had a partial Positive Outcome, as 2012 also had a similar total number of crashes, therefore we can agree that our assumption was correct to an extent.
- Assumption 4: There were more pedestrians involved in crashes in 2016 as compared to other years.
Aggregation Pipeline and output:
[
{“$group”: {
“_id”: {“year”: { “$substr”: [ “$CrashDateTime”, {“$add” :
[{ “$indexOfCP”: [ “$CrashDateTime”, “/”,3 ] },1]}, 4 ] }
}
,
“count”: {“$sum” : {“$cond”:{“if”:{“$eq”: [“$PedestrianAction” , ‘No Pedestrians Involved’]}, “then” : 0,
“else” : 1}}}}},
{“$project”:{
“year”:”$_id.year”,
“count”:”$count”
}},
{ “$sort” : { “year” : 1 } },
{
“$unset”: [“_id”]
}
]
Conclusion: This analysis had a Negative Outcome proving our assumption wrong.
BUILDING CORRELATIONS FROM AGGREGATIONS
Checking for correlation between no: of vehicles involved in a crash and the distance from the intersection to find if more vehicles are involved if the proximity of an intersection is near.
Conclusion: We can see from the output that the correlation coefficient is almost near to 0 but there is a slight negative inclination which tells us that the vehicle count and the distance are negatively correlated. Thus, we conclude that when distance from an intersection increases, there is a lesser probability of vehicles to be involved in the accidents.
2. Checking for correlation between no. of injuries and the Lighting conditions to find if the minor injured accidents are anywhere related to the light in the day.
Conclusion:
In the above code, The lighting number column signifies the amount of Light on the street during the incident. We have quantified the Lighting column with respect to its intensity of brightness starting from the brightest time of the day with 5 and gradually decreasing to 0.
The output here gives you the result that there is a very slight correlation between The lighting of the day and the minor injuries. But since the coefficient is positive ,we can conclude that the lighting in a day is positively correlated with the amount of minor injuries that occurred.
3. Trends which relate the hour of the day with total no. of injuries to find out the frequency of the no. of injuries .
Conclusion:
In the above analysis, The crashdatehour is derived from crashdatetime. Here we can observe that at midnight i.e 10PM or 11 PM the no. of accidents have increased and during the day i.e around 10 AM to 1PM the rate of accidents are significantly low. From this we can conclude that a lot of accidents mostly happen during the night.
2.Neo4j
Neo4j is a graph database and is ACID- complaint.It represents data in the form of nodes and vertices where nodes are entities and vertices are relationships/links between the entities.Ne04j can handle many relationships(64k max) and is based on graph theory .
GOAL
We have uploaded the dataset “crashdata2011-2020.csv” into Neo4j and performed meaningful analysis on it through Cypher. We have found correlations among the various factors to provide certain insights that can help in understanding the causes and contributing factors involved in a road accident.
ABOUT THE DATASET
This dataset is taken from the sanjoseca.gov website. The dataset comprises all the crashes reported in San Jose during 2021. It includes details such as injury types, distance from an intersection, crash date and time, weather conditions, road surface conditions, traffic controls and much more. Click here to view the dataset on the official website.
INSTALLATION OF Neo4j
- Download Ne04j Desktop from https://neo4j.com/
- You will get an activation key , save that
- .dmg file will be downloaded -> open the dmg file , you will be asdked to paste your activation key
- Press Start button to start the Neo4j server .
- Default username and password is neo4j
ESTABLISHING NODES & RELATIONSHIPS
Step 1: Create a Database:
Created a new project as CrashAnalysis and a new database in Neo4j by the name CrashDBMS
Step 2: Loading the dataset
Import the csv file into the Neo4j folder which was created while installing Neo4j.
Placed it in the CrashDBMS folder at :
C:\Users\Himanshi\.Neo4jDesktop\relate-data\dbmss\dbms-6b552873-b924-4589-ac3d-194c04a8510a\import
Graph data created via loading CSV file as:
load csv with headers from ‘file:///crashdata2011-2020.csv’ as row
with row
where row.Name is not null
MERGE (cname:CrashName {name:row.Name})
MERGE (Lighting:Lighting{name:row.Lighting } )
MERGE (Light)-[:Led_To_Fatality_bylight]->(FatalInjury)
MERGE (DATETIME:DATETIME{name:row.CrashDateTime} )
MERGE (cname)-[:Occurred_at]->(DATETIME)
MERGE (RoadwaySurface:RoadwaySurface{name:row.RoadwaySurface} )
MERGE (cname)-[:RoadSurface_Condition_Was]->(RoadwaySurface)
MERGE (Lighting:Lighting{name:row.Lighting } )
MERGE (cname)-[:Lighting_Condition_Was]->(Lighting)
MERGE (Weather:Weather{name:row.Weather } )
MERGE (cname)-[:Weather_Condition_Was]->(Weather)
MERGE (MinorInjury:MinorInjury{name:row.MinorInjury } )
MERGE (cname)-[:Led_To_Minor_Injury]->(MinorInjury))
MERGE (FatalInjury:FatalInjury{name:row.FatalInjuries} )
MERGE (cname)-[:Led_To_Fatality]->(FatalInjury))
MERGE (TrafficControl:TrafficControl{name:row.TrafficControl} )
MERGE (cname)-[:Traffic_Control]->(TrafficControl))
MERGE creates a node and checks if a node already exists with the same properties , it doesn’t create.Hence, it avoids duplicates.
Nodes:
Relationships:
ANALYSIS USING CYPHER
- Finding correlation between lighting condition at streets and fatal injuries occurred
MERGE (Lighting:Lighting{name:row.Lighting} )
MERGE (Lighting)-[:Led_To_Fatality_bylight]->(FatalInjury)
Fetching the relationship:
MATCH p=()-[r:Led_To_Fatality_bylight]->() RETURN p
Output:
Conclusion: Lighting has no correlation with having fatal injuries in an accident. Even in Daylight and Street light, a maximum number of fatal injuries are happening. Hence the conclusion is that there is no positive correlation between lighting and fatal injuries.
- Finding correlation between the condition of the Road surface and the number of fatal injuries occurred
MERGE (RoadwaySurface:RoadwaySurface{name:row.RoadwaySurface} )
MERGE (RoadwaySurface)-[:Led_To_Fatality_byroadsurface]->(FatalInjury))
MATCH p=()-[r:Led_To_Fatality_byroadsurface]->() RETURN p
Output:
Conclusion: Muddy surface and Snowy/Icy surface did not cause fatal injuries. Dry surface has caused the maximum number of fatal injuries.
- Analyzing the data to see if there is any correlation between pedestrian action and the number of fatal injuries occurred.
MERGE (PedestrianAction:PedestrianAction{name:row.PedestrianAction} )
MERGE (PedestrianAction)-[:Pedestrian_Action1]->(FatalInjury))
MATCH p=()-[r:Pedestrian_Action1]->() RETURN p
Output:
Conclusion: There is no direct correlation between the pedestrian action and the number of fatal injuries that occurred.
- Analyzing the data to see if there is any correlation between the weather conditions and the number of fatal injuries.
MERGE (Weather:Weather{name:row.Weather} )
MERGE (Weather)-[:Weather_Condition]->(FatalInjury))
MATCH p=()-[r:Weather_Condition]->() RETURN p
Output:
Conclusion: There is no positive or negative correlation between weather conditions and the number of fatal injuries happening.
- Analyzing the data to see if there is any correlation between weather conditions and the number of severe injuries that occured:
MERGE (Weather:Weather{name:row.Weather} )
MERGE (Weather)-[:Weather_Severe]->(SevereInjuries))
MATCH p=()-[r:Weather_Severe]->() RETURN p
Output:
Conclusion: There is no positive or negative correlation between weather conditions and the number of severe injuries that occurred.
MongoDB vs Neo4j vs RDMS
Top 5 takeaways
Below are the top 5 takeaways that we experienced in comparison between Neo4j, MongoDB and RDBMS:
- We can create relationships between various nodes (entities) in the Neo4j database which enables us to traverse the graph whereas MongoDB does not provide graph visualization of the data.
- We can change the structure of the data we are working on in Neo4j as it provides more flexibility. We can create the table columns as properties of a node or we can create them as a separate node while RDBMS provides a rigid structure where tables and attributes are fixed.
- With the MERGE option, Neo4j does not take the duplicate entries again if your data has multiple duplicate values in a column in a csv. (optional)
- MongoDB offers the ability to deploy a cloud database over Atlas. Once a cluster is established, Atlas offers the ability to load data to the cloud over MongoDB Compass. This process is user friendly, and allows for the cloud data to be visualized in a dashboard with MongoDB Charts.
- Writing queries in mongoDB via pymongo is tedious because we need to embed the entire mongo code written in python within “ “. On the other hand Cypher is more declarative and easy to use.
4.Docker
Docker is used for running and individual containers. This is very helpful in microservices architecture where we run multiple services independently. Docker can be used for creating individual containers for each service.
i.Workflow
ii.Installation of Docker Desktop
- Created docker hub account with docker id as crashesdocker
- Created public repo in the hub as crashesrepo :
- Installed Docker Desktop from https://hub.docker.com/
iii.Dockerize Notebook
(to perform analysis in mongodb using notebook server)
- Search for image in the dockerhub as jupyter/datascience-notebook
- Ran the below command to start the container :
docker run -p 8888:8888 jupyter/minimal-notebook
Since the image jupyter/minimal-notebook:latest wasn’t pulled , docker could not find it locally and first pulled the image from the hub and then started the container
From the image below we have the access to the Notebook serv
Copying the above link and pasting it in browser , we can see notebook is up and running
- We can verify the container logs from the Docker Desktop :
iv.Dockerize MongoDB
- Search for the official image in the dockerhub as mongo
- Ran the below cmd in the terminal:
Successfully pulled latest mongodb image from the hub :
- Ran the below command to start the container :
docker run -d
-p 27017:27017
–name test-mongo
-v file:///opt/homebrew/var/mongodb/
-e MONGODB_INITDB_ROOT_USERNAME=mongo
-e MONGODB_INITDB_ROOT_PASSWORD=mongo
mongo:latest
-name :name of the container
-p :exposing port
-v : mounting volume (“file:///opt/homebrew/var/mongodb/” is the path of my local mongodb instance)
-e :environment variables(to add authentication to MongoDB container to ensure data security)
- Ran docker ps command to check the container information:
(test-mongo is the name of the container)
- We can cross-check if the container is up and running from Docker Desktop.
- Clicking on test-mongo container , we can see the logs :
- Clicking on Inspect option , we can see Environment , Mounts and Port of the container :
- From the Docker desktop , we can open CLI and can connect to mongo shell as:
5. Kubernetes
As we have seen above ,Docker helps in creating container images .
If the application is very complex , and we want to scale all the containers to work together , there comes the role of Kubernetes.
Kubernetes is an open source orchestration tool to automate the management of individual containers .
Setting up of Kubernetes Cluster
- In Docker Desktop, under setting ->Enable Kubernetes
- Click on Apply & Restart :
- Click on Install:
- Docker Desktop downloaded all the Kubernetes images in the background and we can see two green lights in the bottom of the settings screen as : Docker running and Kubernetes running.
In the terminal window , run kubectl get nodes to check the kubernetes cluster
Leave a Reply