diff --git a/.gitignore b/.gitignore
index 1742f88..2777ada 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,3 +13,4 @@ kubernetes/shipa/installs/shipa-helm-chart-1.1.1/
messaging/kafka/data/*
kubernetes/portainer/volume*
kubernetes/rancher/volume/*
+kubernetes/portainer/business/volume*
diff --git a/README.md b/README.md
index 7e0d3f5..c1abbf7 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@ The Ultimate Swiss Army knife for DevOps, Developers and Platform Engineers
| Steps | Playlist :tv: | Source :octocat: |
|---|---|---|
-| Learn Kubernetes :snowflake: |
| [source](./kubernetes/readme.md) |
+| [Learn Kubernetes](./kubernetes/README.md) :snowflake: |
| [source](./kubernetes/readme.md) |
| Learn about CI/CD tools :whale: |
| | | |
| Deploy Kubernetes to the cloud :partly_sunny: |
| [source](./kubernetes/cloud/readme.md) |
| Monitoring Kubernetes :mag: |
| [source](./monitoring/prometheus/kubernetes/readme.md) |
diff --git a/kubernetes/readme.md b/kubernetes/readme.md
index ec223a0..6f2a68e 100644
--- a/kubernetes/readme.md
+++ b/kubernetes/readme.md
@@ -1,4 +1,4 @@
-# Kubernetes Development Series
:hammer::wrench:
+# Learn Kubernetes
:hammer::wrench:
## Full playlist
diff --git a/kubernetes/tutorials/basics/README.md b/kubernetes/tutorials/basics/README.md
new file mode 100644
index 0000000..0d3797f
--- /dev/null
+++ b/kubernetes/tutorials/basics/README.md
@@ -0,0 +1,260 @@
+# Kubernetes Tutorial: The Basics
+
+This guide is aimed to fast-track your Kubernetes learning by focusing on a practical hands-on overview guide.
+
+When learning Kubernetes, you usually have an idea of some existing system you own and manage, or a website that you are building.
+
+The challenge is understanding which Kubernetes building blocks you need in order to run your workloads on Kubernetes
+
+
+The problem: "I want to adopt Kubernetes"
+The problem: "I have some common existing infrastructure"
+
+
+Our focus: Solving the problem by learning each building block
+in order to port our infrastructure to Kubernetes.
+
+## Understanding Containers
+
+Before even looking at Kubernetes, you need to have a general understanding of containers like `docker`.
+Your workloads need to fit in containers in order to be shipped on Kubernetes.
+Containers also have a bunch of assumptions that you need to meet.
+
+* Defining the container - `Dockerfile`
+* Serving traffic - Exposing ports
+* Configuration - mount config files & secrets or `env` variables
+* Data persistence - When a container is terminated, everything inside the container is gone
+* Container entrypoint - The main process that runs in the container. Your app
+
+
+### Docker installation
+
+* Install Docker [here](https://docs.docker.com/get-docker/)
+* Let's take a look at [Wordpress on Docker Hub](https://hub.docker.com/_/wordpress)
+* Build our docker file
+
+## Create Network
+
+```
+docker network create wordpress
+```
+
+## Build & Test container images
+
+ ### Wordpress example
+```
+cd kubernetes\tutorials\basics\
+
+docker build -f dockerfiles/wordpress.dockerfile . -t aimvector/wordpress-example
+
+```
+
+* Run our Wordpress container
+
+```
+docker run -it --rm -p 80:80 --net wordpress aimvector/wordpress-example
+```
+
+The wordpress container will be visible on port 80 on `http://localhost/`
+
+### MySQL example
+
+* We need a database, let's take a look at [MySQL on Docker Hub](https://hub.docker.com/_/mysql)
+* Build our MySQl container image
+
+```
+docker build -f dockerfiles/mysql.dockerfile . -t aimvector/mysql-example
+```
+
+* How do we run our MySQL ?
+
+We need to understand that databases require storage and state
+Just like installing software on a server, it will store its files in some
+directory. Mysql stores its files under `/var/lib/mysql`
+
+* We need a volume mount
+
+Let's see how to run this in docker
+
+```
+mkdir data
+
+docker run --rm -d `
+--name mysql `
+--net wordpress `
+-e MYSQL_DATABASE=exampledb `
+-e MYSQL_USER=exampleuser `
+-e MYSQL_PASSWORD=examplepassword `
+-e MYSQL_RANDOM_ROOT_PASSWORD=1 `
+-v ${PWD}/data:/var/lib/mysql `
+aimvector/mysql-example
+
+# we can see the container with
+docker ps
+CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
+92cde663a3f5 aimvector/mysql-example "docker-entrypoint.s…" 5 seconds ago Up 3 seconds 3306/tcp, 33060/tcp mysql
+
+```
+
+* Run Wordpress and connect it to MySQL
+
+```
+docker run -d `
+--rm `
+-p 80:80 `
+--name wordpress `
+--net wordpress `
+-e WORDPRESS_DB_HOST=mysql `
+-e WORDPRESS_DB_USER=exampleuser `
+-e WORDPRESS_DB_PASSWORD=examplepassword `
+-e WORDPRESS_DB_NAME=exampledb `
+aimvector/wordpress-example
+```
+
+### Clean up
+
+```
+docker rm -f wordpress
+docker rm -f mysql
+docker network rm wordpress
+rm data
+```
+
+## Kubernetes Tools: kubectl
+
+To manage and work with Kubernetes, you need `kubectl`
+Let's grab that from [here](https://kubernetes.io/docs/tasks/tools/)
+
+
+## Run Kubernetes Locally
+
+* Install `kubectl` to work with kubernetes
+
+We'll head over to the [kubernetes](https://kubernetes.io/docs/tasks/tools/) site to download `kubectl`
+
+* Install the `kind` binary
+
+You will want to head over to the [kind](https://kind.sigs.k8s.io/) site
+
+* Create a cluster
+
+```
+kind create cluster --image kindest/node:v1.23.5
+```
+
+## Namespaces
+
+```
+kubectl create namespace cms
+```
+
+## Configmaps
+
+[Environment Variables](https://kubernetes.io/docs/tasks/inject-data-application/define-environment-variable-container/) for pods
+
+[How to use](https://kubernetes.io/docs/concepts/configuration/configmap/) configmaps
+
+```
+kubectl -n cms create configmap mysql `
+--from-literal MYSQL_RANDOM_ROOT_PASSWORD=1
+
+kubectl -n cms get configmaps
+```
+
+## Secrets
+
+[How to use](https://kubernetes.io/docs/concepts/configuration/secret/) secrets in pods
+
+```
+kubectl -n cms create secret generic wordpress `
+--from-literal WORDPRESS_DB_HOST=mysql `
+--from-literal WORDPRESS_DB_USER=exampleuser `
+--from-literal WORDPRESS_DB_PASSWORD=examplepassword `
+--from-literal WORDPRESS_DB_NAME=exampledb
+
+kubectl -n cms create secret generic mysql `
+--from-literal MYSQL_USER=exampleuser `
+--from-literal MYSQL_PASSWORD=examplepassword `
+--from-literal MYSQL_DATABASE=exampledb
+
+
+kubectl -n cms get secret
+
+```
+
+## Deployments
+
+* Deployment [documentation](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/)
+
+cd kubernetes\tutorials\basics
+
+```
+kubectl -n cms apply -f yaml/deploy.yaml
+kubectl -n cms get pods
+```
+
+# Services
+
+Services [documentation](https://kubernetes.io/docs/concepts/services-networking/service/)
+
+```
+kubectl -n cms apply -f .\yaml\service.yaml
+kubectl -n cms get svc
+```
+
+# Storage Class
+
+StorageClass [documentation](https://kubernetes.io/docs/concepts/storage/storage-classes/)
+
+```
+kubectl get storageclass
+```
+
+# Statefulset
+
+Statefulset [documentation](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/)
+
+Let's deploy our `mysql` using what we learnt above:
+
+```
+kubectl -n cms apply -f yaml/statefulset.yaml
+
+kubectl -n cms get pods
+```
+
+## Persistent Volumes
+
+[Documentation](https://kubernetes.io/docs/concepts/storage/persistent-volumes/)
+
+## Port Forwarding
+
+We can access private service endpoints or pods using `port-forward` :
+
+```
+kubectl -n cms get pods
+kubectl -n cms port-forward 80
+```
+
+## Public Traffic
+
+In order to make our site public, its common practise to expose web servers via
+a proxy or API gateway.
+In Kubernetes, an Ingress is used.
+
+## Ingress
+
+To use an ingress, we need an ingress controller
+
+```
+kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.3/deploy/static/provider/cloud/deploy.yaml
+
+kubectl -n ingress-nginx get pods
+
+kubectl -n ingress-nginx --address 0.0.0.0 port-forward svc/ingress-nginx-controller 80
+```
+
+Create an Ingress
+
+```
+kubectl -n cms apply -f yaml/ingress.yaml
+```
diff --git a/kubernetes/tutorials/basics/dockerfiles/mysql.dockerfile b/kubernetes/tutorials/basics/dockerfiles/mysql.dockerfile
new file mode 100644
index 0000000..53d0d5d
--- /dev/null
+++ b/kubernetes/tutorials/basics/dockerfiles/mysql.dockerfile
@@ -0,0 +1,5 @@
+FROM mysql:5.7
+
+# make any changes to MySQL installation
+
+EXPOSE 3306
\ No newline at end of file
diff --git a/kubernetes/tutorials/basics/dockerfiles/wordpress.dockerfile b/kubernetes/tutorials/basics/dockerfiles/wordpress.dockerfile
new file mode 100644
index 0000000..42accc8
--- /dev/null
+++ b/kubernetes/tutorials/basics/dockerfiles/wordpress.dockerfile
@@ -0,0 +1,5 @@
+FROM wordpress:5.9-apache
+
+#COPY files , plugins, install extra stuff
+
+EXPOSE 80
\ No newline at end of file
diff --git a/kubernetes/tutorials/basics/yaml/deploy.yaml b/kubernetes/tutorials/basics/yaml/deploy.yaml
new file mode 100644
index 0000000..121fefe
--- /dev/null
+++ b/kubernetes/tutorials/basics/yaml/deploy.yaml
@@ -0,0 +1,42 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: wordpress-deployment
+ labels:
+ app: wordpress
+spec:
+ replicas: 2
+ selector:
+ matchLabels:
+ app: wordpress
+ template:
+ metadata:
+ labels:
+ app: wordpress
+ spec:
+ containers:
+ - name: wordpress
+ image: aimvector/wordpress-example
+ ports:
+ - containerPort: 80
+ env:
+ - name: WORDPRESS_DB_HOST
+ valueFrom:
+ secretKeyRef:
+ name: wordpress
+ key: WORDPRESS_DB_HOST
+ - name: WORDPRESS_DB_USER
+ valueFrom:
+ secretKeyRef:
+ name: wordpress
+ key: WORDPRESS_DB_USER
+ - name: WORDPRESS_DB_PASSWORD
+ valueFrom:
+ secretKeyRef:
+ name: wordpress
+ key: WORDPRESS_DB_PASSWORD
+ - name: WORDPRESS_DB_NAME
+ valueFrom:
+ secretKeyRef:
+ name: wordpress
+ key: WORDPRESS_DB_NAME
\ No newline at end of file
diff --git a/kubernetes/tutorials/basics/yaml/ingress.yaml b/kubernetes/tutorials/basics/yaml/ingress.yaml
new file mode 100644
index 0000000..77ccdc0
--- /dev/null
+++ b/kubernetes/tutorials/basics/yaml/ingress.yaml
@@ -0,0 +1,18 @@
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+ name: wordpress
+ annotations:
+ nginx.ingress.kubernetes.io/rewrite-target: /
+spec:
+ ingressClassName: nginx
+ rules:
+ - http:
+ paths:
+ - path: /
+ pathType: Prefix
+ backend:
+ service:
+ name: wordpress
+ port:
+ number: 80
diff --git a/kubernetes/tutorials/basics/yaml/service.yaml b/kubernetes/tutorials/basics/yaml/service.yaml
new file mode 100644
index 0000000..87112d9
--- /dev/null
+++ b/kubernetes/tutorials/basics/yaml/service.yaml
@@ -0,0 +1,14 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: wordpress
+ labels:
+ app: wordpress
+spec:
+ ports:
+ - port: 80
+ name: wordpress
+ targetPort: 80
+ type: ClusterIP
+ selector:
+ app: wordpress
\ No newline at end of file
diff --git a/kubernetes/tutorials/basics/yaml/statefulset.yaml b/kubernetes/tutorials/basics/yaml/statefulset.yaml
new file mode 100644
index 0000000..c377d64
--- /dev/null
+++ b/kubernetes/tutorials/basics/yaml/statefulset.yaml
@@ -0,0 +1,69 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: mysql
+ labels:
+ app: mysql
+spec:
+ ports:
+ - port: 3306
+ name: db
+ type: ClusterIP
+ selector:
+ app: mysql
+---
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+ name: mysql
+spec:
+ selector:
+ matchLabels:
+ app: mysql # has to match .spec.template.metadata.labels
+ serviceName: "mysql"
+ replicas: 1
+ template:
+ metadata:
+ labels:
+ app: mysql # has to match .spec.selector.matchLabels
+ spec:
+ terminationGracePeriodSeconds: 10
+ containers:
+ - name: mysql
+ image: aimvector/mysql-example
+ ports:
+ - containerPort: 3306
+ name: db
+ env:
+ - name: MYSQL_DATABASE
+ valueFrom:
+ secretKeyRef:
+ name: mysql
+ key: MYSQL_DATABASE
+ - name: MYSQL_USER
+ valueFrom:
+ secretKeyRef:
+ name: mysql
+ key: MYSQL_USER
+ - name: MYSQL_PASSWORD
+ valueFrom:
+ secretKeyRef:
+ name: mysql
+ key: MYSQL_PASSWORD
+ - name: MYSQL_RANDOM_ROOT_PASSWORD
+ valueFrom:
+ configMapKeyRef:
+ name: mysql
+ key: MYSQL_RANDOM_ROOT_PASSWORD
+ volumeMounts:
+ - name: db
+ mountPath: /var/lib/mysql
+ volumeClaimTemplates:
+ - metadata:
+ name: db
+ spec:
+ accessModes: [ "ReadWriteOnce" ]
+ storageClassName: "standard"
+ resources:
+ requests:
+ storage: 500Mi
\ No newline at end of file