RPI K8S Starting...
I have a fresh cluster installed and i will start with a simple deployment of static website.
Docker Image
For our Website, we will use Nginx for arm32 architecture.
FROM nginx
EXPOSE 80
COPY _site/ /usr/share/nginx/html
Just copy static website source code with index file to "_site" directory in Docker context and just build image, tag then push it to "docker.io" registry. It will be available to our cluster.
docker build . -t {{yourrepository}}/home
docker tag {{yourrepository}}/home:latest {{yourrepository}}/home:arm
docker push {{yourrepository}}/home:arm
We must be logged to Docker hub registry before pushing newly image and replacing {{yourrepository}} by our Docker Hub username.
Kubernetes deployment
After prepared image, it's time to deploy it.
Namespace
apiVersion: v1
kind: Namespace
metadata:
name: front
Create a simple namespace to be a scope for our project.
SSL Secret
apiVersion: v1
kind: Secret
metadata:
name: home-tls
namespace: front
type: Opaque
data:
tls.crt: {{crt}}
tls.key: {{key}}
type: kubernetes.io/tls
To have a HTTPS access to our website, we need to get SSL certificate and it's easy and free with letsencrypt.org by just installing CertBot in any node of your cluster and use it to generate certificate for your domain.
You can use "TXT Record" identification method for certificate generation: CertBot give you a string token and you must add it to your DNS configuration of your domain as "TXT Record" to continue generation.
After, you must replace {{crt}} by fullchain and not just cert.pem certificate encoded base64, like {{key}} who is must be replace by the private key encoded also.
# private key
cat privkey.pem | base64
# fullchain certificate
cat fullchain.pem | base64
Deployment & Service
apiVersion: apps/v1
kind: Deployment
metadata:
name: home
namespace: front
labels:
app: home
spec:
replicas: 1
selector:
matchLabels:
app: home
template:
metadata:
labels:
app: home
spec:
containers:
- name: home
image: medinvention/home:arm
imagePullPolicy: Always
ports:
- containerPort: 80
For our deployment, we define one container for built image and export one port 80 for web access. We defined a label selector "app: home" to bind pod to service and create a HTTP end point to access pod service from outside of cluster.
apiVersion: v1
kind: Service
metadata:
name: home-service
namespace: front
spec:
ports:
- name: http
port: 80
targetPort: 80
selector:
app: home
With this way, we have bound "home-servcice" to HTTP port of container inside pod deployed. "Kube" use match label configuration to make association between service and pod and define end point.
Ingress
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
name: home
namespace: front
labels:
app: home
spec:
rules:
- host: {{host}}
http:
paths:
- backend:
serviceName: home-service
servicePort: http
path: /
tls:
- hosts:
- {{host}}
secretName: home-tls
To make our service accessible from outside of cluster, we define an "Ingress" object to publish home service using Nginx Load Balancer. Change {{host}} by your host and apply it.
If you check the Load Balancer service, you will find dedicated ports like "80:31782/TCP,443:31179/TCP". You must configure your internet router (or box) to NAT 443 external port to 31179 port of master node.