Code Monkey home page Code Monkey logo

asa-lab-4's Introduction

Adaptive Architecture with dapr

dapr-loge

Dapr is a portable, event-driven runtime that makes it easy for any developer to build resilient, stateless and stateful applications that run on the cloud and edge and embraces the diversity of languages and developer frameworks.

Dapr codifies the best practices for building microservice applications into open, independent, building blocks that enable you to build portable applications with the language and framework of your choice.

https://docs.dapr.io/concepts/overview/

Setup

The following components are necessary to run the example.

If you want to build/run the examples using apr-cli the following sdks are needed.

Windows Notes

To execute the commands a decent shell/terminal is needed. In a Unix-like environment like Mac/Linux typically a good shell is available out of the box (bash, zsh) in combination with a terminal (terminal, iTerm, Konsole, gnome-terminal, ...). For Windows a good combination of shell/terminal is PowerShell/Windows Terminal. The commands below either work directly in PowerShell or there is a variant for PowerShell displayed. If you use cmd.exe, you are without help. Nobody shoul use this old command-interpreter any more!

Powershell: For windows users it is quite helpful to set the execution-policy for powershell:

Set-ExecutionPolicy RemoteSigned -Scope CurrentUser

Package Managers: Windows users should use a package manager to simplify installation. winget / Scoop / Chocolaty are excellent choices.

dapr cli

This section is only needed if you have the local sdks installed and want to build/run dapr without kubernetes. To start, the installation is straight-forward, just follow the instructions mentioned above.

  1. Dapr init

The first step is to initialize dapr. As a result dapr itself and the corresponding dapr runtime is installed.

Hint: Docker needs to run!

# kick-start dapr
dapr init

# check the version (as of May 2024)
dapr --version
CLI version: 1.13.0
Runtime version: 1.13.3

With this output the dapr-cli setup is done.

After the initial dapr setup the example can be executed using the dapr-cli. This is only relevant/necessary when local development and dev-sdks are available. A prerequisite for this step is the installation of the golang/.NET SDKs (again see above for the installation link/info).

  1. Via Makefile (Unix-like systems)

To simplify this process open two terminal windows and execute the following make commands.

# terminal1
make agent-cli

# terminal2
make dashboard-cli

To verify if all works as expected open a browser windows with the following URL: http://localhost:9000.

HINT: If you get an error concerning the port this might be caused by a process already having possession of the port :9000.

  1. Via Powershell (Windows)

For the Windows-people the process works the same, open two terminal/powershell/... windows and execute the powershell scripts.

# terminal1
.\dapr-agent-cli.ps1

# terminal2
.\dapr-dashboard-cli.ps1

Again verify the correct execution of the processes by opening a browser window with the URL: http://localhost:9000.

The output will be similar to this:

dapr-cli-output

dapr on k8s (no local development SDKs needed)

Kubernetes is also called k8s => starting with k, 8 characters and ending with s. The easiest way to work with kubernetes/k8s is to locally install minikube, a single-node kubernetes "cluster". The installation is again rather simple and can be easily performed on Windows, Mac, Linux.

  1. minikube

Install minikube according to documentation: https://minikube.sigs.k8s.io/docs/start/

Afterwards startup minikube. The output will be similar to the one shown below:

# versions as of May 2024
> minikube start

๐Ÿ˜„  minikube v1.33.1 on Darwin 14.5 (arm64)
โœจ  Using the docker driver based on existing profile
๐Ÿ‘  Starting "minikube" primary control-plane node in "minikube" cluster
๐Ÿšœ  Pulling base image v0.0.44 ...
๐Ÿ”„  Restarting existing docker container for "minikube" ...
๐Ÿณ  Preparing Kubernetes v1.30.0 on Docker 26.1.1 ...
๐Ÿ”Ž  Verifying Kubernetes components...
๐Ÿ’ก  After the addon is enabled, please run "minikube tunnel" and your ingress resources would be available at "127.0.0.1"
    โ–ช Using image gcr.io/k8s-minikube/storage-provisioner:v5
    โ–ช Using image docker.io/kubernetesui/dashboard:v2.7.0
    โ–ช Using image registry.k8s.io/ingress-nginx/controller:v1.10.1
    โ–ช Using image registry.k8s.io/ingress-nginx/kube-webhook-certgen:v1.4.1
    โ–ช Using image docker.io/kubernetesui/metrics-scraper:v1.0.8
    โ–ช Using image registry.k8s.io/ingress-nginx/kube-webhook-certgen:v1.4.1
๐Ÿ’ก  Some dashboard features require the metrics-server addon. To enable all features please run:

	minikube addons enable metrics-server

๐Ÿ”Ž  Verifying ingress addon...
๐ŸŒŸ  Enabled addons: storage-provisioner, dashboard, default-storageclass, ingress
๐Ÿ„  Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default

To work with k8s/minikube kubectl is needed. Minikube provides a kubectl minikube kubectl -- <kubectl commands>. In addition it is possible to install a plain kubectl. This can be done by typical packages managers.

# Mac
brew install kubectl

# Windows has a couple of package manager

# using winget
winget install -e --id Kubernetes.kubectl

# using scoop
scoop install kubectl

# using chocolatey
choco install kubernetes-cli

This is optional, because the minikube-provided kubectl can also be used, or aliased to "feel" like a standalone kubectl (https://minikube.sigs.k8s.io/docs/handbook/kubectl/).

  1. dapr on k8s

The process is again quite easy. More information is available on the dapr website: https://docs.dapr.io/operations/hosting/kubernetes/cluster/setup-minikube/. The following additional components are installed on minikube:

minikube addons enable dashboard # provides a kubernetes dashboard
minikube addons enable ingress # provides a reverse proxy using nginx to expose services

The finial step to initialize dapr on kubernetes (k8s) / minikube is done via the dapr-cli.

# the command initializes dapr on kubernetes by provisioning a couple of containers
dapr init -k

This command deploys the necessary containers to have the dapr environment available on minikube.

  1. dapr components pubsub

A pubsub component is needed on k8s/minikube for this example. The easiest way is to install redis by using the helm-cli (dapr-docu: https://docs.dapr.io/getting-started/tutorials/configure-state-pubsub/)

3.1 Install helm-cli

We use helm because it simplifies the installation process of components to kubernetes. The helm-documentation lists a number of options how to install helm for different operating-systems: https://helm.sh/docs/intro/install/ Again the easiest way is to use a package manager:

# Mac
brew install helm

# Windows has a couple of package manager

# using winget
winget install Helm.Helm

# using scoop
scoop install helm

# using chocolatey
choco install kubernetes-helm

3.2 Install redis

To install redis on k8s/minikube we use helm (=the kubernetes package manager). This is similar to apt for Debian-based Linux systems (https://wiki.debian.org/AptCLI)

helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
helm install redis bitnami/redis

Once the commands executed successfully check the relevant pods are running (be patient, this takes a couple of seconds. The result is the main noder and 3 replicas.):

> kubectl get pods
NAME               READY   STATUS    RESTARTS      AGE
redis-master-0     1/1     Running   1 (35m ago)   2d23h
redis-replicas-0   1/1     Running   2 (34m ago)   2d23h
redis-replicas-1   1/1     Running   2 (34m ago)   2d23h
redis-replicas-2   1/1     Running   2 (34m ago)   2d23h

3.3 dapr pubsub component

The last step is to "introduce" the pubsub dapr component to k8s. Redis has an extension Redis Streams which we use for publish-subscribe. The definition of the component is stored in deployment/pubsub.yaml.

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: pubsub
  namespace: default
spec:
  type: pubsub.redis
  version: v1
  metadata:
  - name: redisHost
    value: redis-master.default.svc.cluster.local:6379
  - name: redisPassword
    secretKeyRef:
      name: redis
      key: redis-password
 # uncomment below for connecting to redis cache instances over TLS (ex - Azure Redis Cache)
  # - name: enableTLS
  #   value: true

Kubernetes uses a lot of yaml, someone working with kubernetes is sometimes called a "YAML Engineer". This yaml structure is applied via kubectl using the following command:

kubectl apply -f ./deployment/pubsub.yaml

Again this can be done by using the Makefile:

make kube-deploy-pubsub

Or for the Windows by using the following powershell script:

.\k8s-deploy-pubsub.ps1

The result can be verified by listing the component via kubectl:

> kubectl get components
NAME     AGE
pubsub   2d23h
  1. deploy components and service

NOTE: We need to build the container-images before we can deploy the application components. The process is described in the section Build local images.

TL;DR

# unix-like
## we need to tell docker where the images are stored - this is necessary for minikube to find the images used in the pods
eval $(minikube docker-env)
make build-container

# windows
## set docker-env variables to "redirect" the images towards minikube
minikube docker-env --shell powershell | Invoke-Expression
.\docker-build.ps1

To deploy the logic as containers to k8s/minikube another yaml definition is needed. The yaml files creates deployments for two pods and a service to access the dashboard (via ingress). The syntax is typical k8s-yaml (https://kubernetes.io/docs/concepts/overview/working-with-objects/kubernetes-objects/) with some dapr-extensions:

# example and parts of the components yaml file
...
annotations:
    dapr.io/enabled: "true"
    dapr.io/app-id: "dashboard-dotnet"
    dapr.io/app-port: "9000"
spec:
    containers:
    - name: dashboard-dotnet
      image: dapr-demo/dashboard-dotnet:latest
      ports:
      - containerPort: 9000
      imagePullPolicy: Never
...

The app-port and containerPort are kind of used twice, just ensure that the same ports are used. The deployment file is available at: deployment/components.yaml and is applied via

kubectl apply -f ./deployment/components.yaml

# unix-like
make kube-deploy-all

# windows
.\k8s-deploy-components.ps1

The logs of the containers within the pods (stdout) can be shown via kubectl:

# show the agent output
kubectl logs -f --selector app=agent-golang -c agent-golang

# show the output of the dashboard
kubectl logs -f --selector app=dashboard-dotnet -c dashboard-dotnet

The selector and/or container need to be specified, because of the dapr sidecar pattern. The deployed pod contains two containers. The application container and the dapr sidecar.

> kubectl logs -f dashboard-dotnet-<random>-<id>
error: a container name must be specified for pod dashboard-dotnet-<random>-<id>, choose one of: [dashboard-dotnet daprd]

The log-output of the dapr sidecar can also be shown:

> kubectl logs -f dashboard-<random>-<id> -c daprd
time="2022-06-02T17:01:19.962046863Z" level=info msg="starting Dapr Runtime -- version 1.7.4 -- commit 9b3512921bb52af190a2474f3d31f39a1a7a9879" app_id=dashboard instance=dashboard-<random>-<id> scope=dapr.runtime type=log ver=1.7.4
time="2022-06-02T17:01:19.962091072Z" level=info msg="log level set to: info" app_id=dashboard instance=dashboard-<random>-<id> scope=dapr.runtime type=log ver=1.7.4
time="2022-06-02T17:01:19.962208472Z" level=info msg="metrics server started on :9090/" app_id=dashboard instance=dashboard-<random>-<id> scope=dapr.metrics type=log ver=1.7.4
time="2022-06-02T17:01:19.962333421Z" level=info msg="loading default configuration" app_id=dashboard instance=dashboard-<random>-<id> scope=dapr.runtime type=log ver=1.7.4
time="2022-06-02T17:01:19.962372471Z" level=info msg="kubernetes mode configured" app_id=dashboard instance=dashboard-<random>-<id> scope=dapr.runtime type=log ver=1.7.4
time="2022-06-02T17:01:19.962380871Z" level=info msg="app id: dashboard" app_id=dashboard instance=dashboard-<random>-<id> scope=dapr.runtime type=log ver=1.7.4

To access the dashboard a k8s service is defined:

...
apiVersion: v1
kind: Service
metadata:
  name: dashboard-service
  labels:
    app: dashboard-service
spec:
  selector:
    app: dashboard
  ports:
  - protocol: TCP
    port: 9000
    targetPort: 9000
  type: LoadBalancer
  ...

The service definition exposes a TCP port which binds/forwars to the node and port of the container. This is necessary to access the system and the logic within the container from the "outside".

Minikube has a specialty, that additional work is needed to access services, because no "public IP" is created with minikube (this is different with other k8s implementations). But there is an easy way to access the service - minikube has a service command which establishes a connection to the exposed service. In fact it creates a ip-mapping to the LoadBalancer where services are exposed (https://minikube.sigs.k8s.io/docs/commands/service/)

minikube service dashboard-service

k8s deployment works

Build local images

The application images are not published to dockerhub or any other container-registry, because this would just be waste for this demo-purpose. Instead the images are held locally and k8s is instructed to not pull the images!

To build locally a Makefile is available:

# unix-like
make build-container

# windows
.\docker-build.ps1

creates the local images.

containers:
- name: dashboard
  image: dapr-demo/dashboard:latest
  ports:
  - containerPort: 9000
  imagePullPolicy: Never

The important part is the imagePullPolicy. To actually enable this, it is not sufficient to just build the images locally, because minikube does not access those local images. As usual there is an StackOverflow answer how to give the images to minikube!

The trick is to set some relevant ENVs via minikube and build again:

eval $(minikube docker-env)

On Windows and powershell this translates to

minikube docker-env --shell powershell | Invoke-Expression

Cleanup

By executing the powershell script k8s-undeploy.ps1 or make kube-undeploy-all the resources are removed from k8s and a fresh start can be done.

This can be verified by checking the pods:

> kubectl get pods
NAME                         READY   STATUS        RESTARTS        AGE
agent-666d89fb8f-mg5wh       2/2     Terminating   1 (3m34s ago)   3m35s
dashboard-5bd6c7697f-ztbx5   2/2     Terminating   0               3m35s
redis-master-0               1/1     Running       2 (22h ago)     3d23h
redis-replicas-0             1/1     Running       3 (5m16s ago)   3d23h
redis-replicas-1             1/1     Running       3 (5m16s ago)   3d23h
redis-replicas-2             1/1     Running       3 (5m16s ago)   3d23h

The output shows, that the application pods are in the process of being removed from k8s.

asa-lab-4's People

Contributors

bihe avatar

Stargazers

 avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.