Skip to content

Instantly share code, notes, and snippets.

@rosehgal
Last active May 21, 2021 12:05
Show Gist options
  • Save rosehgal/ab39f2a481f4a3ae997ef74fa18cc520 to your computer and use it in GitHub Desktop.
Save rosehgal/ab39f2a481f4a3ae997ef74fa18cc520 to your computer and use it in GitHub Desktop.
Getting started with k8s

Linux prereq

https://jnaapti.com/downloads/linux-prereq.pdf

Resources

https://landscape.cncf.io/ https://jnaapti.com/downloads/visa-kubernetes.pdf

Containers from scratch

https://ericchiang.github.io/post/containers-from-scratch/ https://www.slideshare.net/jnaapti/building-your-own-desktop-cloud-environment

Install Docker

https://docs.docker.com/engine/install/ubuntu/

sudo apt-get update
sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \
    software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"
sudo apt-get install docker-ce docker-ce-cli containerd.io

# Verification
docker --version
# Version 19.03
systemctl status docker
# Ensure that the status is "active (running)"
# You may have to press q to quit

systemctl stop docker
systemctl start docker
systemctl restart docker

# dockerd - Server
# docker - Client

Add current user to Docker group

sudo usermod -aG docker $USER

Basic commands in Docker

docker ps
docker images

Docker Hub

https://hub.docker.com/ https://hub.docker.com/search?q=nginx&type=image https://hub.docker.com/_/nginx

Pull the nginx image

docker pull nginx
docker images

Running nginx

docker run nginx

In another terminal

docker ps

Make a note of the container name

ps aux | grep nginx

docker inspect <container-name>

Make a note of the container's IP address

curl 172.17.0.2

Go back to Terminal 1

Kill the process using Ctrl+C

docker run -d --name webserver1 -p 80:80 nginx
docker ps
ifconfig
ifconfig eth0

Go to your browser at this IP address and view the nginx page

<hostname>-80.cloudlab.jnaapti.io

# Stopping and starting process in the container
docker stop webserver1

# Run another container with the same image
docker run -d --name webserver2 -p 6080:80 nginx

# Create a container
docker container create <image name>
docker container create --name webserver1 nginx

# Getting help
docker container --help

# Getting logs
docker logs <container-name>
docker logs -f <container-name>

# Exec
docker exec webserver1 ls /
docker exec -it webserver1 /bin/bash
# Inside the container
echo "Hello" > /usr/share/nginx/html/index.html
^D

\

docker exec -it webserver1 /bin/bash
# Inside the container
echo "About" > /usr/share/nginx/html/about.html
rm /usr/share/nginx/html/50x.html
^D

# Commit the changes of the container webserver1 as mywebserver (image name)
docker commit webserver1 mywebserver

docker rm -f webserver2 # If webserver2 is present
docker run -d --name webserver2 mywebserver
docker inspect webserver2 | grep IP
curl <ip>

# Dockerfiles and docker build

mkdir -p ~/data/mywebserver
cd ~/data/mywebserver
cat > Dockerfile <<DELIM
FROM nginx

RUN echo "Hello" > /usr/share/nginx/html/index.html
RUN echo "About" > /usr/share/nginx/html/about.html
RUN rm /usr/share/nginx/html/50x.html
DELIM
docker build -t mywebserver .
docker images
docker image history mywebserver

# Nginx Dockerfile
https://github.com/nginxinc/docker-nginx/blob/9774b522d4661effea57a1fbf64c883e699ac3ec/mainline/buster/Dockerfile
https://github.com/debuerreotype/docker-debian-artifacts/blob/a05e37469763ce310295d7ed7529c36152bd6030/buster/slim/Dockerfile

# Networking
# Ping image
mkdir -p ~/data/ping
cd ~/data/ping
cat > Dockerfile <<DELIM
FROM ubuntu:18.04

RUN apt-get update \
 && apt-get -y install iputils-ping net-tools \
 && rm -rf /var/lib/apt/lists/*
DELIM

docker build -t ping .
docker images

# Remove existing containers
docker rm -f $(docker ps -aq)

# Let us now start 2 containers with this image
docker run -itd --name c1 ping
docker run -itd --name c2 ping
docker ps

# Ping from host to container
ping 172.17.0.2

# From container c1 to c2 and to host
docker exec -it c1 /bin/bash
# Inside the container
ping 172.17.0.3 # This is of c2
ping 172.17.0.1 # This is host
ping 8.8.8.8 # This is Internet
ping google.com # This is to show DNS resolution

docker rm -f $(docker ps -aq)

# Custom bridge network
docker network create mynet1
docker network ls
ifconfig
# Observe a network interface with the name starting with br-
docker run -itd --name c3 --net mynet1 ping
docker run -itd --name c4 --net mynet1 ping

docker inspect c3 | grep IP
docker inspect c4 | grep IP

https://docs.docker.com/network/network-tutorial-standalone/#use-user-defined-bridge-networks
https://blog.octo.com/en/how-does-it-work-docker-part-3-load-balancing-service-discovery-and-security/

# Creating a second interface
docker network create mynet2
docker network create --driver bridge --subnet 172.19.0.0/16 mynet2

docker run -itd --name c5 --net mynet2 ping
docker run -itd --name c6 --net mynet2 ping
docker network connect mynet1 c5

# Create a overlay network
docker network create --driver overlay overlay1

# Host network
docker run -it --name c7 --net host ping /bin/bash
# None network
docker run -it --name c8 --net none ping /bin/bash



# Storage, Volumes
docker rm -f $(docker ps -aq)

docker run --name webserver1 -d -v /data/webserver:/usr/share/nginx/html nginx
ls /data/webserver
curl <container-ip> # Gives 403

# Writing from host and reading inside the container
echo "Hello" > /data/webserver/index.html
# OR
echo "Hello" | sudo tee /data/webserver/index.html

curl <container-ip> # Gives the Hello page

docker exec -it webserver1 /bin/bash
# Inside the container
ls /usr/share/nginx/html/
cat /usr/share/nginx/html/index.html

# Write inside the container and read from host
echo "About" > /usr/share/nginx/html/about.html
^D

# Back in host
ls /data/webserver/

# Note that docker diff does not show these changes
docker diff webserver1

# Now remove the container
docker rm -f webserver1
# The files are still here
ls /data/webserver/
# Create a new container with the same volume mount
docker run --name webserver1 -d -v /data/webserver:/usr/share/nginx/html nginx
curl 172.17.0.2/about.html
curl 172.17.0.2

# End to End application
# Java + Spring Boot
https://github.com/buzypi/spring-jpa
# Spring Boot Application server with a MySQL database
# Images
# Database - standard mysql image - https://hub.docker.com/_/mysql
# Spring Boot Application - build your own image - Dockerfile
# Evaluate this image: https://hub.docker.com/_/maven - use jdk8 image
COPY source
RUN mvn clean install
CMD ["java", "-jar", "...jar"]

# Steps
cd ~/data
git clone https://github.com/buzypi/spring-jpa
cd spring-jpa

Dockerfile

FROM openjdk:8

RUN apt-get update && apt-get -y install git
RUN cd /tmp \
 && git clone https://github.com/buzypi/spring-jpa \
 && cd spring-jpa \
 && ./mvnw clean install \
 && mkdir -p /srv \
 && mv target/*.jar /srv

WORKDIR /srv

CMD ["java", "-jar", "demo-0.0.1-SNAPSHOT.jar"]

docker build -t myspringapp .

Python

https://github.com/buzypi/users-service https://github.com/buzypi/payments-service

Python Flask server with a MongoDB database

Golang

https://github.com/buzypi/users-service-go https://github.com/buzypi/payments-service-go

Mux + MongoDB

Kubernetes

Pre-req - Install Docker

Installation

https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
cat <<EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list
deb https://apt.kubernetes.io/ kubernetes-xenial main
EOF
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl

https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/

sudo su
kubeadm init --pod-network-cidr=10.244.0.0/16
^D
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

kubectl get nodes
kubectl describe nodes 


kubectl apply -f \
        https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

https://kubernetes.io/docs/concepts/cluster-administration/addons/#networking-and-network-policy

kubectl taint nodes $(hostname) node-role.kubernetes.io/master:NoSchedule-

# Verification
kubectl get nodes # Should say Status Ready
kubectl describe nodes | grep Taint # Should say <none>

# Uninstallation
# DO THIS ONLY IF YOUR KUBERNETES CLUSTER HAS ISSUES
kubedm reset
rm -rf /var/lib/etcd /etc/kubernetes

# Kubernetes basics
kubectl run --help
kubectl run nginx --image=nginx
# docker run --name nginx nginx
kubectl get pods
# docker ps
kubectl describe pods
# Make a note of the IP address
curl <pod-ip>
# Exec
kubectl exec -it nginx -- /bin/bash
# Inside the container
echo "Hello" > /usr/share/nginx/html/index.html
^D
# From outside the container
curl <pod-ip>
kubectl logs nginx
kubectl logs -f nginx

# Demonstration of failure handling
docker rm -f $(docker ps | grep "k8s_nginx" | awk '{print $1}')

# Delete the pod
kubectl delete pod nginx

# YAML to JSON
https://onlineyamltools.com/convert-yaml-to-json

name:
  first: John
  last: Doe
age: 10
present: true
emails:
  - value: john@example.com
    type: Personal
  - value: john@example.org
    type: Work
values:
  -
    - 10
    - 20
  - 
    - 30
    - 40

description: |-
  Line 1
  Line 2
---

# Pod as a declarative spec
mkdir -p ~/data
cd ~/data
cat > my-first-pod.yaml <<DELIM
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx
DELIM

kubectl delete pods --all
kubectl create -f my-first-pod.yaml
kubectl apply -f my-first-pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx:alpine

kubectl apply -f my-first-pod.yaml
kubectl get pods
docker ps | grep nginx

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx
---
apiVersion: v1
kind: Pod
metadata:
  name: nginx2
spec:
  containers:
  - name: nginx
    image: nginx

# Delete resources from the cluster - all resources mentioned in this file
kubectl delete -f my-first-pod.yaml


apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx
  - name: nginx2
    image: nginx

kubectl logs nginx -c nginx
kubectl logs nginx -c nginx2

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx
  - name: curl
    image: curlimages/curl
    stdin: true
    tty: true
    command: ["/bin/sh"]

kubectl apply -f my-first-pod.yaml
kubectl get pods -w

kubectl exec -it nginx -c curl -- /bin/sh
# Inside the container
ps aux
ip addr show
curl localhost
^D
# Outside the container
kubectl describe pods | grep IP

cd ~/data
cat > my-first-deployment.yaml <<DELIM
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx-app
  template:
    metadata:
      labels:
        app: nginx-app
    spec:
      containers:
      - name: nginx
        image: nginx
DELIM

kubectl delete -f my-first-pod.yaml
kubectl apply -f my-first-deployment.yaml

kubectl get deployments
kubectl get replicasets # rs
kubectl get pods

kubectl describe replicasets
# Look at the events
# Now take one of the pods from the Events and run this
kubectl describe pod <pod-name>

https://kubernetes.io/docs/concepts/overview/components/

kubectl describe deploy #deployment, deployments

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 5
  selector:
    matchLabels:
      app: nginx-app
  template:
    metadata:
      labels:
        app: nginx-app
    spec:
      containers:
      - name: nginx
        image: nginx:alpine

kubectl apply -f my-first-deployment.yaml 
kubectl get pods -w
kubectl describe pod <pod-name> # Use any one of the pods and check the image

kubectl describe deploy
kubectl get rs

kubectl get deployment nginx -o yaml
kubectl rollout undo deploy nginx --to-revision=1

# Getting MySQL to work
root@visa1:~# docker run --name db1 -e MYSQL_ROOT_PASSWORD=mysecretpassword -d mysql:8
Unable to find image 'mysql:8' locally
8: Pulling from library/mysql
d121f8d1c412: Already exists 
f3cebc0b4691: Pull complete 
1862755a0b37: Pull complete 
489b44f3dbb4: Pull complete 
690874f836db: Pull complete 
baa8be383ffb: Pull complete 
55356608b4ac: Pull complete 
dd35ceccb6eb: Pull complete 
429b35712b19: Pull complete 
162d8291095c: Pull complete 
5e500ef7181b: Pull complete 
af7528e958b6: Pull complete 
Digest: sha256:e1bfe11693ed2052cb3b4e5fa356c65381129e87e38551c6cd6ec532ebe0e808
Status: Downloaded newer image for mysql:8
44bbee905fb3a14b43a94bb40d2eacd790232d9e1a7bb556bf867efebcc91a32
root@visa1:~# docker ps | grep mysql
44bbee905fb3        mysql:8                "docker-entrypoint.s…"   21 seconds ago      Up 20 seconds       3306/tcp, 33060/tcp   db1
root@visa1:~# docker exec -it db1 mysql -uroot -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.21 MySQL Community Server - GPL

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> ^DBye
root@visa1:~# 
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment