---
# System prepended metadata

title: Kubernetes for JS Developers

---

# 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
