Skip to content

Commit f36115d

Browse files
committed
Add tutorial
1 parent 12b3e12 commit f36115d

File tree

5 files changed

+258
-6
lines changed

5 files changed

+258
-6
lines changed

app.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ var bodyParser = require('body-parser');
77

88
var index = require('./routes/index');
99
var users = require('./routes/users');
10-
var names = require('./routes/names')
10+
var names = require('./routes/names');
11+
var tutorial = require('./routes/tutorial')
1112

1213
var app = express();
1314

@@ -25,7 +26,8 @@ app.use(express.static(path.join(__dirname, 'public')));
2526

2627
app.use('/', index);
2728
app.use('/users', users);
28-
app.use('/names', names)
29+
app.use('/names', names);
30+
app.use('/tutorial', tutorial)
2931

3032
// catch 404 and forward to error handler
3133
app.use(function(req, res, next) {

routes/tutorial.js

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
var express = require('express');
2+
var router = express.Router();
3+
4+
/* GET home page. */
5+
router.get('/', function(req, res, next) {
6+
res.render('tutorial', { title: 'DevOps Test tutorial'});
7+
});
8+
9+
10+
11+
module.exports = router;

views/index.hbs

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
<!-- Begin page content -->
22
<div class="container">
33
<div class="page-header">
4-
<h1>DevOps Test App for Integritas</h1>
4+
<h1>DevOps Test App for Integritas </h1>
55
</div>
6-
<p class="lead">This App is running on AWS / kubernates.</p>
6+
<p class="lead">This App is running on AWS / kubernates. Click on <a href="/tutorial">Tutorial</a> To see how it was deployed.</p>
7+
<p><strong>Author:</strong> Gabriel Paschoal Vicente - <a href="mailto:[email protected]" target="_top">Send Mail</a></p>
78
<p>Use the button below to access the app.</p>
89
<a class="btn btn-default" href="/names" role="button">Access</a>
10+
<br>
11+
912
</div>
1013
</div>

views/names.hbs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
<!-- Begin page content -->
22
<div class="container">
33
<div class="page-header">
4-
<h1>DevOps Test App for Integritas - CRUD App </h1>
4+
<h3>DevOps Test App for Integritas - CRUD Application <a style="float: right" href="/">Back</a> </h3>
55
</div>
66

77
<div class="row">
88
<div class="col-xs-6"><p class="lead">Type one name and click on Add</p></div>
9-
<div class="col-xs-6"><a href="/">Click here</a> to go back</div>
109
</div>
1110

1211
<form action="/names" method="post" class="form-inline">

views/tutorial.hbs

+237
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
<!-- Begin page content -->
2+
<div class="container">
3+
4+
<h3>This is how the application was deployed using kubernates on aws.<a style="float: right" href="/">back</a></h3>
5+
6+
7+
8+
<p>The github repository of the simple application I developed.</p>
9+
<div class="well"><a href="https://github.com/gabrielpasv/gab-node-app" target="_blank">https://github.com/gabrielpasv/gab-node-app</a></div>
10+
11+
12+
<p>I created a docker image and uploaded it to docker hub. I used to following Dockerfile:</p>
13+
14+
<div class="well">FROM node:boron <br>
15+
# Create app directory <br>
16+
WORKDIR /gab-node-app <br>
17+
# Clone repo <br>
18+
RUN git clone https://github.com/gabrielpasv/gab-node-app.git . <br>
19+
# Install Dependencies <br>
20+
RUN npm install <br>
21+
EXPOSE 80 <br>
22+
CMD [ "npm", "start" ] <br>
23+
</div>
24+
25+
26+
<p>To build the image and upload it to docker hub I used these commands:</p>
27+
28+
<div class="well">docker build -t gabrielpasv/gab-node-app .<br>
29+
docker push gabrielpasv/gab-node-app
30+
</div>
31+
32+
33+
34+
<p>Setting up the environment installing <strong>kops, kubectl, awscli</strong>. And generate keys with <strong>ssh-keygen</strong>.</p>
35+
36+
<p>Create a DNS domain name on aws: <strong> k8s.gabrielpasv.net</strong></p>
37+
<div class="well">aws route53 create-hosted-zone --name k8s.gabrielpasv.net --caller-reference 5</div>
38+
39+
40+
<p>Create the aws cluster with kops</p>
41+
<div class="well">kops create cluster --name=k8s.gabrielpasv.net --state=s3://k8s-gabrielpasv-state --zones=us-east-1a --node-count=2 --node-size=t2.micro --master-size=t2.micro --dns-zone=k8s.gabrielpasv.net</div>
42+
43+
<p>I Validate the cluster is ready</p>
44+
<div class="well">ubuntu@ip-172-31-17-121:~$ kops validate cluster --state=s3://k8s-gabrielpasv-state <br>
45+
Using cluster from kubectl context: k8s.gabrielpasv.net <br>
46+
<br>
47+
Validating cluster k8s.gabrielpasv.net <br>
48+
<br>
49+
INSTANCE GROUPS <br>
50+
NAME ROLE MACHINETYPE MIN MAX SUBNETS <br>
51+
master-us-east-1a Master t2.micro 1 1 us-east-1a <br>
52+
nodes Node t2.micro 2 2 us-east-1a <br>
53+
<br>
54+
NODE STATUS <br>
55+
NAME ROLE READY <br>
56+
ip-172-20-34-7.ec2.internal master True <br>
57+
ip-172-20-35-253.ec2.internal node True <br>
58+
ip-172-20-38-120.ec2.internal node True <br>
59+
<br>
60+
Your cluster k8s.gabrielpasv.net is ready <br>
61+
</div>
62+
63+
64+
<p>I created the deployment with 1 replica for the mysql and 2 for the application with load balance and I also used secrets to pass the credentials. I used these files <strong>storage.yml, pv-claim.yml, gabnodeapp-secrets.yml, gabnodeapp-db.yml, gabnodeapp-db-service.yml, gabnodeapp-web.yml, gabnodeapp-web-service.yml
65+
</strong> </p>
66+
67+
68+
<p>Check the content of each file</p>
69+
<p> <strong>storage.yml</strong> </p>
70+
<div class="well">kind: StorageClass <br>
71+
apiVersion: storage.k8s.io/v1 <br>
72+
metadata: <br>
73+
&nbsp name: standard <br>
74+
provisioner: kubernetes.io/aws-ebs <br>
75+
parameters: <br>
76+
&nbsp type: gp2 <br>
77+
&nbsp zone: us-east-1a <br>
78+
</div>
79+
80+
81+
<p> <strong>pv-claim.yml</strong> </p>
82+
<div class="well">kind: PersistentVolumeClaim <br>
83+
apiVersion: v1 <br>
84+
metadata: <br>
85+
&nbsp name: db-storage <br>
86+
&nbsp annotations: <br>
87+
&nbsp volume.beta.kubernetes.io/storage-class: "standard" <br>
88+
spec: <br>
89+
&nbsp accessModes: <br>
90+
&nbsp - ReadWriteOnce <br>
91+
&nbsp resources: <br>
92+
&nbsp requests: <br>
93+
&nbsp &nbsp storage: 8Gi</div> <br>
94+
95+
<p> <strong>gabnodeapp-secrets.yml</strong> </p>
96+
<div class="well">apiVersion: v1 <br>
97+
kind: Secret <br>
98+
metadata: <br>
99+
&nbsp name: gabnodeapp-secrets <br>
100+
type: Opaque <br>
101+
data: <br>
102+
&nbsp gab-password: Z2FiMTIzNA== <br>
103+
&nbsp root-password: cG9ydGFsMTIzNA== <br>
104+
</div>
105+
106+
<p> <strong>gabnodeapp-db.yml</strong> </p>
107+
<div class="well">apiVersion: v1 <br>
108+
kind: ReplicationController <br>
109+
metadata: <br>
110+
&nbsp name: gabnodeapp-db <br>
111+
spec: <br>
112+
&nbsp replicas: 1 <br>
113+
&nbsp selector: <br>
114+
&nbsp &nbsp app: gabnodeapp-db <br>
115+
&nbsp template: <br>
116+
&nbsp &nbsp metadata: <br>
117+
&nbsp &nbsp &nbsp name: gabnodeapp-db <br>
118+
&nbsp &nbsp &nbsp labels: <br>
119+
&nbsp &nbsp &nbsp &nbsp app: gabnodeapp-db <br>
120+
&nbsp &nbsp spec: <br>
121+
&nbsp &nbsp &nbsp containers: <br>
122+
&nbsp &nbsp &nbsp &nbsp - name: mysql <br>
123+
&nbsp &nbsp &nbsp &nbsp image: mysql:5.7 <br>
124+
&nbsp &nbsp &nbsp &nbsp args: <br>
125+
&nbsp &nbsp &nbsp &nbsp &nbsp - "--ignore-db-dir=lost+found" <br>
126+
&nbsp &nbsp&nbsp &nbsp ports: <br>
127+
&nbsp &nbsp &nbsp &nbsp - name: mysql-port <br>
128+
&nbsp &nbsp&nbsp &nbsp &nbsp containerPort: 3306 <br>
129+
&nbsp &nbsp&nbsp &nbsp env: <br>
130+
&nbsp &nbsp&nbsp &nbsp &nbsp - name: MYSQL_ROOT_PASSWORD <br>
131+
&nbsp &nbsp &nbsp &nbsp &nbsp &nbsp valueFrom: <br>
132+
&nbsp &nbsp &nbsp &nbsp &nbsp &nbsp &nbsp secretKeyRef: <br>
133+
&nbsp &nbsp &nbsp &nbsp &nbsp &nbsp &nbsp&nbsp name: gabnodeapp-secrets <br>
134+
&nbsp &nbsp &nbsp &nbsp &nbsp &nbsp &nbsp &nbsp key: root-password <br>
135+
&nbsp &nbsp &nbsp &nbsp &nbsp - name: MYSQL_DATABASE <br>
136+
&nbsp &nbsp &nbsp &nbsp &nbsp &nbsp value: gabdb <br>
137+
&nbsp &nbsp&nbsp &nbsp &nbsp - name: MYSQL_USER <br>
138+
&nbsp &nbsp &nbsp &nbsp &nbsp &nbsp value: gab <br>
139+
&nbsp &nbsp &nbsp &nbsp &nbsp - name: MYSQL_PASSWORD <br>
140+
&nbsp &nbsp &nbsp &nbsp &nbsp &nbsp valueFrom: <br>
141+
&nbsp &nbsp &nbsp &nbsp &nbsp &nbsp &nbsp secretKeyRef: <br>
142+
&nbsp &nbsp &nbsp &nbsp &nbsp &nbsp &nbsp &nbsp name: gabnodeapp-secrets <br>
143+
&nbsp &nbsp &nbsp &nbsp &nbsp &nbsp &nbsp &nbsp key: gab-password <br>
144+
&nbsp &nbsp&nbsp &nbsp volumeMounts: <br>
145+
&nbsp &nbsp &nbsp &nbsp - mountPath: "/var/lib/mysql" <br>
146+
&nbsp &nbsp&nbsp&nbsp &nbsp name: gabnodeapp-storage <br>
147+
&nbsp &nbsp&nbsp volumes: <br>
148+
&nbsp &nbsp &nbsp &nbsp - name: gabnodeapp-storage <br>
149+
&nbsp &nbsp &nbsp &nbsp &nbsp persistentVolumeClaim: <br>
150+
&nbsp &nbsp &nbsp &nbsp &nbsp &nbsp claimName: db-storage <br>
151+
</div>
152+
153+
<p> <strong>gabnodeapp-db-service.yml</strong> </p>
154+
<div class="well">apiVersion: v1<br>
155+
kind: Service<br>
156+
metadata:<br>
157+
&nbsp name: gabnodeapp-db<br>
158+
spec:<br>
159+
&nbsp ports:<br>
160+
&nbsp - port: 3306<br>
161+
&nbsp &nbsp protocol: TCP<br>
162+
&nbsp selector:<br>
163+
&nbsp&nbsp app: gabnodeapp-db <br>
164+
type: NodePort<br>
165+
</div>
166+
167+
<p> <strong>gabnodeapp-web.yml</strong> </p>
168+
<div class="well">apiVersion: extensions/v1beta1 <br>
169+
kind: Deployment <br>
170+
metadata: <br>
171+
&nbsp name: gabnodeapp-deployment <br>
172+
spec: <br>
173+
&nbsp replicas: 2 <br>
174+
&nbsp template: <br>
175+
&nbsp &nbsp metadata: <br>
176+
&nbsp&nbsp&nbsp labels: <br>
177+
&nbsp&nbsp&nbsp&nbsp app: gabnodeapp <br>
178+
&nbsp&nbsp spec: <br>
179+
&nbsp&nbsp&nbsp containers: <br>
180+
&nbsp&nbsp&nbsp - name: gab-node-app <br>
181+
&nbsp&nbsp&nbsp&nbsp image: gabrielpasv/gab-node-app <br>
182+
&nbsp&nbsp&nbsp&nbsp ports: <br>
183+
&nbsp&nbsp&nbsp&nbsp - name: http-port <br>
184+
&nbsp&nbsp&nbsp&nbsp&nbsp containerPort: 80 <br>
185+
&nbsp&nbsp&nbsp&nbsp env: <br>
186+
&nbsp&nbsp&nbsp&nbsp - name: MYSQL_USER <br>
187+
&nbsp&nbsp&nbsp&nbsp value: gab <br>
188+
&nbsp&nbsp&nbsp&nbsp - name: MYSQL_PASSWORD <br>
189+
&nbsp&nbsp&nbsp&nbsp value: gab1234 <br>
190+
&nbsp&nbsp&nbsp&nbsp - name: MYSQL_DATABASE <br>
191+
&nbsp&nbsp&nbsp&nbsp value: gabdb <br>
192+
&nbsp&nbsp&nbsp&nbsp - name: APP_DB_HOST <br>
193+
&nbsp&nbsp&nbsp&nbsp value: gabnodeapp-db</div>
194+
195+
<p> <strong>gabnodeapp-web-service.yml</strong> </p>
196+
<div class="well">apiVersion: v1 <br>
197+
kind: Service <br>
198+
metadata: <br>
199+
&nbsp name: gabnodeapp <br>
200+
spec: <br>
201+
&nbsp ports: <br>
202+
&nbsp - port: 80 <br>
203+
&nbsp&nbsp targetPort: http-port <br>
204+
&nbsp&nbsp protocol: TCP <br>
205+
&nbsp selector: <br>
206+
&nbsp&nbsp app: gabnodeapp <br>
207+
&nbsp type: LoadBalancer</div>
208+
209+
210+
211+
<p>Check running pods</p>
212+
<div class="well">ubuntu@ip-172-31-17-121:~$ kubectl get pods <br>
213+
NAME READY STATUS RESTARTS AGE <br>
214+
gabnodeapp-db-q97j4 1/1 Running 0 7h <br>
215+
gabnodeapp-deployment-1899699146-4g37c 1/1 Running 0 5h <br>
216+
gabnodeapp-deployment-1899699146-dtxz1 1/1 Running 0 5h <br>
217+
</div>
218+
219+
220+
<p>Check deployment</p>
221+
<div class="well">ubuntu@ip-172-31-17-121:~$ kubectl get deployments<br>
222+
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE<br>
223+
gabnodeapp-deployment &nbsp&nbsp 2 &nbsp&nbsp 2 &nbsp&nbsp 2 &nbsp&nbsp 2 &nbsp&nbsp 5h<br>
224+
</div>
225+
226+
227+
<p>It generates a ELB link</p>
228+
<div class="well">ac7b01a9fb1f311e798aa021c568ee01-417161783.us-east-1.elb.amazonaws.com</div>
229+
230+
<p>And I created a domain for that</p>
231+
<div class="well"> <a href="http://gab-node-app.k8s.gabrielpasv.net/">http://gab-node-app.k8s.gabrielpasv.net/</a> </div>
232+
233+
234+
235+
236+
</div>
237+
</div>

0 commit comments

Comments
 (0)