In this post I will walk through all the steps of deploying a containerized web application and all the required resources to make it externally exposed.

  • Create a Namespace
    • Namespaces separate resources from another namespace.
  • Create a Secret
    • Secrets are like a key vault for the Namespace. It variables such as passwords that should not be in the deployment script.
  • Create a Deployment
    • Deployments create Pods, that are the instance(s) of the container application(s) running.
  • Create a Service
    • Services are what routes the traffic to the Deployments (like an internal load balancer).
  • Create a Ingress
    • Ingresses are what expose the service port externally (like opening a port on the firewall.

The files of this post can also be found in the public repository [Link].


NAMESPACES

nano namespace.yaml
kind: Namespace
apiVersion: v1
metadata:
  name: demo-namespace
  labels:
    name: demo-namespace
kubectl apply -f namespace.yaml
kubectl get ns

SECRETS

nano secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: demo-secret
  namespace: demo-namespace
stringData:
  SECRET_PASS: "stringPassword"
kubectl apply -f secret.yaml
kubectl get secret -n demo-namespace
kubectl describe secret demo-secret -n demo-namespace

DEPLOYMENTS

nano deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo-deployment
  namespace: demo-namespace
spec:
  replicas: 1
  selector:
    matchLabels:
      app: demo-deployment
  template:
    metadata:
      labels:
        app: demo-deployment
    spec:
      containers:
      - name: demo-deployment
        image: nginx:alpine
        ports:
        - containerPort: 80
        startupProbe:
          httpGet:
            path: /
            port: 80
          periodSeconds: 5
          failureThreshold: 20
        env:
        - name: USERNAME
          value: "stringUsername"
        - name: PASSWORD
          valueFrom:
            secretKeyRef:
              name: demo-secret
              key: SECRET_PASS
kubectl apply -f deployment.yaml
kubectl get pods -n demo-namespace
kubectl get pods -n demo-namespace -o wide
kubectl logs -n demo-namespace demo-deployment-********* 
kubectl exec -it demo-deployment-*********-***** -n demo-namespace -- /bin/sh
kubectl get replicaset -n demo-namespace

 SERVICE

nano service.yaml
apiVersion: v1
kind: Service
metadata:
  name: demo-service
  namespace: demo-namespace
spec:
  type: ClusterIP
  ports:
  - port: 80
  selector:
    app: demo-deployment
kubectl apply -f service.yaml
kubectl get svc -n demo-namespace
kubectl describe svc demo-service -n demo-namespace

Now you can test if the service can be reachable from inside the server:

curl http://10.1.1.1:80/

Note: replace 10.1.1.1 with the IP address assigned to the service.

If it works, enter the following command to access it with a browser from outside the server:

kubectl port-forward service/demo-service 80:80 --address='0.0.0.0' -n demo-namespace

INGRESSES

The Ingress requires an Ingress Controller to the installed on the server. It comes out of the box for Minikube.

minikube addons enable ingress

If necessary, check the following list of options and how to install the controller at [Link].

nano ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: demo-ingress
  namespace: demo-namespace
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: "/"
spec:
  ingressClassName: nginx
  rules:
  - host: nginx.local
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: demo-service
            port:
              number: 80
kubectl apply -f ingress.yaml
kubectl get ing -n demo-namespace
kubectl get ing -n demo-namespace --watch
kubectl describe ing demo-ingress -n demo-namespace

Note: the ingress resources will take few seconds to acquire an external IP.


CHECK THE ENVIRONMENT VARIABLES

kubectl get pods -n demo-namespace
kubectl exec -it demo-deployment-**********-***** -n demo-namespace -- bash

OR

kubectl exec --stdin --tty demo-deployment-**********-***** -n demo-namespace -- bash
root@demo-deployment-**********-*****:/# echo $PASSWORD
stringPassword
root@demo-deployment-**********-*****:/# echo $USERNAME
stringUsername

Or change the web page to show the variables:

kubectl exec --stdin --tty demo-deployment-**********-***** -n demo-namespace -- bash -c "echo \$USERNAME : \$PASSWORD > /usr/share/nginx/html/index.html"

SEE ALSO

K3s on Ubuntu 20.04 [Link].

Minikube on Ubuntu 22.04 [Link].

MicroK8s on Ubuntu 22.04 [Link].

Kubernetes Cheat Sheet [Link].

Kubernetes Persistent Volumes [Link].

Kubernetes Dashboard [Link].