Last active
June 9, 2020 17:17
-
-
Save ryanj/9922a49e713d219806f730bffc1e2159 to your computer and use it in GitHub Desktop.
Containers, Kubernetes, and OpenShift at NorthEast PHP 2018 in Boston http://bit.ly/nephp18
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='concave'> | |
<section id="at-NorthEastPHP"> | |
<!-- | |
<a href="http://kubernetes.io/"><img src="https://cdn.rawgit.com/ryanj/1aed9676c69ab0073be0beb60ca77a9c/raw/74f82bdfb47f1addaca529e8ee63ed678356a62f/kubernetes-blueprint-logo.svg" alt="kubernetes" style='width:30%;'></a> | |
--> | |
<h3>Containers,</h3> | |
<h2>Kubernetes,</h2> | |
<p><i>and</i></p> | |
<h1>OpenShift</h1> | |
<p><a href="http://2018.northeastphp.org/schedule.html">NorthEastPHP 2018</a></p> | |
<p><a href="http://sched.co/Fh5e">Wednesday, Sept 19, 9:00am-4:00pm</a></p> | |
<br/> | |
<h3 class='fragment grow'><a style='font-family:monospace;' href="http://bit.ly/nephp18">bit.ly/nephp18</a></h3> | |
<p>WiFi: "WayPHPMeet" php092018</p> | |
</section> | |
<section data-transition='concave' data-background-transition='fade' data-background='black' id='presented-by-ryanj'> | |
<!-- <p>presented by <a href="http://twitter.com/ryanj/">@ryanj</a>, Developer Advocate at Red Hat</p>--> | |
<p>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;'>&</div> | |
<div class='fragment fade-left' style='width:45%; float:left;'> | |
<p><a href="http://twitter.com/joshixisjosh9"><img alt="Josh Wood" src="https://pbs.twimg.com/profile_images/488431660459753472/xCeVbtJV_400x400.jpeg" style="width:70%"/></p> | |
<p><a href="http://twitter.com/joshixisjosh9">Josh Wood @joshixisjosh9</a></p> | |
</div> | |
<br/> | |
<!-- | |
<p 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-markdown> | |
brought to you by | |
[![Red Hat logo](https://i.imgur.com/ArZFG3e.png "")](https://redhat.com) | |
</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 laptop setup 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> | |
<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> <a href="#/agenda">Agenda</a> ✔</li> | |
</ul> | |
--> | |
</li> | |
<li class='fragment'><a href="#/kubernetes-basics">Kubernetes Basics</a></li> | |
<li class='fragment'><a href="#/hands-on-with-openshift">Hands-On with OpenShift</a> | |
<ul style='list-style: none;'> | |
<li><Build, Iterate, Standardize</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' data-markdown> | |
## 2017 Octoverse Report | |
> 🏆 Most-discussed project(s) on GitHub in 2017! | |
http://octoverse.github.com | |
[Kubernetes Community - Top of the Open Source Charts in 2017](https://kubernetes.io/blog/2018/04/25/open-source-charts-2017/) | |
</section> | |
<section id='openshift' data-markdown> | |
# OpenShift | |
* includes, extends, is a distribution of: Kubernetes | |
* adds: mult-tenanant security, PaaS features, a Template broker | |
</section> | |
<section id='more-info' data-markdown> | |
### More Information | |
* OpenShift Sources and Releases: http://github.com/openshift/origin/ | |
* OpenShift Docs: https://docs.openshift.com/ | |
* Kubernetes Docs: http://kubernetes.io/docs/home/ | |
</section> | |
</section> | |
<section> | |
<section id='kubernetes-basics'> | |
<h1>Kubernetes Basics</h1> | |
<p>↓</p> | |
</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 | |
</section> | |
<section data-transition="linear" id='terminology' data-markdown> | |
### Basic K8s Terminology | |
1. [node](#/node) | |
2. [pod](#/po) | |
3. [service](#/svc) | |
4. [deployment](#/deploy) | |
5. [replicaSet](#/rs) | |
Introduction lifted from: [bit.ly/k8s-kubectl](http://bit.ly/k8s-kubectl) | |
</section> | |
</section> | |
<section> | |
<section data-transition="linear" id='node' data-markdown> | |
### Node | |
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>Request the same info, but output the results as structured yaml:</p> | |
<pre><code contenteditable>kubectl get nodes -o yaml</code></pre> | |
<p>Fetch an individual resource by <code>type/id</code>, output as <code>json</code>:</p> | |
<pre><code contenteditable>kubectl get node/minikube -o json</code></pre> | |
<p>View human-readable API output:</p> | |
<pre><code contenteditable>kubectl describe node/minikube</code></pre> | |
</section> | |
<section data-markdown> | |
### Observations: | |
* Designed to exist on multiple machines (distributed system) | |
* high availability of nodes | |
* platform scale out | |
* The API ambidextriously supports both json and yaml | |
</section> | |
</section> | |
<section> | |
<section data-transition="linear" id='po' data-markdown> | |
### Pod | |
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>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/ryanj/metrics-k8s/master/pod.json</code></pre> | |
<pre><code contenteditable>kubectl create -f https://raw.githubusercontent.com/ryanj/metrics-k8s/master/pod.json</code></pre> | |
<p>List resources by type:</p> | |
<pre><code contenteditable>kubectl get pods</code></pre> | |
<p>Fetch a resource by type and id, output the results as <code>yaml</code>:</p> | |
<pre><code contenteditable>kubectl get pod metrics-k8s -o yaml</code></pre> | |
<p>Notice any changes?</p> | |
</section> | |
<section data-markdown> | |
### Observations: | |
* pods are scheduled to be run on nodes | |
* asyncronous fulfilment of requests | |
* declarative specifications | |
* automatic health checks, lifecycle management for containers (processes) | |
</section> | |
<!-- | |
<section data-markdown> | |
</section> | |
--> | |
</section> | |
<section> | |
<section data-transition="linear" id='svc' data-markdown> | |
### Service | |
Services (svc) establish a single endpoint for a collection of replicated pods, distributing inbound traffic based on label selectors | |
In our K8s modeling language they represent a load balancer. Their implementation often varies per cloud provider | |
</section> | |
<section id='services'> | |
<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/metrics-k8s --port 2015 --type=NodePort</code></pre> | |
<p>Contact your newly-exposed pod using the associated service id:</p> | |
<pre><code contenteditable>minikube service metrics-k8s</code></pre> | |
<p>Schedule a pod to be deleted:</p> | |
<pre><code contenteditable>kubectl delete pod metrics-k8s</code></pre> | |
<p>Contact the related service. What happens?:</p> | |
<pre><code contenteditable>minikube service metrics-k8s</code></pre> | |
<p>Delete the service:</p> | |
<pre><code contenteditable>kubectl delete service metrics-k8s</code></pre> | |
</section> | |
<section data-markdown> | |
### Observations: | |
* *"service"* basically means *"loadbalancer"* | |
* Pods and Services exist independently, have disjoint lifecycles | |
</section> | |
</section> | |
<section> | |
<section data-transition="linear" id='deploy' data-markdown> | |
### Deployment | |
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 metrics-k8s --image=quay.io/ryanj/metrics-k8s \ | |
--expose --port=2015 --service-overrides='{ "spec": { "type": "NodePort" } }' \ | |
--dry-run -o yaml > deployment.yaml</code></pre> | |
<p>View the generated deployment spec file:</p> | |
<pre><code contenteditable>cat deployment.yaml</code></pre> | |
</section> | |
<section> | |
<p>Create a new resource based on your yaml specification:</p> | |
<pre><code contenteditable>kubectl create -f deployment.yaml</code></pre> | |
<p>List resources by type:</p> | |
<pre><code contenteditable>kubectl get po,svc</code></pre> | |
<p>Connect to your new deployment via the associated service id:</p> | |
<pre><code contenteditable>minikube service metrics-k8s</code></pre> | |
</section> | |
<section id='replication'> | |
<h2>Replication</h2> | |
<p>Scale up the <code>metrics-k8s</code> deployment to 3 replicas:</p> | |
<pre><code contenteditable>kubectl scale deploy/metrics-k8s --replicas=3</code></pre> | |
<p>List pods:</p> | |
<pre><code contenteditable>kubectl get po</code></pre> | |
</section> | |
<section> | |
<p>Edit <code>deploy/metrics-k8s</code>, setting <code>spec.replicas</code> to <code>5</code>:</p> | |
<pre><code contenteditable>kubectl edit deploy/metrics-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 ^metrics-k8s | cut -f1 -s -d' ' | head -n 3 | tr '\n' ' ')</code></pre> | |
<p>What happend? How many pods remain?</p> | |
<pre><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 | |
</section> | |
</section> | |
<section> | |
<section data-transition="linear" id='rs' data-markdown> | |
### ReplicaSet | |
A `replicaset` provides replication and lifecycle management for a specific image release | |
</section> | |
<section> | |
<p>Watch deployments (leave this running until the 'cleanup' section):</p> | |
<pre><code contenteditable>kubectl get deploy --watch</code></pre> | |
<p>View the current state of your deployment:</p> | |
<pre><code contenteditable>minikube service metrics-k8s</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/metrics-k8s metrics-k8s=quay.io/ryanj/metrics-k8s:v1</code></pre> | |
<p>Reload your browser to view the state of your deployment</p> | |
<pre><code contenteditable>kubectl get rs,deploy</code></pre> | |
</section> | |
<section> | |
<h3>Rollbacks</h3> | |
<p>View the list of previous rollouts:</p> | |
<pre><code contenteditable>kubectl rollout history deploy/metrics-k8s</code></pre> | |
<p>Rollback to the previous state:</p> | |
<pre><code contenteditable>kubectl rollout undo deployment metrics-k8s</code></pre> | |
<p>Reload your browser to view the state of your deployment</p> | |
</section> | |
<section> | |
<h3>Cleanup</h3> | |
<p>Cleanup old resources if you don't plan to use them:</p> | |
<pre><code contenteditable>kubectl delete service,deployment metrics-k8s</code></pre> | |
<p>Close any remaining <code>--watch</code> listeners</p> | |
</section> | |
<section data-markdown> | |
### Observations: | |
* The API allows for watch operations (in addition to get, set, list) | |
* ReplicaSets provide lifecycle management for pod resources | |
* Deployments create ReplicaSets to manage pod replication per rollout (per change in podspec: image:tag, environment vars) | |
</section> | |
<section id='death-by-yaml'> | |
<a href="https://twitter.com/milosgajdos/status/1001932689195372549">https://twitter.com/milosgajdos/status/1001932689195372549</a> | |
</section> | |
<section data-markdown id='from-kubecon'> | |
Developing Locally with Kubernetes isn't easy | |
"[Local Dev with K8s](http://bit.ly/kubecon-dev)": [youtu.be/_W6O_pfA00s](http://youtu.be/_W6O_pfA00s) | |
</section> | |
</section> | |
<section data-transition='zoom'> | |
<section data-transition="convex" id='hands-on-with-openshift'> | |
<h1>Hands-On with OpenShift</h1> | |
<p>↓</p> | |
</section> | |
<section data-transition='zoom-in convex-out' id='ready'> | |
<h1><i>Ready?</i></h1> | |
</section> | |
<section data-background-transition="zoom"> | |
<h1>Let's Go!</h1> | |
<br/> | |
<div class='fragment fade-up'> | |
<p>Follow along at:</p> | |
<p><code><a href="http://starter-guides-lab-infra.apps.nephp.openshiftworkshop.com/">bit.ly/2NWL6LO</a></code></p> | |
</div> | |
</section> | |
</section> | |
<section> | |
<section id='build'> | |
<h1>Build</h1> | |
<p class='fragment'>Build and deploy container images</p> | |
</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 id='add-to-project'> | |
<h2>Web Workflow: Create</h2> | |
<p class='fragment'>For this example, we will deploy a fork of the <code>silex-base</code> repo by clicking on "Add to Project" in the web console. Then, select a nodejs base image, name your webservice, and enter it's github source url</p> | |
<p class='fragment'>Optionally, explore the "Advanced routing, build, and deployment options" before starting your build with the "Create" button</p> | |
<p class="fragment">Example repo source: <a href="http://github.com/ryanj/silex-base/">github.com/ryanj/silex-base</a></p> | |
</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> | |
<section data-transition="linear"> | |
<section id="iterate"> | |
<h1>Iterate</h1> | |
<p class='fragment'>Iterate on container-based solutions</p> | |
</section> | |
<section id='oc-rsync'> | |
<h3>Developing on Docker</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>oc rsync --exclude='.git' . PODNAME:</code></pre> | |
</div> | |
<div class='fragment'> | |
<p>Make sure to use a valid <code>PODNAME</code> from:</p> | |
<pre><code contenteditable>oc get pods</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 | |
</section> | |
<section id='webhooks'> | |
<h2>WebHook Build Automation</h2> | |
<p class='fragment'>Set up a commit WebHook to automate image production</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'>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 silex-base</code></pre> | |
</div> | |
</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/silex-base KEY=VALUE | |
</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> | |
<section id='standardize' data-markdown> | |
# Standardize | |
</section> | |
<section data-markdown> | |
### Extend the base images | |
https://docs.openshift.org/latest/using_images/s2i_images/php.html | |
https://github.com/sclorg/s2i-php-container | |
</section> | |
<section id='open-service-broker-api'> | |
<h2>Open Service Broker API</h2> | |
<!--<p>↓</p>--> | |
<p class='fragment'><a href="http://bit.ly/k8s-catalog">bit.ly/k8s-catalog</a></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> | |
</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/ryanj/restify-mongodb-parks/master/restify-mongodb-parks-template.json</code></pre> | |
<p><a href="https://github.com/ryanj/restify-mongodb-parks/blob/master/restify-mongodb-parks-template.json">github.com/ryanj/restify-mongodb-parks</a></p> | |
</section> | |
</section> | |
<section> | |
<section id='wrap-up'> | |
<h1>Wrap Up</h1> | |
</section> | |
<section data-background-color='black' data-markdown id='q-and-a'> | |
# Q&A | |
</section> | |
</section> | |
<section> | |
<section data-markdown> | |
## Resources | |
</section> | |
<section data-markdown> | |
### Kubernetes SIGs | |
[Kubernetes Special Interest Groups (SIGs)](https://github.com/kubernetes/community/blob/master/sig-list.md) | |
</section> | |
<section data-markdown> | |
### Free O'Reilly Ebook | |
[Deploying to OpenShift](https://www.openshift.com/deploying-to-openshift/) *NEW!* | |
</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/) | |
6. [persistent volume (pv)](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) | |
7. [persistent volume claim (pvc)](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#persistentvolumeclaims) | |
</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> | |
### 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 (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 id='thank-you'> | |
<h1>Thank You!</h1> | |
<p><img style="width:33%;" alt="RyanJ" src="https://tek.phparch.com/wp-content/uploads/sites/7/2018/05/ryan-jarvinen-headshot-e1525184794614-531x424.jpg" /></p> | |
<p><a href="https://twitter.com/ryanj">@RyanJ</a></p> | |
<br/> | |
<h4 class="fragment grow"><a href="http://bit.ly/nephp18">bit.ly/nephp18</a></h4> | |
</section> | |
<!-- | |
<section> | |
<section id='kubernetes-for-OpsEng'> | |
<h1>Kubernetes for OpsEng</h1> | |
<p>↓</p> | |
</section> | |
</section> | |
<section> | |
<section id='kubernetes-for-DevOps'> | |
<h1>Kubernetes for Developers</h1> | |
<p>↓</p> | |
</section> | |
<section data-markdown id='from-kubecon'> | |
> The following section is a repeat of a talk I gave at KubeCon in Austin... | |
"[Local Dev with K8s](http://bit.ly/kubecon-dev)": [youtu.be/_W6O_pfA00s](http://youtu.be/_W6O_pfA00s) | |
</section> | |
<section data-background='black' data-markdown id="the-community-is-terrible-at"> | |
The Kubernetes Community is Terrible at Pitching Kubernetes to Developers | |
</section> | |
<section data-background='black' data-transition='zoom' id='why' data-markdown> | |
## Why? | |
</section> | |
<section data-markdown id='kubernetes-is-an-ops-tool'> | |
# Kubernetes | |
(an ops tool) | |
</section> | |
<section data-transition='fade-out' id='prescription'> | |
<img data-src="https://i.imgur.com/XlhSc6W.jpg"/> | |
</section> | |
<section data-transition='fade-in zoom-out' id='prescription-k8s'> | |
<img data-src="https://i.imgur.com/7BVLtPU.jpg"/> | |
</section> | |
<section data-transition='zoom-in convex-out' id='for-operations'> | |
<p>When used as directed, provides relief for the following:</p> | |
<ol> | |
<li class='fragment'>standardized terminology & packaging - containers, volumes, podspecs, charts</li> | |
<li class='fragment'>load balancing - services</li> | |
<li class='fragment'>scaling automation - replica sets</li> | |
<li class='fragment'>delivery automation - deployments</li> | |
<li class='fragment'>high availability - automated health checking and replacement</li> | |
<li class='fragment'>distributed scheduling and resource management - RBAC, namespaces, labels, federation</li> | |
<li class='fragment'>???</li> | |
</ol> | |
</section> | |
<section data-transition='zoom' id='k8s-logo'> | |
<a href="http://kubernetes.io/"><img src="https://cdn.rawgit.com/ryanj/1aed9676c69ab0073be0beb60ca77a9c/raw/74f82bdfb47f1addaca529e8ee63ed678356a62f/kubernetes-blueprint-logo.svg" alt="kubernetes" style='width:30%;'></a> | |
</section> | |
<section data-background='black' data-markdown id='meanwhile'> | |
meanwhile... | |
</section> | |
<section id='what'> | |
<p>What is an App?</p> | |
<ol> | |
<li class='fragment'><span style='text-decoration:line-through;'>repo code</span></li> | |
<li class='fragment'><span style='text-decoration:line-through;'>docker image</span></li> | |
<li class='fragment'>kubernetes spec files</li> | |
<li class='fragment'>charts</li> | |
<li class='fragment'>kubectl get all -l app=myapp -n mynamespace</li> | |
</ol> | |
<p class='fragment'><a href="https://docs.google.com/document/d/1EVy0wRJRm5nogkHl38fNKbFrhERmSL_CLNE4cxcsc_M/edit">Proposal: Label Recommendations</a></p> | |
</section> | |
<section data-transition='zoom' id='how' data-markdown> | |
### How should we be talking to Developers about | |
# Kubernetes? | |
</section> | |
<section data-background='black' id='why-k8s'> | |
<blockquote> | |
Q: Why Kubernetes? | |
</blockquote> | |
<div class='fragment' style='clear:both;'> | |
<blockquote> | |
A: Development Velocity | |
</blockquote> | |
</div> | |
</section> | |
<section data-transition="convex" id='welcome-to-Austin'> | |
<img data-src="http://mediad.publicbroadcasting.net/p/kut/files/201609/4764611735_3a22b13c0b_b.jpg" /> | |
</section> | |
<section data-transition="concave" id='a-case-study'> | |
<h3>A Case Study: Enterprise Records, Inc.</h3> | |
<img class='fragment fade-up' data-src="https://i.imgur.com/KpTVDt4.jpg" /> | |
</section> | |
<section data-transition="convex" id='pitching-k8s'> | |
<img data-src="https://i.imgur.com/NEMK0xw.gif" /> | |
<p>The Ops team has heard great things about Kubernetes, and is interested in giving it a try - but they're having difficulty convincing other teams of the value</p> | |
</section> | |
<section id='focus-on-delivery'> | |
<p>Product team needs:</p> | |
<h1 class='fragment zoom'>More</h1> | |
<img class='fragment fade-up' data-src="https://i.imgur.com/q9rPpDn.gif" /> | |
<p class='fragment zoom'>(always more)</p> | |
</section> | |
<section data-transition="zoom" id='dont-let-k8s-get-in-the-way'> | |
<img data-src="https://i.imgur.com/Bvq78UI.gif" /> | |
<p>The web team is confused by all the new terminology, and is under a lot of pressure to focus on delivering new tracks to customers</p> | |
</section> | |
<section id='define-a-path-to-productivity'> | |
<img data-src="https://i.imgur.com/jGm2JJ0.gif" /> | |
</section> | |
<section id='convince-the-team'> | |
<p>Convincing the team (minimal onboarding):</p> | |
<ol> | |
<li class='fragment'><a href="#/the-easy-part">Getting started is easy</a></li> | |
<li class='fragment'><a href="#/sharing">Share what you know (and model your I/O)</a></li> | |
<li class='fragment'><a href="#/choose-the-right-tools">Choose the right toolchain</a></li> | |
</ol> | |
</section> | |
<section id='the-easy-part' data-markdown> | |
# 1. The Easy Part | |
is | |
minikube start | |
</section> | |
<section data-markdown id='no-excuses'> | |
* Staging down? | |
* Ops not Ready? | |
No Excuses! | |
</section> | |
<section data-transition="zoom" data-markdown id='kubernetes-all-the-things'> | |
# !!Everyone get a K8s!! | |
</section> | |
<section data-transition='zoom' id='k8s-delivery'> | |
<a href="http://kubernetes.io/"><img src="https://cdn.rawgit.com/ryanj/1aed9676c69ab0073be0beb60ca77a9c/raw/74f82bdfb47f1addaca529e8ee63ed678356a62f/kubernetes-blueprint-logo.svg" alt="kubernetes" style='width:30%;'></a> | |
</section> | |
<section id='minikube-for-all'> | |
<h2>Minikube</h2> | |
<p><a href="https://github.com/kubernetes/minikube"><img style="width:30%;" src="https://raw.githubusercontent.com/kubernetes/minikube/master/logo/logo.png" /></a></p> | |
<ul> | |
<li><a href="https://github.com/kubernetes/minikube">Minikube Docs</a></li> | |
<li><a href="http://bit.ly/k8s-minikube">bit.ly/k8s-minikube</a></li> | |
</ul> | |
</section> | |
<section id='sharing' data-markdown> | |
# 2. Share What You Know | |
and model your I/O | |
</section> | |
<section id='dry-run' data-markdown> | |
### Share What You Know `--dry-run` | |
Generate kubernetes `deployment` and `service` specifications, both named `metrics-review`: | |
```bash | |
kubectl run metrics-review --image=quay.io/ryanj/metrics-k8s \ | |
--expose --port=2015 --service-overrides='{ "spec": { "type": "NodePort" } }' \ | |
--dry-run -o yaml > metrics-review.yaml | |
``` | |
</section> | |
<section data-markdown id='create'> | |
### Share What You Know `--dry-run` | |
Test your generated spec: | |
```bash | |
kubectl create -f metrics-review.yaml | |
``` | |
Minikube users will be able to open the resulting service in their browser by running: | |
```bash | |
minikube service metrics-review | |
``` | |
</section> | |
<section data-markdown id='i-o'> | |
## Model Your I/O | |
</section> | |
<section data-markdown id='example'> | |
### Example Repo | |
Create a local clone of this `metrics-k8s` repo: | |
```bash | |
git clone http://github.com/ryanj/metrics-k8s | |
``` | |
</section> | |
<section data-markdown id='minikube-mount'> | |
### Preview - local files | |
Next, share your local repo contents with minikube: | |
```bash | |
cd metrics-k8s | |
minikube mount $(pwd):/var/www/html | |
``` | |
</section> | |
<section data-markdown id='hostpath'> | |
### Preview - hostPath | |
Then, produce a new deployment spec that includes (minimal) support for live development workflows: | |
1. `cp metrics-review.yaml metrics-dev.yaml` | |
2. replace `metrics-review` with `metrics-dev` (global) | |
2. Add a `hostPort` volume to access your local repo: | |
```diff | |
spec: | |
containers: | |
- image: quay.io/ryanj/metrics-k8s | |
name: metrics-dev | |
ports: | |
- containerPort: 2015 | |
resources: {} | |
+ volumeMounts: | |
+ - mountPath: /var/www/html | |
+ name: metrics-src | |
+ volumes: | |
+ - name: metrics-src | |
+ hostPath: | |
+ path: /var/www/html | |
status: {} | |
``` | |
</section> | |
<section data-markdown id='kubectl-create'> | |
### Share what you know | |
The resulting file should look just like the included [metrics-dev.yaml](https://raw.githubusercontent.com/ryanj/metrics-k8s/master/metrics-dev.yaml) file from the `metrics-k8s` git repo. | |
Try launching it with: | |
```bash | |
kubectl create -f metrics-dev.yaml | |
``` | |
</section> | |
<section data-markdown id='rollout-test'> | |
### Share what you know - Rollout Testing | |
Eval this | |
```bash | |
minikube docker-env | |
``` | |
to send newly-built images to minikube's docker daemon: | |
```bash | |
docker build . | |
``` | |
</section> | |
<section data-markdown id='the-hard-part'> | |
# 3. The Hard Part | |
Keeping it simple, and choosing the right tools for the job | |
</section> | |
<section> | |
<img data-src="https://i.imgur.com/ogR1pSy.gif" /> | |
</section> | |
<section> | |
<h4>The future is already here — it's just not very evenly distributed. (W.Gibson)</h4> | |
</section> | |
--> | |
<!-- | |
<section data-markdown> | |
### Pizza As A Service | |
https://twitter.com/jeffbarr/status/888169783044194304 | |
*how much of your pipeline should be independently reproducible by developers?* | |
</section> | |
--> | |
<!-- | |
<section id='adoption-path'> | |
<p>Typical container adoption path:</p> | |
<ol> | |
<li class='fragment'>docker</li> | |
<li class='fragment'>volumes, PVs</li> | |
<li class='fragment'>minikube</li> | |
<li class='fragment'>k8s modeling and scalability via spec files, pods, and other abstractions</li> | |
<li class='fragment'>charts, openshift templates, or hand-rolled manifest / spec templating</li> | |
<li class='fragment'>monocular, kubeapps, ServiceCatalog</li> | |
<li class='fragment'>PaaS?</li> | |
</ol> | |
</section> | |
<section id='draft'> | |
<h2>Draft</h2> | |
<p class='fragment'>Make it easy to get started</p> | |
<p><a href="https://draft.sh">draft.sh</a></p> | |
</section> | |
<section id='charts'> | |
<h2>Charts</h2> | |
<p class='fragment'>Share what you know</p> | |
<p><a href="https://github.com/kubernetes/charts">github.com/kubernetes/charts</a></p> | |
</section> | |
<section id='helm-tiller'> | |
<h2>Helm & Tiller</h2> | |
<p class='fragment'>Share more</p> | |
<p><a href="https://github.com/kubernetes/helm">github.com/kubernetes/helm</a></p> | |
</section> | |
<section id='brigade'> | |
<h2>Brigade and Kashti</h2> | |
<p class='fragment'>Build more</p> | |
<p><a href="http://brigade.sh/">brigade.sh</a></p> | |
</section> | |
<section id='fabric8'> | |
<h2>Fabric8</h2> | |
<p class='fragment'>Build more</p> | |
<p><a href="https://fabric8.io">fabric8.io</a></p> | |
</section> | |
<section id='telepresence'> | |
<h2>Telepresence</h2> | |
<p class='fragment'>Access more</p> | |
<p><a href="http://telepresence.io">telepresence.io</a></p> | |
</section> | |
<section id='minishift-oc'> | |
<h2>minishift and oc</h2> | |
<p class='fragment'>Security Enhanced Kubernetes</p> | |
<p><a href="https://github.com/minishift/minishift">github.com/minishift/minishift</a></p> | |
<p><a href="https://github.com/openshift/origin">github.com/openshift/origin</a></p> | |
</section> | |
--> | |
<!-- | |
<section data-markdown> | |
Bugs are more expesive to fix when discovered later | |
![https://www.whitesourcesoftware.com/wp-content/uploads/2015/10/graph2.jpg](cost of development) | |
Making the entire pipeline reproducible allows integration bugs to be found during local dev, lowering overall development costs, increasing velocity | |
https://www.nist.gov/sites/default/files/documents/director/planning/report02-3.pdf#table5-1 | |
</section> | |
--> | |
<!-- | |
<section id='easy'> | |
<img data-src="https://i.imgur.com/uJ67uFz.gif" /> | |
<p>Easy, right?</p> | |
</section> | |
</section> | |
<section> | |
<section data-markdown id='learn-more'> | |
## More Learning Opportunities | |
1. Kubernetes.io Tutorials https://kubernetes.io/docs/tutorials/ | |
2. Katacoda https://katacoda.com/courses/kubernetes | |
4. RyanJ's K8s-workshops http://bit.ly/k8s-workshops | |
3. Interactive learning for OpenShift: http://learn.openshift.com | |
</section> | |
<section id='next-steps'> | |
<p>Include the whole team:</p> | |
<ul> | |
<li class='fragment'>Developers: Want to get ahead? Model your I/O, and Share What You Know!</li> | |
<li class='fragment'>Architects: Figure out who owns manifest creation, maintanence, and distribution</li> | |
<li class='fragment'>QA folks: look forward to saying: "can't repro - works fine on my Kubernetes"</li> | |
<li class='fragment'>Ops: provide cloud resources grants to teams, make sure prod has enough IaaS, ensure platform uptime, upgrades, logging, and metrics</li> | |
<li class='fragment'>Security & Compliance: RBAC, config and secrets management; Secret rotation policies; Monitor for CVEs and apply security patches from upstream</li> | |
</ul> | |
</section> | |
<section id='sig-apps'> | |
<p><a href="https://www.youtube.com/watch?v=vyYHfumJ-AM&list=PL69nYSiGNLP2LMq7vznITnpd2Fk1YIZF3"><img style="width:60%;" src="https://i.imgur.com/vibeqs6.png"/></a></p> | |
<p>Join the community on Slack in #kubernetes-users, and in #SIG-Apps!</p> | |
<p>Share What You Know: Help us develop a range of solutions that expose and/or hide kubernetes in appropriate ways</p> | |
</section> | |
<section id='deliver-consistently'> | |
<img data-src="https://i.imgur.com/GPNWcjN.gif" alt="delivering consistently" /> | |
<p>Learn to deliver consistently using containers</p> | |
</section> | |
<section id='choose-the-right-tools'> | |
<img src="https://i.imgur.com/qvzFSaU.gif" /> | |
<p>Choose the right tools for the job</p> | |
</section> | |
<section id='get-back-to-shipping-product'> | |
<img data-src="https://i.imgur.com/VgVLCPG.gif" alt="whole band" /> | |
<p>then get back to making gold records</p> | |
</section> | |
</section> | |
--> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment