# Kubernetes for JS Developers
(3 hours, 22nd March 2021 - Joel Lord, Dev Advocate, Red Hat OpenShift, Twitter: @joel__lord)
## Agenda
- [Intro to Containers and Kubernetes](#Intro)
- [Basic Kubernetes Objects](#Kubernetes)
- Front-End Application Deployment
- Back-End Application Deployment
- Monitoring and Logging
- Health Checks
- [Further Reading](#Further-Reading)
## Intro
#### Prerequisites
The following tools should be installed prior to the workshop:
Docker (or Podman)
Minikube
[Kubectl]()
#### Brief history of containers
A container is a lightweight standalone, executable package of software that includes everything needed to run an application: code, runtime, system tools, system libraries and settings.
```bash=
docker run -d -rm --name my-node -v $(pwd):/app -p 3000:3000 node:14 node /app
```
```
FROM node:14
EXPOSE 3000
WORKDIR /app
COPY . /app
RUN npm install
CMD npm start
```
```bash=
docker build ....
docker run ...
```
Link to presentation on containers http://javascripteverything.com/landing/containers.php
<br/>
## Kubernetes
Kubernetes helps with:
- Ensuring Pods (containers) are always running
- Makes scaling your application easier
- Takes care of networking between Pods
<br/>
#### Nodes
A node is a machine or virtual machine that has all the tools required to run pods
Two types:
1. Master nodes - manage the worker nodes, 2-3 of them
2. Worker nodes - run the containers, if one fails, the master node will manage that
```bash=
kubectl get nodes
# List nodes
```
<br/>
#### Pods
A group of one or more containers with shared storage/network resources
Every container in the pod is very tightly coupled
##### **`1.yaml`**
```yaml=
apiVersion: v1
kind: Pod
metadata:
name: hello
spec:
containers:
- name: hello
image: node:14
command: [
"/bin/bash",
"-c",
"--"
]
args: [
"node -e \"console.log('Hello'); setTimeout(() => console.log('Terminating'),30000)\""
]
```
```bash=
kubectl apply -f 1.yaml
kubectl get all
kubectl describe pod/hello
kubectl logs hello
kubectl delete pod hello
```
##### **`2.yaml`**
```yaml=
apiVersion: v1
kind: Pod
metadata:
name: webserver
spec:
containers:
- name: nginx
image: nginx:1.17
```
```bash=
kubectl apply -f 2.yaml
kubectl get pods
kubectl exec -it pod/webserver -- /bin/bash
root@webserver:/# service nginx status
[ ok ] nginx is running.
```
##### **`3.json`**
```json=
{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"name": "toolbox"
},
"spec": {
"containers": [
{
"name": "toolbox",
"image": "registry.access.redhat.com/ubi8/ubi",
"command": [
"/bin/bash",
"-c",
"--"
],
"args": [
"while true; do sleep 30; done;"
]
}
]
}
}
```
```bash=
kubectl apply -f 3.json
kubectl get pods
kubectl exec -it pod/toolbox -- /bin/bash
printenv #returns all system variables
kubectl exec -it pod/webserver -- /bin/bash
hostname -I # returns 172.17.0.4, internal ip for webserver
kubectl exec -it pod/toolbox -- /bin/bash
curl 172.17.0.4
```
#### Deployments
Describes the pods you want to deploy, how many you want - the plan. Will create replica sets, which ensure that pods are always running
##### **`4.yaml`**
```yaml=
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello
spec:
selector: # look for any pods with this label. If so, it knows it should manage them
matchLabels:
job: say-hello
template:
metadata:
labels:
job: say-hello
spec:
containers:
- name: hello
image: joellord/handson-k8s-say-hello
```
```bash=
kubectl apply -f 4.yaml
kubectl get all
kubectl logs hello-dc64d9cc8-rt87j
kubectl get all
kubectl scale deployment/hello --replicas=3
# kubectl logs -l=say-hello TODO fill in how to log based on labels
```
##### **`5.yaml`**
```yaml=
apiVersion: apps/v1
kind: Deployment
metadata:
name: front
labels:
app: handsonk8s
spec:
replicas: 2
selector:
matchLabels:
section: front
template:
metadata:
labels:
app: handsonk8s
section: front
spec:
containers:
- name: front
image: joellord/handsonk8s-front:latest
ports:
- containerPort: 8080
env:
- name: WORKING_API_URL
value: api
```
```bash=
kubectl apply -f 5.yaml
```
#### Services
Tools to expose your pods. Do load balancing. Manage your network.
##### **`6.yaml`**
```yaml=
apiVersion: v1
kind: Service
metadata:
name: front
labels:
app: handsonk8s
spec:
selector:
section: front # look for any pods with this selector label. If so, applies this service to them
ports:
- port: 8080
targetPort: 8080
protocol: TCP
```
```bash=
kubectl apply -f 6.yaml
kubectl get services
kubectl exec -it pod/toolbox -- /bin/bash
curl front:8080
kubectl logs -f -l section=front --prefix=true
kubectl delete deployment front
```
### Ingresses
Exposes our pods to the outside world. Provide load balancing, SSL termination TODO: what is this?
##### **`7.yaml`**
```yaml=
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: main
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: front
port:
number: 8080
```
```bash=
minikube addons enable ingress
kubectl apply -f 7.yaml
kubectl get ingresses
minikube ip #192.168.49.2
kubectl delete ingresses --all # to delete it
```
##### **`8.yaml`**
```yaml=
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
labels:
app: handsonk8s
spec:
replicas: 1
selector:
matchLabels:
section: api
template:
metadata:
labels:
app: handsonk8s
section: api
spec:
containers:
- name: api
image: joellord/handsonk8s-api:latest
ports:
- containerPort: 3000
---
apiVersion: v1
kind: Service
metadata:
name: api
labels:
app: handsonk8s
spec:
selector:
section: api
ports:
- port: 3000
protocol: TCP
```
```bash=
kubectl apply -f 8.yaml
```
##### **`9.yaml`**
```yaml=
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: main
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
rules:
- http:
paths:
- path: /api(/|$)(.*)
pathType: Prefix
backend:
service:
name: api
port:
number: 3000
- path: /()(.*)
pathType: Prefix
backend:
service:
name: front
port:
number: 8080
```
```bash=
kubectl apply -f 9.yaml
```
tools to debug:
- kubectl describe
- kubectl logs
- kubectl describe pods $PODNAME
## Resources:
- Discord channel: https://discord.gg/jGbHB3YDkf
- Kubernetes docs: https://kubernetes.io
- github folder for yaml files: https://github.com/joellord/handson-k8s/tree/master/node
#### Platforms we may use
- Minikube (https://minikube.sigs.k8s.io)
- Using Katacoda: gives you 1 hour of kubernetes cluster (https://katacoda.com/courses/kubernetes)
- Red Hat: 14 days developer sandbox (https://developers.redhat.com/developer-sandbox)
## Further Reading
- Using Terraform with kubernetes
- Can't seem to get ingress to work - TODO: debug