Skip to content

Instantly share code, notes, and snippets.

@ryanj
Last active March 5, 2020 06:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ryanj/7b57790fe010210e1a4361df0d670922 to your computer and use it in GitHub Desktop.
Save ryanj/7b57790fe010210e1a4361df0d670922 to your computer and use it in GitHub Desktop.
Kubernetes 101 at SCaLE 18x http://bit.ly/K8s-101
<section data-background-transition="none-in zoom-out" data-transition="zoom" id="HANDS-ON" data-background-color="black">
<h1 style="color:white;padding-top:26%;">Kubernetes 101</h1>
<h3 style="color:white;">at SCaLE 18x</h3>
<p class='fragment grow'><a style="font-weight:bold;" href="http://bit.ly/K8s-101">bit.ly/K8s-101</a></p>
<p><a href="https://www.socallinuxexpo.org/scale/18x/presentations/workshop-kubernetes-101">Thursday, March 5, 2020 - 14:00 to 17:00, Room 106</a></p>
</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&hellip;</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;'>&amp;</div>
<div class='fragment fade-left' style='width:45%; float:left;'>
<p><a href="http://twitter.com/Ell_o_Punk"><img alt="Ell Marquez" src="https://www.socallinuxexpo.org/sites/default/files/styles/square_thumbnail/public/speakers/Headshot2jpg.jpg" style="width:70%"/></p>
<p><a href="http://twitter.com/Ell_o_Punk">Ell Marquez @Ell_o_Punk</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://www.underconsideration.com/brandnew/archives/red_hat_logo_inverse.png" /></a></p>
</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'>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 resource types?</li>
</ol>
</section>
</section>
<section>
<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="#/cluster-access">Environment Setup</a></li>
</ul>
</li>
<li class='fragment'><a href="#/kubernetes-basics">Kubernetes Basics</a>
<ul style='list-style: none;'>
<li class='fragment'>Learn five basic resource types</li>
</ul>
</li>
<li class='fragment'><a href="#/wrap-up">Wrap Up / Q&amp;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='openshift' data-markdown>
# OpenShift
* a CNCF certified distribution of Kubernetes
* adds: Multi-tenant security, PaaS-style workflows, a container registry, distributed metrics and logs ...
</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>
<section id='workshop-requirements' data-markdown>
## Workshop Requirements
* *a web browser with JS enabled*
</section>
</section>
<section id='cluster-access' data-markdown>
## Cluster Access
1. Select an available username for today's lab: http://bit.ly/pick-username
2. Add your name in the column to the right to indicate that you have claimed the account name
3. Sign in with your selected username ("userN") and a password of "openshift" at:
https://lab-k8s-101-workshops.apps.cluster-scale-ab86.scale-ab86.example.opentlc.com
</section>
<section>
<section data-transition='zoom-in convex-out' id='ready'>
<h1><i>Ready?</i></h1>
<br/>
<div class='fragment fade-up'>
<p>Before we get started, please export the following env vars:</p>
<pre><code contenteditable>export GUID=ab86
export API_SERVER=https://api.cluster-scale-$GUID.scale-$GUID.example.opentlc.com:6443
export NAMESPACE=$(oc project --short)
export NODE_IP=10.0.132.188</code></pre>
</div>
<div class='fragment fade-up'>
<p>Confirm that you've been authenticated by running:</p>
<pre><code contenteditable>oc whoami</code></pre>
<p>Login credentials are usually persisted to your <code>~/.kube/config</code> file. Which can be generated by running:</p>
<pre><code contenteditable>oc login</code></pre>
</div>
</section>
<section data-background-transition="zoom">
<h1>Set?</h1>
<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>
<section id='kubernetes-basics'>
<h1>Kubernetes Basics</h1>
<p>↓</p>
</section>
<section data-markdown>
## etcd
![etcd logo](https://raw.githubusercontent.com/coreos/etcd/master/logos/etcd-glyph-color.png)
* developed at CoreOS, donated to the CNCF
* distributed key-value store with automatic leader election
* 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)
http://play.etcd.io/play
</section>
<section id='an-api' data-markdown>
Kubernetes provides&hellip;
# 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.17/
</section>
<section data-transition="linear" id='terminology' 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>
<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>
<p class='fragment'>Given OpenShift's RBAC policies, only users with administrative credentials will have sufficient privledges to list nodes in the cluster. (Instuctors may optionally log in as cluster-admin to fetch the list of nodes)</p>
</section>
<section data-markdown>
### Observations:
* Your processes run on Nodes! (machines)
* Kubernetes actively manages process availability and health over groups of machines (distributed system)
* built for high availability (of platform, of workloads)
* Scale out by adding more Nodes to the pool
* RBAC policies can be applied, protecting access to privledged platform state (stored in etcd)
</section>
</section>
<section>
<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.
&gt; "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 based on a json object specification:</p>
<pre><code contenteditable>curl https://raw.githubusercontent.com/jankleinert/hello-workshop/master/pod.json</code></pre>
<pre><code contenteditable>kubectl create -f https://raw.githubusercontent.com/jankleinert/hello-workshop/master/pod.json</code></pre>
</section>
<section>
<p>List pods by type using <code>curl</code>:</p>
<pre><code contenteditable>curl -k -H"Authorization: Bearer $(oc whoami -t)" $API_SERVER/api/v1/namespaces/$NAMESPACE/pods</code></pre>
<p>Fetch an individual resource by <code>type/id</code>; output as <code>json</code>:</p>
<pre><code contenteditable>curl -k -H"Authorization: Bearer $(oc whoami -t)" $API_SERVER/api/v1/namespaces/$NAMESPACE/pods/hello-k8s</code></pre>
<pre><code contenteditable>kubectl get pod hello-k8s -o json</code></pre>
<p class='fragment'>Notice any changes between the json spec and the API response?</p>
</section>
<section>
<!--
<p>Request the same info using <code>curl</code>:</p>
<pre><code contenteditable>curl -k -H'Authorization: Bearer $(oc whoami -t)' $API_SERVER/api/v1/namespaces/$NAMESPACE/pods/hello-world</code></pre>
-->
<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
* see `spec` vs `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>
<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>Contact your newly-exposed pod via internal kube-dns:</p>
<pre><code contenteditable>echo hello-k8s.$NAMESPACE:8080</code></pre>
<pre><code contenteditable>curl hello-k8s.$NAMESPACE:8080</code></pre>
</section>
<section id='connections-2'>
<h3>NodePort Access</h3>
<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 assigned port number:</p>
<pre><code contenteditable>echo $NODE_IP:$(kubectl get svc/hello-k8s -o jsonpath={.spec.ports[0].nodePort})</code></pre>
<pre><code contenteditable>curl $NODE_IP:$(kubectl get svc/hello-k8s -o jsonpath={.spec.ports[0].nodePort})</code></pre>
</section>
<section>
<h3>Cleanup</h3>
<p>Schedule the deletion of all pods that are labeled with <code>run=hello-k8s</code>:</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 hello-k8s.$NAMESPACE:8080</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>
<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 &gt; deployment.json</code></pre>
<p>View the generated deployment spec file:</p>
<pre><code contenteditable>cat deployment.json</code></pre>
</section>
<section>
<p>Create new resources based on your spec files:</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 &gt; service.json</code></pre>
<p>View the resulting spec file:</p>
<pre><code contenteditable>cat service.json</code></pre>
</section>
<section>
<p>Create a new service based on your 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 id:</p>
<pre><code contenteditable>curl hello-k8s.$NAMESPACE:8080</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>
</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>
<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 hello-k8s.$NAMESPACE:8080</code></pre>
<p>Watch deployments:</p>
<pre><code contenteditable>kubectl get deploy -w &amp;</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>
<pre><code contenteditable>kubectl get rs</code></pre>
<p>View the state of your deployment</p>
<pre><code contenteditable>curl hello-k8s.$NAMESPACE:8080</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>View the state of your deployment</p>
<pre><code contenteditable>curl hello-k8s.$NAMESPACE:8080</code></pre> </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 `fg` and sending a break signal (CTRL-c)</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 &gt; ReplicaSets &gt; Pods
</section>
</section>
<section id='exit-survey'>
<h3>Part 1 - 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'>What resource type represents our minimum unit of scale?</li>
<li class='fragment'>What resource type is most similar to a loadbalancer?</li>
<li class='fragment'>What resource type is responsible for replication?</li>
<li class='fragment'>What resource type provides zero-downtime rollouts and rollbacks?</li>
<li class='fragment'>Can you name five basic Kubernetes primitives or resource types?</li>
</ol>
</section>
<section>
<section data-markdown>
## Resources
</section>
<section data-markdown>
### Free O'Reilly Ebook
[Kubernetes Operators](https://www.openshift.com/kubernetes-operators/) *NEW!*
</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>
<section id='try-openshift' data-markdown>
### OpenShift
* [OperatorHub.io](http://OperatorHub.io)
* [OpenShift Learning Portal](http://learn.openshift.com)
* [try.openshift.com](https://try.openshift.com)
</section>
<section data-background-color='black' id='q-and-a'>
<h1 style='color:white;'>Q&amp;A</h1>
</section>
<section id='thank-you' data-background-color="black">
<h1 style='color:white;'>Thank You!</h1>
<div class='fragment fade-right' style='width:45%; float:left;'>
<p><a href="http://twitter.com/ryanj/"><img alt="ryanj" src="https://tek.phparch.com/wp-content/uploads/sites/7/2018/05/ryan-jarvinen-headshot-e1525184794614-531x424.jpg" 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;'>&amp;</div>
<div class='fragment fade-left' style='width:45%; float:left;'>
<p><a href="http://twitter.com/Ell_o_Punk"><img alt="Ell Marquez" src="https://www.socallinuxexpo.org/sites/default/files/styles/square_thumbnail/public/speakers/Headshot2jpg.jpg" style="width:70%"/></p>
<p><a href="http://twitter.com/Ell_o_Punk">Ell Marquez @Ell_o_Punk</a></p>
</div>
<br/>
<h3 class="fragment grow" style='text-transform:none;'><a href="http://bit.ly/K8s-101">bit.ly/K8s-101</a></h3>
</section>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment