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 accessible.

  • Create a Namespace
    • Namespaces isolate resources from other namespaces.
  • Create a Secret
    • Secrets act as a key vault for the Namespace. They store variables such as passwords that should not be hardcoded in the deployment script.
  • Create a Deployment
    • Deployments create Pods, which are the running instance(s) of the container application(s).
  • Create a Service
    • Services route traffic to Deployments (similar to an internal load balancer).
  • Create an Ingress
    • Ingresses expose the service port externally (similar to opening a port on a firewall).

The files for 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 is 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, run the following command to access it from a browser 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 be installed on the server. It comes out of the box with Minikube.

minikube addons enable ingress

If needed, see the following list of options and installation instructions 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 resource will take a 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 update the web page to display 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].