Skip to content

Commit

Permalink
Merge pull request #18 from Liquid-Reply/wasmio-worksop-part1
Browse files Browse the repository at this point in the history
Wasmio worksop part1
  • Loading branch information
0xE282B0 authored Mar 13, 2024
2 parents 48609d5 + d593e2f commit 5ca24e5
Show file tree
Hide file tree
Showing 65 changed files with 44,122 additions and 0 deletions.
69 changes: 69 additions & 0 deletions podtato-head/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
### login to registry ghcr.io using GITHUB_USER and GITHUB_TOKEN env vars in environment or .env file is expected
### (these are the implicit values in the empty parameters - "" - below)
### TODO(?): genericize the registry and login and move logic to Makefile

install-requirements:
scripts/requirements.sh /usr/local/bin

### podtato-head-microservices

podtato-head-verify:
$(MAKE) -C podtato-head-microservices vet
$(MAKE) -C podtato-head-microservices fmt
$(MAKE) -C podtato-head-microservices test

build-microservices-images:
podtato-head-microservices/build/build_images.sh "" "" "" \
scratch ''
podtato-head-microservices/build/build_images.sh "" "" "" \
gcr.io/distroless/static:latest distroless
podtato-head-microservices/build/build_images.sh "" "" "" \
registry.access.redhat.com/ubi9/ubi-micro:latest ubi
podtato-head-microservices/build/build_images.sh "" "" "" \
distroless.dev/alpine-base:latest chainguard

push-microservices-images:
podtato-head-microservices/build/build_images.sh "" "" "" \
scratch '' true
podtato-head-microservices/build/build_images.sh "" "" "" \
gcr.io/distroless/static:latest distroless true
podtato-head-microservices/build/build_images.sh "" "" "" \
registry.access.redhat.com/ubi9/ubi-micro:latest ubi true
podtato-head-microservices/build/build_images.sh "" "" "" \
distroless.dev/alpine-base:latest chainguard true

test-microservices: push-microservices-images
# special build and tag for test images
IMAGE_VERSION=test podtato-head-microservices/build/build_images.sh "" "" "" \
scratch '' true
IMAGE_VERSION=test scripts/test_with_kind.sh

### podtato-head-server

build-server-images:
podtato-head-server/build/build_image.sh '' '' '' \
scratch '' false
podtato-head-server/build/build_image.sh '' '' '' \
gcr.io/distroless/static:latest distroless false
podtato-head-server/build/build_image.sh '' '' '' \
registry.access.redhat.com/ubi9/ubi-micro:latest ubi false
podtato-head-server/build/build_image.sh '' '' '' \
distroless.dev/alpine-base:latest chainguard false

push-server-images:
podtato-head-server/build/build_image.sh '' '' '' \
scratch '' true
podtato-head-server/build/build_image.sh '' '' '' \
gcr.io/distroless/static:latest distroless true
podtato-head-server/build/build_image.sh '' '' '' \
registry.access.redhat.com/ubi9/ubi-micro:latest ubi true
podtato-head-server/build/build_image.sh '' '' '' \
distroless.dev/alpine-base:latest chainguard true

test-server: push-server-images
podtato-head-server/build/test_image.sh
podtato-head-server/build/test_image.sh '' '' '' distroless
podtato-head-server/build/test_image.sh '' '' '' ubi
podtato-head-server/build/test_image.sh '' '' '' chainguard

.PHONY: build-microservices-images push-microservices-images test-microservices install-requirements build-server-images push-server-images test-server podtato-head-verify
71 changes: 71 additions & 0 deletions podtato-head/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# WASM IO Workshop

## Setup

- [ ] Set up a cluster
- [ ] Configure a container registry
- [ ] Install KWasm
```sh
helm install -n kwasm --create-namespace kwasm-operator kwasm/kwasm-operator --set kwasmOperator.autoProvision=true
```
- Check out this repository
```sh
git clone https://github.com/Liquid-Reply/kwasm-demos.git
```
- Deploy podtatohead
```sh
helm upgrade \
--install podtato-head ./delivery/chart
```
- Build podtatohead Wasm
```sh
docker build podtato-head-microservices/crates/podtato-entry -t <REGISTRY> /podtato-head-entry --push
docker build podtato-head-microservices/crates/podtato-parts -t <REGISTRY> /podtato-head-parts --push
```
- Deploy podtatohead Wasm
```sh
helm upgrade \
--install podtato-head ./delivery/chart \
--set images.repositoryDirname=<REGISTRY> \
--set images.pullPolicy=Always \
--set entry.repositoryBasename=podtato-head-entry \
--set entry.runtimeClassName=wasmedge \
--set hat.repositoryBasename=podtato-head-parts \
--set hat.runtimeClassName=wasmedge \
--set leftLeg.repositoryBasename=podtato-head-parts \
--set leftLeg.runtimeClassName=wasmedge \
--set leftArm.repositoryBasename=podtato-head-parts \
--set leftArm.runtimeClassName=wasmedge \
--set rightLeg.repositoryBasename=podtato-head-parts \
--set rightLeg.runtimeClassName=wasmedge \
--set rightArm.repositoryBasename=podtato-head-parts \
--set rightArm.runtimeClassName=wasmedge
```

## Exercise 1: Add Logging

## Exercise 2: Health Checks
- [ ] Startup Probe
- [ ] Readiness Probe
- [ ] Liveness Probe

## Exercise 3: Add Metrics
- Metrics Endpoint

## Exercise 4: Add Tracing
- https://github.com/open-telemetry/opentelemetry-rust/issues/1478
-

## Exercise 5: Load Testing
- K6
```sh
helm repo add grafana https://grafana.github.io/helm-charts
helm install k6-operator grafana/k6-operator
```

## Exercise 6: Chaos Testing
- Chaos Mesh
```sh
helm repo add chaos-mesh https://charts.chaos-mesh.org
helm install chaos-mesh chaos-mesh/chaos-mesh -n=chaos-mesh --set chaosDaemon.runtime=containerd --set chaosDaemon.socketPath=/run/k3s/containerd/containerd.sock --version 2.6.3 --create-namespace
```
5 changes: 5 additions & 0 deletions podtato-head/delivery/chart/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
apiVersion: v2
name: podtato-head
description: Deploys the podtato-head app
version: 0.2.7
appVersion: 0.2.7
143 changes: 143 additions & 0 deletions podtato-head/delivery/chart/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
# Deliver with Helm

Here's how to deliver podtato-head using [Helm](https://helm.sh).

## Prerequisites

- Install Helm ([official instructions](https://helm.sh/docs/intro/install/))

## Deliver

You must clone this repo and install from a local copy of the chart:

```
git clone https://github.com/podtato-head/podtato-head.git && cd podtato-head
helm install podtato-head ./delivery/chart
```

This will install the chart in this directory with release name `podtato-head`.

> NOTE: You can instruct helm to wait for the resources to be ready before
marking the release as successful by adding the `--wait` option to the previous
command.

The installation can be customized by changing the following parameters via
`--set` or a custom `values.yaml` file specified with `--values`:

| Parameter | Description | Default |
| ------------------------------- | ----------------------------------------------------------------| -----------------------------|
| `replicaCount` | Number of replicas of the container | `1` |
| `images.repositoryDirname` | Prefix for image repos | `ghcr.io/podtato-head` |
| `images.pullPolicy` | Podtato Head Container pull policy | `IfNotPresent` |
| `images.pullSecrets` | Podtato Head Pod pull secret | `[]` |
| `<service>.repositoryBasename` | Leaf part of name of image repo for <service> | `entry`, `hat`, etc. |
| `<service>.runtimeClassName` | RuntimeClassName used for pod | `empty` |
| `<service>.tag` | Tag of image repo for <service> | `0.1.0` |
| `<service>.serviceType` | Service type for <service> | `LoadBalancer` for main |
| `<service>.servicePort` | Service port for <service> | `9000`-`9005` |
| `<service>.env` | Add "env:" entries on Deployments (ex: PODTATO_PART_NUMBER) | `[]` |
| `serviceAccount.create` | Whether or not to create dedicated service account | `true` |
| `serviceAccount.name` | Name of the service account to use | `default` |
| `serviceAccount.annotations` | Annotations to add to a created service account | `{}` |
| `podAnnotations` | Map of annotations to add to the pods | `{}` |
| `ingress.enabled` | Enables Ingress | `false` |
| `ingress.className` | IngressClass that will be be used (Kubernetes 1.18+) | `""` |
| `ingress.annotations` | Ingress annotations | `{}` |
| `ingress.hosts` | Ingress accepted hostnames | `[]` |
| `ingress.tls` | Ingress TLS configuration | `[]` |
| `autoscaling.enabled` | Enable horizontal pod autoscaler | `false` |
| `autoscaling.targetCPUUtilizationPercentage` | Target CPU utilization | `80` |
| `autoscaling.targetMemoryUtilizationPercentage` | Target Memory utilization | `80` |
| `autoscaling.minReplicas` | Min replicas for autoscaling | `1` |
| `autoscaling.maxReplicas` | Max replicas for autoscaling | `100` |
| `tolerations` | List of node taints to tolerate | `[]` |
| `resources` | Resource requests and limits | `{}` |
| `nodeSelector` | Labels for pod assignment | `{}` |

## Test

Verify the release succeeded:

```
helm list
kubectl get pods
kubectl get services
```

### Test the API endpoint

To connect to the API you'll first need to determine the correct address and
port.

If using a LoadBalancer-type service for `entry`, get the IP address of the load balancer
and use port 9000:

```
ADDR=$(kubectl get service podtato-head-entry -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
PORT=9000
```

If using a NodePort-type service, get the address of a node and the service's
NodePort as follows:

```
NODE_NAME=$(kubectl get nodes --output json | jq -r '.items[].metadata.name' | head -n 1)
ADDR=$(kubectl get nodes ${NODE_NAME} -o jsonpath={.status.addresses[0].address})
PORT=$(kubectl get services podtato-head-entry -ojsonpath='{.spec.ports[0].nodePort}')
```

If using a ClusterIP-type service, run `kubectl port-forward` in the background
and connect through that:

> NOTE: Find and kill the port-forward process afterwards using `ps` and `kill`.
```
# Choose below the IP address of your machine you want to use to access application
ADDR=127.0.0.1
# Choose below the port of your machine you want to use to access application
PORT=9000
kubectl port-forward --address ${ADDR} svc/podtato-head-entry ${PORT}:9000 &
```

Now test the API itself with curl and/or a browser:

```
curl http://${ADDR}:${PORT}/
xdg-open http://${ADDR}:${PORT}/
```

## Update

To update the application version, you can choose one of the following methods :

- update `<service>.tag` in `values.yaml` for each service and run `helm upgrade podtato-head ./delivery/chart`
- run `helm upgrade podtato-head ./delivery/chart --set entry.tag=0.1.1 --set leftLeg.tag=0.1.1 ...`

A new revision is then installed.

> NOTE : to ensure idempotency between the first installation and the following updates, you should use the following command :
```
helm upgrade --install podtato-head ./delivery/chart
```

## Rollback

To rollback to a previous revision, run :

```
# Check revision history
helm history podtato-head
# Rollback to the revision 1
helm rollback podtato-head 1
# Check the revision
helm status podtato-head
```

## Uninstall

```
helm uninstall podtato-head
```
22 changes: 22 additions & 0 deletions podtato-head/delivery/chart/templates/NOTES.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
## Get the application URL by running these commands:
{{- if .Values.ingress.enabled }}
{{- range $host := .Values.ingress.hosts }}
{{- range .paths }}
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
{{- end }}
{{- end }}
{{- else if contains "NodePort" .Values.entry.serviceType }}
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ printf "%s-%s" (include "podtato-head.fullname" .) "entry" }})
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT
{{- else if contains "LoadBalancer" .Values.entry.serviceType }}
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
You can watch its status by running 'kubectl get --namespace {{ .Release.Namespace }} service --watch {{ printf "%s-%s" (include "podtato-head.fullname" .) "entry" }}'
export SERVICE_IP=$(kubectl get service --namespace {{ .Release.Namespace }} {{ printf "%s-%s" (include "podtato-head.fullname" .) "entry" }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
echo http://$SERVICE_IP:{{ .Values.entry.servicePort }}
{{- else if contains "ClusterIP" .Values.entry.serviceType }}
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/component={{ printf "%s-%s" (include "podtato-head.fullname" .) "entry" }}" -o jsonpath="{.items[0].metadata.name}")
export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
echo "Run the following command then get to you app at http://127.0.0.1:8080"
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
{{- end }}
62 changes: 62 additions & 0 deletions podtato-head/delivery/chart/templates/_helpers.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "podtato-head.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "podtato-head.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}

{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "podtato-head.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/*
Common labels
*/}}
{{- define "podtato-head.labels" -}}
helm.sh/chart: {{ include "podtato-head.chart" . }}
{{ include "podtato-head.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}

{{/*
Selector labels
*/}}
{{- define "podtato-head.selectorLabels" -}}
app.kubernetes.io/name: {{ include "podtato-head.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}

{{/*
Create the name of the service account to use
*/}}
{{- define "podtato-head.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "podtato-head.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}
16 changes: 16 additions & 0 deletions podtato-head/delivery/chart/templates/configmap-discovery.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{{ $componentName := "service-discovery" }}
---
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ printf "%s-%s" (include "podtato-head.fullname" .) $componentName }}
labels:
{{- include "podtato-head.labels" . | nindent 4 }}
app.kubernetes.io/component: {{ printf "%s-%s" (include "podtato-head.fullname" .) $componentName }}
data:
servicesConfig.yaml: |
hat: "http://{{ include "podtato-head.fullname" . }}-hat:{{ .Values.hat.servicePort }}"
left-leg: "http://{{ include "podtato-head.fullname" . }}-left-leg:{{ .Values.leftLeg.servicePort }}"
left-arm: "http://{{ include "podtato-head.fullname" . }}-left-arm:{{ .Values.leftArm.servicePort }}"
right-leg: "http://{{ include "podtato-head.fullname" . }}-right-leg:{{ .Values.rightLeg.servicePort }}"
right-arm: "http://{{ include "podtato-head.fullname" . }}-right-arm:{{ .Values.rightArm.servicePort }}"
Loading

0 comments on commit 5ca24e5

Please sign in to comment.