﻿# 快速體驗建構在 Dapr 架構下的微服務應用程式並部署到 Kubernetes 叢集

[Dapr](https://dapr.io/) (Distributed Application Runtime) 是一個分散式應用程式的引擎(Runtime)，他幫助開發者能在微服務架構下建構**事件驅動**(event-driven)、**高彈性**(resilient)的分散式應用程式。他可以幫助你在打造微服務架構的同時，又能徹底簡化應用程式開發的複雜度，大幅降低服務與服務之間的耦合性，真的是非常漂亮！這篇文章我將分享如何透過一個簡單的例子([hello-kubernetes](https://github.com/dapr/quickstarts/tree/v1.0.0/hello-kubernetes))，讓大家瞭解 Dapr 的運作原理。

### 體驗微服務架構下的應用程式安裝與執行

以下步驟基本上照著做應該不太容易失敗，我已經補充完整的實作命令，不像官方提供的範例省略了許多操作細節。

我的實作環境如下：

-   Windows 10 Pro 20H2 (OS Build 19042.867)
-   Docker Desktop 3.2.2 (61853) (Linux container)
-   以**系統管理員身份**開啟**命令提示字元** (Command Prompt) (使用 [Windows Terminal](https://www.microsoft.com/zh-tw/p/windows-terminal/9n0dx20hk701) 工具)

以下是設定的步驟：

1.  使用 [Minikube](https://minikube.sigs.k8s.io/) 建立 Kubernetes 叢集環境
    
    ```bash
    choco install minikube kubernetes-cli kubernetes-helm k9s -y
    
    minikube config set driver hyperv
    minikube start --cpus=4 --memory=4096 --kubernetes-version=1.16.2 --extra-config=apiserver.authorization-mode=RBAC
    minikube addons enable dashboard
    minikube addons enable ingress
    
    choco install kubernetes-cli --version=1.16.2 --allow-downgrade
    
    kubectl version
    ```
    
    > [Setup an Minikube cluster](https://docs.dapr.io/operations/hosting/kubernetes/cluster/setup-minikube/)
    
    > 請確保 Kubernetes 的 Client (`kubectl`) 與 Server 版本一致
    
2.  安裝 Dapr CLI 工具
    
    ```bash
    powershell -Command "iwr -useb https://raw.githubusercontent.com/dapr/cli/master/install/install.ps1 | iex"
    ```
    
    安裝完後請重開 Command Prompt
    
    ```bash
    dapr -v
    dapr
    ```
    
    > [Install the Dapr CLI](https://docs.dapr.io/getting-started/install-dapr-cli/)
    
3.  初始化 Dapr 到 Kubernetes 叢集
    
    執行 `dapr init --kubernetes` 的過程中會建立一個 `dapr-system` 命名空間，初始化 Dapr 必要的執行環境！
    
    ```bash
    dapr init --kubernetes
    dapr status -k
    ```
    
4.  下載範例程式
    
    這個範例有包含一個 [Node.js 應用程式](https://github.com/dapr/quickstarts/blob/v1.0.0/hello-kubernetes/node/app.js)(Web API)，與一個 [Python 應用程式](https://github.com/dapr/quickstarts/blob/v1.0.0/hello-kubernetes/python/app.py)(Client)，程式碼都非常簡單，建議先閱讀過原始碼再繼續看下去！
    
    ```batch
    git clone -b release-1.0 https://github.com/dapr/quickstarts.git
    cd quickstarts/hello-kubernetes/
    ```
    
5.  建立與設定狀態儲存服務 (Create and configure a state store)
    
    Dapr 包含許多 [Building blocks](https://docs.dapr.io/concepts/building-blocks-concept/)，其中一個就是「狀態管理」能力，他可以讓你在微服務架構下更輕鬆的管理狀態！ 👍
    
    ```bash
    helm repo add bitnami https://charts.bitnami.com/bitnami
    helm repo update
    helm install redis bitnami/redis
    
    kubectl apply -f ./deploy/redis.yaml
    ```
    
    > [Helm Charts to deploy Redis(TM) packaged by Bitnami in Kubernetes](https://bitnami.com/stack/redis/helm)
    
6.  部署 Node.js 應用程式 (包括 Dapr sidecar 容器)
    
    ```bash
    kubectl apply -f ./deploy/node.yaml
    kubectl get svc nodeapp
    ```
    
    因為 Minikube 無法使用 `type: LoadBalancer` 的服務，所以請改用以下命令開啟對外的 Port 連線：
    
    ```bash
    minikube service nodeapp
    ```
    
    > 上述命令會自動開啟瀏覽器，我們假設暫時的服務網址是 `http://172.23.30.21:31768/`，那麼你應該可以用這個網址測試 API 是否運作正常：`http://172.23.30.21:31768/ports`
    
7.  部署 Python 應用程式 (包括 Dapr sidecar 容器)
    
    這個應用程式([app.py](https://github.com/dapr/quickstarts/blob/v1.0.0/hello-kubernetes/python/app.py))基本上就是一直呼叫 Node.js 應用程式的 API 而已，並沒有對外的端點，也沒有任何訊息。比較特別的地方是，他並不會「直接」呼叫 Node.js 的 Pod，而是透過 Dapr 進行呼叫。
    
    ```bash
    kubectl apply -f ./deploy/python.yaml
    ```
    
8.  查看 Node.js 應用程式的紀錄 (Logs)
    
    這裡你將能看到 Node.js 應用程式的紀錄會顯示一直有 Request 進來！
    
    ```bash
    kubectl logs --selector=app=node -c node --tail=-1
    ```
    
9.  查看 Node.js 應用程式確實有儲存狀態 (透過狀態服務)
    
    你可以透過以下網址查看狀態服務是否運作正常 ([app.js](https://github.com/dapr/quickstarts/blob/v1.0.0/hello-kubernetes/node/app.js))：
    
    ```bash
    http://172.23.30.21:31768/order
    ```
    
10.  清空所有服務
     
     ```bash
     cd deploy
     kubectl delete -f .
     ```
     
11.  關閉並刪除 Minikube 叢集
     
     ```bash
     minikube stop
     minikube delete
     ```
     

### 重點綱要

這裡特別要講的地方是：

1.  所有 Pod 附帶的 Daprd sidecar 都會 LISTEN `localhost:3500`，Pod 內的容器都可以直接存取
2.  所有 Pod 內的主要應用程式都只需跟 `localhost:3500` (daprd) 溝通即可，不用明確得知遠端服務的端點在哪邊
3.  所有 Pod 與 Pod 之間的通訊，都由 daprd 全權負責，如此一來將可大幅簡化微服務架構下服務與服務之間的相依性

如果你想看更基礎的範例，建議你參考 [Getting started with Dapr](https://docs.dapr.io/getting-started/) 文件，跟著做一遍，你也會有大致的脈絡！

### 相關連結

-   [Dapr](https://dapr.io/)
    -   入門範例：[dapr/quickstarts](https://github.com/dapr/quickstarts): Dapr quickstart code samples and tutorials
    -   進階範例：[dapr/samples](https://github.com/dapr/samples): Community driven repository for Dapr samples
-   [Dapr Docs](https://docs.dapr.io/)
    -   概念 | [Dapr Concepts](https://docs.dapr.io/concepts/)
    -   起步 | [Getting started with Dapr](https://docs.dapr.io/getting-started/)
    -   開發 | [Developing applications with Dapr](https://docs.dapr.io/developing-applications/)
    -   營運 | [Deploying and configuring Dapr in your environment](https://docs.dapr.io/operations/)
    -   參考 | [Dapr Reference Docs](https://docs.dapr.io/reference/)
    -   貢獻 | [Contributing to Dapr](https://docs.dapr.io/contributing/)
-   [Dapr Blogs](https://blog.dapr.io/posts)
-   [Dapr Discord](https://aka.ms/dapr-discord) (討論區)
-   [Dapr Community](https://github.com/dapr/community/blob/master/README.md)
-   [Dapr Twitter](https://twitter.com/daprdev)
-   [eShop on Dapr](https://github.com/dotnet-architecture/eShopOnDapr)
-   [Visual Studio Code integrations with Dapr](https://docs.dapr.io/developing-applications/local-development/ides/vscode/)
-   影片
    -   [Microservice applications with DAPR and .NET](https://youtu.be/kIfmwmJHNMs?t=143) - YouTube
    -   [ASP.NET Community Standup - Dapr + .NET](https://youtu.be/VkJQR854S1s?t=141) - YouTube
        -   Slide: [slides.pptx](https://github.com/rynowak/Presentations/blob/master/2021/CommunityStandup-Dapr-02/slides.pptx)
