5 - Create complex pods
In previous chapters we deployed an app with the nginx default page. Before deploying more complex images we will start by adding volumes to change that default into somthing ours.
Static websites
For static websites (or even static html served through a flask app that handles login and session through cookies) 1 replica should be enough as it avoids some issues with volumes being read twice at the same time.
We will for these work with volumes but the volumes can’t be just a routing since we don’t know which node will be running the pod (so we don’t know which server to keep the files on). For this we will use a server with nfs to store our files, in this case we’ll use the control pane for this. Just run the following in the control pane server:
apt install nfs-kernel-server
echo "/home/gitlabci/websites *(ro,no_subtree_check)" >> /etc/exports
exportfs -aand on the nodes:
apt install -y nfs-common
which mount.nfsFor the my-app deployement we will add some information:
# /home/gitlabci/conf/websites/my-app.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: my-app-pv
spec:
capacity:
storage: 1Gi
accessModes:
- ReadOnlyMany
nfs:
server: stivm0052 # or its IP
path: /home/gitlabci/websites/my-app
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-app-pvc
namespace: default
spec:
accessModes:
- ReadOnlyMany
resources:
requests:
storage: 1Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: default
spec:
replicas: 1 #changed to 1 for avoiding reading concurrency problems
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: nginx:alpine
ports:
- containerPort: 80
volumeMounts: # add volume mounts
- name: website
mountPath: /usr/share/nginx/html
volumes: # add volume declaration
- name: website
persistentVolumeClaim:
claimName: my-app-pvc
---
apiVersion: v1
kind: Service
metadata:
name: my-app-svc
namespace: default
spec:
selector:
app: my-app
ports:
- port: 80
targetPort: 80
type: ClusterIP kubectl apply -f /home/gitlabci/conf/websites/my-app.yaml- Added the volumes and volumemounts in the app spec.
- Added PersistentVolume and PersistentVolumeClaim
- The first is the cluster wide decalration of the storage the claim sits in between the storage and the pod
- These layers exist because k8s was designed so the volumes can be declared once and the development teams can call them without knowing the exact path
Now lets add another pod so we can work with routing in the next step:
Show YAML
# /home/gitlabci/conf/websites/pinchsmall.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pinchsmall-pv
spec:
capacity:
storage: 1Gi
accessModes:
- ReadOnlyMany
nfs:
server: stivm0052 # or its IP
path: /home/gitlabci/websites/pinchsmall
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pinchsmall-pvc
namespace: default
spec:
accessModes:
- ReadOnlyMany
resources:
requests:
storage: 1Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: pinchsmall
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: pinchsmall
template:
metadata:
labels:
app: pinchsmall
spec:
containers:
- name: pinchsmall
image: nginx:alpine
ports:
- containerPort: 80
volumeMounts:
- name: website
mountPath: /usr/share/nginx/html
volumes:
- name: website
persistentVolumeClaim:
claimName: pinchsmall-pvc
---
apiVersion: v1
kind: Service
metadata:
name: pinchsmall-svc
namespace: default
spec:
selector:
app: pinchsmall
ports:
- port: 80
targetPort: 80
type: ClusterIPkubectl apply -f /home/gitlabci/conf/websites/pinchsmall.yamlAnd upgrade the ingress for our domain with the first website in /test/ and the pinchsmall website at root path:
# /home/gitlabci/conf/ingress/ipese-test.yaml
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: strip-test
namespace: default
spec:
stripPrefix:
prefixes:
- /test
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ipese-test
namespace: default
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.middlewares: default-strip-test@kubernetescrd
spec:
ingressClassName: traefik
tls:
- hosts:
- ipese-test.epfl.ch
secretName: myapp-tls
rules:
- host: ipese-test.epfl.ch
http:
paths:
- path: /test
pathType: Prefix
backend:
service:
name: my-app-svc
port:
number: 80
- path: /
pathType: Prefix
backend:
service:
name: pinchsmall-svc
port:
number: 80kubectl apply -f /home/gitlabci/conf/ingress/ipese-test.yamlCheck status of your kube
$ root@stivm0052:/home/gitlabci/conf/ingress# kubectl get all
NAME READY STATUS RESTARTS AGE
pod/my-app-5fb5c4bb54-z9kfh 1/1 Running 0 2m55s
pod/pinchsmall-6bf6c55b9c-pl4bp 1/1 Running 0 16m
pod/test-ping 0/1 Completed 0 49d
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 53d
service/my-app-svc ClusterIP 10.111.163.238 <none> 80/TCP 2m55s
service/pinchsmall-svc ClusterIP 10.103.131.201 <none> 80/TCP 16m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/my-app 1/1 1 1 2m55s
deployment.apps/pinchsmall 1/1 1 1 16m
NAME DESIRED CURRENT READY AGE
replicaset.apps/my-app-5fb5c4bb54 1 1 1 2m55s
replicaset.apps/pinchsmall-6bf6c55b9c 1 1 1 16m
$ root@stivm0052:/home/gitlabci/conf/ingress# kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
ipese-test traefik ipese-test.epfl.ch 10.95.35.4 80, 443 5m11sHere we can see:
- 2 pods both 1/1 Running — my-app and pinchsmall are up
- 2 services routing internal traffic to each pod
- 2 deployments each managing their replica as expected
- 1 ingress ipese-test handling both /test and / on ipese-test.epfl.ch
- test-ping is just an old completed job, harmless but can be erased with
kubectl delete pod test-ping
Current configuration:
/conf
├── certs
│ ├── ipese-test.epfl.ch.crt
│ └── ipese-test.epfl.ch.key
├── ingress
│ └── ipese-test.yaml # path descriptions (traefic routes/locations)
├── traefik
│ └── values.yaml # ~traefik config - open ports and deployed in which servers as deamonset
└── websites # deployment and service definition for each app
├── my-app.yaml
└── pinchsmall.yamland /website availavle through nfs to all the servers
Deploy image other than nginx
To start we’ll deploy a static website deployed over flask to support authentication through an auth-server. (docker image built for work purposes withihn EPFL).
For this we’ll need environment variables, pulling a new container from a private docker registry and make sure the connection to another tool works properly.
- Create the folder with the static files
mkdir /home/gitlabci/websites/secure && nano /home/gitlabci/websites/secure/index.html
- create your deployment and service
nano /home/gitlabci/conf/websites/secure.yaml
asdfsf- add your new route to your ingress