Skip to content

Commit

Permalink
Merge pull request #926 from mukundansundar/multi-app-run-k8s-example
Browse files Browse the repository at this point in the history
add hello-kubernetes multi-app run k8s template
  • Loading branch information
paulyuk authored Oct 3, 2023
2 parents 8ecc595 + a66386e commit 2157c0c
Show file tree
Hide file tree
Showing 7 changed files with 222 additions and 55 deletions.
2 changes: 1 addition & 1 deletion .github/env/global.env
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
DAPR_CLI_VERSION: 1.12.0-rc.2
DAPR_CLI_VERSION: 1.12.0-rc.3
DAPR_RUNTIME_VERSION: 1.12.0-rc.5
DAPR_INSTALL_URL: https://raw.githubusercontent.com/dapr/cli/v${DAPR_CLI_VERSION}/install/
DAPR_DEFAULT_IMAGE_REGISTRY: ghcr
Expand Down
24 changes: 15 additions & 9 deletions .github/workflows/validate.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,18 @@ jobs:
deploy:
name: Validate tutorials on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
timeout-minutes: 30
timeout-minutes: 40
env:
GOVER: 1.17
KUBERNETES_VERSION: v1.21.1
KIND_VERSION: v0.12.0
KIND_IMAGE_SHA: sha256:69860bda5563ac81e3c0057d654b5253219618a22ec3a346306239bba8cfa1a6
strategy:
matrix:
matrix:
os: [ubuntu-latest]
fail-fast: false
steps:
- name: Check out code
- name: Check out code
uses: actions/checkout@v2
- name: Load environment variables
uses: artursouza/export-env-action@v2
Expand Down Expand Up @@ -90,12 +90,12 @@ jobs:
- role: worker
image: kindest/node:${{ env.KUBERNETES_VERSION }}@${{ env.KIND_IMAGE_SHA }}
EOF
# Log the generated kind.yaml for easy reference.
cat kind.yaml
- name: Create KinD Cluster - Linux
if: matrix.os == 'ubuntu-latest'
if: matrix.os == 'ubuntu-latest'
uses: helm/[email protected]
with:
config: kind.yaml
Expand Down Expand Up @@ -124,7 +124,7 @@ jobs:
run: wget -q ${{ env.DAPR_INSTALL_URL }}/install.sh -O - | /bin/bash -s ${{ env.DAPR_CLI_VERSION }}
- name: Set up Dapr CLI - Windows
if: matrix.os == 'windows-latest'
run: powershell -Command "\$$script=iwr -useb ${{ env.DAPR_INSTALL_URL }}/install.ps1; \$$block=[ScriptBlock]::Create(\$$script); invoke-command -ScriptBlock \$$block -ArgumentList ${{ env.DAPR_CLI_VERSION }}"
run: powershell -Command "\$$script=iwr -useb ${{ env.DAPR_INSTALL_URL }}/install.ps1; \$$block=[ScriptBlock]::Create(\$$script); invoke-command -ScriptBlock \$$block -ArgumentList ${{ env.DAPR_CLI_VERSION }}"
- name: Install Dapr
run: |
export GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }}
Expand All @@ -135,7 +135,7 @@ jobs:
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
helm install redis bitnami/redis --version 17.14.5
dapr init -k --runtime-version=${{ env.DAPR_RUNTIME_VERSION }} --wait || kubectl get pods --all-namespaces
dapr init -k --dev --runtime-version=${{ env.DAPR_RUNTIME_VERSION }} --wait || kubectl get pods --all-namespaces
kubectl get nodes -o wide
for pod in `dapr status -k | awk '/dapr/ {print $1}'`; do kubectl describe pod -l app=$pod -n dapr-system ; kubectl logs -l app=$pod -n dapr-system; done
- name: Install utilities dependencies
Expand All @@ -148,11 +148,17 @@ jobs:
pushd tutorials/hello-world
make validate
popd
- name: Validate hello-kubernetes
- name: Validate hello-kubernetes multi app run
if: matrix.os == 'ubuntu-latest'
run: |
pushd tutorials/hello-kubernetes
make validate
make validate_multi_app_run
popd
- name: Validate hello-kubernetes normal run
if: matrix.os == 'ubuntu-latest'
run: |
pushd tutorials/hello-kubernetes
make validate_normal_run
popd
- name: Validate distributed-calculator
if: matrix.os == 'ubuntu-latest'
Expand Down
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,8 @@ packages

# macOS
.DS_Store

# Auto generated deploy dir inside .dapr directory
**/.dapr/deploy
# Auto generated logs dir inside .dapr directory
**/.dapr/logs
65 changes: 36 additions & 29 deletions tutorials/distributed-calculator/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ This quickstart shows method invocation and state persistent capabilities of Dap
- **Division**: Node [Express](https://expressjs.com/) application
- **Subtraction**: [.NET Core](https://docs.microsoft.com/en-us/dotnet/core/) application

The front-end application consists of a server and a client written in [React](https://reactjs.org/).
Kudos to `ahfarmer` whose [React calculator](https://github.com/ahfarmer/calculator)
The front-end application consists of a server and a client written in [React](https://reactjs.org/).
Kudos to `ahfarmer` whose [React calculator](https://github.com/ahfarmer/calculator)

The following architecture diagram illustrates the components that make up this quickstart:
The following architecture diagram illustrates the components that make up this quickstart:

![Architecture Diagram](./img/Architecture_Diagram.png)

Expand Down Expand Up @@ -109,7 +109,7 @@ name: "Run dotnet app"
output_match_mode: substring
working_dir: "./csharp/bin/Debug/netcoreapp7.0"
background: true
env:
env:
ASPNETCORE_URLS: 'http://localhost:7001'
sleep: 5
-->
Expand Down Expand Up @@ -175,7 +175,7 @@ working_dir: "./python"
```bash
#Linux/Mac OS:
export FLASK_RUN_PORT=5001
#Windows:
set FLASK_RUN_PORT=5001
```
Expand Down Expand Up @@ -245,7 +245,7 @@ sleep: 15

![Calculator Screenshot](./img/calculator-screenshot.JPG)

7. Open your browser's console window (using F12 key) to see the logs produced as you use the calculator. Note that each time you click a button, you see logs that indicate state persistence and the different apps that are contacted to perform the operation.
7. Open your browser's console window (using F12 key) to see the logs produced as you use the calculator. Note that each time you click a button, you see logs that indicate state persistence and the different apps that are contacted to perform the operation.
<!-- STEP
name: Pause for manual validation
Expand Down Expand Up @@ -291,7 +291,7 @@ name: "Curl test"
```
```bash
curl -s http://localhost:8080/state
curl -s http://localhost:8080/state
```
<!-- END_STEP -->
Expand All @@ -302,7 +302,7 @@ name: "Curl test"
18
1.5294117647058822
1768
{"operation":null,"total":"54","next":null}
```
Expand All @@ -328,11 +328,11 @@ name: Cleanup local
```bash
dapr stop --app-id subtractapp
```
```bash
dapr stop --app-id divideapp
```
```bash
dapr stop --app-id multiplyapp
```
Expand All @@ -359,14 +359,14 @@ working_dir: "./node"
1. Navigate to the deploy directory in this quickstart directory: `cd deploy`
> **Note**: `appconfig.yaml` is not used directly for this quickstart but is present for the [observability quickstart](../observability).
2. Follow [these instructions](https://docs.dapr.io/getting-started/tutorials/configure-state-pubsub/#step-1-create-a-redis-store) to create and configure a Redis store
3. Deploy all of your resources:
3. Deploy all of your resources:
<!-- Changing appconfig to configured as validate.yaml GH WF, inits Dapr using dev mode.-->
<!-- STEP
name: "Deploy Kubernetes"
working_dir: "./deploy"
expected_stdout_lines:
- "configuration.dapr.io/appconfig created"
- "configuration.dapr.io/appconfig configured"
- "deployment.apps/subtractapp created"
- "deployment.apps/addapp created"
- "deployment.apps/divideapp created"
Expand All @@ -376,12 +376,19 @@ expected_stdout_lines:
- "component.dapr.io/statestore created"
-->
```bash
```bash
kubectl apply -f .
```
```
<!-- END_STEP -->
> **Note**: If you had previously installed, dapr using the `dapr init -k --dev` command, the `appconfig` previously installed, would have changed with the above command to point to a different zipkin collector. To point it back to the zipkin collector installed during `dapr init -k --dev`, replace the `endpointAddress` in `appconfig.yaml` with the following:
`endpointAddress: "http://dapr-dev-zipkin.default.svc.cluster.local:9411/api/v2/spans"`
and run the following command:
```bash
kubectl apply -f appconfig.yaml
```
> **Note**: Services could also be deployed one-by-one by specifying the .yaml file: `kubectl apply -f go-adder.yaml`.
Each of the services will spin up a pod with two containers: one for your service and one for the Dapr sidecar. It will also configure a service for each sidecar and an external IP for the front-end, which allows us to connect to it externally.
Expand Down Expand Up @@ -462,7 +469,7 @@ This will make your service available on http://localhost:8000. Navigate to this
> **Optional**: If you are using a public cloud provider, you can substitue your EXTERNAL-IP address instead of port forwarding. You can find it with:
```bash
```bash
kubectl get svc
```
Expand Down Expand Up @@ -495,21 +502,21 @@ manual_pause_message: "Calculator APP running on http://localhost:8000. Please o
![Calculator Screenshot](./img/calculator-screenshot.JPG)
6. Open your browser's console window (using F12 key) to see the logs produced as you use the calculator. Note that each time you click a button, you see logs that indicate state persistence:
6. Open your browser's console window (using F12 key) to see the logs produced as you use the calculator. Note that each time you click a button, you see logs that indicate state persistence:

```js
Persisting State:
{total: "21", next: "2", operation: "x"}
```

`total`, `next`, and `operation` reflect the three pieces of state a calculator needs to operate. The app persists these to a Redis store (see [Simplified State Management](#simplified-state-management) section below). By persisting these, you can refresh the page or take down the front-end pod and still jump right back where you were. Try it! Enter something into the calculator and refresh the page. The calculator should have retained the state, and the console should read:
`total`, `next`, and `operation` reflect the three pieces of state a calculator needs to operate. The app persists these to a Redis store (see [Simplified State Management](#simplified-state-management) section below). By persisting these, you can refresh the page or take down the front-end pod and still jump right back where you were. Try it! Enter something into the calculator and refresh the page. The calculator should have retained the state, and the console should read:

```js
Rehydrating State:
{total: "21", next: "2", operation: "x"}
```

Also note that each time you enter a full equation (e.g. "126 ÷ 3 =") the logs indicate that a call is made to the service:
Also note that each time you enter a full equation (e.g. "126 ÷ 3 =") the logs indicate that a call is made to the service:

```js
Calling divide service
Expand Down Expand Up @@ -563,7 +570,7 @@ curl -s http://localhost:8000/persist -H Content-Type:application/json --data @p
```
```bash
curl -s http://localhost:8000/state
curl -s http://localhost:8000/state
```
<!-- END_STEP -->
Expand All @@ -575,7 +582,7 @@ You should get the following output:
18
1.5294117647058822
1768
{"operation":null,"total":"54","next":null}
```
Expand Down Expand Up @@ -624,13 +631,13 @@ const daprUrl = `http://localhost:${daprPort}/v1.0/invoke`;
app.post('/calculate/add', async (req, res) => {
const appResponse = await axios.post(`${daprUrl}/addapp/method/add`, req.body);
return res.send(`${appResponse.data}`);
return res.send(`${appResponse.data}`);
});
app.post('/calculate/subtract', async (req, res) => {
const appResponse = await axios.post(`${daprUrl}/subtractapp/method/subtract`, req.body);
return res.send(`${appResponse.data}`);
return res.send(`${appResponse.data}`);
});
...
```
Expand All @@ -643,20 +650,20 @@ Learn more about Dapr [service invocation](https://docs.dapr.io/developing-appli

Dapr sidecars provide [state management](https://docs.dapr.io/developing-applications/building-blocks/state-management/). In this quickstart, the calculator's state is persisted each time a new button is clicked. This means a user can refresh the page, close the page or even take down the `calculator-front-end` pod, and still retain the same state when they next open it. Dapr adds a layer of indirection so that the app doesn't need to know where it's persisting state. It doesn't have to keep track of keys, handle retry logic or worry about state provider specific configuration. All it has to do is GET or POST against its Dapr sidecar's state endpoint: `http://localhost:3500/v1.0/state/${stateStoreName}`.
Take a look at `server.js` in the `react-calculator` directory. Note that it exposes two state endpoints for the React client to get and set state: the GET `/state` endpoint and the POST `/persist` endpoint. Both forward client calls to the Dapr state endpoint:
Take a look at `server.js` in the `react-calculator` directory. Note that it exposes two state endpoints for the React client to get and set state: the GET `/state` endpoint and the POST `/persist` endpoint. Both forward client calls to the Dapr state endpoint:
```js
const stateUrl = `http://localhost:${daprPort}/v1.0/state/${stateStoreName}`;
```
Our client persists state by simply POSTing JSON key-value pairs (see `react-calculator/client/src/component/App.js`):
Our client persists state by simply POSTing JSON key-value pairs (see `react-calculator/client/src/component/App.js`):
```js
const state = [{
key: "calculatorState",
value
const state = [{
key: "calculatorState",
value
}];
fetch("/persist", {
method: "POST",
body: JSON.stringify(state),
Expand Down
Loading

0 comments on commit 2157c0c

Please sign in to comment.