-
Notifications
You must be signed in to change notification settings - Fork 0
/
parksmap-scaling.html
474 lines (399 loc) · 19.9 KB
/
parksmap-scaling.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="apple-touch-icon" sizes="180x180" href="apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="favicon-16x16.png">
<link rel="manifest" href="site.webmanifest">
<link rel="mask-icon" href="safari-pinned-tab.svg" color="#5bbad5">
<meta name="msapplication-TileColor" content="#da532c">
<meta name="theme-color" content="#ffffff">
<script src="jquery/jquery.min.js"></script>
<script src="popper/popper.min.js"></script>
<script src="bootstrap/js/bootstrap.min.js"></script>
<script src="requirejs/require.js"></script>
<script>var workshop_base_url = "/user/user3/workshop";</script>
<link rel="stylesheet" href="asciidoctor/css/asciidoctor.css">
<link rel="stylesheet" href="bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="fontawesome/css/all.min.css">
<link rel="stylesheet" href="css/workshop.css">
<link rel="stylesheet" href="css/workshop-asciidoc.css">
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-135921114-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag("js", new Date());
gtag("config", "UA-135921114-11");
</script>
</head>
</body>
<!-- Header -->
<header class="header">
<div class="container-fluid">
<div class="row">
<div class="col-sm-6">
<a href="" class="logo">Starter Labs (Java)</a>
</div>
</div>
</div>
</header>
<!-- Main -->
<div class="container-fluid">
<div class="row">
<div class="col-sm-3 d-sm-block d-none">
<!-- Table of Contents -->
<ul class="menu">
<li class="category">
<ul class="modules">
<h5 class="category-title">Workshop Modules</h5>
<li class="page"><a href="common-workshop-summary.html">Workshop Summary</a></li>
<li class="page"><a href="common-environment.html">Environment Overview</a></li>
<li class="page"><a href="common-using-homeroom.html">Using Homeroom</a></li>
<li class="page"><a href="common-parksmap-architecture.html">Architecture Overview of the ParksMap Application</a></li>
<li class="page"><a href="common-explore.html">Exploring the CLI and Web Console</a></li>
<li class="page"><a href="parksmap-container-image.html">Deploying Your First Container Image</a></li>
<li class="page active"><a href="parksmap-scaling.html">Scaling and Self Healing</a></li>
<li class="page"><a href="parksmap-routes.html">Exposing Your Application to the Outside World</a></li>
<li class="page"><a href="parksmap-logging.html">Exploring OpenShift's Logging Capabilities</a></li>
<li class="page"><a href="parksmap-permissions.html">Role-Based Access Control</a></li>
<li class="page"><a href="parksmap-rsh.html">Remote Access to Your Application</a></li>
<li class="page"><a href="nationalparks-java.html">Deploying Java Code</a></li>
<li class="page"><a href="nationalparks-java-databases.html">Adding a Database (MongoDB)</a></li>
<li class="page"><a href="nationalparks-java-application-health.html">Application Health</a></li>
<li class="page"><a href="nationalparks-java-pipeline.html">Automate Build and Deployment with Pipelines</a></li>
<li class="page"><a href="nationalparks-java-pipeline-codechanges-gogs.html">Automation for Your Application on Code Changes</a></li>
<li class="page"><a href="mlbparks-templates.html">Using Application Templates</a></li>
<li class="page"><a href="mlbparks-binary-build.html">Binary Builds for Day to Day Development</a></li>
<li class="page"><a href="common-further-resources.html">Further Resources</a></li>
<li class="page"><a href="common-workshop-links.html">Workshop Links</a></li>
</ul>
</li>
</ul>
</div>
<div class="col-sm-9">
<section class="page-content">
<!-- Top Navigation -->
<div class="btn-group btn-group-xs float-right">
<button type="button" onclick="location.href='parksmap-container-image';" class="btn btn-xs btn-transparent" aria-label="Prev">
<span class="fas fa-arrow-left" aria-hidden="true"></span>
</button>
<button type="button" onclick="location.href='';" class="btn btn-xs btn-transparent" aria-label="Home">
<span class="fas fa-home" aria-hidden="true"></span>
</button>
<button type="button" onclick="location.href='parksmap-routes';" class="btn btn-xs btn-transparent" aria-label="Next">
<span class="fas fa-arrow-right" aria-hidden="true"></span>
</button>
</div>
<!-- Title -->
<h1 class="title">Scaling and Self Healing</h1>
<!-- Content -->
<div class="sect1">
<h2 id="_background_deployments_and_replicasets">Background: Deployments and ReplicaSets</h2>
<div class="sectionbody">
<div class="paragraph">
<p>While <strong>Services</strong> provide routing and load balancing for <strong>Pods</strong>, which may go in and
out of existence, <strong>ReplicaSet</strong> (RS) and <strong>ReplicationController</strong> (RC) are used to specify and then
ensure the desired number of <strong>Pods</strong> (replicas) are in existence. For example, if
you always want your application server to be scaled to 3 <strong>Pods</strong> (instances), a
<strong>ReplicaSet</strong> is needed. Without an RS, any <strong>Pods</strong> that are killed or
somehow die/exit are not automatically restarted. <strong>ReplicaSets</strong> and <strong>ReplicationController</strong> are how OpenShift "self heals" and while <strong>Deployments</strong> control <strong>ReplicaSets</strong>, <strong>ReplicationController</strong> here are controlled by <strong>DeploymentConfigs</strong>.</p>
</div>
<div class="paragraph">
<p>From the <a href="https://docs.openshift.com/container-platform/latest/applications/deployments/what-deployments-are.html">deployments documentation</a>:</p>
</div>
<div class="quoteblock">
<blockquote>
<em>
Similar to a replication controller, a ReplicaSet is a native Kubernetes API object that ensures a specified number of pod replicas are running at any given time. The difference between a replica set and a replication controller is that a replica set supports set-based selector requirements whereas a replication controller only supports equality-based selector requirements.
</em>
</blockquote>
</div>
<div class="paragraph">
<p>In Kubernetes, a <strong>Deployment</strong> (D) defines how something should be deployed. In almost all cases, you will end up using the <strong>Pod</strong>, <strong>Service</strong>,
<strong>ReplicaSet</strong> and <strong>Deployment</strong> resources together. And, in
almost all of those cases, OpenShift will create all of them for you.</p>
</div>
<div class="paragraph">
<p>There are some edge cases where you might want some <strong>Pods</strong> and an <strong>RS</strong> without a <strong>D</strong>
or a <strong>Service</strong>, and others, so feel free to ask us about them after the labs.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_exercise_exploring_deployment_related_objects">Exercise: Exploring Deployment-related Objects</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Now that we know the background of what a <strong>ReplicaSet</strong> and
<strong>Deployment</strong> are, we can explore how they work and are related. Take a
look at the <strong>Deployment</strong> (D) that was created for you when you told
OpenShift to stand up the <code>parksmap</code> image:</p>
</div>
<div class="listingblock execute-1">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">oc get deployment</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">NAME READY UP-TO-DATE AVAILABLE AGE
parksmap 1/1 1 1 20m</code></pre>
</div>
</div>
<div class="paragraph">
<p>To get more details, we can look into the <strong>ReplicaSet</strong> (<strong>RS</strong>).</p>
</div>
<div class="paragraph">
<p>Take a look at the <strong>ReplicaSet</strong> (RS) that was created for you when
you told OpenShift to stand up the <code>parksmap</code> image:</p>
</div>
<div class="listingblock execute-1">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">oc get rs</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">NAME DESIRED CURRENT READY AGE
parksmap-65c4f8b676 1 1 1 21m</code></pre>
</div>
</div>
<div class="paragraph">
<p>This lets us know that, right now, we expect one <strong>Pod</strong> to be deployed
(<code>Desired</code>), and we have one <strong>Pod</strong> actually deployed (<code>Current</code>). By changing
the desired number, we can tell OpenShift that we want more or less <strong>Pods</strong>.</p>
</div>
<div class="paragraph">
<p>OpenShift’s <strong>HorizontalPodAutoscaler</strong> effectively monitors the CPU usage of a
set of instances and then manipulates the RCs accordingly.</p>
</div>
<div class="paragraph">
<p>You can learn more about the CPU-based
<a href="https://docs.openshift.com/container-platform/latest/nodes/pods/nodes-pods-autoscaling.html#nodes-pods-autoscaling-about_nodes-pods-autoscaling">Horizontal Pod Autoscaler here</a></p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_exercise_scaling_the_application">Exercise: Scaling the Application</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Let’s scale our parksmap "application" up to 2 instances. We can do this with
the <code>scale</code> command. You could also do this by incrementing the Desired Count in the OpenShift web console. Pick one of these methods; it’s your choice.</p>
</div>
<div class="listingblock execute-1">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">oc scale --replicas=2 deployment/parksmap</code></pre>
</div>
</div>
<div class="paragraph">
<p>You can also scale up to two pods in the <strong>Developer Perspective</strong>. From the Topology view, first click the <code>parksmap</code> deployment config and select the <strong>Details</strong> tab:</p>
</div>
<div class="imageblock">
<div class="content">
<img src="images/parksmap-details.png" alt="Details">
</div>
</div>
<div class="paragraph">
<p>Next, click the <strong>^</strong> icon next to the Pod visualization to scale up to 2 pods.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="images/parksmap-scaleup.png" alt="Scaling up">
</div>
</div>
<div class="paragraph">
<p>To verify that we changed the number of replicas, issue the following command:</p>
</div>
<div class="listingblock execute-1">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">oc get rs</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">NAME DESIRED CURRENT READY AGE
parksmap-65c4f8b676 2 2 2 23m</code></pre>
</div>
</div>
<div class="paragraph">
<p>You can see that we now have 2 replicas. Let’s verify the number of pods with
the <code>oc get pods</code> command:</p>
</div>
<div class="listingblock execute-1">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">oc get pods</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">NAME READY STATUS RESTARTS AGE
parksmap-65c4f8b676-fxcrq 1/1 Running 0 92s
parksmap-65c4f8b676-k5gkk 1/1 Running 0 24m</code></pre>
</div>
</div>
<div class="paragraph">
<p>And lastly, let’s verify that the <strong>Service</strong> that we learned about in the
previous lab accurately reflects two endpoints:</p>
</div>
<div class="listingblock execute-1">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">oc describe svc parksmap</code></pre>
</div>
</div>
<div class="paragraph">
<p>You will see something like the following output:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">Name: parksmap
Namespace: user1
Labels: app=workshop
app.kubernetes.io/component=parksmap
app.kubernetes.io/instance=parksmap
app.kubernetes.io/part-of=workshop
app.openshift.io/runtime-version=latest
component=parksmap
role=frontend
Annotations: openshift.io/generated-by: OpenShiftWebConsole
Selector: app=parksmap,deploymentconfig=parksmap
Type: ClusterIP
IP: 172.30.136.210
Port: 8080-tcp 8080/TCP
TargetPort: 8080/TCP
Endpoints: 10.128.2.138:8080,10.131.0.93:8080
Session Affinity: None
Events: <none></code></pre>
</div>
</div>
<div class="paragraph">
<p>Another way to look at a <strong>Service</strong>'s endpoints is with the following:</p>
</div>
<div class="listingblock execute-1">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">oc get endpoints parksmap</code></pre>
</div>
</div>
<div class="paragraph">
<p>And you will see something like the following:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">NAME ENDPOINTS AGE
parksmap 10.128.2.90:8080,10.131.0.40:8080 45m</code></pre>
</div>
</div>
<div class="paragraph">
<p>Your IP addresses will likely be different, as each pod receives a unique IP
within the OpenShift environment. The endpoint list is a quick way to see how
many pods are behind a service.</p>
</div>
<div class="paragraph">
<p>You can also see that both <strong>Pods</strong> are running in the Developer Perspective:</p>
</div>
<div class="imageblock">
<div class="content">
<img src="images/parksmap-scaled.png" alt="Scaled">
</div>
</div>
<div class="paragraph">
<p>Overall, that’s how simple it is to scale an application (<strong>Pods</strong> in a
<strong>Service</strong>). Application scaling can happen extremely quickly because OpenShift
is just launching new instances of an existing image, especially if that image
is already cached on the node.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_application_self_healing">Application "Self Healing"</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Because OpenShift’s <strong>RSs</strong> are constantly monitoring to see that the desired number
of <strong>Pods</strong> actually are running, you might also expect that OpenShift will "fix" the
situation if it is ever not right. You would be correct!</p>
</div>
<div class="paragraph">
<p>Since we have two <strong>Pods</strong> running right now, let’s see what happens if we
"accidentally" kill one. Run the <code>oc get pods</code> command again, and choose a <strong>Pod</strong>
name. Then, do the following:</p>
</div>
<div class="listingblock copy-and-edit">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">oc delete pod parksmap-65c4f8b676-k5gkk && oc get pods</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">pod "parksmap-65c4f8b676-k5gkk" deleted
NAME READY STATUS RESTARTS AGE
parksmap-65c4f8b676-bjz5g 1/1 Running 0 13s
parksmap-65c4f8b676-fxcrq 1/1 Running 0 4m48s</code></pre>
</div>
</div>
<div class="paragraph">
<p>Did you notice anything? One container has been deleted, and there’s a new container already being created.</p>
</div>
<div class="paragraph">
<p>Also, the names of the <strong>Pods</strong> are slightly changed.
That’s because OpenShift almost immediately detected that the current state (1
<strong>Pod</strong>) didn’t match the desired state (2 <strong>Pods</strong>), and it fixed it by scheduling
another <strong>Pod</strong>.</p>
</div>
<div class="paragraph">
<p>Additionally, OpenShift provides rudimentary capabilities around checking the
liveness and/or readiness of application instances. If the basic checks are
insufficient, OpenShift also allows you to run a command inside the container in
order to perform the check. That command could be a complicated script that uses
any installed language.</p>
</div>
<div class="paragraph">
<p>Based on these health checks, if OpenShift decided that our <code>parksmap</code>
application instance wasn’t alive, it would kill the instance and then restart
it, always ensuring that the desired number of replicas was in place.</p>
</div>
<div class="paragraph">
<p>More information on probing applications is available in the
<a href="https://docs.openshift.com/container-platform/latest/nodes/containers/nodes-containers-health.html">Application
Health</a> section of the documentation and later in this guide.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_exercise_scale_down">Exercise: Scale Down</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Before we continue, go ahead and scale your application down to a single
instance. Feel free to do this using whatever method you like.</p>
</div>
<div class="admonitionblock warning">
<table>
<tr>
<td class="icon">
<div class="title">Warning</div>
</td>
<td class="content">
Don’t forget to scale down back to 1 instance your <code>parksmap</code> component as otherwise you might experience some weird behavior in later labs. This is due to how the application has been coded and not to OpenShift itself.
</td>
</tr>
</table>
</div>
</div>
</div>
<!-- Bottom Navigation -->
<div class="page-meta clearfix">
<input type="button" class="btn btn-lg btn-primary float-right" onclick="location.href='parksmap-routes';" value="Continue" />
</div>
</section>
</div>
</div>
</div>
<!-- Footer -->
<footer class="footer">
</footer>
<!-- Javascript-->
<script src="js/workshop.js"></script>
<script src="js/workshop-asciidoc.js"></script>
</body>
</html>