· 6 years ago · Jul 01, 2019, 02:06 PM
1<!DOCTYPE html>
2<html>
3<head>
4 <title>
5 Developing Java Applications on OpenShift - Starter Lab
6 </title>
7 <meta name="csrf-param" content="authenticity_token" />
8<meta name="csrf-token" content="SCijRXWP66b5lWSbReQUhEY5SCB3rYN6bKPApj2x0SCnyAu1S9fHXgFf5AfD0wcOIGsw41qnkRCxptajVD/uow==" />
9 <link rel="stylesheet" media="all" href="/assets/application-dcf5640dabe7c086c5db76b2e378b4def3309902bc32af61ab63094a23e1730b.css" data-turbolinks-track="reload" />
10 <script src="/assets/application-1763c4134299cf1911a383dd8d9b23b574b429196c500fbba1a010629fc4c558.js" data-turbolinks-track="reload"></script>
11</head>
12
13<body>
14<nav class="navbar fixed-top navbar-expand-lg navbar-dark bg-dark">
15 <div class="container-fluid d-flex justify-content-start">
16 <button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarContent">
17 <span class="navbar-toggler-icon"></span>
18 </button>
19 <a class="navbar-brand mb-0 h1" href="/workshop/workshop" id="workshopName">Developing Java Applications on OpenShift - Starter Lab</a>
20 </div>
21</nav>
22
23<script type="application/javascript">
24 if (App.hasOwnProperty('subscription_id')) {
25 App.cable.subscriptions.remove(App.subscription_id);
26 }
27
28 App.subscription_id = App.report_page_view('workshop#complete', '0b873e92-84c4-4268-8708-a6853bd0815e');
29</script>
30
31<main class="container-fluid">
32 <div class="row">
33 <div class="col-md-12">
34 <h2>Environment Overview</h2>
35 <div class="imageblock">
36<div class="content">
37<img src="/workshop/workshop/asset/images/common-environment-ocp-architecture.png" alt="OCP Architecture">
38</div>
39</div>
40<div class="paragraph">
41<p>You will be interacting with an OpenShift environment that is running on a
42public cloud. The environment consists of the following systems:</p>
43</div>
44<div class="ulist">
45<ul>
46<li>
47<p>1 master node(s)</p>
48</li>
49<li>
50<p>1 infrastructure node(s)</p>
51</li>
52<li>
53<p>20 "application" nodes</p>
54</li>
55<li>
56<p>An NFS server</p>
57</li>
58</ul>
59</div>
60<div class="paragraph">
61<p>The infrastructure node is providing several services:</p>
62</div>
63<div class="ulist">
64<ul>
65<li>
66<p>Gogs git server</p>
67</li>
68<li>
69<p>This lab manual</p>
70</li>
71<li>
72<p>The OpenShift Docker registry</p>
73</li>
74<li>
75<p>The OpenShift router</p>
76</li>
77<li>
78<p>Etherpad</p>
79</li>
80</ul>
81</div>
82<div class="paragraph">
83<p>Additionally, a predefined number of user accounts have been provisioned.</p>
84</div>
85<div class="paragraph">
86<p>Before continuing, please visit visit the Etherpad at the following URL:</p>
87</div>
88<div class="listingblock">
89<div class="content">
90<pre>http://etherpad-infra.apps.mod-5b05.openshiftworkshop.com/p/workshop</pre>
91</div>
92</div>
93<div class="paragraph">
94<p>Decide on a user account among one of the available users or use
95the one that has been assigned to you by the instructor. Find that user
96account and type your name next to it. This will be your user account for the
97duration of these exercises. For example:</p>
98</div>
99<div class="listingblock">
100<div class="content">
101<pre>userXY=Luke Skywalker</pre>
102</div>
103</div>
104<div class="paragraph">
105<p>If you already see a name next to a user account, it means that someone
106else has already claimed it.</p>
107</div>
108<div class="paragraph">
109<p>You will see various code and command blocks throughout these exercises.
110Some of the command blocks can be copy/pasted directly. Others will require
111modification of the command before execution. If you see a command block with
112a red border (see below), the command will require modification. Typically
113this is a substitution of your username or user number:</p>
114</div>
115<div class="listingblock copypaste">
116<div class="content">
117<pre class="CodeRay highlight"><code>some command for userXY</code></pre>
118</div>
119</div>
120 <hr>
121 <h2>Installing the *oc* client tool</h2>
122 <div class="sect1">
123<h2 id="_command_line_interface">Command Line Interface</h2>
124<div class="sectionbody">
125<div class="paragraph">
126<p>OpenShift ships with a feature rich web console as well as command line tools
127to provide users with a nice interface to work with applications deployed to the
128platform. The OpenShift tools are a single executable written in the Go
129programming language and is available for the following operating systems:</p>
130</div>
131<div class="ulist">
132<ul>
133<li>
134<p>Microsoft Windows</p>
135</li>
136<li>
137<p>macOS 10</p>
138</li>
139<li>
140<p>Linux</p>
141</li>
142</ul>
143</div>
144<div class="paragraph">
145<p>You might already have the OpenShift CLI available on your environment. You can verify
146it by running an <code>oc</code> command:</p>
147</div>
148<div class="listingblock">
149<div class="content">
150<pre class="CodeRay highlight"><code data-lang="bash">$ oc version</code></pre>
151</div>
152</div>
153<div class="paragraph">
154<p>You should see the following (or something similar):</p>
155</div>
156<div class="listingblock">
157<div class="content">
158<pre class="CodeRay highlight"><code data-lang="bash">oc v3.11.0+0cbc58b
159kubernetes v1.11.0+d4cacc0</code></pre>
160</div>
161</div>
162<div class="paragraph">
163<p>If the <code>oc</code> doesn’t exist or you have an older version of the OpenShift CLI, follow
164the next sections to install or update the OpenShift CLI. Otherwise, skip to the
165next lab.</p>
166</div>
167</div>
168</div>
169<div class="sect1">
170<h2 id="_download_and_install_openshift_cli_on_windows">Download and Install OpenShift CLI on Windows</h2>
171<div class="sectionbody">
172<div class="paragraph">
173<p>Download the the OpenShift CLI tool for <a href="https://github.com/openshift/origin/releases/download/v3.11.0/openshift-origin-client-tools-v3.11.0-0cbc58b-windows.zip">Microsoft Windows</a></p>
174</div>
175<div class="paragraph">
176<p>Once the file has been downloaded, you will need to extract the contents as it
177is a compressed archive. I would suggest saving this file to the following
178directories:</p>
179</div>
180<div class="listingblock">
181<div class="content">
182<pre class="CodeRay highlight"><code data-lang="bash">C:\OpenShift</code></pre>
183</div>
184</div>
185<div class="paragraph">
186<p>In order to extract a zip archive on windows, you will need a zip utility
187installed on your system. With newer versions of windows (greater than XP),
188this is provided by the operating system. Just right click on the downloaded
189file using file explorer and select to extract the contents.</p>
190</div>
191<div class="paragraph">
192<p>Now you can add the OpenShift CLI tools to your PATH. Because changing your PATH
193on windows varies by version of the operating system, we will not list each operating system here.
194However, the general workflow is right click on your computer name inside of the file explorer. Select Advanced system settings. I guess changing your PATH is considered an advanced task? :) Click on the advanced tab, and then finally click on Environment variables.
195Once the new dialog opens, select the Path variable and add <strong><code>;C:\OpenShift</code></strong> at
196the end. For an easy way out, you could always just copy it to C:\Windows or a
197directory you know is already on your path. For more detailed instructions:</p>
198</div>
199<div class="ulist">
200<ul>
201<li>
202<p><a href="https://support.microsoft.com/en-us/kb/310519">Windows XP</a></p>
203</li>
204<li>
205<p><a href="http://banagale.com/changing-your-system-path-in-windows-vista.htm">Windows Vista</a></p>
206</li>
207<li>
208<p><a href="http://geekswithblogs.net/renso/archive/2009/10/21/how-to-set-the-windows-path-in-windows-7.aspx">Windows 7</a>
209-<a href="http://www.itechtics.com/customize-windows-environment-variables/">Windows 8</a></p>
210</li>
211<li>
212<p>Windows 10 - Follow the directions above.</p>
213</li>
214</ul>
215</div>
216<div class="paragraph">
217<p>At this point, we should have the oc tool available for use. Let’s test this
218out by printing the version of the oc command:</p>
219</div>
220<div class="listingblock">
221<div class="content">
222<pre class="CodeRay highlight"><code data-lang="bash">> oc version</code></pre>
223</div>
224</div>
225<div class="paragraph">
226<p>You should see the following (or something similar):</p>
227</div>
228<div class="listingblock">
229<div class="content">
230<pre class="CodeRay highlight"><code data-lang="bash">oc v3.11.0+0cbc58b
231kubernetes v1.11.0+d4cacc0</code></pre>
232</div>
233</div>
234<div class="paragraph">
235<p>If you get an error message, you have not updated your path correctly. If you
236need help, raise your hand and the instructor will assist.</p>
237</div>
238</div>
239</div>
240<div class="sect1">
241<h2 id="_download_and_install_openshift_cli_on_linux">Download and Install OpenShift CLI on Linux</h2>
242<div class="sectionbody">
243<div class="paragraph">
244<p>Download the the OpenShift CLI tool for <a href="https://github.com/openshift/origin/releases/download/v3.11.0/openshift-origin-client-tools-v3.11.0-0cbc58b-linux-64bit.tar.gz">Linux 64</a></p>
245</div>
246<div class="paragraph">
247<p>Once the file has been downloaded, you will need to extract the contents as it
248is a compressed archive. I would suggest saving this file to the following
249directories:</p>
250</div>
251<div class="listingblock">
252<div class="content">
253<pre class="CodeRay highlight"><code data-lang="bash">~/openShift</code></pre>
254</div>
255</div>
256<div class="paragraph">
257<p>Open up a terminal window and change to the directory where you downloaded the
258file. Once you are in the directory, enter in the following command:</p>
259</div>
260<div class="admonitionblock caution">
261<table>
262<tr>
263<td class="icon">
264<i class="fa icon-caution" title="Caution"></i>
265</td>
266<td class="content">
267The name of the oc packaged archive may vary. Adjust accordingly.
268</td>
269</tr>
270</table>
271</div>
272<div class="listingblock">
273<div class="content">
274<pre class="CodeRay highlight"><code data-lang="bash">$ tar zxvf oc-linux.tar.gz</code></pre>
275</div>
276</div>
277<div class="paragraph">
278<p>The tar.gz file name needs to be replaced by the entire name that was downloaded in the previous step.</p>
279</div>
280<div class="paragraph">
281<p>Now you can add the OpenShift CLI tools to your PATH.</p>
282</div>
283<div class="listingblock">
284<div class="content">
285<pre class="CodeRay highlight"><code data-lang="bash">$ export PATH=$PATH:~/openShift</code></pre>
286</div>
287</div>
288<div class="paragraph">
289<p>At this point, we should have the oc tool available for use. Let’s test this
290out by printing the version of the oc command:</p>
291</div>
292<div class="listingblock">
293<div class="content">
294<pre class="CodeRay highlight"><code data-lang="bash">$ oc version</code></pre>
295</div>
296</div>
297<div class="paragraph">
298<p>You should see the following (or something similar):</p>
299</div>
300<div class="listingblock">
301<div class="content">
302<pre class="CodeRay highlight"><code data-lang="bash">oc v3.11.0+0cbc58b
303kubernetes v1.11.0+d4cacc0</code></pre>
304</div>
305</div>
306<div class="paragraph">
307<p>If you get an error message, you have not updated your path correctly. If you
308need help, raise your hand and the instructor will assist.</p>
309</div>
310</div>
311</div>
312<div class="sect1">
313<h2 id="_download_and_install_openshift_cli_on_mac">Download and Install OpenShift CLI on Mac</h2>
314<div class="sectionbody">
315<div class="paragraph">
316<p>Download the the OpenShift CLI tool for <a href="https://github.com/openshift/origin/releases/download/v3.11.0/openshift-origin-client-tools-v3.11.0-0cbc58b-mac.zip">Mac</a></p>
317</div>
318<div class="paragraph">
319<p>Once the file has been downloaded, you will need to extract the contents as it
320is a compressed archive. I would suggest saving this file to the following
321directories:</p>
322</div>
323<div class="listingblock">
324<div class="content">
325<pre class="CodeRay highlight"><code data-lang="bash">~/openShift</code></pre>
326</div>
327</div>
328<div class="paragraph">
329<p>Open up a terminal window and change to the directory where you downloaded the
330file. Once you are in the directory, enter in the following command:</p>
331</div>
332<div class="admonitionblock caution">
333<table>
334<tr>
335<td class="icon">
336<i class="fa icon-caution" title="Caution"></i>
337</td>
338<td class="content">
339The name of the oc packaged archive may vary. Adjust accordingly.
340</td>
341</tr>
342</table>
343</div>
344<div class="listingblock">
345<div class="content">
346<pre class="CodeRay highlight"><code data-lang="bash">$ tar zxvf oc-macosx.tar.gz</code></pre>
347</div>
348</div>
349<div class="paragraph">
350<p>The tar.gz file name needs to be replaced by the entire name that was downloaded in the previous step.</p>
351</div>
352<div class="paragraph">
353<p>Now you can add the OpenShift CLI tools to your PATH.</p>
354</div>
355<div class="listingblock">
356<div class="content">
357<pre class="CodeRay highlight"><code data-lang="bash">$ export PATH=$PATH:~/openShift</code></pre>
358</div>
359</div>
360<div class="paragraph">
361<p>At this point, we should have the oc tool available for use. Let’s test this
362out by printing the version of the oc command:</p>
363</div>
364<div class="listingblock">
365<div class="content">
366<pre class="CodeRay highlight"><code data-lang="bash">$ oc version</code></pre>
367</div>
368</div>
369<div class="paragraph">
370<p>You should see the following (or something similar):</p>
371</div>
372<div class="listingblock">
373<div class="content">
374<pre class="CodeRay highlight"><code data-lang="bash">oc v3.11.0+0cbc58b
375kubernetes v1.11.0+d4cacc0</code></pre>
376</div>
377</div>
378<div class="paragraph">
379<p>If you get an error message, you have not updated your path correctly. If you
380need help, raise your hand and the instructor will assist.</p>
381</div>
382</div>
383</div>
384<div class="sect1">
385<h2 id="_tab_completion">Tab Completion</h2>
386<div class="sectionbody">
387<div class="paragraph">
388<p>The OpenShift command line tool supports the ability to use tab completion for the popular zsh and bash shells. This suits the needs of users using either Linux or OS X. If you are using Microsoft Windows, never fear, we will discuss some ways to get tab completion working on that operating system as well.</p>
389</div>
390<div class="sect2">
391<h3 id="_tab_completion_on_mac_and_linux">Tab completion on Mac and Linux</h3>
392<div class="paragraph">
393<p>If you are on the Mac operating system, you will need to ensure that you have the <strong>bash-completion</strong> project installed. This can be accomplished using the popular brew system:</p>
394</div>
395<div class="listingblock">
396<div class="content">
397<pre class="CodeRay highlight"><code data-lang="bash">$ brew install bash-completion</code></pre>
398</div>
399</div>
400<div class="paragraph">
401<p>If you’re on Linux, ensure you have <strong>bash-completion</strong> installed using your package manager (dnf, yum apt-get,…​)</p>
402</div>
403<div class="paragraph">
404<p>Once <strong>bash-completion</strong> package is available in your machine, to enable tab completion in your shell, you can simply enter in the following command from your terminal</p>
405</div>
406<div class="listingblock">
407<div class="content">
408<pre class="CodeRay highlight"><code data-lang="bash">$ oc completion bash >> oc_completion.sh
409$ source oc_completion.sh</code></pre>
410</div>
411</div>
412<div class="paragraph">
413<p>Alternatively, you can add this to your .bashrc file.</p>
414</div>
415<div class="paragraph">
416<p>If you are using zsh, you can run the following command:</p>
417</div>
418<div class="listingblock">
419<div class="content">
420<pre class="CodeRay highlight"><code data-lang="bash">$ source <(oc completion zsh)</code></pre>
421</div>
422</div>
423<div class="paragraph">
424<p>Alternatively, you can add this to your .zshrc file.</p>
425</div>
426</div>
427<div class="sect2">
428<h3 id="_tab_completion_on_windows">Tab completion on Windows</h3>
429<div class="paragraph">
430<p>For Windows users, things become a bit more tricky. You could of course use the Linux Subsystem for Windows but you may want to consider using a combination of babun and cmder. For a full list of instructions, you can check out the following blog post:</p>
431</div>
432<div class="ulist">
433<ul>
434<li>
435<p><a href="https://blog.openshift.com/openshift-3-tab-completion-for-windows/">https://blog.openshift.com/openshift-3-tab-completion-for-windows/</a></p>
436</li>
437</ul>
438</div>
439</div>
440</div>
441</div>
442<div class="sect1">
443<h2 id="_working_with_proxies">Working with proxies</h2>
444<div class="sectionbody">
445<div class="paragraph">
446<p>It might happen that you’re behind a corporate proxy to access the internet. In this case, you’ll need to set
447some additional environment variables for the oc command line to work.</p>
448</div>
449<div class="paragraph">
450<p><strong>Windows:</strong>
451Follow previous section’s instructions on how to set an Environment Variable on Windows. The variables you’ll need
452to set are:</p>
453</div>
454<div class="admonitionblock caution">
455<table>
456<tr>
457<td class="icon">
458<i class="fa icon-caution" title="Caution"></i>
459</td>
460<td class="content">
461Replace the proxy server with the one for your environment/machine.
462</td>
463</tr>
464</table>
465</div>
466<div class="listingblock">
467<div class="content">
468<pre class="CodeRay highlight"><code data-lang="bash">https_proxy=http://proxy-server.mycorp.com:3128/
469HTTPS_PROXY=http://proxy-server.mycorp.com:3128/</code></pre>
470</div>
471</div>
472<div class="paragraph">
473<p><strong>macOS:</strong></p>
474</div>
475<div class="admonitionblock caution">
476<table>
477<tr>
478<td class="icon">
479<i class="fa icon-caution" title="Caution"></i>
480</td>
481<td class="content">
482Replace the proxy server with the one for your environment/machine.
483</td>
484</tr>
485</table>
486</div>
487<div class="listingblock">
488<div class="content">
489<pre class="CodeRay highlight"><code data-lang="bash">$ export https_proxy=http://proxy-server.mycorp.com:3128/
490$ export HTTPS_PROXY=http://proxy-server.mycorp.com:3128/</code></pre>
491</div>
492</div>
493<div class="paragraph">
494<p><strong>Linux:</strong></p>
495</div>
496<div class="admonitionblock caution">
497<table>
498<tr>
499<td class="icon">
500<i class="fa icon-caution" title="Caution"></i>
501</td>
502<td class="content">
503Replace the proxy server with the one for your environment/machine.
504</td>
505</tr>
506</table>
507</div>
508<div class="listingblock">
509<div class="content">
510<pre class="CodeRay highlight"><code data-lang="bash">$ export https_proxy=http://proxy-server.mycorp.com:3128/
511$ export HTTPS_PROXY=http://proxy-server.mycorp.com:3128/</code></pre>
512</div>
513</div>
514<div class="admonitionblock note">
515<table>
516<tr>
517<td class="icon">
518<i class="fa icon-note" title="Note"></i>
519</td>
520<td class="content">
521<div class="paragraph">
522<p>If the proxy is secured, make sure to use the following URL pattern, replacing the contents with the
523appropriate values:</p>
524</div>
525<div class="paragraph">
526<p>export https_proxy=http://USERNAME:PASSOWRD@proxy-server.mycorp.com:3128/</p>
527</div>
528<div class="paragraph">
529<p><em>Special Characters</em>: If your password contains special characters, you must replace them with ASCII codes, for example the at sign @ must be replaced by the %40 code, e.g. p@ssword = p%40ssword.</p>
530</div>
531</td>
532</tr>
533</table>
534</div>
535</div>
536</div>
537 <hr>
538 <h2>Exploring the CLI and Web Console</h2>
539 <div class="sect1">
540<h2 id="_command_line">Command Line</h2>
541<div class="sectionbody">
542<div class="paragraph">
543<p>The first thing we want to do to ensure that our <code>oc</code> command line tools was
544installed and successfully added to our path is to log in to the OpenShift
545environment that has been provided for this Workshop session.</p>
546</div>
547<div class="admonitionblock note">
548<table>
549<tr>
550<td class="icon">
551<i class="fa icon-note" title="Note"></i>
552</td>
553<td class="content">
554<div class="paragraph">
555<p>In case you had trouble installing the command line tools, you can go ahead and use a hosted version running in our OpenShift cluster. Open a new browser tab and point it to:</p>
556</div>
557<div class="listingblock copypaste">
558<div class="content">
559<pre class="CodeRay highlight"><code data-lang="bash">http://terminal-infra.apps.mod-5b05.openshiftworkshop.com</code></pre>
560</div>
561</div>
562<div class="paragraph">
563<p>You will need to log in with your OpenShift user and click on <code>Allow selected permissions</code>. You can then continue with the workshop.</p>
564</div>
565</td>
566</tr>
567</table>
568</div>
569<div class="paragraph">
570<p>In order to log in, we will use the <code>oc</code> command and then specify the server that we
571want to authenticate to. Issue the following command:</p>
572</div>
573<div class="listingblock copypaste">
574<div class="content">
575<pre class="CodeRay highlight"><code data-lang="bash">oc login https://master.mod-5b05.openshiftworkshop.com</code></pre>
576</div>
577</div>
578<div class="paragraph">
579<p>You may see the following output:</p>
580</div>
581<div class="listingblock">
582<div class="content">
583<pre class="CodeRay highlight"><code data-lang="bash">The server uses a certificate signed by an unknown authority.
584You can bypass the certificate check, but any data you send to the server could be intercepted by others.
585Use insecure connections? (y/n):</code></pre>
586</div>
587</div>
588<div class="paragraph">
589<p>Enter in <strong>Y</strong> to use a potentially insecure connection. The reason you received
590this message is because we are using a self-signed certificate for this
591workshop, but we did not provide you with the CA certificate that was generated
592by OpenShift. In a real-world scenario, either OpenShift’s certificate would be
593signed by a standard CA (eg: Thawte, Verisign, StartSSL, etc.) or signed by a
594corporate-standard CA that you already have installed on your system.</p>
595</div>
596<div class="admonitionblock note">
597<table>
598<tr>
599<td class="icon">
600<i class="fa icon-note" title="Note"></i>
601</td>
602<td class="content">
603<div class="paragraph">
604<p>On some versions of Microsoft Windows, you may get an error that the
605server has an invalid x.509 certificate. If you receive this error, enter in
606the following command:</p>
607</div>
608<div class="listingblock">
609<div class="content">
610<pre class="CodeRay highlight"><code data-lang="bash">oc login https://master.mod-5b05.openshiftworkshop.com --insecure-skip-tls-verify=true</code></pre>
611</div>
612</div>
613</td>
614</tr>
615</table>
616</div>
617<div class="paragraph">
618<p>Once you issue the <code>oc login</code> command, you will be prompted for the username and
619password combination for your user account. Use the username and password combination provided to you by the instructor of this workshop:</p>
620</div>
621<div class="listingblock copypaste">
622<div class="content">
623<pre class="CodeRay highlight"><code data-lang="bash">Username: userXY
624Password: openshift</code></pre>
625</div>
626</div>
627<div class="paragraph">
628<p>Once you have authenticated to the OpenShift server, you will see the
629following confirmation message:</p>
630</div>
631<div class="listingblock">
632<div class="content">
633<pre class="CodeRay highlight"><code>Login successful.
634Using project "userXY".</code></pre>
635</div>
636</div>
637<div class="admonitionblock tip">
638<table>
639<tr>
640<td class="icon">
641<i class="fa icon-tip" title="Tip"></i>
642</td>
643<td class="content">
644<div class="paragraph">
645<p>If you don’t have any projects. You can try to create a new project, by running:</p>
646</div>
647<div class="listingblock">
648<div class="content">
649<pre class="CodeRay highlight"><code>oc new-project <projectname></code></pre>
650</div>
651</div>
652</td>
653</tr>
654</table>
655</div>
656<div class="paragraph">
657<p>Congratulations, you are now authenticated to the OpenShift server. The
658OpenShift master includes a built-in OAuth server. Developers and administrators
659obtain OAuth access tokens to authenticate themselves to the API. By default
660your authorization token will last for 24 hours. There is more information about
661the login command and its configuration in the <a href="https://docs.openshift.com/container-platform/latest/cli_reference/get_started_cli.html#basic-setup-and-login">OpenShift Documentation</a>.</p>
662</div>
663</div>
664</div>
665<div class="sect1">
666<h2 id="_using_a_project">Using a Project</h2>
667<div class="sectionbody">
668<div class="paragraph">
669<p>Projects are a top level concept to help you organize your deployments. An
670OpenShift project allows a community of users (or a user) to organize and manage
671their content in isolation from other communities. Each project has its own
672resources, policies (who can or cannot perform actions), and constraints (quotas
673and limits on resources, etc). Projects act as a "wrapper" around all the
674application services and endpoints you (or your teams) are using for your work.</p>
675</div>
676<div class="paragraph">
677<p>During this lab, we are going to use a few different commands to make sure that
678things in the environment are working as expected. Don’t worry if you don’t
679understand all of the terminology as we will cover it in detail in later labs.</p>
680</div>
681<div class="paragraph">
682<p>If you didn’t have a project already created for you, the first thing we want
683to do is create the <strong>userXY</strong> project. You can do this with the following command:</p>
684</div>
685<div class="admonitionblock caution">
686<table>
687<tr>
688<td class="icon">
689<i class="fa icon-caution" title="Caution"></i>
690</td>
691<td class="content">
692In the following command, replace <code>userXY</code> with the project provided to you.
693</td>
694</tr>
695</table>
696</div>
697<div class="listingblock copypaste">
698<div class="content">
699<pre class="CodeRay highlight"><code data-lang="bash">oc new-project userXY</code></pre>
700</div>
701</div>
702<div class="paragraph">
703<p>You will see the following confirmation message:</p>
704</div>
705<div class="listingblock">
706<div class="content">
707<pre class="CodeRay highlight"><code data-lang="bash">Now using project "userXY" on server "https://master.mod-5b05.openshiftworkshop.com".</code></pre>
708</div>
709</div>
710<div class="paragraph">
711<p>If you had multiple projects, the first thing you would want to do is to switch
712to the <strong>userXY</strong> project to make sure you’re on the correct project from now on.
713You can do this with the following command:</p>
714</div>
715<div class="admonitionblock caution">
716<table>
717<tr>
718<td class="icon">
719<i class="fa icon-caution" title="Caution"></i>
720</td>
721<td class="content">
722In the following command, replace <code>userXY</code> with the project provided to you.
723</td>
724</tr>
725</table>
726</div>
727<div class="listingblock copypaste">
728<div class="content">
729<pre class="CodeRay highlight"><code data-lang="bash">oc project userXY</code></pre>
730</div>
731</div>
732<div class="paragraph">
733<p>You will see the following confirmation message:</p>
734</div>
735<div class="listingblock">
736<div class="content">
737<pre class="CodeRay highlight"><code data-lang="bash">Now using project "userXY" on server "https://master.mod-5b05.openshiftworkshop.com".</code></pre>
738</div>
739</div>
740</div>
741</div>
742<div class="sect1">
743<h2 id="_the_web_console">The Web Console</h2>
744<div class="sectionbody">
745<div class="paragraph">
746<p>OpenShift ships with a web-based console that will allow users to
747perform various tasks via a browser. To get a feel for how the web console
748works, open your browser and go to the following URL:</p>
749</div>
750<div class="paragraph">
751<p><strong><a href="https://master.mod-5b05.openshiftworkshop.com" class="bare">https://master.mod-5b05.openshiftworkshop.com</a></strong></p>
752</div>
753<div class="paragraph">
754<p>The first screen you will see is the authentication screen. You will be prompted for the username and password combination for your user account. Use the username and password combination provided to you by the instructor of this workshop:</p>
755</div>
756<div class="listingblock copypaste">
757<div class="content">
758<pre class="CodeRay highlight"><code data-lang="bash">Username: userXY
759Password: openshift</code></pre>
760</div>
761</div>
762<div class="imageblock">
763<div class="content">
764<img src="/workshop/workshop/asset/images/ocp-login.png" alt="OpenShift Login Screen">
765</div>
766</div>
767<div class="paragraph">
768<p>After you have authenticated to the web console, you will be presented with a
769list of items that you can add to your project. This is called the service catalog. You will see
770something that looks like the following image:</p>
771</div>
772<div class="imageblock">
773<div class="content">
774<img src="/workshop/workshop/asset/images/explore-webconsole1sc.png" alt="Web Console">
775</div>
776</div>
777<div class="paragraph">
778<p>Click on the <strong>userXY</strong> project on the right hand side of the screen. When you click on the
779<strong>userXY</strong> project, you will be taken to the project overview page
780which will list all of the routes, services, deployments, and pods that you have
781running as part of your project. There’s nothing there now, but that’s about to
782change.</p>
783</div>
784<div class="imageblock">
785<div class="content">
786<img src="/workshop/workshop/asset/images/explore-webconsole2.png" alt="Explore Project">
787</div>
788</div>
789<div class="paragraph">
790<p>When the provided cluster has metrics aggregation capabilities configured you might see an
791error in the web console (when the cluster uses self signed certificates):</p>
792</div>
793<div class="imageblock">
794<div class="content">
795<img src="/workshop/workshop/asset/images/explore-webconsole2-error.png" alt="Web Console">
796</div>
797</div>
798<div class="paragraph">
799<p>Click the link that says <strong>Open metrics URL</strong>, and accept the certificate.</p>
800</div>
801<div class="imageblock">
802<div class="content">
803<img src="/workshop/workshop/asset/images/explore-acceptcertificate.png" alt="Acept Certificates">
804</div>
805</div>
806<div class="paragraph">
807<p>We need to accept another self-signed certificate for OpenShift’s metrics
808aggregation. If we don’t, then the metrics will not display in the OpenShift UI.</p>
809</div>
810<div class="imageblock">
811<div class="content">
812<img src="/workshop/workshop/asset/images/explore-hawkular.png" alt="Hawkular web">
813</div>
814</div>
815<div class="paragraph">
816<p>We will be using a mix of command line tooling and the web console for the labs.
817Get ready!</p>
818</div>
819</div>
820</div>
821 <hr>
822 <h2>Architecture Overview of the ParksMap Application</h2>
823 <div class="paragraph">
824<p>This lab introduces you to the architecture of the ParksMap application used throughout this workshop, to get a better understanding of the things you’ll be doing from a developer perspective. ParksMap is a polyglot geo-spatial data visualization application built using the microservices architecture and is composed of a set of services which are developed using different programming languages and frameworks.</p>
825</div>
826<div class="imageblock text-center">
827<div class="content">
828<img src="/workshop/workshop/asset/images/roadshow-app-architecture.png" alt="Application architecture" width="800">
829</div>
830</div>
831<div class="paragraph">
832<p>The main service is a web application which has a server-side component in charge of aggregating the geo-spatial APIs provided by multiple independent backend services and a client-side component in JavaScript that is responsible for visualizing the geo-spatial data on the map. The client-side component which runs in your browser communicates with the server-side via WebSockets protocol in order to update the map in real-time.</p>
833</div>
834<div class="paragraph">
835<p>There will be a set of independent backend services deployed that will provide different mapping and geo-spatial information. The set of available backend services that provide geo-spatial information are:</p>
836</div>
837<div class="ulist">
838<ul>
839<li>
840<p>WorldWide National Parks</p>
841</li>
842<li>
843<p>Major League Baseball Stadiums in the US</p>
844</li>
845<li>
846<p>International Airports</p>
847</li>
848<li>
849<p>Earthquakes epicenters in New Zealand in November 2017</p>
850</li>
851<li>
852<p>Aussie Dunnies</p>
853</li>
854</ul>
855</div>
856<div class="paragraph">
857<p>The original source code for this application is located <a href="https://github.com/openshift-roadshow/">here</a>.</p>
858</div>
859<div class="paragraph">
860<p>The server-side component of the ParksMap web application acts as a communication gateway to all the available backends. These backends will be dynamically discovered by using service discovery mechanisms provided by OpenShift which will be discussed in more details in the following labs.</p>
861</div>
862 <hr>
863 <h2>Deploying Your First Container Image</h2>
864 <div class="paragraph">
865<p>In this lab, we’re going to deploy the web component of the ParksMap application which is also called <code>parksmap</code> and uses OpenShift’s service discovery mechanism to discover the backend services deployed and shows their data on the map.</p>
866</div>
867<div class="imageblock text-center">
868<div class="content">
869<img src="/workshop/workshop/asset/images/roadshow-app-architecture-parksmap-1.png" alt="Application architecture" width="800">
870</div>
871</div>
872<div class="sect1">
873<h2 id="_exercise_deploying_your_first_image">Exercise: Deploying your First Image</h2>
874<div class="sectionbody">
875<div class="paragraph">
876<p>Let’s start by doing the simplest thing possible - get a plain old
877Docker-formatted image to run on OpenShift. This is incredibly simple to do.
878With OpenShift it can be done directly from the web console.</p>
879</div>
880<div class="paragraph">
881<p>Return to the web console:</p>
882</div>
883<div class="paragraph">
884<p><strong><a href="https://master.mod-5b05.openshiftworkshop.com" class="bare">https://master.mod-5b05.openshiftworkshop.com</a></strong></p>
885</div>
886<div class="admonitionblock caution">
887<table>
888<tr>
889<td class="icon">
890<i class="fa icon-caution" title="Caution"></i>
891</td>
892<td class="content">
893In the following steps, replace <code>userXY</code> with the project provided to you.
894</td>
895</tr>
896</table>
897</div>
898<div class="paragraph">
899<p>Find your <strong>userXY</strong> project and click it. On the next page, click <strong>"Add to Project"</strong> and a drop down menu will appear. There are several options, but we are only concerned with "Deploy Image". Click "Deploy Image" in the <strong>"Add to Project"</strong> drop down.</p>
900</div>
901<div class="imageblock">
902<div class="content">
903<img src="/workshop/workshop/asset/images/parksmap-add-to-project-dialog.png" alt="Add to Project">
904</div>
905</div>
906<div class="paragraph">
907<p>This will open a dialog that will allow you to specify the information for the image you want to deploy. We will learn more about image streams and image stream tags later. For now,
908select the "Image Name" option, and copy/paste the following into the box:</p>
909</div>
910<div class="listingblock">
911<div class="content">
912<pre class="CodeRay highlight"><code>docker.io/openshiftroadshow/parksmap:1.2.0</code></pre>
913</div>
914</div>
915<div class="paragraph">
916<p>Your screen will end up looking something like this:</p>
917</div>
918<div class="imageblock">
919<div class="content">
920<img src="/workshop/workshop/asset/images/parksmap-image.png" alt="Explore Project">
921</div>
922</div>
923<div class="paragraph">
924<p>Either press <strong>enter</strong> or click on the magnifying glass. OpenShift will then go
925out to the Docker registry specified and interrogate the image. You then are
926presented with some options to add things like environment variables, labels,
927and etc. — which we will learn about later.</p>
928</div>
929<div class="paragraph">
930<p>Make sure to have the correct application name:</p>
931</div>
932<div class="imageblock">
933<div class="content">
934<img src="/workshop/workshop/asset/images/parksmap-image-options.png" alt="Explore Project">
935</div>
936</div>
937<div class="paragraph">
938<p>Let’s scroll to the bottom of this page and add some labels to better identify
939this deployment later. Labels will help us identify and filter components in the
940web UI and in the command line.</p>
941</div>
942<div class="paragraph">
943<p>We will add 3 labels:</p>
944</div>
945<div class="ulist">
946<ul>
947<li>
948<p><strong><em>app</em>=workshop</strong> (the name we will be giving to the app)</p>
949</li>
950<li>
951<p><strong><em>component</em>=parksmap</strong> (the name of this deployment)</p>
952</li>
953<li>
954<p><strong><em>role</em>=frontend</strong> (the role this component plays in the overall application)</p>
955</li>
956</ul>
957</div>
958<div class="imageblock">
959<div class="content">
960<img src="/workshop/workshop/asset/images/parksmap-image-options-labels.png" alt="Explore Project">
961</div>
962</div>
963<div class="paragraph">
964<p>Hit the blue "Deploy" button at the bottom of the dialog and then click the
965"Continue to the project overview." link or the "Close" button. Take a moment to look at the various messages that
966you now see on the overview page.</p>
967</div>
968<div class="paragraph">
969<p>WINNING! These few steps are the only ones you need to run to get a
970container image deployed on OpenShift. This should work with any
971container image that follows best practices, such as defining an EXPOSE
972port, not needing to run specifically as the <strong>root user</strong> or other user name, and
973a single non-exiting CMD to execute on start.</p>
974</div>
975<div class="admonitionblock note">
976<table>
977<tr>
978<td class="icon">
979<i class="fa icon-note" title="Note"></i>
980</td>
981<td class="content">
982Providing appropriate labels is desired when deploying complex applications for organization purposes. OpenShift uses a label <strong>app</strong> to define and group components together in the Overview page. OpenShift will create this label with some default if the user don’t provide it explicitly.
983</td>
984</tr>
985</table>
986</div>
987</div>
988</div>
989<div class="sect1">
990<h2 id="_background_containers_and_pods">Background: Containers and Pods</h2>
991<div class="sectionbody">
992<div class="paragraph">
993<p>Before we start digging in, we need to understand how containers and <strong>Pods</strong> are
994related. We will not be covering the background on these technologies in this lab but if you have questions please inform the instructor. Instead, we will dive right in and start using them.</p>
995</div>
996<div class="paragraph">
997<p>In OpenShift, the smallest deployable unit is a <strong>Pod</strong>. A <strong>Pod</strong> is a group of one or more OCI containers deployed together and guaranteed to be on the same host.
998From the official OpenShift documentation:</p>
999</div>
1000<div class="quoteblock">
1001<blockquote>
1002<em>
1003Each pod has its own IP address, therefore owning its entire port space, and
1004containers within pods can share storage. Pods can be "tagged" with one or
1005more labels, which are then used to select and manage groups of pods in a
1006single operation.
1007</em>
1008</blockquote>
1009</div>
1010<div class="paragraph">
1011<p><strong>Pods</strong> can contain multiple OCI containers. The general idea is for a Pod to
1012contain a "main process" and any auxiliary services you want to run along with that process. Examples of containers you might put in a <strong>Pod</strong> are, an Apache HTTPD
1013server, a log analyzer, and a file service to help manage uploaded files.</p>
1014</div>
1015</div>
1016</div>
1017<div class="sect1">
1018<h2 id="_exercise_examining_the_pod">Exercise: Examining the Pod</h2>
1019<div class="sectionbody">
1020<div class="paragraph">
1021<p>In the web console’s overview page you will see that there is a single <strong>Pod</strong> that
1022was created by your actions.</p>
1023</div>
1024<div class="imageblock">
1025<div class="content">
1026<img src="/workshop/workshop/asset/images/parksmap-overview.png" alt="Pod overview">
1027</div>
1028</div>
1029<div class="paragraph">
1030<p>You can also get a list of all the pods created within your project, by navigating to
1031"Applications → Pods"</p>
1032</div>
1033<div class="imageblock">
1034<div class="content">
1035<img src="/workshop/workshop/asset/images/parksmap-podlist.png" alt="Pod list">
1036</div>
1037</div>
1038<div class="paragraph">
1039<p>This <strong>Pod</strong> contains a single container, which
1040happens to be the <code>parksmap</code> application - a simple Spring Boot/Java application.</p>
1041</div>
1042<div class="paragraph">
1043<p>You can also examine <strong>Pods</strong> from the command line:</p>
1044</div>
1045<div class="listingblock copypaste">
1046<div class="content">
1047<pre class="CodeRay highlight"><code data-lang="bash">oc get pods</code></pre>
1048</div>
1049</div>
1050<div class="paragraph">
1051<p>You should see output that looks similar to:</p>
1052</div>
1053<div class="listingblock">
1054<div class="content">
1055<pre class="CodeRay highlight"><code data-lang="bash">NAME READY STATUS RESTARTS AGE
1056parksmap-1-hx0kv 1/1 Running 0 2m</code></pre>
1057</div>
1058</div>
1059<div class="paragraph">
1060<p>The above output lists all of the <strong>Pods</strong> in the current <strong>Project</strong>, including the
1061<strong>Pod</strong> name, state, restarts, and uptime. Once you have a <strong>Pod</strong>'s name, you can
1062get more information about the <strong>Pod</strong> using the <strong>oc get</strong> command. To make the
1063output readable, I suggest changing the output type to <strong>YAML</strong> using the
1064following syntax:</p>
1065</div>
1066<div class="admonitionblock note">
1067<table>
1068<tr>
1069<td class="icon">
1070<i class="fa icon-note" title="Note"></i>
1071</td>
1072<td class="content">
1073Make sure you use the correct <strong>Pod</strong> name from your output.
1074</td>
1075</tr>
1076</table>
1077</div>
1078<div class="listingblock copypaste">
1079<div class="content">
1080<pre class="CodeRay highlight"><code data-lang="bash">oc get pod parksmap-1-hx0kv -o yaml</code></pre>
1081</div>
1082</div>
1083<div class="paragraph">
1084<p>You should see something like the following output (which has been truncated due
1085to space considerations of this workshop manual):</p>
1086</div>
1087<div class="listingblock">
1088<div class="content">
1089<pre class="CodeRay highlight"><code data-lang="bash">apiVersion: v1
1090kind: Pod
1091metadata:
1092 annotations:
1093 kubernetes.io/created-by: |
1094 {"kind":"SerializedReference","apiVersion":"v1","reference":{"kind":"ReplicationController","namespace":"explore-00","name":"parksmap-1","uid":"f1b37b1b-e3e2-11e6-81a2-0696d1181070","apiVersion":"v1","reso
1095urceVersion":"36222"}}
1096 kubernetes.io/limit-ranger: 'LimitRanger plugin set: cpu, memory request for container
1097 parksmap; cpu, memory limit for container parksmap'
1098 openshift.io/deployment-config.latest-version: "1"
1099 openshift.io/deployment-config.name: parksmap
1100 openshift.io/deployment.name: parksmap-1
1101 openshift.io/generated-by: OpenShiftWebConsole
1102 openshift.io/scc: restricted
1103 creationTimestamp: 2017-01-26T16:17:36Z
1104 generateName: parksmap-1-
1105 labels:
1106 app: parksmap
1107 deployment: parksmap-1
1108 deploymentconfig: parksmap
1109 name: parksmap-1-bvaz6
1110...............</code></pre>
1111</div>
1112</div>
1113<div class="paragraph">
1114<p>The web interface also shows a lot of the same information on the <strong>Pod</strong> details
1115page. If you click in the <strong>Pod</strong> circle, you will
1116find the details page. You can also get there by clicking "Applications", then
1117"Pods", at the left, and then clicking the <strong>Pod</strong> name.</p>
1118</div>
1119<div class="imageblock">
1120<div class="content">
1121<img src="/workshop/workshop/asset/images/parksmap-pod.png" alt="Pod list">
1122</div>
1123</div>
1124<div class="paragraph">
1125<p>Getting the parksmap image running may take a little while to complete. Each
1126OpenShift node that is asked to run the image has to pull (download) it, if the
1127node does not already have it cached locally. You can check on the status of the
1128image download and deployment in the <strong>Pod</strong> details page, or from the command
1129line with the <code>oc get pods</code> command that you used before.</p>
1130</div>
1131</div>
1132</div>
1133<div class="sect1">
1134<h2 id="_background_customizing_the_image_lifecycle_behavior">Background: Customizing the Image Lifecycle Behavior</h2>
1135<div class="sectionbody">
1136<div class="paragraph">
1137<p>Whenever OpenShift asks the node’s CRI (Container Runtime Interface) runtime (Docker daemon or CRI-O) to run an image, the runtime will check to make sure it has the right "version" of the image to run.
1138If it doesn’t, it will pull it from the specified registry.</p>
1139</div>
1140<div class="paragraph">
1141<p>There are a number of ways to customize this behavior. They are documented in
1142<a href="https://docs.openshift.com/container-platform/latest/dev_guide/application_lifecycle/new_app.html#specifying-an-image">specifying an image</a>
1143as well as
1144<a href="https://docs.openshift.com/container-platform/latest/dev_guide/managing_images.html#image-pull-policy">image pull policy</a>.</p>
1145</div>
1146</div>
1147</div>
1148<div class="sect1">
1149<h2 id="_background_services">Background: Services</h2>
1150<div class="sectionbody">
1151<div class="paragraph">
1152<p><strong>Services</strong> provide a convenient abstraction layer inside OpenShift to find a
1153group of similar <strong>Pods</strong>. They also act as an internal proxy/load balancer between
1154those <strong>Pods</strong> and anything else that needs to access them from inside the
1155OpenShift environment. For example, if you needed more parksmap instances to
1156handle the load, you could spin up more <strong>Pods</strong>. OpenShift automatically maps
1157them as endpoints to the <strong>Service</strong>, and the incoming requests would not notice
1158anything different except that the <strong>Service</strong> was now doing a better job handling
1159the requests.</p>
1160</div>
1161<div class="paragraph">
1162<p>When you asked OpenShift to run the image, it automatically created a <strong>Service</strong>
1163for you. Remember that services are an internal construct. They are not
1164available to the "outside world", or anything that is outside the OpenShift
1165environment. That’s okay, as you will learn later.</p>
1166</div>
1167<div class="paragraph">
1168<p>The way that a <strong>Service</strong> maps to a set of <strong>Pods</strong> is via a system of <strong>Labels</strong> and
1169<strong>Selectors</strong>. <strong>Services</strong> are assigned a fixed IP address and many ports and
1170protocols can be mapped.</p>
1171</div>
1172<div class="paragraph">
1173<p>There is a lot more information about
1174<a href="https://docs.openshift.com/container-platform/latest/architecture/core_concepts/pods_and_services.html#services">Services</a>,
1175including the YAML format to make one by hand, in the official documentation.</p>
1176</div>
1177<div class="paragraph">
1178<p>Now that we understand the basics of what a <strong>Service</strong> is, let’s take a look at
1179the <strong>Service</strong> that was created for the image that we just deployed. In order to
1180view the <strong>Services</strong> defined in your <strong>Project</strong>, enter in the following command:</p>
1181</div>
1182<div class="listingblock copypaste">
1183<div class="content">
1184<pre class="CodeRay highlight"><code data-lang="bash">oc get services</code></pre>
1185</div>
1186</div>
1187<div class="paragraph">
1188<p>You should see output similar to the following:</p>
1189</div>
1190<div class="listingblock">
1191<div class="content">
1192<pre class="CodeRay highlight"><code data-lang="bash">NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
1193parksmap ClusterIP 172.30.169.213 <none> 8080/TCP 3h</code></pre>
1194</div>
1195</div>
1196<div class="paragraph">
1197<p>In the above output, we can see that we have a <strong>Service</strong> named <code>parksmap</code> with an
1198IP/Port combination of 172.30.169.213/8080TCP. Your IP address may be different, as
1199each <strong>Service</strong> receives a unique IP address upon creation. <strong>Service</strong> IPs are
1200fixed and never change for the life of the <strong>Service</strong>.</p>
1201</div>
1202<div class="paragraph">
1203<p>In the web console, service information is available by clicking "Applications"
1204and then clicking "Services".</p>
1205</div>
1206<div class="imageblock">
1207<div class="content">
1208<img src="/workshop/workshop/asset/images/parksmap-serviceslist.png" alt="Services list">
1209</div>
1210</div>
1211<div class="paragraph">
1212<p>You can also get more detailed information about a <strong>Service</strong> by using the
1213following command to display the data in YAML:</p>
1214</div>
1215<div class="listingblock copypaste">
1216<div class="content">
1217<pre class="CodeRay highlight"><code data-lang="bash">oc get service parksmap -o yaml</code></pre>
1218</div>
1219</div>
1220<div class="paragraph">
1221<p>You should see output similar to the following:</p>
1222</div>
1223<div class="listingblock">
1224<div class="content">
1225<pre class="CodeRay highlight"><code data-lang="bash">apiVersion: v1
1226kind: Service
1227metadata:
1228 annotations:
1229 openshift.io/generated-by: OpenShiftWebConsole
1230 creationTimestamp: 2016-10-03T15:33:17Z
1231 labels:
1232 app: parksmap
1233 name: parksmap
1234 namespace: userXY
1235 resourceVersion: "6893"
1236 selfLink: /api/v1/namespaces/userXY/services/parksmap
1237 uid: b51260a9-897e-11e6-bdaa-2cc2602f8794
1238spec:
1239 clusterIP: 172.30.169.213
1240 ports:
1241 - name: 8080-tcp
1242 port: 8080
1243 protocol: TCP
1244 targetPort: 8080
1245 selector:
1246 deploymentconfig: parksmap
1247 sessionAffinity: None
1248 type: ClusterIP
1249status:
1250 loadBalancer: {}</code></pre>
1251</div>
1252</div>
1253<div class="paragraph">
1254<p>Take note of the <code>selector</code> stanza. Remember it.</p>
1255</div>
1256<div class="paragraph">
1257<p>Alternatively, you can use the web console to view information about the <strong>Service</strong>.</p>
1258</div>
1259<div class="imageblock">
1260<div class="content">
1261<img src="/workshop/workshop/asset/images/parksmap-service.png" alt="Service">
1262</div>
1263</div>
1264<div class="paragraph">
1265<p>It is also of interest to view the YAML of the <strong>Pod</strong> to understand how OpenShift
1266wires components together. For example, run the following command to get the
1267name of your <code>parksmap</code> <strong>Pod</strong>:</p>
1268</div>
1269<div class="listingblock copypaste">
1270<div class="content">
1271<pre class="CodeRay highlight"><code data-lang="bash">oc get pods</code></pre>
1272</div>
1273</div>
1274<div class="paragraph">
1275<p>You should see output similar to the following:</p>
1276</div>
1277<div class="listingblock">
1278<div class="content">
1279<pre class="CodeRay highlight"><code data-lang="bash">NAME READY STATUS RESTARTS AGE
1280parksmap-1-hx0kv 1/1 Running 0 3h</code></pre>
1281</div>
1282</div>
1283<div class="paragraph">
1284<p>Now you can view the detailed data for your <strong>Pod</strong> with the following command:</p>
1285</div>
1286<div class="listingblock copypaste">
1287<div class="content">
1288<pre class="CodeRay highlight"><code data-lang="bash">oc get pod parksmap-1-hx0kv -o yaml</code></pre>
1289</div>
1290</div>
1291<div class="paragraph">
1292<p>Under the <code>metadata</code> section you should see the following:</p>
1293</div>
1294<div class="listingblock">
1295<div class="content">
1296<pre class="CodeRay highlight"><code data-lang="bash"> labels:
1297 app: workshop
1298 component: parksmap
1299 deployment: parksmap-1
1300 deploymentconfig: parksmap
1301 role: frontend</code></pre>
1302</div>
1303</div>
1304<div class="ulist">
1305<ul>
1306<li>
1307<p>The <strong>Service</strong> has <code>selector</code> stanza that refers to <code>deploymentconfig=parksmap</code>.</p>
1308</li>
1309<li>
1310<p>The <strong>Pod</strong> has multiple <strong>Labels</strong>:</p>
1311<div class="ulist">
1312<ul>
1313<li>
1314<p><code>app=workshop</code></p>
1315</li>
1316<li>
1317<p><code>component=parksmap</code></p>
1318</li>
1319<li>
1320<p><code>role=frontend</code></p>
1321</li>
1322<li>
1323<p><code>deploymentconfig=parksmap</code></p>
1324</li>
1325<li>
1326<p><code>deployment=parksmap-1</code></p>
1327</li>
1328</ul>
1329</div>
1330</li>
1331</ul>
1332</div>
1333<div class="paragraph">
1334<p><strong>Labels</strong> are just key/value pairs. Any <strong>Pod</strong> in this <strong>Project</strong> that has a <strong>Label</strong> that
1335matches the <strong>Selector</strong> will be associated with the <strong>Service</strong>. To see this in
1336action, issue the following command:</p>
1337</div>
1338<div class="listingblock copypaste">
1339<div class="content">
1340<pre class="CodeRay highlight"><code data-lang="bash">oc describe service parksmap</code></pre>
1341</div>
1342</div>
1343<div class="paragraph">
1344<p>You should see something like the following output:</p>
1345</div>
1346<div class="listingblock">
1347<div class="content">
1348<pre class="CodeRay highlight"><code data-lang="bash">Name: parksmap
1349Namespace: userXY
1350Labels: app=workshop
1351 component=parksmap
1352 role=frontend
1353Selector: deploymentconfig=parksmap
1354Type: ClusterIP
1355IP: 172.30.169.213
1356Port: 8080-tcp 8080/TCP
1357Endpoints: 10.1.2.5:8080
1358Session Affinity: None
1359Events: <none></code></pre>
1360</div>
1361</div>
1362<div class="paragraph">
1363<p>You may be wondering why only one endpoint is listed. That is because there is
1364only one <strong>Pod</strong> currently running. In the next lab, we will learn how to scale
1365an application, at which point you will be able to see multiple endpoints
1366associated with the <strong>Service</strong>.</p>
1367</div>
1368</div>
1369</div>
1370 <hr>
1371 <h2>Scaling and Self Healing</h2>
1372 <div class="sect1">
1373<h2 id="_background_deployment_configurations_and_replication_controllers">Background: Deployment Configurations and Replication Controllers</h2>
1374<div class="sectionbody">
1375<div class="paragraph">
1376<p>While <strong>Services</strong> provide routing and load balancing for <strong>Pods</strong>, which may go in and
1377out of existence, <strong>ReplicationControllers</strong> (RC) are used to specify and then
1378ensure the desired number of <strong>Pods</strong> (replicas) are in existence. For example, if
1379you always want your application server to be scaled to 3 <strong>Pods</strong> (instances), a
1380<strong>ReplicationController</strong> is needed. Without an RC, any <strong>Pods</strong> that are killed or
1381somehow die/exit are not automatically restarted. <strong>ReplicationControllers</strong> are
1382how OpenShift "self heals".</p>
1383</div>
1384<div class="paragraph">
1385<p>A <strong>DeploymentConfiguration</strong> (DC) defines how something in OpenShift should be
1386deployed. From the <a href="https://docs.openshift.com/container-platform/latest/architecture/core_concepts/deployments.html#deployments-and-deployment-configurations">deployments documentation</a>:</p>
1387</div>
1388<div class="quoteblock">
1389<blockquote>
1390<em>
1391Building on replication controllers, OpenShift adds expanded support for the
1392software development and deployment lifecycle with the concept of deployments.
1393In the simplest case, a deployment just creates a new replication controller and
1394lets it start up pods. However, OpenShift deployments also provide the ability
1395to transition from an existing deployment of an image to a new one and also
1396define hooks to be run before or after creating the replication controller.
1397</em>
1398</blockquote>
1399</div>
1400<div class="paragraph">
1401<p>In almost all cases, you will end up using the <strong>Pod</strong>, <strong>Service</strong>,
1402<strong>ReplicationController</strong> and <strong>DeploymentConfiguration</strong> resources together. And, in
1403almost all of those cases, OpenShift will create all of them for you.</p>
1404</div>
1405<div class="paragraph">
1406<p>There are some edge cases where you might want some <strong>Pods</strong> and an <strong>RC</strong> without a <strong>DC</strong>
1407or a <strong>Service</strong>, and others, so feel free to ask us about them after the labs.</p>
1408</div>
1409</div>
1410</div>
1411<div class="sect1">
1412<h2 id="_exercise_exploring_deployment_related_objects">Exercise: Exploring Deployment-related Objects</h2>
1413<div class="sectionbody">
1414<div class="paragraph">
1415<p>Now that we know the background of what a <strong>ReplicatonController</strong> and
1416<strong>DeploymentConfig</strong> are, we can explore how they work and are related. Take a
1417look at the <strong>DeploymentConfig</strong> (DC) that was created for you when you told
1418OpenShift to stand up the <code>parksmap</code> image:</p>
1419</div>
1420<div class="listingblock copypaste">
1421<div class="content">
1422<pre class="CodeRay highlight"><code data-lang="bash">oc get dc</code></pre>
1423</div>
1424</div>
1425<div class="listingblock">
1426<div class="content">
1427<pre class="CodeRay highlight"><code data-lang="bash">NAME REVISION DESIRED CURRENT TRIGGERED BY
1428parksmap 1 1 1 config,image(parksmap:1.2.0)</code></pre>
1429</div>
1430</div>
1431<div class="paragraph">
1432<p>To get more details, we can look into the <strong>ReplicationController</strong> (<strong>RC</strong>).</p>
1433</div>
1434<div class="paragraph">
1435<p>Take a look at the <strong>ReplicationController</strong> (RC) that was created for you when
1436you told OpenShift to stand up the <code>parksmap</code> image:</p>
1437</div>
1438<div class="listingblock copypaste">
1439<div class="content">
1440<pre class="CodeRay highlight"><code data-lang="bash">oc get rc</code></pre>
1441</div>
1442</div>
1443<div class="listingblock">
1444<div class="content">
1445<pre class="CodeRay highlight"><code data-lang="bash">NAME DESIRED CURRENT READY AGE
1446parksmap-1 1 1 0 4h</code></pre>
1447</div>
1448</div>
1449<div class="paragraph">
1450<p>This lets us know that, right now, we expect one <strong>Pod</strong> to be deployed
1451(<code>Desired</code>), and we have one <strong>Pod</strong> actually deployed (<code>Current</code>). By changing
1452the desired number, we can tell OpenShift that we want more or less <strong>Pods</strong>.</p>
1453</div>
1454<div class="paragraph">
1455<p>OpenShift’s <strong>HorizontalPodAutoscaler</strong> effectively monitors the CPU usage of a
1456set of instances and then manipulates the RCs accordingly.</p>
1457</div>
1458<div class="paragraph">
1459<p>You can learn more about the CPU-based
1460<a href="https://docs.openshift.com/container-platform/latest/dev_guide/pod_autoscaling.html">Horizontal Pod Autoscaler here</a></p>
1461</div>
1462</div>
1463</div>
1464<div class="sect1">
1465<h2 id="_exercise_scaling_the_application">Exercise: Scaling the Application</h2>
1466<div class="sectionbody">
1467<div class="paragraph">
1468<p>Let’s scale our parksmap "application" up to 2 instances. We can do this with
1469the <code>scale</code> command. You could also do this by clicking the "up" arrow next to
1470the <strong>Pod</strong> in the OpenShift web console on the overview page. It’s your choice.</p>
1471</div>
1472<div class="listingblock copypaste">
1473<div class="content">
1474<pre class="CodeRay highlight"><code data-lang="bash">$ oc scale --replicas=2 dc/parksmap</code></pre>
1475</div>
1476</div>
1477<div class="paragraph">
1478<p>You can also scale up to two pods by clicking the up arrow in the web console as shown in the following image:</p>
1479</div>
1480<div class="imageblock">
1481<div class="content">
1482<img src="/workshop/workshop/asset/images/parksmap-scaleup.png" alt="Scaling">
1483</div>
1484</div>
1485<div class="paragraph">
1486<p>To verify that we changed the number of replicas, issue the following command:</p>
1487</div>
1488<div class="listingblock copypaste">
1489<div class="content">
1490<pre class="CodeRay highlight"><code data-lang="bash">oc get rc</code></pre>
1491</div>
1492</div>
1493<div class="listingblock">
1494<div class="content">
1495<pre class="CodeRay highlight"><code data-lang="bash">NAME DESIRED CURRENT READY AGE
1496parksmap-1 2 2 0 4h</code></pre>
1497</div>
1498</div>
1499<div class="paragraph">
1500<p>You can see that we now have 2 replicas. Let’s verify the number of pods with
1501the <code>oc get pods</code> command:</p>
1502</div>
1503<div class="listingblock copypaste">
1504<div class="content">
1505<pre class="CodeRay highlight"><code data-lang="bash">oc get pods</code></pre>
1506</div>
1507</div>
1508<div class="listingblock">
1509<div class="content">
1510<pre class="CodeRay highlight"><code data-lang="bash">NAME READY STATUS RESTARTS AGE
1511parksmap-1-8g6lb 1/1 Running 0 1m
1512parksmap-1-hx0kv 1/1 Running 0 4h</code></pre>
1513</div>
1514</div>
1515<div class="paragraph">
1516<p>And lastly, let’s verify that the <strong>Service</strong> that we learned about in the
1517previous lab accurately reflects two endpoints:</p>
1518</div>
1519<div class="listingblock copypaste">
1520<div class="content">
1521<pre class="CodeRay highlight"><code data-lang="bash">oc describe svc parksmap</code></pre>
1522</div>
1523</div>
1524<div class="paragraph">
1525<p>You will see something like the following output:</p>
1526</div>
1527<div class="listingblock">
1528<div class="content">
1529<pre class="CodeRay highlight"><code data-lang="bash">Name: parksmap
1530Namespace: userXY
1531Labels: app=workshop
1532 component=parksmap
1533 role=frontend
1534Selector: deploymentconfig=parksmap
1535Type: ClusterIP
1536IP: 172.30.169.213
1537Port: 8080-tcp 8080/TCP
1538TargetPort: 8080/TCP
1539Endpoints: 10.1.0.5:8080,10.1.1.5:8080
1540Session Affinity: None
1541Events: <none></code></pre>
1542</div>
1543</div>
1544<div class="paragraph">
1545<p>Another way to look at a <strong>Service</strong>'s endpoints is with the following:</p>
1546</div>
1547<div class="listingblock copypaste">
1548<div class="content">
1549<pre class="CodeRay highlight"><code data-lang="bash">oc get endpoints parksmap</code></pre>
1550</div>
1551</div>
1552<div class="paragraph">
1553<p>And you will see something like the following:</p>
1554</div>
1555<div class="listingblock">
1556<div class="content">
1557<pre class="CodeRay highlight"><code data-lang="bash">NAME ENDPOINTS AGE
1558parksmap 10.1.0.5:8080,10.1.1.5:8080 4h</code></pre>
1559</div>
1560</div>
1561<div class="paragraph">
1562<p>Your IP addresses will likely be different, as each pod receives a unique IP
1563within the OpenShift environment. The endpoint list is a quick way to see how
1564many pods are behind a service.</p>
1565</div>
1566<div class="paragraph">
1567<p>You can also see that both <strong>Pods</strong> are running using the web console:</p>
1568</div>
1569<div class="imageblock">
1570<div class="content">
1571<img src="/workshop/workshop/asset/images/parksmap-scaled.png" alt="Scaling">
1572</div>
1573</div>
1574<div class="paragraph">
1575<p>Overall, that’s how simple it is to scale an application (<strong>Pods</strong> in a
1576<strong>Service</strong>). Application scaling can happen extremely quickly because OpenShift
1577is just launching new instances of an existing image, especially if that image
1578is already cached on the node.</p>
1579</div>
1580</div>
1581</div>
1582<div class="sect1">
1583<h2 id="_application_self_healing">Application "Self Healing"</h2>
1584<div class="sectionbody">
1585<div class="paragraph">
1586<p>Because OpenShift’s <strong>RCs</strong> are constantly monitoring to see that the desired number
1587of <strong>Pods</strong> actually are running, you might also expect that OpenShift will "fix" the
1588situation if it is ever not right. You would be correct!</p>
1589</div>
1590<div class="paragraph">
1591<p>Since we have two <strong>Pods</strong> running right now, let’s see what happens if we
1592"accidentally" kill one. Run the <code>oc get pods</code> command again, and choose a <strong>Pod</strong>
1593name. Then, do the following:</p>
1594</div>
1595<div class="listingblock copypaste">
1596<div class="content">
1597<pre class="CodeRay highlight"><code data-lang="bash">oc delete pod parksmap-1-hx0kv && oc get pods</code></pre>
1598</div>
1599</div>
1600<div class="listingblock">
1601<div class="content">
1602<pre class="CodeRay highlight"><code data-lang="bash">pod "parksmap-1-h45hj" deleted
1603NAME READY STATUS RESTARTS AGE
1604parksmap-1-h45hj 1/1 Terminating 0 4m
1605parksmap-1-q4b4r 0/1 ContainerCreating 0 1s
1606parksmap-1-vdkd9 1/1 Running 0 32s</code></pre>
1607</div>
1608</div>
1609<div class="paragraph">
1610<p>Did you notice anything? There is a container being terminated (the one we deleted),
1611and there’s a new container already being created.</p>
1612</div>
1613<div class="paragraph">
1614<p>Also, the names of the <strong>Pods</strong> are slightly changed.
1615That’s because OpenShift almost immediately detected that the current state (1
1616<strong>Pod</strong>) didn’t match the desired state (2 <strong>Pods</strong>), and it fixed it by scheduling
1617another <strong>Pod</strong>.</p>
1618</div>
1619<div class="paragraph">
1620<p>Additionally, OpenShift provides rudimentary capabilities around checking the
1621liveness and/or readiness of application instances. If the basic checks are
1622insufficient, OpenShift also allows you to run a command inside the container in
1623order to perform the check. That command could be a complicated script that uses
1624any installed language.</p>
1625</div>
1626<div class="paragraph">
1627<p>Based on these health checks, if OpenShift decided that our <code>parksmap</code>
1628application instance wasn’t alive, it would kill the instance and then restart
1629it, always ensuring that the desired number of replicas was in place.</p>
1630</div>
1631<div class="paragraph">
1632<p>More information on probing applications is available in the
1633<a href="https://docs.openshift.com/container-platform/latest/dev_guide/application_health.html">Application
1634Health</a> section of the documentation and later in this guide.</p>
1635</div>
1636</div>
1637</div>
1638<div class="sect1">
1639<h2 id="_exercise_scale_down">Exercise: Scale Down</h2>
1640<div class="sectionbody">
1641<div class="paragraph">
1642<p>Before we continue, go ahead and scale your application down to a single
1643instance. Feel free to do this using whatever method you like.</p>
1644</div>
1645<div class="admonitionblock warning">
1646<table>
1647<tr>
1648<td class="icon">
1649<i class="fa icon-warning" title="Warning"></i>
1650</td>
1651<td class="content">
1652Don’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.
1653</td>
1654</tr>
1655</table>
1656</div>
1657</div>
1658</div>
1659 <hr>
1660 <h2>Exposing Your Application to the Outside World</h2>
1661 <div class="paragraph">
1662<p>In this lab, we’re going to make our application visible to the end users, so they can access it.</p>
1663</div>
1664<div class="imageblock text-center">
1665<div class="content">
1666<img src="/workshop/workshop/asset/images/roadshow-app-architecture-parksmap-2.png" alt="Application architecture" width="800">
1667</div>
1668</div>
1669<div class="sect1">
1670<h2 id="_background_routes">Background: Routes</h2>
1671<div class="sectionbody">
1672<div class="paragraph">
1673<p>While <strong>Services</strong> provide internal abstraction and load balancing within an
1674OpenShift environment, sometimes clients (users, systems, devices, etc.)
1675<strong>outside</strong> of OpenShift need to access an application. The way that external
1676clients are able to access applications running in OpenShift is through the
1677OpenShift routing layer. And the data object behind that is a <strong>Route</strong>.</p>
1678</div>
1679<div class="paragraph">
1680<p>The default OpenShift router (HAProxy) uses the HTTP header of the incoming
1681request to determine where to proxy the connection. You can optionally define
1682security, such as TLS, for the <strong>Route</strong>. If you want your <strong>Services</strong>, and, by
1683extension, your <strong>Pods</strong>, to be accessible from the outside world, you need to
1684create a <strong>Route</strong>.</p>
1685</div>
1686</div>
1687</div>
1688<div class="sect1">
1689<h2 id="_exercise_creating_a_route">Exercise: Creating a Route</h2>
1690<div class="sectionbody">
1691<div class="paragraph">
1692<p>Fortunately, creating a <strong>Route</strong> is a pretty straight-forward process. You simply
1693<code>expose</code> the <strong>Service</strong> via the command line. Or, via the web console, just click
1694the "Create Route" button associated with the service and choose the defaults as highlighted in the following image:</p>
1695</div>
1696<div class="imageblock text-center">
1697<div class="content">
1698<img src="/workshop/workshop/asset/images/parksmap-route-create.png" alt="Create Route">
1699</div>
1700</div>
1701<div class="paragraph">
1702<p>When creating a route, some options can be provided, like the hostname for the route or the TLS configuration for the Route.</p>
1703</div>
1704<div class="imageblock text-center">
1705<div class="content">
1706<img src="/workshop/workshop/asset/images/parksmap-route-editor.png" alt="Create Route editor">
1707</div>
1708</div>
1709<div class="paragraph">
1710<p>When using the command line, we can first verify that we don’t already have any existing route:</p>
1711</div>
1712<div class="listingblock copypaste">
1713<div class="content">
1714<pre class="CodeRay highlight"><code data-lang="bash">oc get routes</code></pre>
1715</div>
1716</div>
1717<div class="listingblock">
1718<div class="content">
1719<pre class="CodeRay highlight"><code data-lang="bash">No resources found.</code></pre>
1720</div>
1721</div>
1722<div class="paragraph">
1723<p>Now we need to get the <strong>Service</strong> name to expose:</p>
1724</div>
1725<div class="listingblock copypaste">
1726<div class="content">
1727<pre class="CodeRay highlight"><code data-lang="bash">oc get services</code></pre>
1728</div>
1729</div>
1730<div class="listingblock">
1731<div class="content">
1732<pre class="CodeRay highlight"><code data-lang="bash">NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
1733parksmap 172.30.169.213 <none> 8080/TCP 5h</code></pre>
1734</div>
1735</div>
1736<div class="paragraph">
1737<p>Once we know the <strong>Service</strong> name, creating a <strong>Route</strong> is a simple one-command task:</p>
1738</div>
1739<div class="listingblock copypaste">
1740<div class="content">
1741<pre class="CodeRay highlight"><code data-lang="bash">oc expose service parksmap</code></pre>
1742</div>
1743</div>
1744<div class="listingblock">
1745<div class="content">
1746<pre class="CodeRay highlight"><code data-lang="bash">route "parksmap" exposed</code></pre>
1747</div>
1748</div>
1749<div class="paragraph">
1750<p>Verify the <strong>Route</strong> was created with the following command:</p>
1751</div>
1752<div class="listingblock copypaste">
1753<div class="content">
1754<pre class="CodeRay highlight"><code data-lang="bash">oc get route</code></pre>
1755</div>
1756</div>
1757<div class="listingblock">
1758<div class="content">
1759<pre class="CodeRay highlight"><code data-lang="bash">NAME HOST/PORT PATH SERVICES PORT TERMINATION
1760parksmap parksmap-userXY.apps.mod-5b05.openshiftworkshop.com parksmap 8080-tcp</code></pre>
1761</div>
1762</div>
1763<div class="paragraph">
1764<p>You can also verify the <strong>Route</strong> by looking at the project in the OpenShift web console:</p>
1765</div>
1766<div class="imageblock">
1767<div class="content">
1768<img src="/workshop/workshop/asset/images/parksmap-route-created.png" alt="Route created">
1769</div>
1770</div>
1771<div class="paragraph">
1772<p>Pretty nifty, huh? This application is now available at the URL shown in the
1773web console. Click the link and you will see:</p>
1774</div>
1775<div class="imageblock">
1776<div class="content">
1777<img src="/workshop/workshop/asset/images/parksmap-route-empty-map.png" alt="Empty map">
1778</div>
1779</div>
1780</div>
1781</div>
1782 <hr>
1783 <h2>Exploring OpenShift's Logging Capabilities</h2>
1784 <div class="paragraph">
1785<p>OpenShift provides some convenient mechanisms for viewing application logs.
1786First and foremost is the ability to examine a <strong>Pod</strong>'s logs directly from the
1787web console or via the command line.</p>
1788</div>
1789<div class="sect1">
1790<h2 id="_background_container_logs">Background: Container Logs</h2>
1791<div class="sectionbody">
1792<div class="paragraph">
1793<p>OpenShift is constructed in such a way that it expects containers to log all
1794information to <code>STDOUT</code>. In this way, both regular and error information is
1795captured via standardized Docker mechanisms. When exploring the <strong>Pod</strong>'s logs
1796directly, you are essentially going through the Docker daemon to access the
1797container’s logs, through OpenShift’s API. Neat!</p>
1798</div>
1799<div class="admonitionblock note">
1800<table>
1801<tr>
1802<td class="icon">
1803<i class="fa icon-note" title="Note"></i>
1804</td>
1805<td class="content">
1806<div class="paragraph">
1807<p>In some cases, applications may not have been designed to send all of their
1808information to <code>STDOUT</code> and <code>STDERR</code>. In many cases, multiple local log files
1809are used. While OpenShift cannot parse any information from these files, nothing
1810prevents them from being created, either. In other cases, log information is
1811sent to some external system. Here, too, OpenShift does not prohibit these
1812behaviors. If you have an application that does not log to <code>STDOUT</code>, either because it
1813already sends log information to some "external" system or because it writes
1814various log information to various files, fear not.</p>
1815</div>
1816</td>
1817</tr>
1818</table>
1819</div>
1820</div>
1821</div>
1822<div class="sect1">
1823<h2 id="_exercise_examining_logs">Exercise: Examining Logs</h2>
1824<div class="sectionbody">
1825<div class="paragraph">
1826<p>Since we already deployed our application, we can take some time to examine its
1827logs. In the web console <code>Overview</code> page, click on the kebab menu (three squares) at the
1828far right of the deployment and then click on the <code>View Logs</code> item.</p>
1829</div>
1830<div class="imageblock">
1831<div class="content">
1832<img src="/workshop/workshop/asset/images/parksmap-logging-overview-view-log-menu.png" alt="View Logs">
1833</div>
1834</div>
1835<div class="paragraph">
1836<p>You should see a nice view of the <strong>Pod</strong>'s logs:</p>
1837</div>
1838<div class="imageblock">
1839<div class="content">
1840<img src="/workshop/workshop/asset/images/parksmap-logging-console-logs.png" alt="Application Logs">
1841</div>
1842</div>
1843<div class="admonitionblock warning">
1844<table>
1845<tr>
1846<td class="icon">
1847<i class="fa icon-warning" title="Warning"></i>
1848</td>
1849<td class="content">
1850It appears there are some errors in the log, and that’s okay. We’ll remedy those in a little bit.
1851</td>
1852</tr>
1853</table>
1854</div>
1855<div class="paragraph">
1856<p>You also have the option of viewing logs from the command line. Get the name of
1857your <strong>Pod</strong>:</p>
1858</div>
1859<div class="listingblock copypaste">
1860<div class="content">
1861<pre class="CodeRay highlight"><code data-lang="bash">oc get pods</code></pre>
1862</div>
1863</div>
1864<div class="listingblock">
1865<div class="content">
1866<pre class="CodeRay highlight"><code data-lang="bash">NAME READY STATUS RESTARTS AGE
1867parksmap-1-hx0kv 1/1 Running 0 5h</code></pre>
1868</div>
1869</div>
1870<div class="paragraph">
1871<p>And then use the <code>logs</code> command to view this <strong>Pod</strong>'s logs:</p>
1872</div>
1873<div class="listingblock copypaste">
1874<div class="content">
1875<pre class="CodeRay highlight"><code data-lang="bash">oc logs parksmap-1-hx0kv</code></pre>
1876</div>
1877</div>
1878<div class="paragraph">
1879<p>You will see all of the application logs scroll on your screen:</p>
1880</div>
1881<div class="listingblock">
1882<div class="content">
1883<pre class="CodeRay highlight"><code data-lang="bash">15:34:25.844 [main] DEBUG io.fabric8.kubernetes.client.Config - Trying to configure client from Kubernetes config...
188415:34:25.937 [main] DEBUG io.fabric8.kubernetes.client.Config - Did not find Kubernetes config at: [/.kube/config]. Ignoring.
188515:34:25.937 [main] DEBUG io.fabric8.kubernetes.client.Config - Trying to configure client from service account...
188615:34:25.938 [main] DEBUG io.fabric8.kubernetes.client.Config - Found service account ca cert at: [/var/run/secrets/kubernetes.io/serviceaccount/ca.crt].
188715:34:25.960 [main] DEBUG io.fabric8.kubernetes.client.Config - Found service account token at: [/var/run/secrets/kubernetes.io/serviceaccount/token].
188815:34:25.961 [main] DEBUG io.fabric8.kubernetes.client.Config - Trying to configure client namespace from Kubernetes service account namespace path...
188915:34:25.962 [main] DEBUG io.fabric8.kubernetes.client.Config - Found service account namespace at: [/var/run/secrets/kubernetes.io/serviceaccount/namespace].
1890....</code></pre>
1891</div>
1892</div>
1893<div class="admonitionblock warning">
1894<table>
1895<tr>
1896<td class="icon">
1897<i class="fa icon-warning" title="Warning"></i>
1898</td>
1899<td class="content">
1900You may have noticed an error that mentions a service account. What’s that? Never fear, we will cover that shortly.
1901</td>
1902</tr>
1903</table>
1904</div>
1905</div>
1906</div>
1907<div class="sect1">
1908<h2 id="_exercise_aggregated_pod_logs">Exercise: Aggregated Pod Logs</h2>
1909<div class="sectionbody">
1910<div class="admonitionblock warning">
1911<table>
1912<tr>
1913<td class="icon">
1914<i class="fa icon-warning" title="Warning"></i>
1915</td>
1916<td class="content">
1917This section is only relevant if the aggregated logging
1918capability is available in the OpenShift cluster, as this capability is optional.
1919</td>
1920</tr>
1921</table>
1922</div>
1923<div class="paragraph">
1924<p>When your application consists of only one <strong>Pod</strong> and it never fails, restarts,
1925or has other issues, these ways to view logs may not be so bad. However in a
1926scaled-out application where <strong>Pods</strong> may have restarted, been scaled up or down,
1927or if you just want to get historical information, these mechanisms may be
1928insufficient.</p>
1929</div>
1930<div class="paragraph">
1931<p>Fortunately, OpenShift provides an optional system for log aggregation that uses
1932Elasticsearch, Fluentd, and Kibana (EFK).</p>
1933</div>
1934<div class="paragraph">
1935<p>In the OpenShift web console on the <strong>Pod</strong>'s logs page, at the right you will see
1936a "View Archive" link. Go ahead and click it. If you do not see the "archive" link, ensure that you have at least two pods running. If you don’t, use the information you learned in a previous lab to scale up to two instances of the application. You will need to accept the SSL
1937certificate.</p>
1938</div>
1939<div class="imageblock">
1940<div class="content">
1941<img src="/workshop/workshop/asset/images/parksmap-logging-view-log-archive.png" alt="View Logs">
1942</div>
1943</div>
1944<div class="admonitionblock note">
1945<table>
1946<tr>
1947<td class="icon">
1948<i class="fa icon-note" title="Note"></i>
1949</td>
1950<td class="content">
1951<div class="paragraph">
1952<p>The previous link only appears on the page for the pod logs. If you want to access the Kibana interface at any time, you can do so by using the following URL:</p>
1953</div>
1954<div class="paragraph">
1955<p><a href="https://kibana.apps.mod-5b05.openshiftworkshop.com" class="bare">https://kibana.apps.mod-5b05.openshiftworkshop.com</a></p>
1956</div>
1957<div class="paragraph">
1958<p>Use the same credentials as with OpenShift</p>
1959</div>
1960</td>
1961</tr>
1962</table>
1963</div>
1964<div class="paragraph">
1965<p>Clicking this link takes you to the Kibana web interface. This interface is
1966secured with OpenShift’s role-based access controls, so you can only see logs
1967for projects that you have access to.</p>
1968</div>
1969<div class="imageblock">
1970<div class="content">
1971<img src="/workshop/workshop/asset/images/parksmap-logging-kibana.png" alt="Kibana Interface">
1972</div>
1973</div>
1974<div class="paragraph">
1975<p>The "View Archive" link that you clicked takes you to a default view with a specific search term
1976pre-populated. Kibana will only show you logs where the pod name is
1977<code>parksmap-1-hx0kv</code> and in the <strong>Project</strong> (namespace) userXY.</p>
1978</div>
1979<div class="admonitionblock caution">
1980<table>
1981<tr>
1982<td class="icon">
1983<i class="fa icon-caution" title="Caution"></i>
1984</td>
1985<td class="content">
1986In the following Kibana search(es), replace <code>userXY</code> with the project provided to you and the pod_name to match your pod.
1987</td>
1988</tr>
1989</table>
1990</div>
1991<div class="listingblock copypaste">
1992<div class="content">
1993<pre class="CodeRay highlight"><code data-lang="bash">kubernetes.pod_name:"parksmap-1-hx0kv" AND kubernetes.namespace_name:"userXY"</code></pre>
1994</div>
1995</div>
1996<div class="admonitionblock note">
1997<table>
1998<tr>
1999<td class="icon">
2000<i class="fa icon-note" title="Note"></i>
2001</td>
2002<td class="content">
2003<div class="paragraph">
2004<p>If your search returns no hits, try changing the time-picker in the top right-hand corner from the default "Last 15 miutes" to something else, like "The day so far" or "Last 1 hour"</p>
2005</div>
2006</td>
2007</tr>
2008</table>
2009</div>
2010<div class="paragraph">
2011<p>If you want to see all the historical logs for this <strong>Project</strong>, simply remove the
2012pod name reference and click the magnifying glass or press the enter key.</p>
2013</div>
2014<div class="admonitionblock caution">
2015<table>
2016<tr>
2017<td class="icon">
2018<i class="fa icon-caution" title="Caution"></i>
2019</td>
2020<td class="content">
2021In the following Kibana search(es), replace <code>userXY</code> with the project provided to you.
2022</td>
2023</tr>
2024</table>
2025</div>
2026<div class="listingblock copypaste">
2027<div class="content">
2028<pre class="CodeRay highlight"><code data-lang="bash">kubernetes.namespace_name:"userXY"</code></pre>
2029</div>
2030</div>
2031<div class="paragraph">
2032<p>If you click the "x" in the column for the container name, and, in the left bar,
2033click "add" for <code>kubernetes.pod_name</code>, you’ll then see your old <strong>Pod</strong>'s logs,
2034too. Remember, we scaled them down before coming here, so you can see how the
2035log system is keeping a historical record.</p>
2036</div>
2037<div class="imageblock">
2038<div class="content">
2039<img src="/workshop/workshop/asset/images/parksmap-logging-kibana-parksmap-headers.png" alt="Kibana Interface">
2040</div>
2041</div>
2042<div class="paragraph">
2043<p>Try the following search string ensuring that you use the correct name for your project:</p>
2044</div>
2045<div class="admonitionblock caution">
2046<table>
2047<tr>
2048<td class="icon">
2049<i class="fa icon-caution" title="Caution"></i>
2050</td>
2051<td class="content">
2052In the following Kibana search(es), replace <code>userXY</code> with the project provided to you.
2053</td>
2054</tr>
2055</table>
2056</div>
2057<div class="listingblock copypaste">
2058<div class="content">
2059<pre class="CodeRay highlight"><code data-lang="bash">kubernetes.namespace_name:"userXY" AND message:"Failure executing"</code></pre>
2060</div>
2061</div>
2062</div>
2063</div>
2064 <hr>
2065 <h2>Role-Based Access Control</h2>
2066 <div class="paragraph">
2067<p>Almost every interaction with an OpenShift environment that you can think of
2068requires going through the OpenShift’s control plane API. All API interactions are both authenticated (AuthN - who are you?) and authorized (AuthZ - are you allowed to do what you are asking?).</p>
2069</div>
2070<div class="paragraph">
2071<p>In the log aggregation lab we saw that there was an
2072error in reference to a <strong>Service Account</strong>.</p>
2073</div>
2074<div class="paragraph">
2075<p>As OpenShift is a declarative platform, some actions will be performed by the platform and not by the end user (when he or she issues a command). These actions are performed using a <strong>Service Account</strong> which is a special type of <code>user</code> that the platform will use internally.</p>
2076</div>
2077<div class="paragraph">
2078<p>OpenShift automatically creates a few special service accounts in every project.
2079The <strong>default</strong> service account is the one taking the responsibility of running the pods, and OpenShift uses and injects this service account into
2080every pod that is launched. By changing the permissions for that service
2081account, we can do interesting things.</p>
2082</div>
2083<div class="paragraph">
2084<p>You can view current permissions in the web UI, by navigating to "Resources → Membership" page.</p>
2085</div>
2086<div class="imageblock">
2087<div class="content">
2088<img src="/workshop/workshop/asset/images/parksmap-permissions-membership.png" alt="Membership">
2089</div>
2090</div>
2091<div class="sect1">
2092<h2 id="_exercise_grant_service_account_view_permissions">Exercise: Grant Service Account View Permissions</h2>
2093<div class="sectionbody">
2094<div class="paragraph">
2095<p>The parksmap application wants to talk to the OpenShift API to learn about other
2096<strong>Pods</strong>, <strong>Services</strong>, and resources within the <strong>Project</strong>. You’ll soon learn why!</p>
2097</div>
2098<div class="admonitionblock caution">
2099<table>
2100<tr>
2101<td class="icon">
2102<i class="fa icon-caution" title="Caution"></i>
2103</td>
2104<td class="content">
2105In the following command(s), replace <code>userXY</code> with the project provided to you.
2106</td>
2107</tr>
2108</table>
2109</div>
2110<div class="listingblock copypaste">
2111<div class="content">
2112<pre class="CodeRay highlight"><code data-lang="bash">oc project userXY</code></pre>
2113</div>
2114</div>
2115<div class="paragraph">
2116<p>Then:</p>
2117</div>
2118<div class="listingblock copypaste">
2119<div class="content">
2120<pre class="CodeRay highlight"><code data-lang="bash">oc policy add-role-to-user view -z default</code></pre>
2121</div>
2122</div>
2123<div class="paragraph">
2124<p>The <code>oc policy</code> command above is giving a defined <em>role</em> (<code>view</code>) to a user. But
2125we are using a special flag, <code>-z</code>. What does this flag do? From the <code>-h</code> output:</p>
2126</div>
2127<div class="listingblock">
2128<div class="content">
2129<pre class="CodeRay highlight"><code data-lang="bash">-z, --serviceaccount=[]: service account in the current namespace to use as a user</code></pre>
2130</div>
2131</div>
2132<div class="paragraph">
2133<p>The <code>-z</code> syntax is a special one that saves us from having to type out the
2134entire string, which, in this case, is
2135<code>system:serviceaccount:userXY:default</code>. It’s a nifty shortcut.</p>
2136</div>
2137<div class="admonitionblock note">
2138<table>
2139<tr>
2140<td class="icon">
2141<i class="fa icon-note" title="Note"></i>
2142</td>
2143<td class="content">
2144<div class="paragraph">
2145<p>The <code>-z</code> flag will only work for service accounts in the <strong>current</strong> project.
2146If you’re referring to a service account in a different project, use the `-n <project>`switch.</p>
2147</div>
2148</td>
2149</tr>
2150</table>
2151</div>
2152<div class="paragraph">
2153<p>Now that the <code>default</code> <strong>Service Account</strong> now has <strong>view</strong> access, so now it can query the API to see what resources are within the <strong>Project</strong>. This also has the added benefit of suppressing the error message! Although, in reality, we fixed the application.</p>
2154</div>
2155<div class="paragraph">
2156<p>Another way you could have done the same is by using the OpenShift console. Once you’re on the
2157<strong>"Resources -→ Membership"</strong> page, click on Service Accounts, and then on <strong>"Edit Membership"</strong> button.</p>
2158</div>
2159<div class="imageblock">
2160<div class="content">
2161<img src="/workshop/workshop/asset/images/parksmap-permissions-membership-serviceaccount-list.png" alt="Service account list">
2162</div>
2163</div>
2164<div class="paragraph">
2165<p>Add the view role to the <strong>userXY/default</strong> Service Account, and then
2166click the <strong>"Add"</strong> button.</p>
2167</div>
2168<div class="imageblock">
2169<div class="content">
2170<img src="/workshop/workshop/asset/images/parksmap-permissions-membership-serviceaccount-edit.png" alt="Service account edit">
2171</div>
2172</div>
2173<div class="paragraph">
2174<p>Once you’re finished editing permissions, click on the <strong>"Done Editing"</strong> button.</p>
2175</div>
2176<div class="imageblock">
2177<div class="content">
2178<img src="/workshop/workshop/asset/images/parksmap-permissions-membership-serviceaccount-done.png" alt="Service account changed">
2179</div>
2180</div>
2181</div>
2182</div>
2183<div class="sect1">
2184<h2 id="_exercise_redeploy_application">Exercise: Redeploy Application</h2>
2185<div class="sectionbody">
2186<div class="paragraph">
2187<p>One more step is required. We need to re-deploy the parksmap application because it’s
2188given up trying to query the API.</p>
2189</div>
2190<div class="paragraph">
2191<p>This time we’ll use the web console. Find your <code>userXY</code> project,
2192and then click "Applications" and then "Deployments". You’ll see your only
2193application, <code>parksmap</code>, listed. Click that.</p>
2194</div>
2195<div class="paragraph">
2196<p>The deployment screen tells you a lot about how the application will be
2197deployed. At the top right, there is a button labeled "Deploy". This button will
2198cause a new deployment (which you know creates a new <strong>ReplicationController</strong>, right?).</p>
2199</div>
2200<div class="paragraph">
2201<p>Click it.</p>
2202</div>
2203<div class="imageblock">
2204<div class="content">
2205<img src="/workshop/workshop/asset/images/parksmap-permissions-redeploy.png" alt="Deploy Button">
2206</div>
2207</div>
2208<div class="paragraph">
2209<p>You’ll see that a new deployment is immediately started. Return to the overview
2210page and watch it happen. You might not be fast enough! But it will be in the list of
2211deployments.</p>
2212</div>
2213<div class="imageblock">
2214<div class="content">
2215<img src="/workshop/workshop/asset/images/parksmap-permissions-redeployed.png" alt="Application deployed">
2216</div>
2217</div>
2218<div class="paragraph">
2219<p>If you look at the logs for the application now, you should see no errors. That’s great.</p>
2220</div>
2221</div>
2222</div>
2223<div class="sect1">
2224<h2 id="_exercise_grant_user_view_permissions">Exercise: Grant User View Permissions</h2>
2225<div class="sectionbody">
2226<div class="paragraph">
2227<p>If you create a project, you are that project’s administrator. This means that
2228you can grant access to other users, too. If you like, give your neighbor view
2229access to your project using the following command:</p>
2230</div>
2231<div class="admonitionblock caution">
2232<table>
2233<tr>
2234<td class="icon">
2235<i class="fa icon-caution" title="Caution"></i>
2236</td>
2237<td class="content">
2238In the following command(s), replace <code>userXY</code> with the user name of the person to whom you want to grant access.
2239</td>
2240</tr>
2241</table>
2242</div>
2243<div class="listingblock copypaste">
2244<div class="content">
2245<pre class="CodeRay highlight"><code data-lang="bash">oc policy add-role-to-user view userXY</code></pre>
2246</div>
2247</div>
2248<div class="paragraph">
2249<p>Have them go to the project view by clicking the <strong>Projects</strong> button and verify
2250that they can see your project and its resources. This type of arrangement (view
2251but not edit) might be ideal for a developer getting visibility into a
2252production application’s project.</p>
2253</div>
2254</div>
2255</div>
2256 <hr>
2257 <h2>Remote Access to Your Application</h2>
2258 <div class="paragraph">
2259<p>Containers are treated as immutable infrastructure and therefore it is generally
2260not recommended to modify the content of a container through SSH or running custom
2261commands inside the container. Nevertheless, in some use-cases, such as debugging
2262an application, it might be beneficial to get into a container and inspect the
2263application.</p>
2264</div>
2265<div class="sect1">
2266<h2 id="_exercise_remote_shell_session_to_a_container_using_the_cli">Exercise: Remote Shell Session to a Container Using the CLI</h2>
2267<div class="sectionbody">
2268<div class="paragraph">
2269<p>OpenShift allows establishing remote shell sessions to a container without the
2270need to run an SSH service inside each container. In order to establish an
2271interactive session inside a container, you can use the <code>oc rsh</code> command. First
2272get the list of available pods:</p>
2273</div>
2274<div class="listingblock copypaste">
2275<div class="content">
2276<pre class="CodeRay highlight"><code data-lang="bash">oc get pods</code></pre>
2277</div>
2278</div>
2279<div class="paragraph">
2280<p>You should an output similar to the following:</p>
2281</div>
2282<div class="listingblock">
2283<div class="content">
2284<pre class="CodeRay highlight"><code data-lang="bash">NAME READY STATUS RESTARTS AGE
2285parksmap-2-tegp4 1/1 Running 0 2m</code></pre>
2286</div>
2287</div>
2288<div class="paragraph">
2289<p>Now you can establish a remote shell session into the pod by using the pod name:</p>
2290</div>
2291<div class="listingblock copypaste">
2292<div class="content">
2293<pre class="CodeRay highlight"><code data-lang="bash">oc rsh parksmap-2-tegp4</code></pre>
2294</div>
2295</div>
2296<div class="paragraph">
2297<p>You would see the following output:</p>
2298</div>
2299<div class="listingblock">
2300<div class="content">
2301<pre class="CodeRay highlight"><code data-lang="bash">sh-4.2$</code></pre>
2302</div>
2303</div>
2304<div class="admonitionblock note">
2305<table>
2306<tr>
2307<td class="icon">
2308<i class="fa icon-note" title="Note"></i>
2309</td>
2310<td class="content">
2311<div class="paragraph">
2312<p>The default shell used by <code>oc rsh</code> is <code>/bin/sh</code>. If the deployed container does
2313not have <strong>sh</strong> installed and uses another shell, (e.g. <strong>A Shell</strong>) the shell command
2314can be specified after the pod name in the issued command.</p>
2315</div>
2316</td>
2317</tr>
2318</table>
2319</div>
2320<div class="paragraph">
2321<p>Run the following command to list the files in the top folder:</p>
2322</div>
2323<div class="listingblock copypaste">
2324<div class="content">
2325<pre class="CodeRay highlight"><code data-lang="bash">ls /</code></pre>
2326</div>
2327</div>
2328<div class="listingblock">
2329<div class="content">
2330<pre class="CodeRay highlight"><code data-lang="bash">anaconda-post.log bin dev etc home lib lib64 lost+found media mnt opt parksmap.jar proc root run sbin srv sys tmp usr var</code></pre>
2331</div>
2332</div>
2333</div>
2334</div>
2335<div class="sect1">
2336<h2 id="_exercise_remote_shell_session_to_a_container_using_the_web_console">Exercise: Remote Shell Session to a Container Using the Web Console</h2>
2337<div class="sectionbody">
2338<div class="paragraph">
2339<p>The OpenShift Web Console also provides a convenient way to access a terminal session on the container without having to use the CLI.</p>
2340</div>
2341<div class="paragraph">
2342<p>In order to access a pods terminal via the Web Console, click on "Applications", then "Pods" and finally the pod name as shown in the following image:</p>
2343</div>
2344<div class="imageblock">
2345<div class="content">
2346<img src="/workshop/workshop/asset/images/parksmap-rsh-applications-pods.png" alt="Pod List">
2347</div>
2348</div>
2349<div class="paragraph">
2350<p>Once you are viewing the information for the selected pod, click on the "Terminal" tab to open up a shell session.</p>
2351</div>
2352<div class="imageblock">
2353<div class="content">
2354<img src="/workshop/workshop/asset/images/parksmap-rsh-applications-pods-terminal.png" alt="Pod List">
2355</div>
2356</div>
2357<div class="paragraph">
2358<p>Pretty nifty! Go ahead and execute the same commands you did when using the CLI to see how the Web Console based terminal behaves.</p>
2359</div>
2360<div class="paragraph">
2361<p>Before proceeding, close the connection to the pod.</p>
2362</div>
2363<div class="listingblock copypaste">
2364<div class="content">
2365<pre class="CodeRay highlight"><code data-lang="bash">exit</code></pre>
2366</div>
2367</div>
2368</div>
2369</div>
2370<div class="sect1">
2371<h2 id="_exercise_execute_a_command_in_a_container">Exercise: Execute a Command in a Container</h2>
2372<div class="sectionbody">
2373<div class="paragraph">
2374<p>In addition to remote shell, it is also possible to run a command remotely in an
2375already running container using the <code>oc exec</code> command. This does not require
2376that a shell is installed, but only that the desired command is present and in
2377the executable path.</p>
2378</div>
2379<div class="paragraph">
2380<p>In order to show just the JAR file, run the following:</p>
2381</div>
2382<div class="listingblock copypaste">
2383<div class="content">
2384<pre class="CodeRay highlight"><code data-lang="bash">oc exec parksmap-2-tegp4 -- ls -l /parksmap.jar</code></pre>
2385</div>
2386</div>
2387<div class="paragraph">
2388<p>You would see something like the following:</p>
2389</div>
2390<div class="listingblock">
2391<div class="content">
2392<pre class="CodeRay highlight"><code data-lang="bash">-rw-r--r--. 1 root root 21753918 Nov 23 15:54 /parksmap.jar</code></pre>
2393</div>
2394</div>
2395<div class="admonitionblock note">
2396<table>
2397<tr>
2398<td class="icon">
2399<i class="fa icon-note" title="Note"></i>
2400</td>
2401<td class="content">
2402<div class="paragraph">
2403<p>The <code>--</code> syntax in the <code>oc exec</code> command delineates where exec’s options
2404end and where the actual command to execute begins. Take a look at <code>oc exec
2405--help</code> for more details.</p>
2406</div>
2407</td>
2408</tr>
2409</table>
2410</div>
2411<div class="paragraph">
2412<p>You can also specify the shell commands to run directly with the <strong>oc rsh</strong> command:</p>
2413</div>
2414<div class="listingblock copypaste">
2415<div class="content">
2416<pre class="CodeRay highlight"><code data-lang="bash">oc rsh parksmap-2-tegp4 whoami</code></pre>
2417</div>
2418</div>
2419<div class="paragraph">
2420<p>You would see something like:</p>
2421</div>
2422<div class="listingblock">
2423<div class="content">
2424<pre class="CodeRay highlight"><code data-lang="bash">whoami: cannot find name for user ID 1000060000
2425command terminated with exit code 1</code></pre>
2426</div>
2427</div>
2428<div class="admonitionblock note">
2429<table>
2430<tr>
2431<td class="icon">
2432<i class="fa icon-note" title="Note"></i>
2433</td>
2434<td class="content">
2435<div class="paragraph">
2436<p>It is important to understand that, for security reasons, OpenShift does not run containers as the user specified in the Dockerfile by default. In fact,
2437when OpenShift launches a container its user is actually randomized.</p>
2438</div>
2439<div class="paragraph">
2440<p>If you want or need to allow OpenShift users to deploy container images that do
2441expect to run as root (or any specific user), a small configuration change is
2442needed. You can learn more about the
2443<a href="https://docs.openshift.com/container-platform/latest/creating_images/guidelines.html">container image guidelines</a>
2444for OpenShift, or you can look at the section on
2445<a href="https://docs.openshift.com/container-platform/latest/admin_guide/manage_scc.html#enable-images-to-run-with-user-in-the-dockerfile">enabling
2446images to run with a USER in the Dockerfile</a>.</p>
2447</div>
2448</td>
2449</tr>
2450</table>
2451</div>
2452</div>
2453</div>
2454 <hr>
2455 <h2>Deploying Java Code</h2>
2456 <div class="paragraph">
2457<p>In this lab, we’re going to deploy a backend service, developed in Java that will expose 2 main REST endpoints to the visualizer
2458application (<code>parksmap</code> web component that was deployed in the previous labs).
2459The application will query for national parks information (including its
2460coordinates) that is stored in a MongoDB database. This application will also
2461provide an external access point, so that the API provided can be directly used
2462by the end user.</p>
2463</div>
2464<div class="imageblock text-center">
2465<div class="content">
2466<img src="/workshop/workshop/asset/images/roadshow-app-architecture-nationalparks-1.png" alt="Application architecture" width="800">
2467</div>
2468</div>
2469<div class="sect1">
2470<h2 id="_background_source_to_image_s2i">Background: Source-to-Image (S2I)</h2>
2471<div class="sectionbody">
2472<div class="paragraph">
2473<p>In a previous lab, we learned how to deploy a pre-existing image
2474image. Now we will expand on that by learning how OpenShift builds
2475container images using source code from an existing repository. This is accomplished using the Source-to-Image project.</p>
2476</div>
2477<div class="paragraph">
2478<p><a href="https://github.com/openshift/source-to-image">Source-to-Image (S2I)</a> is a
2479open source project sponsored by Red Hat that has the following goal:</p>
2480</div>
2481<div class="listingblock">
2482<div class="content">
2483<pre class="CodeRay highlight"><code>Source-to-image (S2I) is a tool for building reproducible container images. S2I
2484produces ready-to-run images by injecting source code into a container image and
2485assembling a new container image which incorporates the builder image and built
2486source. The result is then ready to use with docker run. S2I supports
2487incremental builds which re-use previously downloaded dependencies, previously
2488built artifacts, etc.</code></pre>
2489</div>
2490</div>
2491<div class="paragraph">
2492<p>OpenShift is S2I-enabled and can use S2I as one of its build mechanisms (in
2493addition to building container images from Dockerfiles, and "custom" builds).</p>
2494</div>
2495<div class="paragraph">
2496<p>OpenShift runs the S2I process inside a special <strong>Pod</strong>, called a Build
2497Pod, and thus builds are subject to quotas, limits, resource scheduling, and
2498other aspects of OpenShift.</p>
2499</div>
2500<div class="paragraph">
2501<p>A full discussion of S2I is beyond the scope of this class, but you can find
2502more information about it either in the
2503<a href="https://docs.openshift.com/container-platform/latest/creating_images/s2i.html">OpenShift S2I documentation</a>
2504or on <a href="https://github.com/openshift/source-to-image">GitHub</a>. The only key concept you need to
2505remember about S2I is that it’s magic.</p>
2506</div>
2507</div>
2508</div>
2509<div class="sect1">
2510<h2 id="_exercise_creating_a_java_application">Exercise: Creating a Java application</h2>
2511<div class="sectionbody">
2512<div class="paragraph">
2513<p>The backend service that we will be deploying as part of this exercise is
2514called <code>nationalparks</code>. This is a Java Spring Boot application that performs 2D
2515geo-spatial queries against a MongoDB database to locate and return map
2516coordinates of all National Parks in the world. That was just a fancy way of
2517saying that we are going to deploy a webservice that returns a JSON list of
2518places.</p>
2519</div>
2520<div class="sect2">
2521<h3 id="_add_to_project">Add to Project</h3>
2522<div class="paragraph">
2523<p>Because the <code>nationalparks</code> component is a backend to serve data that our
2524existing frontend (parksmap) will consume, we are going to build it inside the existing
2525project that we have been working with. To illustrate how you can interact with OpenShift via the CLI or the web console, we will deploy the nationalparks component using the web console.</p>
2526</div>
2527</div>
2528<div class="sect2">
2529<h3 id="_using_application_code_on_an_embedded_git_server">Using Application Code on an Embedded Git Server</h3>
2530<div class="paragraph">
2531<p>OpenShift can work with any accessible Git repository. This could be GitHub,
2532GitLab, or any other server that speaks Git. You can even register webhooks in
2533your Git server to initiate OpenShift builds triggered by any update to the
2534application code!</p>
2535</div>
2536<div class="paragraph">
2537<p>The repository that we are going to use is already cloned in the internal Gogs repository
2538and located at the following URL:</p>
2539</div>
2540<div class="admonitionblock caution">
2541<table>
2542<tr>
2543<td class="icon">
2544<i class="fa icon-caution" title="Caution"></i>
2545</td>
2546<td class="content">
2547In the following url(s), replace <code>userXY</code> with the Gogs username provided to you. Your Gogs credentials are the same as your OpenShift credentials.
2548</td>
2549</tr>
2550</table>
2551</div>
2552<div class="listingblock copypaste">
2553<div class="content">
2554<pre class="CodeRay highlight"><code>http://gogs-infra.apps.mod-5b05.openshiftworkshop.com/userXY/nationalparks.git</code></pre>
2555</div>
2556</div>
2557<div class="paragraph">
2558<p>Later in the lab, we want you to make a code change and then rebuild your
2559application. This is a fairly simple Spring framework Java application.</p>
2560</div>
2561</div>
2562<div class="sect2">
2563<h3 id="_build_the_code_on_openshift">Build the Code on OpenShift</h3>
2564<div class="paragraph">
2565<p>Similar to how we used "Add to project" before with an existing image, we
2566can do the same for specifying a source code repository. Since for this lab you
2567have your own git repository, let’s use it with a simple Java S2I image.</p>
2568</div>
2569<div class="admonitionblock caution">
2570<table>
2571<tr>
2572<td class="icon">
2573<i class="fa icon-caution" title="Caution"></i>
2574</td>
2575<td class="content">
2576In the following step(s), replace <code>userXY</code> with the project provided to you.
2577</td>
2578</tr>
2579</table>
2580</div>
2581<div class="paragraph">
2582<p>In the OpenShift web console, find your <code>userXY</code> project, and then
2583click the <strong>"Add to Project"</strong> button and then the browse catalog link as highlighted in the following image:</p>
2584</div>
2585<div class="imageblock">
2586<div class="content">
2587<img src="/workshop/workshop/asset/images/nationalparks-show-catalog.png" alt="Add to Project">
2588</div>
2589</div>
2590<div class="paragraph">
2591<p>This is the service catalog which allows a user to select components they want to add to their application. In this case, we are using Spring Boot so we want to select a JDK without an application server.</p>
2592</div>
2593<div class="paragraph">
2594<p>Search for <code>openjdk</code>, and finally "Red Hat OpenJDK" as shown in the following image:</p>
2595</div>
2596<div class="imageblock">
2597<div class="content">
2598<img src="/workshop/workshop/asset/images/nationalparks-java-sarch-jdk.png" alt="Service Catalog Languages">
2599</div>
2600</div>
2601<div class="paragraph">
2602<p>After you click <code>Red Hat OpenJDK 8</code>, a dialog is presented as shown in the following image:</p>
2603</div>
2604<div class="imageblock">
2605<div class="content">
2606<img src="/workshop/workshop/asset/images/nationalparks-java-new-java-service.png" alt="Create application">
2607</div>
2608</div>
2609<div class="paragraph">
2610<p>Click on the "Next" button and then enter a name and a Git repository URL. For the name, enter <code>nationalparks</code>,
2611and for the Git repository URL, enter:</p>
2612</div>
2613<div class="admonitionblock caution">
2614<table>
2615<tr>
2616<td class="icon">
2617<i class="fa icon-caution" title="Caution"></i>
2618</td>
2619<td class="content">
2620In the following url(s), replace <code>userXY</code> with the Git username provided to you.
2621</td>
2622</tr>
2623</table>
2624</div>
2625<div class="listingblock copypaste">
2626<div class="content">
2627<pre class="CodeRay highlight"><code>http://gogs-infra.apps.mod-5b05.openshiftworkshop.com/userXY/nationalparks.git</code></pre>
2628</div>
2629</div>
2630<div class="admonitionblock note">
2631<table>
2632<tr>
2633<td class="icon">
2634<i class="fa icon-note" title="Note"></i>
2635</td>
2636<td class="content">
2637All of these runtimes shown are made available via <strong>Templates</strong> and
2638<strong>ImageStreams</strong>, which will be discussed in a later lab.
2639</td>
2640</tr>
2641</table>
2642</div>
2643<div class="paragraph">
2644<p>In the <strong>Git Repository</strong> field enter the base of the Git repository for
2645your <code>nationalparks</code> application. This will cause the S2I
2646process to grab that specific tag in the code repository.</p>
2647</div>
2648<div class="paragraph">
2649<p>If you were to specify a specific branch or directory in the repository for your code, you would be able to do it in the <strong>Advanced Options</strong>.</p>
2650</div>
2651<div class="paragraph">
2652<p>Don’t click <strong>Create</strong>, but click on <strong>Advanced Options</strong>, as there are more things we are going to configure.</p>
2653</div>
2654<div class="imageblock">
2655<div class="content">
2656<img src="/workshop/workshop/asset/images/nationalparks-java-configure-java-service.png" alt="Runtimes">
2657</div>
2658</div>
2659<div class="admonitionblock tip">
2660<table>
2661<tr>
2662<td class="icon">
2663<i class="fa icon-tip" title="Tip"></i>
2664</td>
2665<td class="content">
2666<div class="paragraph">
2667<p>To speed build process, a Sonatype Nexus server is running in the environment
2668that will cache your dependencies as you pull them down. To use it, you need to
2669scroll down to <strong>Build Configuration</strong> and add an environment variable named
2670<strong>MAVEN_MIRROR_URL</strong> with value
2671<code><a href="http://nexus.infra.svc.cluster.local:8081/repository/maven-all-public" class="bare">http://nexus.infra.svc.cluster.local:8081/repository/maven-all-public</a></code></p>
2672</div>
2673<div class="imageblock">
2674<div class="content">
2675<img src="/workshop/workshop/asset/images/nationalparks-java-configure-java-service-maven2.png" alt="Runtimes">
2676</div>
2677</div>
2678</td>
2679</tr>
2680</table>
2681</div>
2682<div class="paragraph">
2683<p>We will again set 3 labels to the deployment.</p>
2684</div>
2685<div class="ulist">
2686<ul>
2687<li>
2688<p><strong><em>app</em>=workshop</strong> (the name we will be giving to the app)</p>
2689</li>
2690<li>
2691<p><strong><em>component</em>=nationalparks</strong> (the name of this deployment)</p>
2692</li>
2693<li>
2694<p><strong><em>role</em>=backend</strong> (the role this component plays in the overall application)</p>
2695</li>
2696</ul>
2697</div>
2698<div class="imageblock">
2699<div class="content">
2700<img src="/workshop/workshop/asset/images/nationalparks-configure-service-labels.png" alt="Adding labels">
2701</div>
2702</div>
2703<div class="paragraph">
2704<p>You can then hit the button labeled <strong>"Create"</strong>. Then click <strong>Continue to the project
2705overview</strong> and toggle the <strong>></strong> icon next to the deployment config for <code>nationalparks</code> . You will see the build log output directly there.</p>
2706</div>
2707<div class="imageblock">
2708<div class="content">
2709<img src="/workshop/workshop/asset/images/nationalparks-java-new-java-build.png" alt="Nationalparks build">
2710</div>
2711</div>
2712<div class="paragraph">
2713<p>This is a Java-based application that uses Maven as the build and dependency system. For this reason, the initial build
2714will take a few minutes as Maven downloads all of the dependencies needed for
2715the application. You can see all of this happening in real time!</p>
2716</div>
2717<div class="paragraph">
2718<p>From the command line, you can also see the <strong>Builds</strong>:</p>
2719</div>
2720<div class="listingblock copypaste">
2721<div class="content">
2722<pre class="CodeRay highlight"><code data-lang="bash">oc get builds</code></pre>
2723</div>
2724</div>
2725<div class="paragraph">
2726<p>You’ll see output like:</p>
2727</div>
2728<div class="listingblock">
2729<div class="content">
2730<pre class="CodeRay highlight"><code data-lang="bash">NAME TYPE FROM STATUS STARTED DURATION
2731nationalparks-1 Source Git@b052ae6 Running About a minute ago 1m2s</code></pre>
2732</div>
2733</div>
2734<div class="paragraph">
2735<p>You can also view the build logs with the following command:</p>
2736</div>
2737<div class="listingblock copypaste">
2738<div class="content">
2739<pre class="CodeRay highlight"><code data-lang="bash">oc logs -f builds/nationalparks-1</code></pre>
2740</div>
2741</div>
2742<div class="paragraph">
2743<p>After the build has completed and successfully:</p>
2744</div>
2745<div class="ulist">
2746<ul>
2747<li>
2748<p>The S2I process will push the resulting image to the internal OpenShift registry</p>
2749</li>
2750<li>
2751<p>The <strong>DeploymentConfiguration</strong> (DC) will detect that the image has changed, and this
2752will cause a new deployment to happen.</p>
2753</li>
2754<li>
2755<p>A <strong>ReplicationController</strong> (RC) will be spawned for this new deployment.</p>
2756</li>
2757<li>
2758<p>The RC will detect no <strong>Pods</strong> are running and will cause one to be deployed, as our default replica count is just 1.</p>
2759</li>
2760</ul>
2761</div>
2762<div class="paragraph">
2763<p>In the end, when issuing the <code>oc get pods</code> command, you will see that the build Pod
2764has finished (exited) and that an application <strong>Pod</strong> is in a ready and running state:</p>
2765</div>
2766<div class="listingblock">
2767<div class="content">
2768<pre class="CodeRay highlight"><code data-lang="bash">NAME READY STATUS RESTARTS AGE
2769nationalparks-1-tkid3 1/1 Running 3 2m
2770nationalparks-1-build 0/1 Completed 0 3m
2771parksmap-1-4hbtk 1/1 Running 0 2h</code></pre>
2772</div>
2773</div>
2774<div class="paragraph">
2775<p>If you look again at the web console, you will notice that, when you create the
2776application this way, OpenShift also creates a <strong>Route</strong> for you. You can see the
2777URL in the web console, or via the command line:</p>
2778</div>
2779<div class="listingblock copypaste">
2780<div class="content">
2781<pre class="CodeRay highlight"><code data-lang="bash">oc get routes</code></pre>
2782</div>
2783</div>
2784<div class="paragraph">
2785<p>Where you should see something like the following:</p>
2786</div>
2787<div class="listingblock">
2788<div class="content">
2789<pre class="CodeRay highlight"><code data-lang="bash">NAME HOST/PORT PATH SERVICES PORT TERMINATION
2790nationalparks nationalparks-userXY.apps.mod-5b05.openshiftworkshop.com nationalparks 8080-tcp
2791parksmap parksmap-userXY.apps.mod-5b05.openshiftworkshop.com parksmap 8080-tcp</code></pre>
2792</div>
2793</div>
2794<div class="paragraph">
2795<p>In the above example, the URL is:</p>
2796</div>
2797<div class="admonitionblock caution">
2798<table>
2799<tr>
2800<td class="icon">
2801<i class="fa icon-caution" title="Caution"></i>
2802</td>
2803<td class="content">
2804In the following url(s), replace <code>userXY</code> with the project provided to you.
2805</td>
2806</tr>
2807</table>
2808</div>
2809<div class="listingblock copypaste">
2810<div class="content">
2811<pre class="CodeRay highlight"><code data-lang="bash">http://nationalparks-userXY.apps.mod-5b05.openshiftworkshop.com</code></pre>
2812</div>
2813</div>
2814<div class="paragraph">
2815<p>Since this is a backend application, it doesn’t actually have a web interface.
2816However, it can still be used with a browser. All backends that work with the parksmap
2817frontend are required to implement a <code>/ws/info/</code> endpoint. To test, the
2818complete URL to enter in your browser is:</p>
2819</div>
2820<div class="admonitionblock caution">
2821<table>
2822<tr>
2823<td class="icon">
2824<i class="fa icon-caution" title="Caution"></i>
2825</td>
2826<td class="content">
2827In the following url(s), replace <code>userXY</code> with the project provided to you.
2828</td>
2829</tr>
2830</table>
2831</div>
2832<div class="listingblock copypaste">
2833<div class="content">
2834<pre class="CodeRay highlight"><code data-lang="bash">http://nationalparks-userXY.apps.mod-5b05.openshiftworkshop.com/ws/info/</code></pre>
2835</div>
2836</div>
2837<div class="admonitionblock warning">
2838<table>
2839<tr>
2840<td class="icon">
2841<i class="fa icon-warning" title="Warning"></i>
2842</td>
2843<td class="content">
2844The trailing slash is <strong>required</strong>.
2845</td>
2846</tr>
2847</table>
2848</div>
2849<div class="paragraph">
2850<p>You will see a simple JSON string:</p>
2851</div>
2852<div class="listingblock">
2853<div class="content">
2854<pre class="CodeRay highlight"><code data-lang="json">{<span class="key"><span class="delimiter">"</span><span class="content">id</span><span class="delimiter">"</span></span>:<span class="string"><span class="delimiter">"</span><span class="content">nationalparks</span><span class="delimiter">"</span></span>,<span class="key"><span class="delimiter">"</span><span class="content">displayName</span><span class="delimiter">"</span></span>:<span class="string"><span class="delimiter">"</span><span class="content">National Parks</span><span class="delimiter">"</span></span>,<span class="key"><span class="delimiter">"</span><span class="content">center</span><span class="delimiter">"</span></span>:{<span class="key"><span class="delimiter">"</span><span class="content">latitude</span><span class="delimiter">"</span></span>:<span class="string"><span class="delimiter">"</span><span class="content">47.039304</span><span class="delimiter">"</span></span>,<span class="key"><span class="delimiter">"</span><span class="content">longitude</span><span class="delimiter">"</span></span>:<span class="string"><span class="delimiter">"</span><span class="content">14.505178</span><span class="delimiter">"</span></span>},<span class="key"><span class="delimiter">"</span><span class="content">zoom</span><span class="delimiter">"</span></span>:<span class="integer">4</span>}</code></pre>
2855</div>
2856</div>
2857<div class="paragraph">
2858<p>Earlier we said:</p>
2859</div>
2860<div class="listingblock">
2861<div class="content">
2862<pre class="CodeRay highlight"><code data-lang="bash">This is a Java Spring Boot application that performs 2D geo-spatial queries
2863against a MongoDB database</code></pre>
2864</div>
2865</div>
2866<div class="paragraph">
2867<p>But we don’t have a database. Yet.</p>
2868</div>
2869</div>
2870</div>
2871</div>
2872 <hr>
2873 <h2>Adding a Database (MongoDB)</h2>
2874 <div class="paragraph">
2875<p>In this lab, we’re going to deploy a Mongo database that will be used to store
2876the data for the <code>nationalparks</code> application. We will also connect the
2877<code>nationalparks</code> service with the newly deployed MongoDB database, so that the
2878<code>nationalparks</code> service can load and query the database for the corresponding
2879information.</p>
2880</div>
2881<div class="paragraph">
2882<p>Finally, we will mark the <code>nationalparks</code> application as a backend for the map
2883visualization tool, so that it can be dynamically discovered by the <code>parksmap</code>
2884component using the OpenShift discovery mechanism and the map will be displayed
2885automatically.</p>
2886</div>
2887<div class="imageblock text-center">
2888<div class="content">
2889<img src="/workshop/workshop/asset/images/roadshow-app-architecture-nationalparks-2.png" alt="Application architecture" width="800">
2890</div>
2891</div>
2892<div class="sect1">
2893<h2 id="_background_storage">Background: Storage</h2>
2894<div class="sectionbody">
2895<div class="paragraph">
2896<p>Most useful applications are "stateful" or "dynamic" in some way, and this is
2897usually achieved with a database or other data storage. In this lab we are
2898going to add MongoDB to our <code>nationalparks</code> application and then rewire it to
2899talk to the database using environment variables via a secret.</p>
2900</div>
2901<div class="paragraph">
2902<p>We are going to use the MongoDB image that is included with OpenShift.</p>
2903</div>
2904<div class="paragraph">
2905<p>By default, this will use <strong>EmptyDir</strong> for data storage, which means if the <strong>Pod</strong>
2906disappears the data does as well. In a real application you would use
2907OpenShift’s persistent storage mechanism to attach real-world storage (NFS,
2908Gluster, EBS, etc) to the <strong>Pods</strong> to give them a persistent place to store their
2909data.</p>
2910</div>
2911</div>
2912</div>
2913<div class="sect1">
2914<h2 id="_exercise_deploy_mongodb">Exercise: Deploy MongoDB</h2>
2915<div class="sectionbody">
2916<div class="paragraph">
2917<p>As you’ve seen so far, the web console makes it very easy to deploy things onto
2918OpenShift. When we deploy the database, we pass in some values for configuration.
2919These values are used to set the username, password, and name of
2920the database.</p>
2921</div>
2922<div class="paragraph">
2923<p>The database image is built in a way that it will automatically configure itself
2924using the supplied information (assuming there is no data already present in the
2925persistent storage!). The image will ensure that:</p>
2926</div>
2927<div class="ulist">
2928<ul>
2929<li>
2930<p>A database exists with the specified name</p>
2931</li>
2932<li>
2933<p>A user exists with the specified name</p>
2934</li>
2935<li>
2936<p>The user can access the specified database with the specified password</p>
2937</li>
2938</ul>
2939</div>
2940<div class="paragraph">
2941<p>In the web console in your <code>userXY</code> project,
2942click the <strong>"Add to Project"</strong> button and then <strong>"Browse Catalog"</strong>. Select the <strong>"Databases"</strong> category and then <strong>"Mongo"</strong>.</p>
2943</div>
2944<div class="imageblock">
2945<div class="content">
2946<img src="/workshop/workshop/asset/images/nationalparks-databases-catalog-databases.png" alt="Data Stores">
2947</div>
2948</div>
2949<div class="paragraph">
2950<p>Alternatively, you could type <code>mongodb</code> in the search box. Once you have drilled down to see MongoDB, scroll down to find the <strong>MongoDB
2951(Ephemeral)</strong> template, and select it. You will notice that there are several
2952MongoDB templates available. We do not need a database with persistent storage, so the ephemeral Mongo
2953template is what you should choose. Go ahead and select the ephemeral template and click the next button.</p>
2954</div>
2955<div class="imageblock">
2956<div class="content">
2957<img src="/workshop/workshop/asset/images/nationalparks-databases-catalog-databases-mongodb.png" alt="MongoDB">
2958</div>
2959</div>
2960<div class="paragraph">
2961<p>When we performed the application build, there was no template. Rather, we selected the
2962builder image directly and OpenShift presented only the standard build workflow.
2963Now we are using a template - a preconfigured set of resources that includes
2964parameters that can be customized. In our case, the parameters we are concerned
2965with are — user, password, database, and
2966admin password.</p>
2967</div>
2968<div class="imageblock">
2969<div class="content">
2970<img src="/workshop/workshop/asset/images/nationalparks-databases-catalog-databases-mongodb-config.png" alt="MongoDB Deploy">
2971</div>
2972</div>
2973<div class="admonitionblock caution">
2974<table>
2975<tr>
2976<td class="icon">
2977<i class="fa icon-caution" title="Caution"></i>
2978</td>
2979<td class="content">
2980Make sure you name your database service name <strong>mongodb-nationalparks</strong>
2981</td>
2982</tr>
2983</table>
2984</div>
2985<div class="paragraph">
2986<p>You can see that some of the fields say <strong>"generated if empty"</strong>. This is a
2987feature of <strong>Templates</strong> in OpenShift. For
2988now, be sure to use the following values in their respective fields:</p>
2989</div>
2990<div class="ulist">
2991<ul>
2992<li>
2993<p><code>MONGODB_USER</code> : <code>mongodb</code></p>
2994</li>
2995<li>
2996<p><code>MONGODB_PASSWORD</code> : <code>mongodb</code></p>
2997</li>
2998<li>
2999<p><code>MONGODB_DATABASE</code>: <code>mongodb</code></p>
3000</li>
3001<li>
3002<p><code>MONGODB_ADMIN_PASSWORD</code> : <code>mongodb</code></p>
3003</li>
3004</ul>
3005</div>
3006<div class="admonitionblock caution">
3007<table>
3008<tr>
3009<td class="icon">
3010<i class="fa icon-caution" title="Caution"></i>
3011</td>
3012<td class="content">
3013Make sure to have configured the <strong><code>MONGODB_DATABASE</code></strong> parameter with the appropriate value as by default it will already have a value of <code>sampledb</code>.
3014</td>
3015</tr>
3016</table>
3017</div>
3018<div class="paragraph">
3019<p>Once you have entered in the above information, click on "Next" to go to the next step which will allow us to add a binding.</p>
3020</div>
3021<div class="imageblock">
3022<div class="content">
3023<img src="/workshop/workshop/asset/images/nationalparks-databases-catalog-databases-mongodb-create-bining.png" alt="Bind Mongo">
3024</div>
3025</div>
3026<div class="paragraph">
3027<p>This creates a <strong>"binding"</strong> (as a secret) in our project that we can use in other components, such as the national parks backend, to authenticate to the database.</p>
3028</div>
3029<div class="paragraph">
3030<p>While the database deploys, we will fix the labels assigned to the deployment. Currenly we can <code>not</code> set
3031a label when using templates from the Service Catalog, so in this case we will fix this manually.</p>
3032</div>
3033<div class="paragraph">
3034<p>Like before, we will add 3 labels:</p>
3035</div>
3036<div class="ulist">
3037<ul>
3038<li>
3039<p><strong><em>app</em>=workshop</strong> (the name we will be giving to the app)</p>
3040</li>
3041<li>
3042<p><strong><em>component</em>=nationalparks</strong> (the name of this deployment)</p>
3043</li>
3044<li>
3045<p><strong><em>role</em>=backend</strong> (the role this component plays in the overall application)</p>
3046</li>
3047</ul>
3048</div>
3049<div class="paragraph">
3050<p>Execute the following command:</p>
3051</div>
3052<div class="listingblock copypaste">
3053<div class="content">
3054<pre class="CodeRay highlight"><code data-lang="bash">oc label dc/mongodb-nationalparks svc/mongodb-nationalparks app=workshop component=nationalparks role=database --overwrite</code></pre>
3055</div>
3056</div>
3057<div class="paragraph">
3058<p>Now that the connection and authentication information is in a binding in our project, we need to add it to the nationalparks backend.</p>
3059</div>
3060<div class="imageblock">
3061<div class="content">
3062<img src="/workshop/workshop/asset/images/nationalparks-databases-binding-view-secret.png" alt="National Parks Binding">
3063</div>
3064</div>
3065<div class="paragraph">
3066<p>This will bring us to the binding information. Click <code>Reveal Secret</code> next to the word <code>Opaque</code> in the screen. Then click the <code>Add to Application</code> button.</p>
3067</div>
3068<div class="imageblock">
3069<div class="content">
3070<img src="/workshop/workshop/asset/images/nationalparks-databases-binding-add-binding-to-app.png" alt="Add binding to application">
3071</div>
3072</div>
3073<div class="paragraph">
3074<p>Select <code>nationalparks</code> application and click <code>Save</code>.</p>
3075</div>
3076<div class="imageblock">
3077<div class="content">
3078<img src="/workshop/workshop/asset/images/nationalparks-databases-binding-add-binding-to-nationalparks.png" alt="Add binding to application">
3079</div>
3080</div>
3081<div class="paragraph">
3082<p>This change in configuration will trigger a new deployment of the <code>nationalparks</code> application with the binding properly injected.</p>
3083</div>
3084</div>
3085</div>
3086<div class="sect1">
3087<h2 id="_exercise_exploring_openshift_magic">Exercise: Exploring OpenShift Magic</h2>
3088<div class="sectionbody">
3089<div class="paragraph">
3090<p>As soon as we changed the <strong>DeploymentConfiguration</strong>, some
3091magic happened. OpenShift decided that this was a significant enough change to
3092warrant updating the internal version number of the <strong>DeploymentConfiguration</strong>. You
3093can verify this by looking at the output of <code>oc get dc</code>:</p>
3094</div>
3095<div class="listingblock">
3096<div class="content">
3097<pre class="CodeRay highlight"><code data-lang="bash">NAME REVISION DESIRED CURRENT TRIGGERED BY
3098mongodb-nationalparks 1 1 1 config,image(mongodb:3.2)
3099nationalparks 2 1 1 config,image(nationalparks:master)
3100parksmap 2 1 1 config,image(parksmap:1.2.0))</code></pre>
3101</div>
3102</div>
3103<div class="paragraph">
3104<p>Something that increments the version of a <strong>DeploymentConfiguration</strong>, by default,
3105causes a new deployment. You can verify this by looking at the output of <code>oc get
3106rc</code>:</p>
3107</div>
3108<div class="listingblock">
3109<div class="content">
3110<pre class="CodeRay highlight"><code data-lang="bash">NAME DESIRED CURRENT READY AGE
3111mongodb-nationalparks-1 1 1 1 24m
3112nationalparks-1 0 0 0 3h
3113nationalparks-2 1 1 1 8m
3114parksmap-1 0 0 0 6h
3115parksmap-2 1 1 1 5h</code></pre>
3116</div>
3117</div>
3118<div class="paragraph">
3119<p>We see that the desired and current number of instances for the "-1" deployment
3120is 0. The desired and current number of instances for the "-2" deployment is 1.
3121This means that OpenShift has gracefully torn down our "old" application and
3122stood up a "new" instance.</p>
3123</div>
3124</div>
3125</div>
3126<div class="sect1">
3127<h2 id="_exercise_data_data_everywhere">Exercise: Data, Data, Everywhere</h2>
3128<div class="sectionbody">
3129<div class="paragraph">
3130<p>Now that we have a database deployed, we can again visit the <code>nationalparks</code> web
3131service to query for data:</p>
3132</div>
3133<div class="admonitionblock caution">
3134<table>
3135<tr>
3136<td class="icon">
3137<i class="fa icon-caution" title="Caution"></i>
3138</td>
3139<td class="content">
3140In the following url(s), replace <code>userXY</code> with the project provided to you.
3141</td>
3142</tr>
3143</table>
3144</div>
3145<div class="listingblock copypaste">
3146<div class="content">
3147<pre class="CodeRay highlight"><code data-lang="bash">http://nationalparks-userXY.apps.mod-5b05.openshiftworkshop.com/ws/data/all</code></pre>
3148</div>
3149</div>
3150<div class="paragraph">
3151<p>And the result?</p>
3152</div>
3153<div class="listingblock">
3154<div class="content">
3155<pre class="CodeRay highlight"><code data-lang="bash">[]</code></pre>
3156</div>
3157</div>
3158<div class="paragraph">
3159<p>Where’s the data? Think about the process you went through. You deployed the
3160application and then deployed the database. Nothing actually loaded anything
3161<strong>INTO</strong> the database, though.</p>
3162</div>
3163<div class="paragraph">
3164<p>The application provides an endpoint to do just that:</p>
3165</div>
3166<div class="admonitionblock caution">
3167<table>
3168<tr>
3169<td class="icon">
3170<i class="fa icon-caution" title="Caution"></i>
3171</td>
3172<td class="content">
3173In the following url(s), replace <code>userXY</code> with the project provided to you.
3174</td>
3175</tr>
3176</table>
3177</div>
3178<div class="listingblock copypaste">
3179<div class="content">
3180<pre class="CodeRay highlight"><code data-lang="bash">http://nationalparks-userXY.apps.mod-5b05.openshiftworkshop.com/ws/data/load</code></pre>
3181</div>
3182</div>
3183<div class="paragraph">
3184<p>And the result?</p>
3185</div>
3186<div class="listingblock">
3187<div class="content">
3188<pre class="CodeRay highlight"><code data-lang="bash">Items inserted in database: 2740</code></pre>
3189</div>
3190</div>
3191<div class="paragraph">
3192<p>If you then go back to <code>/ws/data/all</code> you will see tons of JSON data now.
3193That’s great. Our parks map should finally work!</p>
3194</div>
3195<div class="admonitionblock note">
3196<table>
3197<tr>
3198<td class="icon">
3199<i class="fa icon-note" title="Note"></i>
3200</td>
3201<td class="content">
3202There are some errors reported with browsers like Firefox 54 that don’t properly parse the resulting JSON. It’s
3203a browser problem, and the application is working properly.
3204</td>
3205</tr>
3206</table>
3207</div>
3208<div class="admonitionblock caution">
3209<table>
3210<tr>
3211<td class="icon">
3212<i class="fa icon-caution" title="Caution"></i>
3213</td>
3214<td class="content">
3215In the following url(s), replace <code>userXY</code> with the project provided to you.
3216</td>
3217</tr>
3218</table>
3219</div>
3220<div class="listingblock copypaste">
3221<div class="content">
3222<pre class="CodeRay highlight"><code data-lang="bash">http://parksmap-userXY.apps.mod-5b05.openshiftworkshop.com</code></pre>
3223</div>
3224</div>
3225<div class="paragraph">
3226<p>Hmm…​ There’s just one thing. The main map <strong>STILL</strong> isn’t displaying the parks.
3227That’s because the front end parks map only tries to talk to services that have
3228the right <strong>Label</strong>.</p>
3229</div>
3230<div class="admonitionblock note">
3231<table>
3232<tr>
3233<td class="icon">
3234<i class="fa icon-note" title="Note"></i>
3235</td>
3236<td class="content">
3237<div class="paragraph">
3238<p>You are probably wondering how the database connection magically started
3239working? When deploying applications to OpenShift, it is always best to use
3240environment variables, secrets, or configMaps to define connections to dependent systems. This allows
3241for application portability across different environments. The source file that
3242performs the connection as well as creates the database schema can be viewed
3243here:</p>
3244</div>
3245<div class="listingblock copypaste">
3246<div class="content">
3247<pre class="CodeRay highlight"><code data-lang="bash">http://www.github.com/openshift-roadshow/nationalparks/blob/master/src/main/java/com/openshift/evg/roadshow/parks/db/MongoDBConnection.java#L44-l48</code></pre>
3248</div>
3249</div>
3250<div class="paragraph">
3251<p>In short summary: By referring to bindings to connect to services
3252(like databases), it can be trivial to promote applications throughout different
3253lifecycle environments on OpenShift without having to modify application code.</p>
3254</div>
3255</td>
3256</tr>
3257</table>
3258</div>
3259</div>
3260</div>
3261<div class="sect1">
3262<h2 id="_exercise_working_with_labels">Exercise: Working With Labels</h2>
3263<div class="sectionbody">
3264<div class="paragraph">
3265<p>We explored how a <strong>Label</strong> is just a key=value pair earlier when looking at
3266<strong>Services</strong> and <strong>Routes</strong> and <strong>Selectors</strong>. In general, a <strong>Label</strong> is simply an
3267arbitrary key=value pair. It could be anything.</p>
3268</div>
3269<div class="ulist">
3270<ul>
3271<li>
3272<p><code>pizza=pepperoni</code></p>
3273</li>
3274<li>
3275<p><code>wicked=googly</code></p>
3276</li>
3277<li>
3278<p><code>openshift=awesome</code></p>
3279</li>
3280</ul>
3281</div>
3282<div class="paragraph">
3283<p>In the case of the parks map, the application is actually querying the OpenShift
3284API and asking about the <strong>Routes</strong> and <strong>Services</strong> in the project. If any of them have a
3285<strong>Label</strong> that is <code>type=parksmap-backend</code>, the application knows to interrogate
3286the endpoints to look for map data.
3287You can see the code that does this
3288<a href="https://github.com/openshift-roadshow/parksmap-web/blob/1.2.0/src/main/java/com/openshift/evg/roadshow/rest/RouteWatcher.java#L20">here</a>.</p>
3289</div>
3290<div class="paragraph">
3291<p>Fortunately, the command line provides a convenient way for us to manipulate
3292labels. <code>describe</code> the <code>nationalparks</code> service:</p>
3293</div>
3294<div class="listingblock copypaste">
3295<div class="content">
3296<pre class="CodeRay highlight"><code data-lang="bash">$ oc describe route nationalparks</code></pre>
3297</div>
3298</div>
3299<div class="listingblock">
3300<div class="content">
3301<pre class="CodeRay highlight"><code data-lang="bash">Name: nationalparks
3302Namespace: userXY
3303Created: 2 hours ago
3304Labels: app=workshop
3305 component=nationalparks
3306 role=backend
3307Requested Host: nationalparks-userXY.apps.mod-5b05.openshiftworkshop.com
3308 exposed on router router 2 hours ago
3309Path: <none>
3310TLS Termination: <none>
3311Insecure Policy: <none>
3312Endpoint Port: 8080-tcp
3313
3314Service: nationalparks
3315Weight: 100 (100%)
3316Endpoints: 10.1.9.8:8080</code></pre>
3317</div>
3318</div>
3319<div class="paragraph">
3320<p>You see that it already has some labels. Now, use <code>oc label</code>:</p>
3321</div>
3322<div class="listingblock copypaste">
3323<div class="content">
3324<pre class="CodeRay highlight"><code data-lang="bash">oc label route nationalparks type=parksmap-backend</code></pre>
3325</div>
3326</div>
3327<div class="paragraph">
3328<p>You will see something like:</p>
3329</div>
3330<div class="listingblock">
3331<div class="content">
3332<pre class="CodeRay highlight"><code data-lang="bash">route "nationalparks" labeled</code></pre>
3333</div>
3334</div>
3335<div class="paragraph">
3336<p>If you check your browser now:</p>
3337</div>
3338<div class="admonitionblock caution">
3339<table>
3340<tr>
3341<td class="icon">
3342<i class="fa icon-caution" title="Caution"></i>
3343</td>
3344<td class="content">
3345In the following url(s), replace <code>userXY</code> with the project provided to you.
3346</td>
3347</tr>
3348</table>
3349</div>
3350<div class="listingblock copypaste">
3351<div class="content">
3352<pre class="CodeRay highlight"><code data-lang="bash">http://parksmap-userXY.apps.mod-5b05.openshiftworkshop.com/</code></pre>
3353</div>
3354</div>
3355<div class="imageblock">
3356<div class="content">
3357<img src="/workshop/workshop/asset/images/nationalparks-databases-new-parks.png" alt="MongoDB">
3358</div>
3359</div>
3360<div class="paragraph">
3361<p>You’ll notice that the parks suddenly are showing up. That’s really cool!</p>
3362</div>
3363</div>
3364</div>
3365 <hr>
3366 <h2>Application Health</h2>
3367 <div class="sect1">
3368<h2 id="_background_readiness_and_liveness_probes">Background: Readiness and Liveness Probes</h2>
3369<div class="sectionbody">
3370<div class="paragraph">
3371<p>As we have seen before in the UI via warnings, there is a concept of application
3372health checks in OpenShift. These come in two flavors:</p>
3373</div>
3374<div class="ulist">
3375<ul>
3376<li>
3377<p>Readiness probe</p>
3378</li>
3379<li>
3380<p>Liveness probe</p>
3381</li>
3382</ul>
3383</div>
3384<div class="paragraph">
3385<p>From the
3386<a href="https://docs.openshift.com/container-platform/latest/dev_guide/application_health.html">Application
3387Health</a> section of the documentation, we see the definitions:</p>
3388</div>
3389<div class="dlist glossary">
3390<dl>
3391<dt>Liveness Probe</dt>
3392<dd>
3393<p>A liveness probe checks if the container in which it is configured is still
3394running. If the liveness probe fails, the kubelet kills the container, which
3395will be subjected to its restart policy. Set a liveness check by configuring
3396the <code>template.spec.containers.livenessprobe</code> stanza of a pod configuration.</p>
3397</dd>
3398<dt>Readiness Probe</dt>
3399<dd>
3400<p>A readiness probe determines if a container is ready to service requests. If
3401the readiness probe fails a container, the endpoints controller ensures the
3402container has its IP address removed from the endpoints of all services. A
3403readiness probe can be used to signal to the endpoints controller that even
3404though a container is running, it should not receive any traffic from a proxy.
3405Set a readiness check by configuring the
3406<code>template.spec.containers.readinessprobe</code> stanza of a pod configuration.</p>
3407</dd>
3408</dl>
3409</div>
3410<div class="paragraph">
3411<p>It sounds complicated, but it really isn’t. We will use the web console to add
3412these probes to our <code>nationalparks</code> application.</p>
3413</div>
3414</div>
3415</div>
3416<div class="sect1">
3417<h2 id="_exercise_add_health_checks">Exercise: Add Health Checks</h2>
3418<div class="sectionbody">
3419<div class="paragraph">
3420<p>As we are going to be implementing a realistic CI/CD pipeline, we will be doing
3421some testing of the "development" version of the application. However, in order
3422to test the app, it must be ready. This is where OpenShift’s application health
3423features come in very handy.</p>
3424</div>
3425<div class="paragraph">
3426<p>We are going to add both a readiness and liveness probe to the existing
3427<code>nationalparks</code> deployment. This will ensure that OpenShift does not add any
3428instances to the service until they pass the readiness checks, and will ensure
3429that unhealthy instances are restarted (if they fail the liveness checks).</p>
3430</div>
3431<div class="paragraph">
3432<p>Click <strong>Applications</strong> → <strong>Deployments</strong> on the left-side bar. Click
3433<code>nationalparks</code>. Click on <code>Configuration</code>.
3434You will see the warning about health checks, with a link to
3435click in order to add them.</p>
3436</div>
3437<div class="imageblock text-center">
3438<div class="content">
3439<img src="/workshop/workshop/asset/images/nationalparks-application-health-warning.png" alt="Healthchecks warning">
3440</div>
3441</div>
3442<div class="paragraph">
3443<p>Click <strong>Add health checks</strong> now.</p>
3444</div>
3445<div class="paragraph">
3446<p>You will want to click both <strong>Add Readiness Probe</strong> and <strong>Add Liveness Probe</strong> and
3447then fill them out as follows:</p>
3448</div>
3449<div class="paragraph">
3450<p><em>Readiness Probe</em></p>
3451</div>
3452<div class="ulist">
3453<ul>
3454<li>
3455<p>Path: <code>/ws/healthz/</code></p>
3456</li>
3457<li>
3458<p>Initial Delay: <code>20</code></p>
3459</li>
3460<li>
3461<p>Timeout: <code>1</code></p>
3462</li>
3463</ul>
3464</div>
3465<div class="paragraph">
3466<p><em>Liveness Probe</em></p>
3467</div>
3468<div class="ulist">
3469<ul>
3470<li>
3471<p>Path: <code>/ws/healthz/</code></p>
3472</li>
3473<li>
3474<p>Initial Delay: <code>120</code></p>
3475</li>
3476<li>
3477<p>Timeout: <code>1</code></p>
3478</li>
3479</ul>
3480</div>
3481<div class="paragraph">
3482<p>This is shown in the following image:</p>
3483</div>
3484<div class="imageblock">
3485<div class="content">
3486<img src="/workshop/workshop/asset/images/nationalparks-application-health-config.png" alt="Readiness and Liveness Probe">
3487</div>
3488</div>
3489<div class="admonitionblock warning">
3490<table>
3491<tr>
3492<td class="icon">
3493<i class="fa icon-warning" title="Warning"></i>
3494</td>
3495<td class="content">
3496Note the trailing slash in the URL
3497</td>
3498</tr>
3499</table>
3500</div>
3501<div class="paragraph">
3502<p>Once you have entered in the values show above, click <strong>Save</strong> and then click the <strong>Overview</strong> button in the left navigation. You
3503will notice that these changes caused a new deployment — they counted as a
3504configuration change.</p>
3505</div>
3506<div class="paragraph">
3507<p>You will also notice that the circle around the new deployment stays light blue
3508for a while. This is a sign that the pod(s) have not yet passed their readiness
3509checks — it’s working!</p>
3510</div>
3511<div class="imageblock">
3512<div class="content">
3513<img src="/workshop/workshop/asset/images/nationalparks-application-health-redeploy.png" alt="Application Health">
3514</div>
3515</div>
3516</div>
3517</div>
3518 <hr>
3519 <h2>Automate Build and Deployment with Pipelines</h2>
3520 <div class="paragraph">
3521<p>In this lab you will learn about pipelines and how to configure a pipeline in OpenShift so
3522that it will take care of the application lifecycle.</p>
3523</div>
3524<div class="sect1">
3525<h2 id="_background_continuous_integration_and_pipelines">Background: Continuous Integration and Pipelines</h2>
3526<div class="sectionbody">
3527<div class="paragraph">
3528<p>A continuous delivery (CD) pipeline is an automated expression of your process for getting software
3529from version control right through to your users and customers.
3530Every change to your software (committed in source control) goes through a complex process on
3531its way to being released. This process involves building the software in a reliable and repeatable
3532manner, as well as progressing the built software (called a "build") through multiple stages of
3533testing and deployment.</p>
3534</div>
3535<div class="paragraph">
3536<p>Pipeline provides an extensible set of tools for modeling simple-to-complex delivery pipelines
3537"as code" via the <a href="https://jenkins.io/doc/book/pipeline/syntax">Pipeline domain-specific language (DSL)</a>
3538syntax. OpenShift provides also an <a href="https://github.com/openshift/jenkins-client-plugin">OpenShift Jenkins Pipeline DSL</a>
3539for interacting with the platform from within a Jenkins pipeline in a fluent manner.</p>
3540</div>
3541<div class="paragraph">
3542<p>The definition of a Jenkins Pipeline is written into a text file (called a Jenkinsfile) which
3543in turn can be committed to a project’s source control repository. This is the foundation of
3544"Pipeline-as-code"; treating the CD pipeline a part of the application to be versioned
3545and reviewed like any other code.</p>
3546</div>
3547<div class="imageblock">
3548<div class="content">
3549<img src="/workshop/workshop/asset/images/devops-pipeline-flow.png" alt="Pipelines">
3550</div>
3551</div>
3552</div>
3553</div>
3554<div class="sect1">
3555<h2 id="_set_up_your_pipeline">Set Up Your Pipeline</h2>
3556<div class="sectionbody">
3557<div class="paragraph">
3558<p>A deployment configuration in OpenShift can contain
3559<a href="https://docs.openshift.com/container-platform/latest/dev_guide/deployments/basic_deployment_operations.html#triggers">triggers</a>, which tells OpenShift to automatically redeploy the pod whenever a new image is built for that service or configuration changes.</p>
3560</div>
3561<div class="paragraph">
3562<p>As we want the Jenkins pipeline to control when builds and deployments happen, we need to disable the ability
3563on the current Deployment to automatically trigger when there is a new image or a configuration change.</p>
3564</div>
3565</div>
3566</div>
3567<div class="sect1">
3568<h2 id="_configure_manual_deployments_on_dev_application">Configure Manual Deployments on Dev Application</h2>
3569<div class="sectionbody">
3570<div class="paragraph">
3571<p>In the <strong>userXY</strong> project, click on <strong>Applications → Deployments</strong> on the left sidebar menu
3572and then on <strong>nationalparks</strong> deployment. Click on <strong>Actions → Edit</strong> button:</p>
3573</div>
3574<div class="imageblock">
3575<div class="content">
3576<img src="/workshop/workshop/asset/images/devops-pipeline-deployment-edit.png" alt="Edit pipeline">
3577</div>
3578</div>
3579<div class="paragraph">
3580<p>Unselect the checkboxes for the Image Change trigger and for the Config change trigger.</p>
3581</div>
3582<div class="imageblock">
3583<div class="content">
3584<img src="/workshop/workshop/asset/images/devops-pipeline-deployment-triggers.png" alt="Remove triggers">
3585</div>
3586</div>
3587</div>
3588</div>
3589<div class="sect1">
3590<h2 id="_create_your_pipeline">Create Your Pipeline</h2>
3591<div class="sectionbody">
3592<div class="paragraph">
3593<p>As pipelines provide the ability to promote applications between different stages of the delivery cycle, Jenkins, which is our Continuous Integration server that will execute our pipelines, will be deployed on a project with a Continuous Integration role. Pipelines executed in this project will have permissions to interact with all the projects modeling the different stages of our delivery cycle.</p>
3594</div>
3595<div class="paragraph">
3596<p>We’re going to deploy a Jenkins instance to this project to configure and run our pipelines. As we want our Jenkins instance to be able to survive restarts (in case we need to update any plugin configuration) we will select the Jenkins persistent template from the Service Catalog.</p>
3597</div>
3598<div class="paragraph">
3599<p>Use the <strong>Search Catalog</strong> search field on the menu bar and search for <strong>Jenkins</strong>. Select the one named <strong>Jenkins</strong>.</p>
3600</div>
3601<div class="imageblock">
3602<div class="content">
3603<img src="/workshop/workshop/asset/images/devops-pipeline-catalog-search.png" alt="Empty CICD project">
3604</div>
3605</div>
3606<div class="paragraph">
3607<p>We will be prompted with the configuration screens for deploying our Jenkins server instance.</p>
3608</div>
3609<div class="imageblock">
3610<div class="content">
3611<img src="/workshop/workshop/asset/images/devops-jenkins-template.png" alt="Jenkins template">
3612</div>
3613</div>
3614<div class="paragraph">
3615<p>Review the configuration if you like and click <strong>next</strong> leaving all the default parameters, as these are ok for this lab.</p>
3616</div>
3617<div class="admonitionblock note">
3618<table>
3619<tr>
3620<td class="icon">
3621<i class="fa icon-note" title="Note"></i>
3622</td>
3623<td class="content">
3624Make sure that Jenkins is configured with at least <code>1Gi Memory Limit</code>
3625</td>
3626</tr>
3627</table>
3628</div>
3629<div class="imageblock">
3630<div class="content">
3631<img src="/workshop/workshop/asset/images/devops-jenkins-template-config.png" alt="Jenkins template config">
3632</div>
3633</div>
3634<div class="paragraph">
3635<p>A binding are the credentials and connection info to the service we are about to deploy. These are useful when you want to provide that information to a consumer application. As an example, if you deploy a database you will want to provide the credentials and connection information for that database to your application.</p>
3636</div>
3637<div class="paragraph">
3638<p>In the case of Jenkins we can move ahead without creating a binding. Select <strong>Do not bind at this time</strong> and click <strong>Create</strong>.</p>
3639</div>
3640<div class="imageblock">
3641<div class="content">
3642<img src="/workshop/workshop/asset/images/devops-jenkins-template-binding.png" alt="Jenkins template binding">
3643</div>
3644</div>
3645<div class="paragraph">
3646<p>Jenkins will now be provisioned on the background. Return back to the <strong>userXY</strong> project by clicking <strong>Continue to the project overview</strong> link.</p>
3647</div>
3648<div class="imageblock">
3649<div class="content">
3650<img src="/workshop/workshop/asset/images/devops-jenkins-template-create.png" alt="Jenkins template create">
3651</div>
3652</div>
3653<div class="paragraph">
3654<p>We will see now Jenkins being provisioned on our project. Once provisioning is finished, we should see a similar screen to this:</p>
3655</div>
3656<div class="imageblock">
3657<div class="content">
3658<img src="/workshop/workshop/asset/images/devops-jenkins-deployed.png" alt="Jenkins deployed">
3659</div>
3660</div>
3661<div class="paragraph">
3662<p>Notice how you see the actual Jenkins deployment and a Provisioned Service, this is because we deployed Jenkins from the Service Catalog as a service for our current project.</p>
3663</div>
3664<div class="paragraph">
3665<p>We could have done the same as we just did by using one single command on the OpenShift CLI. This command will deploy the service Jenkins with a persistent configuration in your <strong>userXY</strong> project.</p>
3666</div>
3667<div class="admonitionblock warning">
3668<table>
3669<tr>
3670<td class="icon">
3671<i class="fa icon-warning" title="Warning"></i>
3672</td>
3673<td class="content">
3674If you have successfully deployed Jenkins, do NOT execute this command.
3675</td>
3676</tr>
3677</table>
3678</div>
3679<div class="listingblock">
3680<div class="content">
3681<pre class="CodeRay highlight"><code data-lang="shell">oc new-app jenkins-persistent -n userXY</code></pre>
3682</div>
3683</div>
3684</div>
3685</div>
3686<div class="sect1">
3687<h2 id="_store_your_pipeline_definition_in_git">Store Your Pipeline Definition in Git</h2>
3688<div class="sectionbody">
3689<div class="paragraph">
3690<p>For this example, we’re going to store our pipeline in the same Gogs repository where we have our code. In a more real scenario, and in order to honor <a href="https://en.wikipedia.org/wiki/Infrastructure_as_Code">infrastructure as code</a> principles, we would store all the pipeline definitions along with every OpenShift resources definitions we would use.</p>
3691</div>
3692<div class="paragraph">
3693<p>Log into your <code>nationalparks</code> repository in Git as we are going to store in this repository our Jenkinsfile, that is, our pipeline definition.</p>
3694</div>
3695<div class="admonitionblock caution">
3696<table>
3697<tr>
3698<td class="icon">
3699<i class="fa icon-caution" title="Caution"></i>
3700</td>
3701<td class="content">
3702In the following url(s), replace <code>userXY</code> with the Git username provided to you.
3703</td>
3704</tr>
3705</table>
3706</div>
3707<div class="listingblock copypaste">
3708<div class="content">
3709<pre class="CodeRay highlight"><code data-lang="bash">http://gogs-infra.apps.mod-5b05.openshiftworkshop.com/userXY/nationalparks</code></pre>
3710</div>
3711</div>
3712<div class="imageblock">
3713<div class="content">
3714<img src="/workshop/workshop/asset/images/devops-pipeline-gogs-nationalparks.png" alt="Nationalparks project">
3715</div>
3716</div>
3717<div class="paragraph">
3718<p>We are going to create a Jenkinsfile to build and deploy our <code>nationalparks</code> application.</p>
3719</div>
3720<div class="paragraph">
3721<p>Create a file called <code>Jenkinsfile.workshop</code> with the following content:</p>
3722</div>
3723<div class="listingblock copypaste">
3724<div class="content">
3725<pre class="CodeRay highlight"><code data-lang="shell">pipeline {
3726 agent {
3727 label 'maven'
3728 }
3729 stages {
3730 stage('Build JAR') {
3731 steps {
3732 git url: 'http://gogs-infra.apps.mod-5b05.openshiftworkshop.com/userXY/nationalparks'
3733 sh "cp .settings.xml ~/.m2/settings.xml"
3734 sh "mvn package"
3735 }
3736 }
3737 stage('Archive JAR') {
3738 steps {
3739 sh "mvn deploy -DskipTests"
3740 }
3741 }
3742 stage('Build Image') {
3743 steps {
3744 script {
3745 openshift.withCluster() {
3746 openshift.withProject() {
3747 openshift.startBuild("nationalparks",
3748 "--from-file=target/nationalparks.jar",
3749 "--wait")
3750 }
3751 }
3752 }
3753 }
3754 }
3755 stage('Deploy') {
3756 steps {
3757 script {
3758 openshift.withCluster() {
3759 openshift.withProject() {
3760 def result, dc = openshift.selector("dc", "nationalparks")
3761 dc.rollout().latest()
3762 timeout(10) {
3763 result = dc.rollout().status("-w")
3764 }
3765 if (result.status != 0) {
3766 error(result.err)
3767 }
3768 }
3769 }
3770 }
3771 }
3772 }
3773 }
3774}</code></pre>
3775</div>
3776</div>
3777<div class="paragraph">
3778<p>And commit the changes into the git server.</p>
3779</div>
3780<div class="imageblock">
3781<div class="content">
3782<img src="/workshop/workshop/asset/images/devops-pipeline-gogs-add-jenkinsfile.png" alt="Nationalparks project">
3783</div>
3784</div>
3785<div class="paragraph">
3786<p>As we can see now, the Jenkinsfile is already stored in our version control system.</p>
3787</div>
3788<div class="imageblock">
3789<div class="content">
3790<img src="/workshop/workshop/asset/images/devops-pipeline-gogs-jenkinsfile-list.png" alt="Nationalparks project">
3791</div>
3792</div>
3793<div class="paragraph">
3794<p>A <strong>Pipeline</strong> is a user-defined model of a CD pipeline. A Pipeline’s code defines your entire build process, which typically includes stages for building an application, testing it and then delivering it.</p>
3795</div>
3796<div class="paragraph">
3797<p>A <strong>stage</strong> block defines a conceptually distinct subset of tasks performed through the entire Pipeline (e.g. <em>Build</em>, <em>Test</em> and <em>Deploy</em> stages), which is used by many plugins to visualize or present Jenkins Pipeline status/progress.</p>
3798</div>
3799<div class="paragraph">
3800<p><strong>Step</strong> is a single task. Fundamentally, a step tells Jenkins what to do at a particular point in time (or "step" in the process).</p>
3801</div>
3802<div class="paragraph">
3803<p>This pipeline has 4 stages defined:</p>
3804</div>
3805<div class="ulist">
3806<ul>
3807<li>
3808<p><strong>Build JAR</strong>: will clone our source repository for nationalparks and will use maven’s package goal to create a .jar file.</p>
3809</li>
3810<li>
3811<p><strong>Archive JAR</strong>: will upload our .jar file to nexus repository, to have it under control.</p>
3812</li>
3813<li>
3814<p><strong>Build Image</strong>: will build an image using a binary file as input in OpenShift. The build will use the .jar file that was created.</p>
3815</li>
3816<li>
3817<p><strong>Deploy</strong>: it will deploy the created image on OpenShift using the DeploymentConfig named <code>nationalparks</code> we created in the previous lab.</p>
3818</li>
3819</ul>
3820</div>
3821</div>
3822</div>
3823<div class="sect1">
3824<h2 id="_create_your_pipeline_definition_on_openshift">Create Your Pipeline Definition on OpenShift</h2>
3825<div class="sectionbody">
3826<div class="paragraph">
3827<p>Create the OpenShift pipeline definition to use the Jenkins file. This is a regular OpenShift BuildConfig with a <strong>JenkinsPipeline</strong> strategy.</p>
3828</div>
3829<div class="paragraph">
3830<p>In the <strong>userXY</strong> project, click on <strong>Add to Project</strong> > <strong>Import YAML/JSON</strong> and paste the following YAML file to create a pipeline
3831that uses the <code>Jenkinsfile.workshop</code> from the <code>userXY</code> git repository</p>
3832</div>
3833<div class="imageblock">
3834<div class="content">
3835<img src="/workshop/workshop/asset/images/devops-pipeline-add-yaml-menu.png" alt="Add yaml to project - Menu">
3836</div>
3837</div>
3838<div class="paragraph">
3839<p>Now, copy the following code into the yaml input box and click <code>create</code>.</p>
3840</div>
3841<div class="listingblock copypaste">
3842<div class="content">
3843<pre class="CodeRay highlight"><code data-lang="shell">apiVersion: build.openshift.io/v1
3844kind: BuildConfig
3845metadata:
3846 name: nationalparks-build
3847spec:
3848 runPolicy: Serial
3849 source:
3850 git:
3851 ref: master
3852 uri: "http://gogs-infra.apps.mod-5b05.openshiftworkshop.com/userXY/nationalparks"
3853 type: Git
3854 strategy:
3855 jenkinsPipelineStrategy:
3856 env:
3857 - name: NEXUS_URL
3858 value: "http://nexus.infra.svc:8081"
3859 jenkinsfilePath: Jenkinsfile.workshop
3860 type: JenkinsPipeline
3861 triggers:
3862 - github:
3863 secret: CqPGlXcKJXXqKxW4Ye6z
3864 type: GitHub
3865 - generic:
3866 secret: 4LXwMdx9vhQY4WXbLcFR
3867 type: Generic
3868 - type: ConfigChange</code></pre>
3869</div>
3870</div>
3871<div class="paragraph">
3872<p>In OpenShift Web Console, click on <strong>Builds</strong> > <strong>Pipelines</strong> to see the pipeline you just created.</p>
3873</div>
3874<div class="imageblock">
3875<div class="content">
3876<img src="/workshop/workshop/asset/images/devops-pipeline-running.png" alt="Pipeline running">
3877</div>
3878</div>
3879<div class="paragraph">
3880<p>The pipeline will start automatically and execute all stages that are defined in the Jenkinsfile
3881in the git repository.</p>
3882</div>
3883<div class="admonitionblock note">
3884<table>
3885<tr>
3886<td class="icon">
3887<i class="fa icon-note" title="Note"></i>
3888</td>
3889<td class="content">
3890the first time you are running it might take a little while before the pipeline starts. The reason for that is
3891that you are using the built-in <a href="https://plugins.jenkins.io/kubernetes">Kubernetes Jenkins Plugin</a> which dynamically provisions
3892a Jenkins slave pod to run the pipeline. The dynamic provisioning allows scaling the pipeline execution to many concurrent jobs. The
3893first time that pipeline runs, it will pull the jenkins slave image from the registry and therefore it might take a little bit of time.
3894</td>
3895</tr>
3896</table>
3897</div>
3898<div class="paragraph">
3899<p>As the pipeline is running, you can watch the build logs. Click on the <code>view Logs</code> link in the appropriate build and you will be directed to Jenkins. In order to grant you access, Jenkins is configured to use Single Sign On with OpenShift, and you’ll need to log in with OpenShift credentials.</p>
3900</div>
3901<div class="imageblock">
3902<div class="content">
3903<img src="/workshop/workshop/asset/images/devops-pipeline-jenkins-sso.png" alt="Jenkins SSO">
3904</div>
3905</div>
3906<div class="paragraph">
3907<p>You need to authorize your user account to access Jenkins.</p>
3908</div>
3909<div class="imageblock">
3910<div class="content">
3911<img src="/workshop/workshop/asset/images/devops-pipeline-jenkins-sso-authorize.png" alt="Jenkins SSO">
3912</div>
3913</div>
3914<div class="paragraph">
3915<p>You will see the output of your maven build as it’s running in Jenkins.</p>
3916</div>
3917<div class="imageblock">
3918<div class="content">
3919<img src="/workshop/workshop/asset/images/devops-pipeline-jenkins-log.png" alt="Jenkins logs">
3920</div>
3921</div>
3922<div class="paragraph">
3923<p>After a little while, it will finish, hopefully with success.</p>
3924</div>
3925<div class="imageblock">
3926<div class="content">
3927<img src="/workshop/workshop/asset/images/devops-pipeline-finished.png" alt="Pipeline finished">
3928</div>
3929</div>
3930<div class="paragraph">
3931<p>Once the pipeline has finished, you should see the nationalparks application redeployed in your project.</p>
3932</div>
3933<div class="paragraph">
3934<p>You should notice that the number of the deployment (the number to the side of the deployment name) has increased.</p>
3935</div>
3936<div class="imageblock">
3937<div class="content">
3938<img src="/workshop/workshop/asset/images/devops-pipeline-nationalparks-deployed.png" alt="Nationalparks component deployed">
3939</div>
3940</div>
3941</div>
3942</div>
3943 <hr>
3944 <h2>Automation for Your Application on Code Changes</h2>
3945 <div class="sect1">
3946<h2 id="_background_web_hooks">Background: Web Hooks</h2>
3947<div class="sectionbody">
3948<div class="paragraph">
3949<p>Most Git repository servers support the concept of web hooks — calling to an
3950external source via HTTP(S) when a change in the code repository happens.
3951OpenShift provides an API endpoint that supports receiving hooks from
3952remote systems in order to trigger builds. By pointing the code repository’s
3953hook at the OpenShift API, automated code/build/deploy pipelines can be
3954achieved.</p>
3955</div>
3956</div>
3957</div>
3958<div class="sect1">
3959<h2 id="_exercise_configuring_gogs_web_hooks">Exercise: Configuring Gogs Web Hooks</h2>
3960<div class="sectionbody">
3961<div class="paragraph">
3962<p>In this lab you can use a build webhook to trigger a pipeline execution every time there is a change in the nationalparks Gogs repository. In the OpenShift web console, navigate to your <code>userXY</code> project, and then mouse-over <code>Builds</code> and then <code>Pipelines</code>. Click the <code>nationalparks-build</code> build and then <code>Configuration</code> tab.</p>
3963</div>
3964<div class="paragraph">
3965<p>On this screen you will see the option to copy the generic webhook URL as shown in the following image:</p>
3966</div>
3967<div class="imageblock">
3968<div class="content">
3969<img src="/workshop/workshop/asset/images/nationalparks-pipeline-codechanges-webhook-config.png" alt="Webhook">
3970</div>
3971</div>
3972<div class="paragraph">
3973<p>Once you have the URL copied to your clipboard, navigate to the code repository
3974that you have on your local Gogs:</p>
3975</div>
3976<div class="admonitionblock caution">
3977<table>
3978<tr>
3979<td class="icon">
3980<i class="fa icon-caution" title="Caution"></i>
3981</td>
3982<td class="content">
3983In the following url(s), replace <code>userXY</code> with the Git username provided to you.
3984</td>
3985</tr>
3986</table>
3987</div>
3988<div class="listingblock copypaste">
3989<div class="content">
3990<pre class="CodeRay highlight"><code data-lang="bash">http://gogs-infra.apps.mod-5b05.openshiftworkshop.com/userXY/nationalparks</code></pre>
3991</div>
3992</div>
3993<div class="admonitionblock note">
3994<table>
3995<tr>
3996<td class="icon">
3997<i class="fa icon-note" title="Note"></i>
3998</td>
3999<td class="content">
4000<div class="paragraph">
4001<p>The credentials for this Gogs instance are the same as for our OpenShift instance</p>
4002</div>
4003</td>
4004</tr>
4005</table>
4006</div>
4007<div class="paragraph">
4008<p>Click the Settings link on the top right of the screen:</p>
4009</div>
4010<div class="imageblock">
4011<div class="content">
4012<img src="/workshop/workshop/asset/images/nationalparks-codechanges-gogs-settings.png" alt="Webhook">
4013</div>
4014</div>
4015<div class="paragraph">
4016<p>Click on webhooks, and the on <code>Add Webhook</code> button.</p>
4017</div>
4018<div class="imageblock">
4019<div class="content">
4020<img src="/workshop/workshop/asset/images/nationalparks-codechanges-gogs-add-webhook.png" alt="Webhook">
4021</div>
4022</div>
4023<div class="paragraph">
4024<p>In the next screen, paste your link into the "URL" field. You can leave the
4025secret token field blank — the secret is already in the URL and does not need
4026to be in the payload, or copy it from the URL.</p>
4027</div>
4028<div class="paragraph">
4029<p>Change the <code>Content Type</code> to <code>application/x-www-form-urlencoded</code>.</p>
4030</div>
4031<div class="paragraph">
4032<p>Finally, click on "Add webhook".</p>
4033</div>
4034<div class="imageblock">
4035<div class="content">
4036<img src="/workshop/workshop/asset/images/nationalparks-codechanges-gogs-config-webhook.png" alt="Webhook">
4037</div>
4038</div>
4039<div class="paragraph">
4040<p>Boom! From now on, every time you commit new source code to your Gogs
4041repository, a new build and deploy will occur inside of OpenShift. Let’s try
4042this out.</p>
4043</div>
4044</div>
4045</div>
4046<div class="sect1">
4047<h2 id="_exercise_using_gogs_web_hooks">Exercise: Using Gogs Web Hooks</h2>
4048<div class="sectionbody">
4049<div class="paragraph">
4050<p>Click "Project" at the top of the Gogs page, and then "Files" towards the
4051middle of the page. This is Gogs’s repository view.</p>
4052</div>
4053<div class="admonitionblock caution">
4054<table>
4055<tr>
4056<td class="icon">
4057<i class="fa icon-caution" title="Caution"></i>
4058</td>
4059<td class="content">
4060Make sure that the drop-down menu at the upper right is set for
4061the <strong><code>master</code></strong> branch. Navigate to the
4062following path:
4063</td>
4064</tr>
4065</table>
4066</div>
4067<div class="listingblock">
4068<div class="content">
4069<pre class="CodeRay highlight"><code data-lang="bash">src/main/java/com/openshift/evg/roadshow/parks/rest/</code></pre>
4070</div>
4071</div>
4072<div class="paragraph">
4073<p>Then click on the <code>BackendController.java</code> file.</p>
4074</div>
4075<div class="paragraph">
4076<p>Once you have the file on the screen, click the edit button in the top right
4077hand corner as shown here:</p>
4078</div>
4079<div class="imageblock">
4080<div class="content">
4081<img src="/workshop/workshop/asset/images/nationalparks-codechanges-gogs-change-code.png" alt="Webhook">
4082</div>
4083</div>
4084<div class="paragraph">
4085<p>Change line number 20:</p>
4086</div>
4087<div class="listingblock">
4088<div class="content">
4089<pre class="CodeRay highlight"><code data-lang="java"><span class="keyword">return</span> <span class="keyword">new</span> Backend(<span class="string"><span class="delimiter">"</span><span class="content">nationalparks</span><span class="delimiter">"</span></span>,<span class="string"><span class="delimiter">"</span><span class="content">National Parks</span><span class="delimiter">"</span></span>, <span class="keyword">new</span> Coordinates(<span class="string"><span class="delimiter">"</span><span class="content">47.039304</span><span class="delimiter">"</span></span>, <span class="string"><span class="delimiter">"</span><span class="content">14.505178</span><span class="delimiter">"</span></span>), <span class="integer">4</span>);</code></pre>
4090</div>
4091</div>
4092<div class="paragraph">
4093<p>To</p>
4094</div>
4095<div class="listingblock">
4096<div class="content">
4097<pre class="CodeRay highlight"><code data-lang="java"><span class="keyword">return</span> <span class="keyword">new</span> Backend(<span class="string"><span class="delimiter">"</span><span class="content">nationalparks</span><span class="delimiter">"</span></span>,<span class="string"><span class="delimiter">"</span><span class="content">Amazing National Parks</span><span class="delimiter">"</span></span>, <span class="keyword">new</span> Coordinates(<span class="string"><span class="delimiter">"</span><span class="content">47.039304</span><span class="delimiter">"</span></span>, <span class="string"><span class="delimiter">"</span><span class="content">14.505178</span><span class="delimiter">"</span></span>), <span class="integer">4</span>);</code></pre>
4098</div>
4099</div>
4100<div class="paragraph">
4101<p>Click on Commit changes at the bottom of the screen. Feel free to enter a commit
4102message.</p>
4103</div>
4104<div class="paragraph">
4105<p>Once you have committed your changes, a <strong>Pipeline Build</strong> should almost instantaneously be
4106triggered in OpenShift. Look at the <strong>Pipelines</strong> page in the web console,</p>
4107</div>
4108<div class="imageblock">
4109<div class="content">
4110<img src="/workshop/workshop/asset/images/nationalparks-codechanges-pipeline-running.png" alt="Webhook">
4111</div>
4112</div>
4113<div class="paragraph">
4114<p>or run the
4115following command to verify:</p>
4116</div>
4117<div class="listingblock copypaste">
4118<div class="content">
4119<pre class="CodeRay highlight"><code data-lang="bash">oc get builds</code></pre>
4120</div>
4121</div>
4122<div class="paragraph">
4123<p>You should see that a new build is running:</p>
4124</div>
4125<div class="listingblock">
4126<div class="content">
4127<pre class="CodeRay highlight"><code data-lang="bash">NAME TYPE FROM STATUS STARTED DURATION
4128nationalparks-1 Source Git@b052ae6 Complete 18 hours ago 36s
4129nationalparks-2 Source Git@3b26e1a Complete 35 minutes ago
4130nationalparks-3 Binary Git@3a56cb1 Running 43 seconds ago
4131nationalparks-build-1 JenkinsPipeline Git@master Complete 35 minutes ago
4132nationalparks-build-2 JenkinsPipeline Git@master Running 58 seconds ago</code></pre>
4133</div>
4134</div>
4135<div class="paragraph">
4136<p>Once the build and deploy has finished, verify your new image was
4137automatically deployed by viewing the application in your browser:</p>
4138</div>
4139<div class="admonitionblock caution">
4140<table>
4141<tr>
4142<td class="icon">
4143<i class="fa icon-caution" title="Caution"></i>
4144</td>
4145<td class="content">
4146In the following url(s), replace <code>userXY</code> with the project provided to you.
4147</td>
4148</tr>
4149</table>
4150</div>
4151<div class="listingblock copypaste">
4152<div class="content">
4153<pre class="CodeRay highlight"><code data-lang="bash">http://nationalparks-userXY.apps.mod-5b05.openshiftworkshop.com/ws/info/</code></pre>
4154</div>
4155</div>
4156<div class="paragraph">
4157<p>You should now see the new name you have set in the JSON string returned.</p>
4158</div>
4159<div class="admonitionblock note">
4160<table>
4161<tr>
4162<td class="icon">
4163<i class="fa icon-note" title="Note"></i>
4164</td>
4165<td class="content">
4166To see this in the map’s legend itself, you will need to scale down your parksmap to 0, then back up to 1 to force the app to refresh its cache.
4167</td>
4168</tr>
4169</table>
4170</div>
4171</div>
4172</div>
4173<div class="sect1">
4174<h2 id="_exercise_rollback">Exercise: Rollback</h2>
4175<div class="sectionbody">
4176<div class="paragraph">
4177<p>OpenShift allows you to move between different versions of an application
4178without the need to rebuild each time. Every version (past builds) of the
4179application exists as an image in the OpenShift registry. Using
4180the <code>oc rollback</code> and <code>oc deploy</code> commands you can move back- or forward between
4181various versions of applications.</p>
4182</div>
4183<div class="paragraph">
4184<p>In order to perform a rollback, you need to know the name of the <strong>Deployment Config</strong>
4185which has deployed the application:</p>
4186</div>
4187<div class="listingblock copypaste">
4188<div class="content">
4189<pre class="CodeRay highlight"><code data-lang="bash">oc get dc</code></pre>
4190</div>
4191</div>
4192<div class="paragraph">
4193<p>The output will be similar to the following:</p>
4194</div>
4195<div class="listingblock">
4196<div class="content">
4197<pre class="CodeRay highlight"><code data-lang="bash">NAME REVISION DESIRED CURRENT TRIGGERED BY
4198mongodb 1 1 1 config,image(mongodb:3.2)
4199parksmap 2 1 1 config,image(parksmap:1.2.0)
4200nationalparks 9 1 1 config,image(nationalparks:master)</code></pre>
4201</div>
4202</div>
4203<div class="paragraph">
4204<p>Now run the following command to rollback the latest code change:</p>
4205</div>
4206<div class="listingblock copypaste">
4207<div class="content">
4208<pre class="CodeRay highlight"><code data-lang="bash">oc rollback nationalparks</code></pre>
4209</div>
4210</div>
4211<div class="paragraph">
4212<p>You will see output like the following:</p>
4213</div>
4214<div class="listingblock">
4215<div class="content">
4216<pre class="CodeRay highlight"><code data-lang="bash">#5 rolled back to nationalparks-3
4217Warning: the following images triggers were disabled: nationalparks:latest
4218 You can re-enable them with: oc set triggers dc/nationalparks --auto</code></pre>
4219</div>
4220</div>
4221<div class="paragraph">
4222<p>Once the deploy is complete, verify that the page header is reverted to the
4223original header by viewing the application in your browser.</p>
4224</div>
4225<div class="admonitionblock caution">
4226<table>
4227<tr>
4228<td class="icon">
4229<i class="fa icon-caution" title="Caution"></i>
4230</td>
4231<td class="content">
4232In the following url(s), replace <code>userXY</code> with the project provided to you.
4233</td>
4234</tr>
4235</table>
4236</div>
4237<div class="listingblock copypaste">
4238<div class="content">
4239<pre class="CodeRay highlight"><code data-lang="bash">http://nationalparks-userXY.apps.mod-5b05.openshiftworkshop.com/ws/info/</code></pre>
4240</div>
4241</div>
4242<div class="admonitionblock note">
4243<table>
4244<tr>
4245<td class="icon">
4246<i class="fa icon-note" title="Note"></i>
4247</td>
4248<td class="content">
4249<div class="paragraph">
4250<p>Automatic deployment of new images is disabled as part of the rollback
4251to prevent unwanted deployments soon after the rollback is complete. To re-enable
4252the automatic deployments run this:</p>
4253</div>
4254<div class="listingblock copypaste">
4255<div class="content">
4256<pre class="CodeRay highlight"><code data-lang="bash">oc set triggers dc/nationalparks --auto</code></pre>
4257</div>
4258</div>
4259</td>
4260</tr>
4261</table>
4262</div>
4263</div>
4264</div>
4265<div class="sect1">
4266<h2 id="_exercise_rollforward">Exercise: Rollforward</h2>
4267<div class="sectionbody">
4268<div class="paragraph">
4269<p>Just like you performed a rollback, you can also perform a roll-forward using
4270the same command. You’ll notice above that when you requested a <strong>rollback</strong>, it
4271caused a new deployment (#3). In essence, we always move forwards in OpenShift,
4272even if we are going "back".</p>
4273</div>
4274<div class="paragraph">
4275<p>So, if we want to return to the "new code" version, that is deployment #4.</p>
4276</div>
4277<div class="listingblock copypaste">
4278<div class="content">
4279<pre class="CodeRay highlight"><code data-lang="bash">oc rollback nationalparks-4</code></pre>
4280</div>
4281</div>
4282<div class="paragraph">
4283<p>And you will see the following:</p>
4284</div>
4285<div class="listingblock">
4286<div class="content">
4287<pre class="CodeRay highlight"><code data-lang="bash">#6 rolled back to nationalparks-4
4288Warning: the following images triggers were disabled: nationalparks
4289 You can re-enable them with: oc set triggers dc/nationalparks --auto</code></pre>
4290</div>
4291</div>
4292<div class="paragraph">
4293<p>Cool! Once the <strong>rollback</strong> is complete, verify you again see "Amazing
4294National Parks".</p>
4295</div>
4296</div>
4297</div>
4298 <hr>
4299 <h2>Using Application Templates</h2>
4300 <div class="paragraph">
4301<p>In this lab, we’re going to deploy a complete backend application, consisting of
4302a REST API backend and a MongoDB database. The complete application will already
4303be wired together and described as a backend for the map visualization tool, so
4304that once the application is built and deployed, you will be able to see the new
4305map.</p>
4306</div>
4307<div class="imageblock text-center">
4308<div class="content">
4309<img src="/workshop/workshop/asset/images/roadshow-app-architecture-mlbparks.png" alt="Application architecture" width="800">
4310</div>
4311</div>
4312<div class="sect1">
4313<h2 id="_background_templates">Background: Templates</h2>
4314<div class="sectionbody">
4315<div class="paragraph">
4316<p>Running all these individual commands can be tedious and error prone.
4317Fortunately for you, all of this configuration can be put together into a single
4318<strong>Template</strong> which can then be processed to create a full set of resources. As you
4319saw with MongoDB, a <strong>Template</strong> may define parameters for certain values, such as
4320DB username or password, and they can be automatically generated by OpenShift at
4321processing time.</p>
4322</div>
4323<div class="paragraph">
4324<p>Administrators can load <strong>Templates</strong> into OpenShift and make them available to
4325all users, even via the web console. Users can create <strong>Templates</strong> and load them
4326into their own <strong>Projects</strong> for other users (with access) to share and use.</p>
4327</div>
4328<div class="paragraph">
4329<p>The great thing about <strong>Templates</strong> is that they can speed up the deployment
4330workflow for application development by providing a "recipe" of sorts that can
4331be deployed with a single command. Not only that, they can be loaded into
4332OpenShift from an external URL, which will allow you to keep your templates in a
4333version control system.</p>
4334</div>
4335<div class="paragraph">
4336<p>Let’s combine all of the exercises we have performed in the last several labs by
4337using a <strong>Template</strong> that we can instantiate with a single command. While we
4338could have used templates to deploy everything in the workshop today, remember
4339that it is important for you to understand how to create, deploy, and wire
4340resources together.</p>
4341</div>
4342</div>
4343</div>
4344<div class="sect1">
4345<h2 id="_exercise_instantiate_a_template">Exercise: Instantiate a Template</h2>
4346<div class="sectionbody">
4347<div class="paragraph">
4348<p>The front end application we’ve been working with this whole time will display
4349as many back end services' data as are created. Adding more stuff with the right
4350<strong>Label</strong> will make more stuff show up on the map.</p>
4351</div>
4352<div class="paragraph">
4353<p>Now you will deploy a map of Major League Baseball stadiums in the US by using a
4354template. It is pre-configured to build the back end Java application, and
4355deploy the MongoDB database. It also uses a <strong>Hook</strong> to call the <code>/ws/data/load</code>
4356endpoint to cause the data to be loaded into the database from a JSON file in
4357the source code repository. Execute the following command:</p>
4358</div>
4359<div class="listingblock copypaste">
4360<div class="content">
4361<pre class="CodeRay highlight"><code data-lang="bash">oc create -f https://raw.githubusercontent.com/openshift-roadshow/mlbparks/master/ose3/application-template-eap.json</code></pre>
4362</div>
4363</div>
4364<div class="paragraph">
4365<p>What just happened? What did you just <code>create</code>? The item that we passed to the <code>create</code>
4366command is a <strong>Template</strong>. <code>create</code> simply makes the template available in
4367your <strong>Project</strong>. You can see this with the following command:</p>
4368</div>
4369<div class="listingblock copypaste">
4370<div class="content">
4371<pre class="CodeRay highlight"><code data-lang="bash">oc get template</code></pre>
4372</div>
4373</div>
4374<div class="paragraph">
4375<p>You will see output like the following:</p>
4376</div>
4377<div class="listingblock">
4378<div class="content">
4379<pre class="CodeRay highlight"><code data-lang="bash">mlbparks Application template MLBParks backend running on Wildfly and using mongodb 12 (2 blank) 8</code></pre>
4380</div>
4381</div>
4382<div class="paragraph">
4383<p>In the web console, you can see the templates you have in your project, by clicking on the
4384<strong>"Add to project -→ Select from project"</strong> dropdown menu.</p>
4385</div>
4386<div class="imageblock">
4387<div class="content">
4388<img src="/workshop/workshop/asset/images/mlbparks-templates-from-project-menu.png" alt="Select from project menu">
4389</div>
4390</div>
4391<div class="paragraph">
4392<p>You’ll be presented with a list of templates local to your own project. You will see the template we just loaded.</p>
4393</div>
4394<div class="imageblock">
4395<div class="content">
4396<img src="/workshop/workshop/asset/images/mlbparks-templates-from-project.png" alt="Local templates">
4397</div>
4398</div>
4399<div class="paragraph">
4400<p>Are you ready for the magic command?</p>
4401</div>
4402<div class="paragraph">
4403<p>Here it is!</p>
4404</div>
4405<div class="paragraph">
4406<p>If you want to use command line:</p>
4407</div>
4408<div class="listingblock copypaste">
4409<div class="content">
4410<pre class="CodeRay highlight"><code data-lang="bash">oc new-app mlbparks -p APPLICATION_NAME=mlbparks</code></pre>
4411</div>
4412</div>
4413<div class="admonitionblock tip">
4414<table>
4415<tr>
4416<td class="icon">
4417<i class="fa icon-tip" title="Tip"></i>
4418</td>
4419<td class="content">
4420<div class="paragraph">
4421<p>The template can also use maven for the build. In case you want to try this option
4422provide the <strong>MAVEN_MIRROR_URL</strong> parameter with the location of the internal nexus
4423repository:</p>
4424</div>
4425<div class="listingblock copypaste">
4426<div class="content">
4427<pre class="CodeRay highlight"><code data-lang="bash">oc new-app mlbparks --name=mlbparks -p MAVEN_MIRROR_URL=http://nexus.infra.svc.cluster.local:8081/repository/maven-all-public</code></pre>
4428</div>
4429</div>
4430</td>
4431</tr>
4432</table>
4433</div>
4434<div class="paragraph">
4435<p>You will see some output similar to this:</p>
4436</div>
4437<div class="listingblock">
4438<div class="content">
4439<pre class="CodeRay highlight"><code data-lang="bash">--> Deploying template "user2/mlbparks" to project user2
4440
4441 MLBparks
4442 ---------
4443 Application template MLBParks backend running on Wildfly and using mongodb
4444
4445 * With parameters:
4446 * Application Name=mlbparks
4447 * Application route=
4448 * Mongodb App=mongodb-mlbparks
4449 * Git source repository=https://github.com/openshift-roadshow/mlbparks.git
4450 * Git branch/tag reference=master
4451 * Database name=mongodb
4452 * MONGODB_NOPREALLOC=
4453 * MONGODB_SMALLFILES=
4454 * MONGODB_QUIET=
4455 * Database user name=userGhR # generated
4456 * Database user password=KhnHKCQI # generated
4457 * Database admin password=UyUV6ReU # generated
4458 * GitHub Trigger=dAOuD7s4 # generated
4459 * Generic Trigger=tWSkmNLn # generated
4460
4461--> Creating resources ...
4462 configmap "mlbparks" created
4463 service "mongodb-mlbparks" created
4464 deploymentconfig "mongodb-mlbparks" created
4465 imagestream "mlbparks" created
4466 buildconfig "mlbparks" created
4467 deploymentconfig "mlbparks" created
4468 service "mlbparks" created
4469 route "mlbparks" created
4470--> Success
4471 Build scheduled, use 'oc logs -f bc/mlbparks' to track its progress.
4472 Run 'oc status' to view your app.</code></pre>
4473</div>
4474</div>
4475<div class="paragraph">
4476<p>Or if you prefer using the web UI, you can just click on the template we just saw. If you followed the command line steps above then <strong>do not</strong> follow the web console steps below. This is simply demonstrating an alternate way to instantiate the template.</p>
4477</div>
4478<div class="imageblock">
4479<div class="content">
4480<img src="/workshop/workshop/asset/images/mlparks-templates-from-project-info.png" alt="Template info">
4481</div>
4482</div>
4483<div class="paragraph">
4484<p>Then, you’ll see a guided wizard showing you some information and allowing you to provide
4485the desired configuration to instantiate the template</p>
4486</div>
4487<div class="imageblock">
4488<div class="content">
4489<img src="/workshop/workshop/asset/images/mlparks-templates-from-project-info.png" alt="Template config">
4490</div>
4491</div>
4492<div class="paragraph">
4493<p>Go ahead and click <strong>"Create"</strong></p>
4494</div>
4495<div class="paragraph">
4496<p>OpenShift will now:</p>
4497</div>
4498<div class="ulist">
4499<ul>
4500<li>
4501<p>Configure and start a build</p>
4502<div class="ulist">
4503<ul>
4504<li>
4505<p>Using the supplied Maven mirror URL (In case you have specified the parameter)</p>
4506</li>
4507<li>
4508<p>From the supplied source code repository</p>
4509</li>
4510</ul>
4511</div>
4512</li>
4513<li>
4514<p>Configure and deploy MongoDB</p>
4515<div class="ulist">
4516<ul>
4517<li>
4518<p>Using auto-generated user, password, and database name</p>
4519</li>
4520</ul>
4521</div>
4522</li>
4523<li>
4524<p>Configure environment variables for the app to connect to the DB</p>
4525</li>
4526<li>
4527<p>Create the correct services</p>
4528</li>
4529<li>
4530<p>Label the app service with <code>type=parksmap-backend</code></p>
4531</li>
4532</ul>
4533</div>
4534<div class="paragraph">
4535<p>All with one command!</p>
4536</div>
4537<div class="paragraph">
4538<p>When the build is complete, visit the parks map. Does it work? Think about how
4539this could be used in your environment. For example, a template could define a
4540large set of resources that make up a "reference application", complete with
4541several app servers, databases, and more. You could deploy the entire set of
4542resources with one command, and then hack on them to develop new features,
4543microservices, fix bugs, and more.</p>
4544</div>
4545<div class="imageblock">
4546<div class="content">
4547<img src="/workshop/workshop/asset/images/mlbparks-templates-complete-overview.png" alt="Complete overview">
4548</div>
4549</div>
4550<div class="paragraph">
4551<p>As a final exercise, look at the template that was used to create the
4552resources for our <strong>mlbparks</strong> application.</p>
4553</div>
4554<div class="listingblock copypaste">
4555<div class="content">
4556<pre class="CodeRay highlight"><code data-lang="bash">oc get template mlbparks -o yaml</code></pre>
4557</div>
4558</div>
4559<div class="paragraph">
4560<p>But as always, you can use the OpenShift web console to do the same. Under <strong>"Resources menu"</strong>, click on <strong>"Other resources"</strong>,
4561then select <strong>"Templates</strong>" from the dropdown, and select the <strong>"Edit YAML"</strong> action, on the <strong>"Actions"</strong> dropdown.</p>
4562</div>
4563<div class="imageblock">
4564<div class="content">
4565<img src="/workshop/workshop/asset/images/mlbparks-templates-yaml-menu.png" alt="Complete overview">
4566</div>
4567</div>
4568<div class="paragraph">
4569<p>You’ll be able to see/edit the YAML as well from here.</p>
4570</div>
4571<div class="imageblock">
4572<div class="content">
4573<img src="/workshop/workshop/asset/images/mlbparks-templates-yaml-edit.png" alt="Template YAML edit">
4574</div>
4575</div>
4576</div>
4577</div>
4578 <hr>
4579 <h2>Clustering Stateful Java EE Applications</h2>
4580 <div class="sect1">
4581<h2 id="_jboss_eap_clustering">JBoss EAP Clustering</h2>
4582<div class="sectionbody">
4583<div class="paragraph">
4584<p>Clustering in JBoss EAP is achieved using the Kubernetes discovery mechanism for
4585finding other JBoss EAP containers and forming a cluster. This is done by
4586configuring the JGroups protocol stack in <code>standalone-openshift.xml</code> with
4587<code><openshift.KUBE_PING/></code> elements.</p>
4588</div>
4589<div class="paragraph">
4590<p>For <code>KUBE_PING</code> to work, the following steps must be taken:</p>
4591</div>
4592<div class="olist arabic">
4593<ol class="arabic">
4594<li>
4595<p>The <code>OPENSHIFT_KUBE_PING_NAMESPACE</code> environment variable must be set. If not
4596set, the server will act as if it is a single-node cluster (a "cluster of
4597one").</p>
4598</li>
4599<li>
4600<p>The <code>OPENSHIFT_KUBE_PING_LABELS</code> environment variables should be set. If not
4601set, pods outside of your application (albeit in your namespace) will try to
4602join.</p>
4603</li>
4604<li>
4605<p>Authorization must be granted to the service account the pod is running under
4606to be allowed to access Kubernetes' REST api.</p>
4607</li>
4608</ol>
4609</div>
4610<div class="paragraph">
4611<p>You have already configured the default service account to have access to
4612Kubernetes' REST API during previous labs. Now you can scale up the <strong>mlbparks</strong>
4613pod to two by clicking on the upper arrows on the console. Alternatively, you
4614can use the command line to scale up the pods and form a two-member cluster.</p>
4615</div>
4616<div class="listingblock copypaste">
4617<div class="content">
4618<pre class="CodeRay highlight"><code data-lang="bash">oc scale dc/mlbparks --replicas=2</code></pre>
4619</div>
4620</div>
4621<div class="paragraph">
4622<p>For pods based on Java images, the web console also exposes access to a
4623hawt.io-based JVM console for viewing and managing any relevant Java components.
4624A link is displayed in the pod’s details on the <strong>Applications</strong> → <strong>Pods</strong> page,
4625provided the container has a port named jolokia. On the console, click on
4626mlbparks pods, then on any of the two pods deployed. On the <strong>Details</strong> tab, click
4627on <strong>Open Java Console</strong>.</p>
4628</div>
4629<div class="imageblock text-center">
4630<div class="content">
4631<img src="/workshop/workshop/asset/images/mlbparks-clustering-details.png" alt="Java Console Link" width="880">
4632</div>
4633</div>
4634<div class="paragraph">
4635<p>In the Java Console, use the <strong>JMX</strong> browser and click on <strong>jgroups → channel
4636→ ee</strong>. The right pane shows the list of clustering JMX attributes including
4637<strong>view</strong> which is the current state of the cluster. This attribute shows the name
4638of two pods which are currently members of the cluster. When <strong>mlbparks</strong> pod gets
4639scaled up or down, JBoss EAP gets notified by calling Kubernetes' REST API and
4640updates the cluster status based on the number of pods available.</p>
4641</div>
4642<div class="imageblock text-center">
4643<div class="content">
4644<img src="/workshop/workshop/asset/images/mlbparks-clustering-hawtio.png" alt="Java Console - Clustering" width="1000">
4645</div>
4646</div>
4647</div>
4648</div>
4649 <hr>
4650 <h2>Binary Builds for Day to Day Development</h2>
4651 <div class="sect1">
4652<h2 id="_moving_on_from_s2i">Moving on From S2I</h2>
4653<div class="sectionbody">
4654<div class="paragraph">
4655<p>As you saw before S2I is a great way to get from source code to a container, but the process is a bit too slow for daily fast iterative
4656development. For example, if you want to change some CSS or change one method in a class you don’t want to go through
4657a full git commit and build cycle. In this lab we are going to show you a more efficient method for quick iteration. While
4658we are at it we will also show you how to debug your code.</p>
4659</div>
4660<div class="paragraph">
4661<p>Now that we built the MLB parks service let’s go ahead and make some quick changes.</p>
4662</div>
4663</div>
4664</div>
4665<div class="sect1">
4666<h2 id="_fast_iterative_code_change_using_binary_deploy">Fast Iterative Code Change Using Binary Deploy</h2>
4667<div class="sectionbody">
4668<div class="paragraph">
4669<p>The OpenShift command line has the ability to do a deployment from your local machine. In this case we are going to use S2I,
4670but we are going to tell OpenShift to just take the war file from our local machine and bake it in the image.</p>
4671</div>
4672<div class="paragraph">
4673<p>Doing this pattern of development let’s us do quick builds on our local machine (benefitting from our local cache and
4674all the horsepower on our machine) and then just quickly send up the war file.</p>
4675</div>
4676<div class="admonitionblock note">
4677<table>
4678<tr>
4679<td class="icon">
4680<i class="fa icon-note" title="Note"></i>
4681</td>
4682<td class="content">
4683You could also use this pattern to actually send up your working directory to the S2I builder to have it do the Maven build
4684on OpenShift. Using the local directory would relieve you from having Maven or any of the Java toolchain on your local
4685machine AND would also not require git commit with a push. Read more in the
4686<a href="https://docs.openshift.com/container-platform/latest/dev_guide/dev_tutorials/binary_builds.html">official documentation</a>
4687</td>
4688</tr>
4689</table>
4690</div>
4691</div>
4692</div>
4693<div class="sect1">
4694<h2 id="_exercise_using_binary_deployment">Exercise: Using Binary Deployment</h2>
4695<div class="sectionbody">
4696<div class="sect2">
4697<h3 id="_clone_source">Clone source</h3>
4698<div class="paragraph">
4699<p>The first step is to clone the MLB source code from GitHub to your local machine:</p>
4700</div>
4701<div class="listingblock copypaste">
4702<div class="content">
4703<pre class="CodeRay highlight"><code data-lang="bash">git clone https://github.com/openshift-roadshow/mlbparks.git</code></pre>
4704</div>
4705</div>
4706<div class="admonitionblock note">
4707<table>
4708<tr>
4709<td class="icon">
4710<i class="fa icon-note" title="Note"></i>
4711</td>
4712<td class="content">
4713We are using Intellij here in the guide for screenshots but this should work regardless of your tool chain. JBoss
4714Developer Studio and JBoss Developer Tools have built in functionality that makes this close to seamless right from the IDE.
4715</td>
4716</tr>
4717</table>
4718</div>
4719</div>
4720<div class="sect2">
4721<h3 id="_setup_the_build_of_the_war_file">Setup the Build of the war file</h3>
4722<div class="paragraph">
4723<p>If you have Maven all set up on your machine, then you can just do a:</p>
4724</div>
4725<div class="listingblock copypaste">
4726<div class="content">
4727<pre class="CodeRay highlight"><code data-lang="bash">mvn package</code></pre>
4728</div>
4729</div>
4730<div class="paragraph">
4731<p>Pay attention to the output location for the ROOT.war, we will need that directory later.</p>
4732</div>
4733<div class="paragraph">
4734<p>If you’re using IntelliJ or eclipse/JBoss Developer Studio package the maven artifact using the IDE.</p>
4735</div>
4736</div>
4737<div class="sect2">
4738<h3 id="_code_change">Code Change</h3>
4739<div class="paragraph">
4740<p>Time for a source code change! Go to src/main/java/com/openshift/evg/roadshow/rest/BackendController.java. This is the REST endpoint
4741that gives basic info on the service and can be reached at:</p>
4742</div>
4743<div class="admonitionblock caution">
4744<table>
4745<tr>
4746<td class="icon">
4747<i class="fa icon-caution" title="Caution"></i>
4748</td>
4749<td class="content">
4750In the following url(s), replace <code>userXY</code> with the guid provided to you.
4751</td>
4752</tr>
4753</table>
4754</div>
4755<div class="listingblock copypaste">
4756<div class="content">
4757<pre class="CodeRay highlight"><code data-lang="bash">http://mlbparks-userXY.apps.mod-5b05.openshiftworkshop.com/ws/info/</code></pre>
4758</div>
4759</div>
4760<div class="paragraph">
4761<p>Please change line 23 to add a <em>AMAZING</em> in front of "MLB Parks" look like this:</p>
4762</div>
4763<div class="listingblock">
4764<div class="content">
4765<pre class="CodeRay highlight"><code data-lang="java"><span class="keyword">return</span> <span class="keyword">new</span> Backend(<span class="string"><span class="delimiter">"</span><span class="content">mlbparks</span><span class="delimiter">"</span></span>, <span class="string"><span class="delimiter">"</span><span class="content">AMAZING MLB Parks</span><span class="delimiter">"</span></span>, <span class="keyword">new</span> Coordinates(<span class="string"><span class="delimiter">"</span><span class="content">39.82</span><span class="delimiter">"</span></span>, <span class="string"><span class="delimiter">"</span><span class="content">-98.57</span><span class="delimiter">"</span></span>), <span class="integer">5</span>);</code></pre>
4766</div>
4767</div>
4768<div class="paragraph">
4769<p>Don’t forget to save the file and run <code>mvn package</code> again.</p>
4770</div>
4771</div>
4772<div class="sect2">
4773<h3 id="_doing_the_binary_build">Doing the Binary Build</h3>
4774<div class="paragraph">
4775<p>Alright we have our war file built, time to kick off a build using it.</p>
4776</div>
4777<div class="paragraph">
4778<p>If you built your war with Maven:</p>
4779</div>
4780<div class="listingblock copypaste">
4781<div class="content">
4782<pre class="CodeRay highlight"><code data-lang="bash">oc start-build bc/mlbparks --from-file=target/ROOT.war --follow</code></pre>
4783</div>
4784</div>
4785<div class="admonitionblock note">
4786<table>
4787<tr>
4788<td class="icon">
4789<i class="fa icon-note" title="Note"></i>
4790</td>
4791<td class="content">
4792The --follow is optional if you want to follow the build output in your terminal.
4793</td>
4794</tr>
4795</table>
4796</div>
4797<div class="paragraph">
4798<p>Using labels and a recreate deployment strategy, as soon as the new deployment finishes the map name will be updated. Under a recreate deployment strategy we first tear down the pod before doing our new deployment.
4799When the pod is torn down, the parksmap service removes the MLBParks map from the layers. When it comes back up, the layer
4800automatically gets added back with our new title. This would not have happened with a rolling deployment because
4801rolling spins up the new version of the pod before it takes down the old one. Rolling strategy enables a zero-downtime deployment.</p>
4802</div>
4803<div class="paragraph">
4804<p>When the deployment is finished and the container is deployed you will see the new content at:</p>
4805</div>
4806<div class="admonitionblock caution">
4807<table>
4808<tr>
4809<td class="icon">
4810<i class="fa icon-caution" title="Caution"></i>
4811</td>
4812<td class="content">
4813In the following url(s), replace <code>userXY</code> with the project provided to you.
4814</td>
4815</tr>
4816</table>
4817</div>
4818<div class="listingblock copypaste">
4819<div class="content">
4820<pre class="CodeRay highlight"><code data-lang="bash">http://mlbparks-userXY.apps.mod-5b05.openshiftworkshop.com/ws/info/</code></pre>
4821</div>
4822</div>
4823<div class="paragraph">
4824<p>So now you have seen how we can speed up the build and deploy process.</p>
4825</div>
4826</div>
4827</div>
4828</div>
4829 <hr>
4830 <h2>Using Port-Forwarding and Remote Debugging</h2>
4831 <div class="sect1">
4832<h2 id="_background_port_forwarding_and_debugging">Background: Port Forwarding and Debugging</h2>
4833<div class="sectionbody">
4834<div class="paragraph">
4835<p>Just as we did before with remote shelling into our pods, we can also set up a port-forward between our local machine
4836and our pod. The is useful for operations like connecting to a database running in a pod, viewing an administrative web
4837interface we don’t want to expose to the public, or, in our case, attaching a debugger to the JVM running our application
4838server.</p>
4839</div>
4840<div class="paragraph">
4841<p>You can read more about port-forwarding from the
4842<a href="https://docs.openshift.com/container-platform/latest/dev_guide/port_forwarding.html">developer documentation</a>.</p>
4843</div>
4844<div class="paragraph">
4845<p>By port forwarding the debugging port for the application server, we can attach the debugger from our IDE and actually
4846step through the code in the pod as it is running in real time. By default EAP is not in debug mode, therefore we first
4847need to turn on the debug ports</p>
4848</div>
4849</div>
4850</div>
4851<div class="sect1">
4852<h2 id="_exercise_enabling_debugging_in_eap_on_openshift">Exercise: Enabling Debugging in EAP on OpenShift</h2>
4853<div class="sectionbody">
4854<div class="paragraph">
4855<p>It is very simple to turn on debugging. The EAP S2I container we are using is looking for an environment variable to
4856control whether or not to enable the debug port. All we need to do is set an environment variable for the deployment.</p>
4857</div>
4858<div class="listingblock copypaste">
4859<div class="content">
4860<pre class="CodeRay highlight"><code data-lang="bash">oc set env dc/mlbparks DEBUG=true</code></pre>
4861</div>
4862</div>
4863<div class="paragraph">
4864<p>This will force a redeploy of our MLBparks pod, this time with the JDWT transport enabled and serving on port 8787.</p>
4865</div>
4866</div>
4867</div>
4868<div class="sect1">
4869<h2 id="_exercise_port_forwarding_from_the_pod_to_our_local_machine">Exercise: Port-Forwarding from the pod to our local machine</h2>
4870<div class="sectionbody">
4871<div class="paragraph">
4872<p>It is quite simple to do port-forwarding.</p>
4873</div>
4874<div class="paragraph">
4875<p>First get the pods:</p>
4876</div>
4877<div class="listingblock copypaste">
4878<div class="content">
4879<pre class="CodeRay highlight"><code data-lang="bash">oc get pods</code></pre>
4880</div>
4881</div>
4882<div class="listingblock">
4883<div class="content">
4884<pre class="CodeRay highlight"><code data-lang="bash">NAME READY STATUS RESTARTS AGE
4885mlbparks-1-build 0/1 Completed 0 9m
4886mlbparks-2-7c6zb 1/1 Running 0 4m
4887mongodb-mlbparks-1-887pq 1/1 Running 0 8m
4888parksmap-2-wms5l 1/1 Running 0 13m</code></pre>
4889</div>
4890</div>
4891<div class="paragraph">
4892<p>Now we are all set to set up the port-forward:</p>
4893</div>
4894<div class="listingblock copypaste">
4895<div class="content">
4896<pre class="CodeRay highlight"><code data-lang="bash">oc port-forward mlbparks-2-7c6zb 8787:8787</code></pre>
4897</div>
4898</div>
4899<div class="paragraph">
4900<p>We said to port-forward from port 8787 on the pod to 8787 on the local machine. Now we can attach a remote debugger.</p>
4901</div>
4902<div class="admonitionblock note">
4903<table>
4904<tr>
4905<td class="icon">
4906<i class="fa icon-note" title="Note"></i>
4907</td>
4908<td class="content">
4909To stop port-forwarding just hit ctrl-c in the terminal window where you did the port forward command
4910</td>
4911</tr>
4912</table>
4913</div>
4914<div class="sect2">
4915<h3 id="_setting_up_remote_debug_in_intellij">Setting up Remote Debug in IntelliJ</h3>
4916<div class="paragraph">
4917<p>Setting up remote debugging is quite easy in IntelliJ. First edit the run/debug configurations.
4918Under the Run menu (alt-u), choose edit configurations. This will bring up the new configuration dialog.</p>
4919</div>
4920<div class="paragraph">
4921<p>Click the plus in the top left corner, scroll down, and choose remote.</p>
4922</div>
4923<div class="imageblock">
4924<div class="content">
4925<img src="/workshop/workshop/asset/images/mlbparks-debugging-intellij-debug-new.png" alt="IntelliJ New Configuration">
4926</div>
4927</div>
4928<div class="paragraph">
4929<p>On the resulting dialog page, change the name at the top to "on OpenShift" or whatever is informative to you. Then
4930towards the bottom right, change the port number to 8787. When you have done that click "OK".</p>
4931</div>
4932<div class="imageblock">
4933<div class="content">
4934<img src="/workshop/workshop/asset/images/mlbparks-debugging-intellij-debug-info.png" alt="IntelliJ New Configuration">
4935</div>
4936</div>
4937<div class="paragraph">
4938<p>Now when you click the Debug icon in IntelliJ, it will open the debugger and attach to JVM in the pod on OpenShift. Go
4939ahead and set a break point in any class you want and it will do normal debugging - just like you know and love!</p>
4940</div>
4941</div>
4942</div>
4943</div>
4944 <hr>
4945 <h2>Further Resources</h2>
4946 <div class="paragraph">
4947<p>The exercices in this workshop have shown you how OpenShift can be used not only for deploying
4948stateless web applications, but also applications which require persistent
4949file system storage.</p>
4950</div>
4951<div class="paragraph">
4952<p>This flexibility makes OpenShift an ideal platform for deploying both web
4953applications and databases.</p>
4954</div>
4955<div class="paragraph">
4956<p>If you have finished this workshop early and want to experiment some more,
4957we have additional exercises you can try out using our online interactive
4958learning environment.</p>
4959</div>
4960<div class="ulist">
4961<ul>
4962<li>
4963<p><strong><a href="https://learn.openshift.com/">OpenShift Interactive Learning
4964Portal</a></strong> - An online interactive learning environment where you can run
4965through various scenarios related to using OpenShift.</p>
4966</li>
4967</ul>
4968</div>
4969<div class="paragraph">
4970<p>The online interactive learning environment is always available so you
4971can continue to work on those exercises even after the workshop is over.</p>
4972</div>
4973<div class="ulist">
4974<ul>
4975<li>
4976<p><strong><a href="http://cookbook.openshift.org/">OpenShift Cookbook</a></strong> - Recipes of common tasks that users could need to do on OpenShift.</p>
4977</li>
4978</ul>
4979</div>
4980<div class="paragraph">
4981<p>Below you will find further resources for learning about OpenShift and
4982running OpenShift on your own computer, as well as details about OpenShift
4983Online or other OpenShift related products and services.</p>
4984</div>
4985<div class="ulist">
4986<ul>
4987<li>
4988<p><strong><a href="https://www.okd.io/">OKD</a></strong> - The upstream Open
4989Source community distribution of Kubernetes that powers OpenShift.</p>
4990</li>
4991<li>
4992<p><strong><a href="https://www.okd.io/minishift/">Minishift</a></strong> - A tool which can
4993be used to install a local OpenShift cluster on your own computer, running
4994in a virtual machine.</p>
4995</li>
4996<li>
4997<p><strong><a href="https://manage.openshift.com/">OpenShift Online</a></strong> - A shared public
4998hosting environment for running your applications using OpenShift.</p>
4999</li>
5000<li>
5001<p><strong><a href="https://openshift.io/">OpenShift.io</a></strong> - An online development
5002environment for planning, creating and deploying hybrid cloud services
5003using OpenShift.</p>
5004</li>
5005<li>
5006<p><strong><a href="https://www.openshift.com/dedicated">OpenShift Dedicated</a></strong> - A
5007dedicated hosting environment for running your applications, managed and
5008supported for you by Red Hat.</p>
5009</li>
5010<li>
5011<p><strong><a href="https://www.openshift.com/">OpenShift Container Platform</a></strong> - The Red
5012Hat supported OpenShift product for installation on premise or in hosted
5013cloud environments.</p>
5014</li>
5015</ul>
5016</div>
5017<div class="paragraph">
5018<p>The following free online eBooks are also available for download related to
5019OpenShift.</p>
5020</div>
5021<div class="ulist">
5022<ul>
5023<li>
5024<p><strong><a href="https://www.openshift.com/for-developers/">OpenShift
5025for Developers</a></strong></p>
5026</li>
5027</ul>
5028</div>
5029<div class="imageblock">
5030<div class="content">
5031<img src="/workshop/workshop/asset/images/further-resources-openshift-for-developers.png" alt="OpenShift for Developers">
5032</div>
5033</div>
5034<div class="ulist">
5035<ul>
5036<li>
5037<p><strong><a href="https://www.openshift.com/devops-with-openshift/">DevOps with OpenShift</a></strong></p>
5038</li>
5039</ul>
5040</div>
5041<div class="imageblock">
5042<div class="content">
5043<img src="/workshop/workshop/asset/images/further-resources-devops-with-openshift.png" alt="DevOps with OpenShift">
5044</div>
5045</div>
5046<div class="ulist">
5047<ul>
5048<li>
5049<p><strong><a href="https://www.openshift.com/deploying-to-openshift/">Deploying with OpenShift</a></strong></p>
5050</li>
5051</ul>
5052</div>
5053<div class="imageblock">
5054<div class="content">
5055<img src="/workshop/workshop/asset/images/further-resources-deploying-to-openshift.png" alt="Deploying to OpenShift">
5056</div>
5057</div>
5058 <hr>
5059 <h2>Workshop Links</h2>
5060 <div class="paragraph">
5061<p>You can find all urls, hostnames, usernames and passwords that are needed during the workshop in this page. Note that the urls are also embedded inside the labs so that you don’t have to go back and forth between this page and the labs.</p>
5062</div>
5063<div class="sect1">
5064<h2 id="_openshift_cluster_url">OpenShift cluster URL</h2>
5065<div class="sectionbody">
5066<div class="paragraph">
5067<p>Address: <a href="https://master.mod-5b05.openshiftworkshop.com" class="bare">https://master.mod-5b05.openshiftworkshop.com</a><br></p>
5068</div>
5069<div class="paragraph">
5070<p>Username: <code>userXY</code><br>
5071Password: <code>openshift</code><br></p>
5072</div>
5073</div>
5074</div>
5075<div class="sect1">
5076<h2 id="_workshop_guides">Workshop Guides</h2>
5077<div class="sectionbody">
5078<div class="paragraph">
5079<p>Web: <a href="http://starter-guides-infra.apps.mod-5b05.openshiftworkshop.com" class="bare">http://starter-guides-infra.apps.mod-5b05.openshiftworkshop.com</a></p>
5080</div>
5081</div>
5082</div>
5083<div class="sect1">
5084<h2 id="_etherpad">Etherpad</h2>
5085<div class="sectionbody">
5086<div class="paragraph">
5087<p>Web: <a href="http://etherpad-infra.apps.mod-5b05.openshiftworkshop.com/p/workshop" class="bare">http://etherpad-infra.apps.mod-5b05.openshiftworkshop.com/p/workshop</a></p>
5088</div>
5089</div>
5090</div>
5091<div class="sect1">
5092<h2 id="_web_terminal">Web terminal</h2>
5093<div class="sectionbody">
5094<div class="paragraph">
5095<p>Web: <a href="http://terminal-infra.apps.mod-5b05.openshiftworkshop.com" class="bare">http://terminal-infra.apps.mod-5b05.openshiftworkshop.com</a></p>
5096</div>
5097</div>
5098</div>
5099<div class="sect1">
5100<h2 id="_git_server">Git Server</h2>
5101<div class="sectionbody">
5102<div class="paragraph">
5103<p>Web: <a href="http://gogs-infra.apps.mod-5b05.openshiftworkshop.com" class="bare">http://gogs-infra.apps.mod-5b05.openshiftworkshop.com</a></p>
5104</div>
5105<div class="paragraph">
5106<p>Username: <code>userXY</code><br>
5107Password: <code>openshift</code><br></p>
5108</div>
5109</div>
5110</div>
5111<div class="sect1">
5112<h2 id="_nexus_maven_repository">Nexus Maven repository</h2>
5113<div class="sectionbody">
5114<div class="paragraph">
5115<p>Web: <a href="http://nexus-infra.apps.mod-5b05.openshiftworkshop.com" class="bare">http://nexus-infra.apps.mod-5b05.openshiftworkshop.com</a></p>
5116</div>
5117</div>
5118</div>
5119<div class="sect1">
5120<h2 id="_openshift_ops_view">OpenShift Ops View</h2>
5121<div class="sectionbody">
5122<div class="paragraph">
5123<p>Web: <a href="http://ocp-ops-view-infra.apps.mod-5b05.openshiftworkshop.com" class="bare">http://ocp-ops-view-infra.apps.mod-5b05.openshiftworkshop.com</a></p>
5124</div>
5125</div>
5126</div>
5127 <hr>
5128 </div>
5129 </div>
5130</main>
5131
5132</body>
5133</html>