CCP2 CNA Kubernets LAB

Page content

12 factor Applications LAB

Overview

  • Cloud-Native application is an application optimized for running in the cloud (IaaS or PaaS)
  • Each phase in the application life-cycle has to be adopted and optimized to run in the cloud
  • typically desigened as a distributed application

LAB

Used Applications

  • K3S: a lightweigt Kubernetes designed to run on low-ressource systems
    fully CNCF-certified
  • K3D: a wrapper to run K3s in Docker
    makes it easy to run single- and multi-node k3s clusters i.e. for local development of kubernetes

Commands

Command Description
k3d cluster delete --all delete all running clusters
k3d cluster create --config ./lab-setup/k3d-ccp2-config.yaml create new cluster with config file
kubectl cluster-info check status of cluster
kubect create namespace ccp2-lab using a non default namespace to deploy the application
kubectl -n ccp2-lab get all -n tell kubectl which namespace to use
./gradlew assemble compile and package the spring boot application
docker-build.sh script to create docker images (see scripts section
docker push registry.localhost:5000/ccp2-postgres:latest push image to local registry
docker push registry.localhost:5000/ccp2-order:1 same
kubectl apply -f postgres.yaml apply deployment
kubectl create secret generic postgres-secret
--from-literal=postgres-user=ccp2DbUser
--from-literal=postgres-password=newFancyPassword
create secret with db credentials
kubectl get secret postgres-secret -o yaml show created secret
kubectl describe pod/postgres-7bfd5c7d7b-8f5wn get debug info on a pod

Task3 externalizing config

using secrets

kubectl create secret generic postgres-secret
--from-literal=postgres-user=ccp2DbUser
--from-literal=postgres-password=newFancyPassword

Modifications to postgres.yaml


env:
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
key: postgres-user
name: postgres-secret
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
key: postgres-password
name: postgres-secret

Modifications to microservices.yaml

spec:
containers:
- name: order
image: registry.localhost:5000/ccp2-order:1
imagePullPolicy: Always
ports:
- containerPort: 8080
resources: {}
env:
- name: SPRING_DATASOURCE_USERNAME
valueFrom:
secretKeyRef:
key: postgres-user
name: postgres-secret
- name: SPRING_DATASOURCE_PASSWORD
valueFrom:
secretKeyRef:
key: postgres-password
name: postgres-secret

using config maps

used when config contains no critical info like passwords and doesn’t need to be obfuscated

create config map

kubectl create configmap pg-init-user-db
--from-file=postgres/init-user-db.sh

changes to deployment manifest

spec:
  containers:
  - name: postgres
    image: postgres:14.0
    imagePullPolicy: IfNotPresent

And add the following volumeMounts and volumes to the container section:

  volumeMounts:
  - name: postgres
    mountPath: /var/lib/postgresql/data
  - name: init-user-db
    mountPath: /docker-entrypoint-initdb.d
  volumes:
  - name: postgres
    emptyDir: {}
  - name: init-user-db
    configMap:
    name: pg-init-user-db

once config map and secrets are created and yaml files update restart the postgres pod by chaning replicas to 0 and back to 1

kubectl scale --replicas=0 deployment.apps/postgres deploy/order
kubectl scale --replicas=1 deployment.apps/postgres deploy/order

Files

microservices.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: order
    version: "1.0"
  name: order
spec:
  replicas: 1
  selector:
    matchLabels:
      app: order
  strategy: {}
  template:
    metadata:
      labels:
        app: order
    spec:
      containers:
      - name: order
        image: registry.localhost:5000/ccp2-order:1
        imagePullPolicy: Always
        ports:
        - containerPort: 8080
        resources: {}
        env:
          - name: SPRING_DATASOURCE_USERNAME
            valueFrom:
              secretKeyRef:
                key: postgres-user
                name: postgres-secret
          - name: SPRING_DATASOURCE_PASSWORD
            valueFrom:
              secretKeyRef:
                key: postgres-password
                name: postgres-secret

---

apiVersion: v1
kind: Service
metadata:
  labels:
    app: order
  name: order
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 8080
    name: http
  selector:
    app: order
  type: ClusterIP

---

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: order
  labels:
    name: order
spec:
  rules:
  - host: order.160.85.253.63.nip.io
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: order
            port:
              number: 80

postgres.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: postgres
    version: "1.0"
  name: postgres
spec:
  replicas: 1
  selector:
    matchLabels:
      app: postgres
  strategy: {}
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
      - name: postgres
        image: postgres:14.0
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 5432
        env:
        - name: POSTGRES_USER
          valueFrom:
            secretKeyRef:
              key: postgres-user
              name: postgres-secret
        - name: POSTGRES_PASSWORD
          valueFrom:
            secretKeyRef:
              key: postgres-password
              name: postgres-secret
        resources: {}
        volumeMounts:
        - name: postgres
          mountPath: /var/lib/postgresql/data
        - name: init-user-db
          mountPath: /docker-entrypoint-initdb.d
      volumes:
      - name: postgres
        emptyDir: {}
      - name: init-user-db
        configMap:
          name: pg-init-user-db
status: {}

---

apiVersion: v1
kind: Service
metadata:
  labels:
    app: postgres
  name: postgres
spec:
  ports:
  - port: 5432
    protocol: TCP
    targetPort: 5432
  selector:
    app: postgres
  type: NodePort
status:
  loadBalancer: {}

k3d config

apiVersion: k3d.io/v1alpha4
kind: Simple
metadata:
  name: ccp2
servers: 1
agents: 2
image: docker.io/rancher/k3s:v1.22.6-k3s1
kubeAPI:
  host: api.160.85.253.63.nip.io
  hostIP: "0.0.0.0"
  hostPort: "6443"
ports:
  - port: 0.0.0.0:80:80 # same as `--port '8080:80@loadbalancer'`
    nodeFilters:
      - loadbalancer
  - port: 0.0.0.0:443:443 # same as `--port '8443:443@loadbalancer'`
    nodeFilters:
      - loadbalancer
  - port: 127.0.0.1:9000:9000 # traefik dashboard only local
    nodeFilters:
      - loadbalancer
volumes: # map directory for local-path-provisioner
  - volume: $HOME/storage:/var/lib/rancher/k3s/storage
    nodeFilters:
    - all
registries:
  create: # creates a default registry to be used with the cluster; same as `--r
egistry-create registry.localhost`
    name: registry.localhost
    host: "0.0.0.0"
    hostPort: "5000"
options:
  k3d:
    wait: true                   # wait for cluster to be usable before returini
ng; same as `--wait` (default: true)
    timeout: "60s"               # wait timeout before aborting; same as `--time out 60s`
    disableLoadbalancer: false   # same as `--no-lb`
    disableImageVolume: false    # same as `--no-image-volume`
    disableRollback: false       # same as `--no-Rollback`
  k3s:
    extraArgs:
      - arg: --tls-san=api.160.85.253.63.nip.io
        nodeFilters:
          - server:*
      - arg: --node-taint=CriticalAddonsOnly=true:NoExecute # set server nodes t o not run pods
        nodeFilters:
          - server:*

docker-build.sh

#!/bin/sh
docker build --tag=ccp2-postgres postgres
docker tag ccp2-postgres registry.localhost:5000/ccp2-postgres

docker build --tag=ccp2-order:1 microservice-order
docker tag ccp2-order:1 registry.localhost:5000/ccp2-order:1