Last active
May 2, 2020 22:35
-
-
Save ryanj/4f1293efbe5ee01b7fc51a4d42cb61c5 to your computer and use it in GitHub Desktop.
"Hands-on Intro to Kubernetes & OpenShift for JS Hackers" at #NodeJSInteractive 2018 http://bit.ly/nodejs-on-k8s
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- | |
<section data-transition="none" id="NODEJS-INTERACTIVE" data-background="https://gist.githubusercontent.com/ryanj/9181e48c0dd8e6b45d692a11d5a72bd5/raw/9892bcb34a809c25c24c43a2ea33bb69b7684f0b/node-js-interactive-0.jpg" data-background-color="black" data-background-size="cover" data-background-position="top"> | |
| |
</section> | |
--> | |
<section data-background-transition="none-in zoom-out" data-transition="zoom" id="HANDS-ON" data-background="https://gist.githubusercontent.com/ryanj/9181e48c0dd8e6b45d692a11d5a72bd5/raw/9892bcb34a809c25c24c43a2ea33bb69b7684f0b/node-js-interactive-1.jpg" data-background-color="black" data-background-size="cover" data-background-position="top"> | |
<h3 style="color:white;padding-top:26%;">Hands-on Intro to</h3> | |
<h1 style="color:white;font-size:113px;">Kubernetes & OpenShift</h1> | |
<h3 style="color:white;">{ for JS Hackers }</h3> | |
<p class='fragment grow'><a style="font-weight:bold;" href="http://gist-reveal.it/bit.ly/nodejs-on-k8s?theme=9181e48c0dd8e6b45d692a11d5a72bd5">bit.ly/nodejs-on-k8s</a></p> | |
<p><a href='https://www.youtube.com/watch?v=PDSJ-t4vl04&list=PLfMzBWSH11xaZvhv1X5Fq1H-oMdnAtG6k&index=33'>Recorded on</a> <a href="http://sched.co/F76D">Thursday 9am-10:50</a></p> | |
</section> | |
<section> | |
<section style="color:white;" data-transition='concave' data-background-transition='fade' data-background='#000000' data-background-color="black" id='presented-by'> | |
<p style="color:white;">presented by…</p> | |
<div class='fragment fade-right' style='width:45%; float:left;'> | |
<p><a href="http://twitter.com/ryanj/"><img alt="ryanj" src="http://ryanjarvinen.com/images/ryanj-mestrefungo-com.gif" style="width:70%" /></p> | |
<p><a href="http://twitter.com/ryanj/">Ryan Jarvinen @ryanj</a></p> | |
</div> | |
<div class='fragment fade-up' style='width:10%;float:left;margin-top: 13%;font-size: 250%;font-weight: bold;color:white;'>&</div> | |
<div class='fragment fade-left' style='width:45%; float:left;'> | |
<p><a href="http://twitter.com/jankleinert"><img alt="Jan Kleinert" src="https://i.imgur.com/HoF47Kj.jpg" style="width:70%"/></p> | |
<p><a href="http://twitter.com/jankleinert">Jan Kleinert @jankleinert</a></p> | |
</div> | |
<br/> | |
<!-- <p style="color:white;">presented by <a href="http://twitter.com/ryanj/">@ryanj</a>, Developer Advocate at Red Hat</p> | |
<p style="color:white;" class='fragment fade-up'><a href="http://twitter.com/ryanj/"><img alt="ryanj" src="http://ryanjarvinen.com/images/ryanj-mestrefungo-com.gif" style="width:50%"/><br/>@ryanj</p> --> | |
</section> | |
<section id='brought-to-you-by' data-background='black' data-background-color="black"> | |
<p style="color:white;">brought to you by</p> | |
<p style="color:white;"><a href="https://redhat.com"><img alt="Red Hat logo" src="https://i.imgur.com/ArZFG3e.png" /></a></p> | |
</section> | |
</section> | |
<section data-transition='convex'> | |
<section id='introduction'> | |
<h1>Introduction</h1> | |
</section> | |
<section id='survey'> | |
<h3>Intro Survey / Who are you?</h3> | |
<ol> | |
<li class='fragment'>do you have any experience using containers?</li> | |
<li class='fragment'>have you completed all of the <a href="#/laptop-setup">laptop setup</a> tasks?</li> | |
<li class='fragment'>do you have any experience using Kubernetes?</li> | |
<li class='fragment'>do you consider yourself to be proficient with the <code>oc</code> or <code>kubectl</code> cli tools?</li> | |
<li class='fragment'>can you name five basic Kubernetes primitives or resource types?</li> | |
<li class='fragment'>do you have a plan for iterative web development using containers?</li> | |
</ol> | |
</section> | |
</section> | |
<section data-transition='concave'> | |
<section data-transition='convex' id='agenda'> | |
<h2>Workshop Agenda</h2> | |
<ul style='list-style: none;'> | |
<li class='fragment'><a href="#/introduction">Introduction</a> | |
<ul style='list-style: none;'> | |
<li class='fragment'><a href="#/agenda">Agenda</a></li> | |
<li class='fragment'><a href="#/kubernetes">Overview</a></li> | |
<li class='fragment'><a href="#/laptop-setup">Laptop Setup</a></li> | |
</ul> | |
</li> | |
<li class='fragment'><a href="#/kubernetes-basics">Kubernetes Basics</a> | |
<ul style='list-style: none;'> | |
<li class='fragment'><a href="#/basic-resource-types">Learn five basic resource types</a></li> | |
</ul> | |
</li> | |
<li class='fragment'><a href="#/hands-on-with-openshift">Hands-On with OpenShift</a> | |
<ul style='list-style: none;'> | |
<li class='fragment'><a href="#/build">Build</a>, <a href="#/automate">Automate</a>, <a href="#/iterate">Iterate</a>, <a href="#/collaborate">Collaborate</a></li> | |
</ul> | |
</li> | |
<li class='fragment'><a href="#/wrap-up">Wrap Up / Q&A</a></li> | |
</ul> | |
</section> | |
<section id='kubernetes' data-markdown> | |
# Kubernetes | |
* [is](https://kubernetes.io/docs/concepts/overview/what-is-kubernetes/): an ops tool; a collection of APIs for managing container-based workloads | |
* [is not](https://kubernetes.io/docs/concepts/overview/what-is-kubernetes/#what-kubernetes-is-not): a PaaS | |
</section> | |
<section id='all-the-most-popular-platforms' data-background='black'> | |
<h2 style="color: white;">2017 Octoverse Report</h2> | |
<blockquote style="color:white;">🏆 Most-discussed on GitHub in 2017!</blockquote> | |
<p style="color: white;"><a href="http://octoverse.github.com">http://octoverse.github.com</a></p> | |
<p style="color:white;"><a href="https://kubernetes.io/blog/2018/04/25/open-source-charts-2017">Kubernetes Community - Top of the Open Source Charts in 2017</a> | |
</section> | |
<section id='openshift' data-markdown> | |
# OpenShift | |
* includes, extends, & is a distribution of: Kubernetes | |
* adds: Multi-tenant security, PaaS-style workflows, Service Catalog and Brokers, a container registry, distributed metrics and logs ... | |
![octoverse_chart](https://d33wubrfki0l68.cloudfront.net/d5511b44cad712d8ba3e7139448c081366808fa0/27939/images/blog-logging/2018-04-24-open-source-charts-2017/most-discussed.png) | |
</section> | |
<section id='more-info'> | |
<h3>More Information</h3> | |
<ul> | |
<li>Kubernetes Sources and Official Releases:<br/> | |
<a href="http://github.com/kubernetes/kubernetes">http://github.com/kubernetes/kubernetes</a></li> | |
<li>Kubernetes Docs: <a href="http://kubernetes.io/docs/home/">http://kubernetes.io/docs/home/</a></li> | |
<li>OpenShift Sources and Official Releases:<br/> | |
<a href="http://github.com/openshift/origin/">http://github.com/openshift/origin/</a></li> | |
<li>OpenShift Docs: <a href="https://docs.openshift.com/">https://docs.openshift.com/</a></li> | |
</ul> | |
</section> | |
</section> | |
<section data-transition='convex'> | |
<section id='laptop-setup' data-markdown> | |
## Workshop Requirements | |
To run this workshop locally, you'll need: | |
1. [kubectl](#/kubectl) | |
2. [oc](#/oc) | |
3. [bash](#/bash) | |
3. [minishift](#/minishift) | |
<!-- 4. [docker](#/docker) --> | |
↓ | |
</section> | |
<section id='kubectl'> | |
<h3>Install <code>kubectl</code></h3> | |
<p>For detailed installation notes, see the <a href="https://kubernetes.io/docs/tasks/tools/install-kubectl/"><code>kubectl</code> install doc</a></p> | |
<p>One line install for linux/amd64:</p> | |
<pre><code contenteditable>curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl && chmod +x kubectl && sudo mv kubectl /usr/local/bin/ | |
</code></pre> | |
<p>One line install for macOS:</p> | |
<pre><code contenteditable>curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/darwin/amd64/kubectl && chmod +x kubectl && sudo mv kubectl /usr/local/bin/ | |
</code></pre> | |
<br/> | |
<p>To verify <code>kubectl</code> availability, try running:</p> | |
<pre><code contenteditable>kubectl help</code></pre> | |
</section> | |
<section id='oc'> | |
<h3>Install oc</h3> | |
<p>For detailed installation notes, see the <a href="https://docs.openshift.org/latest/cli_reference/get_started_cli.html"><code>oc</code> installation doc</a></p> | |
<p>One line install for linux/amd64:</p> | |
<pre><code contenteditable>curl -Lo oc.tar.gz https://github.com/openshift/origin/releases/download/v3.11.0/openshift-origin-client-tools-v3.11.0-0cbc58b-linux-64bit.tar.gz && tar xvzf oc.tar.gz */oc && sudo mv $_ /usr/local/bin/ && rm -d openshift-origin-client-tools-* && rm oc.tar.gz</code></pre> | |
<p>One line install for macOS:</p> | |
<pre><code contenteditable>curl -Lo oc.zip https://github.com/openshift/origin/releases/download/v3.11.0/openshift-origin-client-tools-v3.11.0-0cbc58b-mac.zip && tar xvzf oc.zip oc && sudo mv oc /usr/local/bin/ && rm oc.zip</code></pre> | |
<br/> | |
<p>To verify <code>oc</code> availability, try running:</p> | |
<pre><code contenteditable>oc help</code></pre> | |
</section> | |
<section id='bash'> | |
<h3>Bash for Windows</h3> | |
<p>Windows users should install the <code>Windows Subsystem for Linux</code> and related command-line tools:</p> | |
<p>Enable <b>Control Panel > Programs > Windows Features > Windows Subsystem for Linux</b></p> | |
</section> | |
<section id='minishift'> | |
<h3>Install <code>minishift</code></h3> | |
<p>For detailed installation notes, see the <a href="https://github.com/minishift/minishift/releases"><code>minishift</code> release notes</a></i></p> | |
<p>One line install for linux/amd64:</p> | |
<pre><code contenteditable>curl -Lo minishift.tgz https://github.com/minishift/minishift/releases/download/v1.25.0/minishift-1.25.0-linux-amd64.tgz && tar xvzf minishift.tgz */minishift && sudo mv $_ /usr/local/bin/ && rm -d minishift-* && rm minishift.tgz</code></pre> | |
<p>One line install for macOS:</p> | |
<pre><code contenteditable>curl -Lo minishift.tgz https://github.com/minishift/minishift/releases/download/v1.25.0/minishift-1.25.0-darwin-amd64.tgz && tar xvzf minishift.tgz */minishift && sudo mv $_ /usr/local/bin/ && rm -d minishift-* && rm minishift.tgz</code></pre> | |
<p>Optionally, customize your cluster's memory or cpu allocation:</p> | |
<pre><code contenteditable>minishift config set memory 4096 | |
minishift config set cpus 2 | |
minishift config set openshift-version latest</code></pre> | |
<p>to verify <code>minishift</code> availability:</p> | |
<pre><code contenteditable>minishift version</code></pre> | |
</section> | |
<section id='minishift-virt'> | |
<h4>Virtualization Plugins</h4> | |
<p>See the <a href="https://docs.openshift.org/latest/minishift/getting-started/installing.html#install-prerequisites"><code>minishift</code> installation guide</a> for <a href="https://docs.openshift.org/latest/minishift/getting-started/setting-up-driver-plugin.html">virt driver plugin requirements</a></p> | |
<br/> | |
<p>If your minishift environment does not boot correctly:</p> | |
<ol> | |
<li>Minishift <a href="https://docs.openshift.org/latest/minishift/getting-started/installing.html#install-prerequisites">requires an OS virtualization solution</a>. Most OSes already include one!</li> | |
<li><a href="https://docs.openshift.org/latest/minishift/getting-started/setting-up-driver-plugin.html">Install the appropriate driver plugin</a> for your system</li> | |
<li>Use the <a href="https://docs.openshift.org/latest/minishift/getting-started/setting-up-driver-plugin.html"><code>--vm-driver</code></a> flag to select specific plugins by name</li> | |
</ol> | |
<pre><code contenteditable>minishift start --vm-driver=virtualbox</code></pre> | |
</section> | |
<section id='minishift-basics' markdown> | |
<h2>Minishift Basics</h2> | |
<p><code>minishift</code> provides an easy way to run OpenShift locally:</p> | |
<pre><code contenteditable>minishift start</code></pre> | |
<p>When you are done, halt the VM to free up system resources:</p> | |
<pre><code contenteditable>minishift stop</code></pre> | |
<p>Need a fresh start? Delete your VM instance with:</p> | |
<pre><code contenteditable>minishift delete</code></pre> | |
</section> | |
<!-- | |
<section id='docker'> | |
<h3>Install docker</h3> | |
<p>Use your package manager, or download a release from <a href="https://store.docker.com/search?offering=community&type=edition">Docker</a></p> | |
<pre><code contenteditable>brew cask install docker | |
dnf install docker | |
apt-get install docker</code></pre> | |
<br/> | |
<p>To verify <code>docker</code> availability, run:</p> | |
<pre><code contenteditable>docker version</code></pre> | |
</section> | |
--> | |
</section> | |
<section data-transition='zoom'> | |
<section data-transition='zoom-in convex-out' id='ready'> | |
<h1><i>Ready?</i></h1> | |
<br/> | |
<div class='fragment fade-up'> | |
<p>Verify that your cli tools are configured to connect to your Kubernetes environment:<br/> | |
<pre><code contenteditable>kubectl version</code></pre> | |
<p>The output should include your <code>kubectl</code> version info, and the release version of the kubernetes API server (when available)</p> | |
</div> | |
</section> | |
<section data-background-transition="zoom"> | |
<h1><i>Let's Go!</i></h1> | |
</section> | |
</section> | |
<section data-transition='convex'> | |
<section id='kubernetes-basics'> | |
<h1>Kubernetes Basics</h1> | |
<p>↓</p> | |
</section> | |
<section data-markdown> | |
Kubernetes uses | |
## etcd | |
to keep track of the cluster's state | |
![etcd logo](https://raw.githubusercontent.com/coreos/etcd/master/logos/etcd-glyph-color.png) | |
* distributed key-value store | |
* implements the [RAFT](https://raft.github.io/raft.pdf) consensus protocol | |
* CAP theorum: [CAP twelve years later](https://www.infoq.com/articles/cap-twelve-years-later-how-the-rules-have-changed) | |
</section> | |
<section data-markdown> | |
## Etcd cluster sizes | |
Fault tolerance sizing chart: | |
![etcd cluster sizing chart](http://cloudgeekz.com/wp-content/uploads/2016/10/etcd-fault-tolerance-table.png) | |
</section> | |
<section id='an-api' data-markdown> | |
Kubernetes provides… | |
# An API | |
API object primitives include the following attributes: | |
``` | |
kind | |
apiVersion | |
metadata | |
spec | |
status | |
``` | |
*mostly true | |
Extended Kubernetes API Reference: | |
http://k8s.io/docs/reference/generated/kubernetes-api/v1.12/ | |
</section> | |
<section data-transition="linear" id='basic-resource-types' data-markdown> | |
### Basic K8s Terminology | |
1. [node](#/node) | |
2. [pod](#/po) | |
3. [service](#/svc) | |
4. [deployment](#/deployment) | |
5. [replicaSet](#/rs) | |
Introduction borrowed from: [bit.ly/k8s-kubectl](http://bit.ly/k8s-kubectl) | |
</section> | |
</section> | |
<section data-transition='convex'> | |
<section data-transition="linear" id='node' data-markdown> | |
### Nodes | |
A node is a host machine (physical or virtual) where containerized processes run. | |
Node activity is managed via one or more Master instances. | |
</section> | |
<section> | |
<p>Try using <code>kubectl</code> to list resources by type:</p> | |
<pre><code contenteditable>kubectl get nodes</code></pre> | |
</section> | |
<section> | |
<p>Log in as an admin user (password "openshift")</p> | |
<pre><code contenteditable>minishift addon apply admin-user | |
oc login -u admin</code></pre> | |
<p>Try to list nodes using admin credentials:</p> | |
<pre><code contenteditable>kubectl get nodes</code></pre> | |
<p>Now try using <code>curl</code> to make the same request:</p> | |
<pre><code contenteditable>curl -k -H"Authorization: Bearer $(oc whoami -t)" https://$(minishift ip):8443/api/v1/nodes</code></pre> | |
<p>We won't need admin priveleges for the remaining content, so let's swap back to the "developer" user:</p> | |
<pre><code contenteditable>oc login -u developer</code></pre> | |
</section> | |
<section data-markdown> | |
### Observations: | |
* Designed to exist on multiple machines (distributed system) | |
* built for high availability | |
* platform scale out | |
* The Kubernetes API checks auth credentials and restricts access to Etcd, our platform's distributed consensus store | |
* Your JS runs on nodes! | |
</section> | |
</section> | |
<section data-transition='concave'> | |
<section data-transition="linear" id='po' data-markdown> | |
### Pods | |
A group of one or more co-located containers. Pods represent your minimum increment of scale. | |
> "Pods Scale together, and they Fail together" @theSteve0 | |
</section> | |
<section> | |
<p>Try using <code>kubectl</code> to list resources by type:</p> | |
<pre><code contenteditable>kubectl get pods</code></pre> | |
<p>Create a new resource from a json object specification:</p> | |
<pre><code contenteditable>curl https://raw.githubusercontent.com/jankleinert/hello-workshop/master/pod.json | |
curl -k -H"Authorization: Bearer $(oc whoami -t)" -H'Content-Type: application/json' https://$(minishift ip):8443/api/v1/namespaces/myproject/pods -X POST --data-binary @pod.json</code></pre> | |
<p>Attempt the same using <code>kubectl</code>:</p> | |
<pre><code contenteditable>kubectl create -f https://raw.githubusercontent.com/jankleinert/hello-workshop/master/pod.json</code></pre> | |
</section> | |
<section> | |
<!-- | |
<p>Request the same info using <code>curl</code>:</p> | |
<pre><code contenteditable>curl -k -H'Authorization: Bearer $(oc whoami -t)' $(minishift ip):8443/api/v1/namespaces/$(oc whoami)/pods/hello-k8s</code></pre> | |
--> | |
<p>List pods by type using <code>curl</code>:</p> | |
<pre><code contenteditable>curl -k -H"Authorization: Bearer $(oc whoami -t)" https://$(minishift ip):8443/api/v1/namespaces/myproject/pods</code></pre> | |
<p>Fetch an individual resource by <code>type/id</code>; output as <code>json</code>:</p> | |
<pre><code contenteditable>kubectl get pod hello-k8s -o json</code></pre> | |
<p>Attempt the same using <code>curl</code>:</p> | |
<pre><code contenteditable>curl -k -H"Authorization: Bearer $(oc whoami -t)" https://$(minishift ip):8443/api/v1/namespaces/myproject/pods/hello-k8s</code></pre> | |
<p class='fragment'>Notice any changes between the initial json podspec and the API response?</p> | |
</section> | |
<section> | |
<p>Request the same info, but output the results as structured yaml:</p> | |
<pre><code contenteditable>kubectl get pod hello-k8s -o yaml</code></pre> | |
<p>Print human-readable API output:</p> | |
<pre><code contenteditable>kubectl describe pod/hello-k8s</code></pre> | |
</section> | |
<section data-markdown> | |
### Observations: | |
* API resources provide declarative specifications with asyncronous fulfilment of requests | |
* you set the `spec`, the platform will populate the `status` | |
* automated health checking for PID1 in each container | |
* Pods are scheduled to be run on nodes | |
* The API ambidextriously supports both json and yaml | |
</section> | |
<!-- | |
<section data-markdown> | |
</section> | |
--> | |
</section> | |
<section data-transition='convex'> | |
<section data-transition="linear" id='svc' data-markdown> | |
### Services | |
Services (svc) establish a single endpoint for a collection of replicated pods, distributing traffic based on label selectors | |
In our K8s modeling language they represent a load balancer. Their implementation may vary per cloud provider | |
</section> | |
<section id='connections'> | |
<h3>Contacting your App</h3> | |
<p>Expose the pod by creating a new <code>service</code> (or "loadbalancer"):</p> | |
<pre><code contenteditable>kubectl expose pod/hello-k8s --port 8080 --type=NodePort</code></pre> | |
<p>Take a look at the resulting <code>{.spec.selector}</code> attribute:</p> | |
<pre><code contenteditable>kubectl get svc/hello-k8s -o json</code></pre> | |
<p>Try using a <a href="https://kubernetes.io/docs/reference/kubectl/jsonpath/">JSONpath</a> selector to find the assigned port number:</p> | |
<pre><code contenteditable>kubectl get svc/hello-k8s -o jsonpath={.spec.ports[0].nodePort}</code></pre> | |
<p>Contact your newly-exposed pod via the exposed nodePort:</p> | |
<pre><code contenteditable>echo http://$(minishift ip):$(kubectl get svc/hello-k8s -o jsonpath={.spec.ports[0].nodePort})</code></pre> | |
<pre><code contenteditable>curl http://$(minishift ip):$(kubectl get svc/hello-k8s -o jsonpath={.spec.ports[0].nodePort})</code></pre> | |
</section> | |
<section> | |
<p>Schedule the deletion of all pods that are labeled with:</p> | |
<pre><code contenteditable>kubectl get pods -l run=hello-k8s</code></pre> | |
<pre><code contenteditable>kubectl delete pods -l run=hello-k8s</code></pre> | |
<p>Contact the related service. What happens?:</p> | |
<pre><code contenteditable>curl $(minishift ip):$(kubectl get svc/hello-k8s -o jsonpath={.spec.ports[0].nodePort})</code></pre> | |
<p>Delete the service:</p> | |
<pre><code contenteditable>kubectl delete service hello-k8s</code></pre> | |
</section> | |
<section data-markdown> | |
### Observations: | |
* *"service"* basically means *"loadbalancer"* | |
* Label selectors can be used to organize workloads and manage groups of related resouces | |
* The Service resource uses label selectors to discover where traffic should be directed | |
* Pods and Services exist independently, have disjoint lifecycles | |
</section> | |
</section> | |
<section data-transition='convex'> | |
<section data-transition="linear" id='deployment' data-markdown> | |
### Deployments | |
A `deployment` helps you specify container runtime requirements (in terms of pods) | |
</section> | |
<section> | |
<p>Create a specification for your <code>deployment</code>:</p> | |
<pre><code contenteditable>kubectl run hello-k8s --image=jkleinert/nodejsint-workshop \ | |
--dry-run -o json > deployment.json</code></pre> | |
<p>View the generated deployment spec file:</p> | |
<pre><code contenteditable>cat deployment.json</code></pre> | |
<p>Create a new deployment from your local spec file:</p> | |
<pre><code contenteditable>kubectl create -f deployment.json</code></pre> | |
</section> | |
<section> | |
<p>Create a <code>Service</code> spec to direct traffic:</p> | |
<pre><code contenteditable>kubectl expose deploy/hello-k8s --type=NodePort --port=8080 --dry-run -o json > service.json</code></pre> | |
<p>View the resulting spec file:</p> | |
<pre><code contenteditable>cat service.json</code></pre> | |
<p>Create a new service from your local spec file:</p> | |
<pre><code contenteditable>kubectl create -f service.json</code></pre> | |
<p>List multiple resources by type:</p> | |
<pre><code contenteditable>kubectl get po,svc,deploy</code></pre> | |
<p>Connect to your new deployment via the associated service port:</p> | |
<pre><code contenteditable>curl $(minishift ip):$(kubectl get svc/hello-k8s -o jsonpath={.spec.ports[0].nodePort})</code></pre> | |
</section> | |
<section id='replication'> | |
<h2>Replication</h2> | |
<p>Scale up the <code>hello-k8s</code> deployment to 3 replicas:</p> | |
<pre><code contenteditable>kubectl scale deploy/hello-k8s --replicas=3</code></pre> | |
<p>List pods:</p> | |
<pre><code contenteditable>kubectl get po</code></pre> | |
</section> | |
<section> | |
<p>Edit <code>deploy/hello-k8s</code>, setting <code>spec.replicas</code> to <code>5</code>:</p> | |
<pre><code contenteditable>kubectl edit deploy/hello-k8s -o json</code></pre> | |
<p>Save and quit. What happens?</p> | |
<pre><code contenteditable>kubectl get pods</code></pre> | |
</section> | |
<section id='autorecovery'> | |
<h2>AutoRecovery</h2> | |
<p>Watch for changes to <code>pod</code> resources:</p> | |
<pre><code contenteditable>kubectl get pods --watch &</code></pre> | |
<p>In another terminal, delete several pods by id:</p> | |
<pre><code contenteditable>kubectl delete pod $(kubectl get pods | grep ^hello-k8s | cut -f1 -s -d' ' | head -n 3 | tr '\n' ' ')</code></pre> | |
<p class='fragment'>What happened? How many pods remain?</p> | |
<pre class='fragment'><code contenteditable>kubectl get pods</code></pre> | |
<p class='fragment'>Close your backgrounded <code>--watch</code> processes by running <code>fg</code>, then sending a break signal (<code>CTRL-c</code>)</p> | |
</section> | |
<section data-markdown> | |
### Observations: | |
* Use the `--dry-run` flag to generate new resource specifications | |
* A deployment spec contains a pod spec in it's "template" element | |
* The API provides `edit` and `watch` operations (in addition to `get`, `set`, and `list`) | |
</section> | |
</section> | |
<section data-transition='concave'> | |
<section data-transition="linear" id='rs' data-markdown> | |
### ReplicaSets | |
A `replicaset` provides replication and lifecycle management for a specific image release | |
</section> | |
<section> | |
<p>View the current state of your deployment:</p> | |
<pre><code contenteditable>curl $(minishift ip):$(kubectl get svc/hello-k8s -o jsonpath={.spec.ports[0].nodePort})</code></pre> | |
<p>Watch deployments:</p> | |
<pre><code contenteditable>kubectl get deploy -w &</code></pre> | |
</section> | |
<section> | |
<h3>Rollouts</h3> | |
<p>Update your deployment's image spec to rollout a new release:</p> | |
<pre><code contenteditable>kubectl set image deploy/hello-k8s hello-k8s=jkleinert/nodejsint-workshop:v1</code></pre> | |
<p>View the current state of your deployment</p> | |
<pre><code contenteditable>curl $(minishift ip):$(kubectl get svc/hello-k8s -o jsonpath={.spec.ports[0].nodePort})</code></pre> | |
<p>Ask the API to list <code>replicaSets</code></p> | |
<pre><code contenteditable>kubectl get rs</code></pre> | |
</section> | |
<section> | |
<h3>Rollbacks</h3> | |
<p>View the list of previous rollouts:</p> | |
<pre><code contenteditable>kubectl rollout history deploy/hello-k8s</code></pre> | |
<p>Rollback to the previous state:</p> | |
<pre><code contenteditable>kubectl rollout undo deployment hello-k8s</code></pre> | |
<p>Reload your browser to view the state of your deployment</p> | |
</section> | |
<section> | |
<h3>Cleanup</h3> | |
<p>Cleanup all resources:</p> | |
<pre><code contenteditable>kubectl delete service,deployment hello-k8s</code></pre> | |
<p>Close your remaining <code>--watch</code> listeners by running <code>fg</code> before sending a break signal (<code>CTRL-c</code>)</p> | |
<br/> | |
<p>Verify that your namespace is clean:</p> | |
<pre><code contenteditable>kubectl get all</code></pre> | |
</section> | |
<section data-markdown> | |
### Observations: | |
* ReplicaSets provide lifecycle management for pod resources | |
* Deployments create ReplicaSets to manage pod replication per rollout (per change in podspec: image:tag, environment vars) | |
* `Deployments` > `ReplicaSets` > `Pods` | |
</section> | |
<section id='from-kubecon'> | |
<h3>From KubeCon NA 2017</h3> | |
<p><a href="http://bit.ly/kubecon-dev"><img style='width:75%' src="https://i.imgur.com/znrD3yq.jpg" alt="Developing Locally with Kubernetes" title="from KubeCon / CloudNativeCon North America 2017"></a></p> | |
<p>"<a href="http://bit.ly/kubecon-dev">Developing locally with Minikube</a>": <a href="http://youtu.be/_W6O_pfA00s">youtu.be/_W6O_pfA00s</a></p> | |
</section> | |
</section> | |
<section data-background-transition="zoom" data-transition="zoom" id='hands-on-with-openshift'> | |
<h1>Hands-On with OpenShift</h1> | |
</section> | |
<section data-transition='convex'> | |
<section id='build'> | |
<h1>Build</h1> | |
<p class='fragment'>Build and deploy container images</p> | |
</section> | |
<section id='openshift-web-console'> | |
<h3>Introducing…</h3> | |
<h2>The OpenShift Web Console</h2> | |
<br/> | |
<div class='fragment'> | |
<p>Access the dashboard by running:</p> | |
<pre><code contenteditable>minishift dashboard</code></pre> | |
</div> | |
</section> | |
<section id='add-to-project'> | |
<h2>Web Workflow: Create</h2> | |
<p>For this example, we will deploy a fork of the <code>ryanj/http-base</code> repo by clicking on "<b>Add to Project</b>" in the web console</p> | |
<p>Example repo source: <a href="http://github.com/ryanj/http-base/">http://github.com/ryanj/http-base</a></p> | |
<ol> | |
<li class='fragment'>Fork the <code>ryanj/http-base</code> repo on GitHub. This will allow you to configure your own GitHub webhooks in the upcoming <a href='#/deploy'>Deploy</a> section</li> | |
<li class='fragment'>Return to the web console and click on "Add to Project"</li> | |
<li class='fragment'>Next, select a <code>nodejs</code> base image, and name your webservice "<code>http-base</code>". Then enter the github url for <b>your</b> fork</li> | |
<li class='fragment'>Review the options, then press the "<b>Create</b>" button when you're ready to proceed</li> | |
</ol> | |
</section> | |
<section id='get-pods'> | |
<h2>Container Status</h2> | |
<p class='fragment'>The web console uses a socket stream to report status changes as they occur throughout the cluster</p> | |
<div class='fragment'> | |
<p>After the build task has completed, find the <code>NAME</code> of the pod where your image has been deployed:</p> | |
<pre><code contenteditable>oc get pods</code></pre> | |
</div> | |
<div class='fragment'> | |
<p>As with the core APIs, the CLI output is consistently formatted, following established patterns:</p> | |
<pre><code contenteditable>kubectl get pods</code></pre> | |
</div> | |
</section> | |
<section id='source-to-image-demo'> | |
<h2>Source</h2> | |
<p>to</p> | |
<h1>Image</h1> | |
<p class='fragment'>Combines source repos and operationally-maintained builder images to produce application images</p> | |
<p class='fragment'>Available as a standalone project, for use with Jenkins or other external builder processes: <a href="https://github.com/openshift/source-to-image">github.com/openshift/source-to-image</a></p> | |
</section> | |
</section> | |
<section data-transition="linear"> | |
<section id="automate"> | |
<h1>Automate</h1> | |
<p class='fragment'><code>git push</code> to deploy</p> | |
</section> | |
<section id='clone'> | |
<h3>Send in the Clones</h3> | |
<p>Clone a local copy of <b>your repo fork</b> by adding <b>your own github username</b> to the following command:</p> | |
<pre><code>git clone http://github.com/YOUR_GH_USERNAME/http-base | |
cd http-base</code></pre> | |
</section> | |
<section id='webhooks'> | |
<h2>WebHook Build Automation</h2> | |
<p>Set up a commit WebHook to automate image production</p> | |
<p class='fragment'>Explore the <code>Build</code> resources using the web console. Look for the GitHub Webhook settings. Copy the webhook url, and paste it into your repo's Webhook settings on GitHub</p> | |
<p class='fragment'>If you're running OpenShift locally in a VM, try using <a href="http://www.ultrahook.com/">ultrahook</a> to proxy webhook events to your laptop</p> | |
</section> | |
<section id='git-push-to-build-and-ship'> | |
<h2>ReBuild on Push</h2> | |
<p class='fragment'>After configuring the webhook for your repo, add a small commit locally, then <code>git push</code> to deploy</p> | |
<pre class='fragment'><code contenteditable>git push</code></pre> | |
<p class='fragment'>Or, use GitHub's web-based editor to make a minor change</p> | |
<div class='fragment'><p>If you don't have a working webhook to automate the build process, it can also be started manually:</p> | |
<pre><code contenteditable>oc start-build http-base</code></pre> | |
</div> | |
</section> | |
</section> | |
<section data-transition="linear"> | |
<section id="iterate"> | |
<h1>Iterate</h1> | |
<p class='fragment'>Iterate using a fully containerized toolchain</p> | |
</section> | |
<section id='oc-rsync'> | |
<h3>Live Development</h3> | |
<p class='fragment'>Make a minor edit to your local repo's <code>index.html</code> file,</p> | |
<div class='fragment'> | |
<p>then test your changes <i>before you commit</i> by synching content into your hosted container:</p> | |
<pre><code contenteditable>export PODNAME=$(oc get pods -l app=http-base | tail -n 1 | cut -f1 -d' ') | |
oc rsync -w --exclude='.git,node_modules' . $PODNAME:</code></pre> | |
</div> | |
</section> | |
<section id="terminal" data-markdown> | |
## Terminal Access | |
* Available in the Web Console | |
* And on the CLI, with: | |
oc exec -it $PODNAME -- bash | |
curl http-base | |
</section> | |
<section id='keys-and-configs' data-markdown> | |
## Configuration | |
[Environment Variables](https://docs.openshift.org/latest/dev_guide/environment_variables.html) are one way to add configuration settings to your images: | |
oc env dc/http-base KEY=VALUE | |
ConfigMaps and Secrets are also useful configuration abstractions | |
</section> | |
<section id='logging' data-markdown> | |
## Logs | |
Centralized logging and metrics | |
</section> | |
<section id="deployment-strategies"> | |
<h2>Deployment Strategies</h2> | |
<p class="fragment">Get more control of your container rollout and update processes by selecting appropriate <a href="https://docs.openshift.org/latest/dev_guide/deployments.html#strategies">deployment strategies</a> for your fleet of managed containers</p> | |
</section> | |
</section> | |
<section data-transition="concave"> | |
<section id='collaborate'> | |
<h1>Collaborate</h1> | |
<p class='fragment'>Share and replicate your success</p> | |
</section> | |
<section id='service-catalog-on-openshift'> | |
<h2>Service Catalog & Brokers</h2> | |
<p>Expose and provision services</p> | |
<p><img style='width:100%;' src='https://github.com/ryanj/redisconf-2018/raw/master/static/catalog-options.png' alt='pluggable-broker-options' /></p> | |
<p><a href='https://www.openservicebrokerapi.org/'>www.openservicebrokerapi.org</a> | |
</section> | |
<section id='service-catalog' data-markdown> | |
### Everyone's Service Catalog | |
> "The Open Service Broker API project allows developers, ISVs, and SaaS vendors a single, simple, and elegant way to deliver services to applications running within cloud native platforms" | |
Works with: [Kubernetes](https://github.com/kubernetes-incubator/service-catalog), [OpenShift](https://docs.openshift.com/container-platform/3.6/architecture/service_catalog/template_service_broker.html), [Cloud Foundry](https://github.com/spring-cloud/spring-cloud-open-service-broker) | |
</section> | |
<section data-markdown> | |
### Available Service Brokers | |
* [Template Broker](#) | |
* [Helm Chart Broker](#) | |
* [AWS Broker](https://aws.amazon.com/blogs/opensource/aws-service-operator-kubernetes-available/) | |
* [DIY Broker example](#) | |
</section> | |
<section id='installers'> | |
<h2>Templates as Installers</h2> | |
<div class='fragment'> | |
<p>Install a template into the current project, making it easier to reuse:</p> | |
<pre><code contenteditable>oc create -f template.json</code></pre> | |
</div> | |
<div class='fragment'> | |
<p>Create an application from an installed template, from a file, or from a url:</p> | |
<pre><code contenteditable>oc new-app -f template.json</code></pre> | |
</div> | |
</section> | |
<section id='composable-app-example'> | |
<h2>Multi-Service App Example</h2> | |
<p>Nodejs and MongoDB multi-service application example:</p> | |
<pre><code contenteditable>oc create -f https://raw.githubusercontent.com/openshift-roadshow/nationalparks-js/master/nationalparks-js.json</code></pre> | |
<p><a href="https://raw.githubusercontent.com/openshift-roadshow/nationalparks-js/master/nationalparks-js.json">github.com/ryanj/nationalparks-js</a></p> | |
<p>Review and install the above template content using <code>oc create</code>, then try launching it via the web-based Service Catalog.</p> | |
<div class="fragment"> | |
<p>When you're done, list all available API resources to review the contents of your project namespace:</p> | |
<pre><code contenteditable>oc get all</code></pre> | |
</div> | |
</section> | |
</section> | |
<section data-transition="convex"> | |
<section id='extensibility'> | |
<h1>Advanced Extensibility</h1> | |
</section> | |
<section id='standardize' data-markdown> | |
### Standardize your environments with custom base images | |
https://docs.okd.io/latest/using_images/s2i_images/nodejs.html | |
https://github.com/bucharest-gold/centos7-s2i-nodejs | |
<!-- TODO: include node10 installation notes --> | |
</section> | |
<section id='Operators'> | |
<h1>"Operators"</h1> | |
<p>Operators = <a href="https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/">Custom Resources</a> + <a href="https://github.com/kubernetes/sample-controller">Custom Controllers</a></p> | |
<p class='fragment'><a href="https://coreos.com/operators/">coreos.com/operators</a></p> | |
<p class='fragment'><a href=" https://github.com/operator-framework/awesome-operators">github.com/operator-framework/awesome-operators</a></p> | |
</section> | |
</section> | |
<section data-transition="concave"> | |
<section id='wrap-up'> | |
<h1>Wrap Up</h1> | |
</section> | |
<section id='exit-survey'> | |
<h3>Exit Survey</h3> | |
<ol> | |
<li class='fragment'>have experience using containers?</li> | |
<li class='fragment'>have experience using Kubernetes?</li> | |
<li class='fragment'>Do you consider yourself to be basically proficient with the <code>oc</code> or <code>kubectl</code> command-line tools?</li> | |
<li class='fragment'>Can you name five basic Kubernetes primitives or resource types?</li> | |
<li class='fragment'>Ready to start standardizing your web development processes with containers?</li> | |
</ol> | |
</section> | |
</section> | |
<section data-transition="concave"> | |
<section data-markdown> | |
## Resources | |
</section> | |
<section id='Deploying-to-OpenShift'> | |
<h3>Free O'Reilly Ebook</h3> | |
<p><a href="https://www.openshift.com/deploying-to-openshift/"><img src="https://www.openshift.com/hubfs/images/openshift-legacy/promotions/deploying-to-openshift/deploying-to-openshift.png" style="margin-left:auto;margin-right:auto;width:45%;display:block;box-shadow:none;align:center;"></a></p> | |
<p><a href="https://www.openshift.com/deploying-to-openshift/">Deploying to OpenShift</a></p> | |
</section> | |
<section data-markdown> | |
## Top Tools for K8s JS Hackers | |
* https://www.npmjs.com/package/openshift-rest-client | |
* https://www.npmjs.com/package/nodeshift | |
* https://github.com/bucharest-gold/centos7-s2i-nodejs | |
</section> | |
<!-- | |
<section data-markdown> | |
### Kubernetes SIGs | |
[Kubernetes Special Interest Groups (SIGs)](https://github.com/kubernetes/community/blob/master/sig-list.md) | |
</section> | |
--> | |
<section data-transition="linear" id='kubernetes-terminology' data-markdown> | |
## K8s Terminology | |
1. [node](https://kubernetes.io/docs/concepts/architecture/nodes/) | |
2. [pod](https://kubernetes.io/docs/concepts/workloads/pods/pod/) | |
3. [deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/) | |
4. [service](https://kubernetes.io/docs/concepts/services-networking/service/) | |
5. [replicaSet (rs)](https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/) | |
</section> | |
<section data-transition="linear" id='openshift-terminology' data-markdown> | |
## OpenShift Terminology | |
1. [buildConfig (bc)](https://docs.openshift.org/latest/rest_api/apis-build.openshift.io/v1.BuildConfig.html) | |
2. [imageStream (is)](https://docs.openshift.org/latest/rest_api/apis-image.openshift.io/v1.ImageStream.html) | |
3. [deploymentConfig (dc)](https://docs.openshift.org/latest/rest_api/apis-apps.openshift.io/v1.DeploymentConfig.html) | |
4. [route](https://docs.openshift.org/latest/rest_api/apis-route.openshift.io/v1.Route.html) | |
5. [template](https://docs.openshift.org/latest/rest_api/oapi/v1.Template.html) | |
</section> | |
</section> | |
<section id='try-openshift' data-markdown data-transition="concave"> | |
### More Ways to Try OpenShift | |
* [OpenShift Learning Portal](http://learn.openshift.com) | |
* [OpenShift Origin](https://github.com/openshift/origin) (and [minishift](https://github.com/minishift/minishift)) | |
* [OpenShift Online (Starter and Pro plans available)](https://www.openshift.com/products/online/) | |
* [OpenShift Dedicated (operated on AWS, GCE, and Azure)](https://www.openshift.com/products/dedicated/) | |
* [OpenShift Container Platform (supported on RHEL, CoreOS)](https://www.openshift.com/products/container-platform/) | |
for a local laptop install see [minikube](http://bit.ly/k8s-minikube) and/or [minishift](http://bit.ly/k8s-minishift) | |
</section> | |
<section data-transition="zoom" data-background-color='black' id='q-and-a'> | |
<h1 style='color:white;'>Q&A</h1> | |
</section> | |
<section data-background="https://gist.githubusercontent.com/ryanj/9181e48c0dd8e6b45d692a11d5a72bd5/raw/9892bcb34a809c25c24c43a2ea33bb69b7684f0b/node-js-interactive-1.jpg" data-background-color="black" data-background-size="cover" data-background-position="top" id='thank-you'> | |
<h2 style='color:white;margin-bottom:0px;' class="fragment grow">Thank You!</h2> | |
<p style='color:white;margin-bottom:0px;margin-top:0px;'><img style="margin-bottom:0px;width:56%;" alt="RyanJ" src="https://tek.phparch.com/wp-content/uploads/sites/7/2018/05/ryan-jarvinen-headshot-e1525184794614-531x424.jpg" /></p> | |
<p style='margin-top:0px;color:white;'><a href="https://twitter.com/ryanj">@RyanJ / ryanj@redhat.com</a></p> | |
<h3 class="fragment grow" style='color:white;text-transform:none;'><a href="http://bit.ly/nodejs-on-k8s">bit.ly/nodejs-on-k8s</a></h3> | |
</section> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment