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