Home

The Microservices

A Brief review of the microservices "architecture" here:

control plane (cp) node
redis-caching
postgres-data
results-app
voting-app
worker

  • A Voting App: A frontend app with an api + a frontend, where users can login and vote 1 of 2 options (simple webapp here)
  • A redis datastore
  • A postgres DB
  • A "worker" service that syncs data from the redis service to the postgres service
  • A Voting-Results App: Another frontend that show vote tallies, mocking an "analytics" frontend

Each service will get a pod.

Definition File Directory Structure

# all configs go in a "cfgs" dir
/cfgs
  # config "types" get broken into sub-directories
  /pods
    pg.yaml           # postgres
    redis.yaml        # redis
    results-app.yaml  # web-app
    voting-app.yaml   # web-app
    worker.yaml       # db-syncing
  /services
    redis.yaml        # internal service
    pg.yaml           # internal service

The Definition Files

Note: the externalIps key/val pair are to publicize the nodes through docker - some detail I'm not 1000% sure about...

Pods

Postgres:

apiVersion: v1
kind: Pod
metadata:
  name: pg-pod
  labels:
    name: pg-pod
    app: demo-voting-app
spec:
  containers:
    - name: pg-box
      image: postgres:9.4
      ports:
        # default
        - containerPort: 5432
      # hard-coded for p.o.c here
      # these are hard-coded in other pod code
      env:
        - name: POSTGRES_USER
          value: "postgres"
        - name: POSTGRES_PASSWORD
          value: "postgres"

redis:

apiVersion: v1
kind: Pod
metadata:
  name: redis-pod
  labels:
    name: redis-pod
    app: demo-voting-app
spec:
  containers:
    # hard-coded per service codebase
    - name: redis
      image: redis
      ports:
        # default
        - containerPort: 6379

results App:

apiVersion: v1
kind: Pod
metadata:
  name: result-app-pod
  labels:
    name: result-app-pod
    app: demo-voting-app
spec:
  containers:
    - name: result-app-box
      image: kodekloud/examplevotingapp_result:v1
      ports:
        # app listens on port 80
        - containerPort: 80

voting app:

apiVersion: v1
kind: Pod
metadata:
  name: voting-app-pod
  labels:
    name: voting-app-pod
    app: demo-voting-app
spec:
  containers:
    - name: voting-app-box
      image: kodekloud/examplevotingapp_vote:v1
      ports:
        # app listens on port 80
        - containerPort: 80

worker service:

apiVersion: v1
kind: Pod
metadata:
  name: worker-pod
  labels:
    name: worker-pod
    app: demo-voting-app
spec:
  containers:
    - name: worker-box
      image: kodekloud/examplevotingapp_worker:v1

Services

Postgres Service:

# NOTE: no ports as this is not available to other apps
apiVersion: v1
kind: Service
metadata:
  # this is hard-coded in the worker code
  name: db
  labels:
    name: db-service
    app: demo-voting-app
spec:
  ports:
    - port: 5432
      targetPort: 5432
  selector:
    # match the pod labels from the pg yaml
    name: pg-pod
    app: demo-voting-app

Redis Service:

# NOTE: no ports as this is not available to other apps
apiVersion: v1
kind: Service
metadata:
  name: redis
  labels:
    name: redis-service
    app: demo-voting-app
spec:
  ports:
    - port: 6379
      targetPort: 6379
  selector:
    # match the pod labels from the redis yaml
    name: redis-pod
    app: demo-voting-app

Results Service:

# NOTE: no ports as this is not available to other apps
apiVersion: v1
kind: Service
metadata:
  name: result-service
  labels:
    name: result-service
    app: demo-voting-app
spec:
  type: NodePort
  ports:
    - port: 80
      targetPort: 80
      nodePort: 30004
  selector:
    # match the pod labels from the pg yaml
    name: result-app-pod
    app: demo-voting-app
  externalIPs:
    - 1.2.3.111

Voting Service:

# NOTE: no ports as this is not available to other apps
apiVersion: v1
kind: Service
metadata:
  name: voting-service
  labels:
    name: voting-service
    app: demo-voting-app
spec:
  type: NodePort
  ports:
    - port: 80
      targetPort: 80
      nodePort: 30005
  selector:
    # match the pod labels from the pg yaml
    name: voting-app-pod
    app: demo-voting-app
  # makes it available through docker...
  externalIPs:
    - 1.2.3.110

Building The Services with Kubectl

The Voting-App Services

# the voting-app pod
Jakes-4:k8s Jake$ kubectl create -f cfgs/pods/voting-app.yaml
pod/voting-app-pod created

# the voting-app service
Jakes-4:k8s Jake$ kubectl create -f cfgs/services/voting-app.yaml
service/voting-service created

# see em
Jakes-4:k8s Jake$ kubectl get all
NAME                 READY   STATUS    RESTARTS   AGE
pod/voting-app-pod   1/1     Running   0          108s

NAME                     TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
service/kubernetes       ClusterIP   10.96.0.1      <none>        443/TCP        12d
service/voting-service   NodePort    10.101.11.48   <none>        80:30005/TCP   35s

#
# see em, differently
#
Jakes-4:k8s Jake$ kubectl get pods,svc
NAME                 READY   STATUS    RESTARTS   AGE
pod/voting-app-pod   1/1     Running   0          3m9s

NAME                     TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
service/kubernetes       ClusterIP   10.96.0.1      <none>        443/TCP        12d
service/voting-service   NodePort    10.101.11.48   <none>        80:30005/TCP   116s

See the Voting App with minikube

Jakes-4:k8s Jake$ minikube service voting-service --url
http://127.0.0.1:51286

go there!

The Redis Services

Jakes-4:k8s Jake$ kubectl create -f cfgs/pods/redis.yaml
pod/redis-pod created
Jakes-4:k8s Jake$ kubectl create -f cfgs/services/redis.yaml
service/redis-service created

# see it all
Jakes-4:k8s Jake$ kubectl get pods,svc
NAME                 READY   STATUS    RESTARTS   AGE
pod/redis-pod        1/1     Running   0          26s
pod/voting-app-pod   1/1     Running   0          11m

NAME                     TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
service/kubernetes       ClusterIP   10.96.0.1       <none>        443/TCP        12d
service/redis-service    ClusterIP   10.108.99.93    <none>        6379/TCP       20s
service/voting-service   NodePort    10.110.227.44   1.2.3.110     80:30005/TCP   6m19s

The Postgres Services

Jakes-4:k8s Jake$ kubectl create -f cfgs/pods/pg.yaml
pod/pg-pod created
Jakes-4:k8s Jake$ kubectl create -f cfgs/services/pg.yaml
service/db created

# see it all
Jakes-4:k8s Jake$ kubectl get pods,svc
NAME                 READY   STATUS    RESTARTS   AGE
pod/pg-pod           1/1     Running   0          25s
pod/redis-pod        1/1     Running   0          2m10s
pod/voting-app-pod   1/1     Running   0          13m

NAME                     TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
service/db               ClusterIP   10.108.7.31     <none>        5432/TCP       18s
service/kubernetes       ClusterIP   10.96.0.1       <none>        443/TCP        12d
service/redis-service    ClusterIP   10.108.99.93    <none>        6379/TCP       2m4s
service/voting-service   NodePort    10.110.227.44   1.2.3.110     80:30005/TCP   8m3s

The Worker Service

Jakes-4:k8s Jake$ kubectl create -f cfgs/pods/worker.yaml
pod/worker-pod created

The Results Services

Jakes-4:k8s Jake$ kubectl create -f cfgs/pods/result-app.yaml
pod/result-app-pod created
Jakes-4:k8s Jake$ kubectl create -f cfgs/services/result-app.yaml
service/result-service created

Some Consistent Details to Remember

Pay.
Attention.
To details.
To spelling.
To port numbers.
To Directions.
Pod names, deployment names, service names, namespace names.
These things, although they don't take up a lot of code (perhaps compared to building a backend system or a complex single-page app), these details make-or-break the kubernetes world.

Tags: