Skip to content

Commit

Permalink
doc: Include samples (#1279)
Browse files Browse the repository at this point in the history
* sample for Deploying Akka Cluster to Kubernetes
* zip download from docs
  • Loading branch information
patriknw authored Apr 18, 2024
1 parent 7be9741 commit 6b744c2
Show file tree
Hide file tree
Showing 28 changed files with 973 additions and 13 deletions.
62 changes: 62 additions & 0 deletions .github/workflows/integration-tests-samples.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
name: Integration test for akka-sample-cluster-kubernetes-scala

on:
pull_request:
push:
branches:
- main
- release-*
tags-ignore: [ v.* ]
schedule:
- cron: '0 2 * * *' # every day 2am

permissions:
contents: read

jobs:
integration-test:
name: Integration Tests for akka-sample-cluster-kubernetes-scala
runs-on: ubuntu-22.04
steps:
- name: Checkout
# https://github.com/actions/checkout/releases
# v4.1.1
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
with:
fetch-depth: 0

- name: Checkout GitHub merge
if: github.event.pull_request
run: |-
git fetch origin pull/${{ github.event.pull_request.number }}/merge:scratch
git checkout scratch
- name: Cache Coursier cache
# https://github.com/coursier/cache-action/releases
# v6.4.5
uses: coursier/cache-action@1ff273bff02a8787bc9f1877d347948af647956d

- name: Set up JDK 17
# https://github.com/coursier/setup-action/releases
# v1.3.5
uses: coursier/setup-action@7bde40eee928896f074dbb76d22dd772eed5c65f
with:
jvm: temurin:1.17.0

- name: Setup Minikube
# https://github.com/manusa/actions-setup-minikube/releases
# v2.7.1
uses: manusa/actions-setup-minikube@4582844dcacbf482729f8d7ef696f515d2141bb9
with:
minikube version: 'v1.32.0'
kubernetes version: 'v1.28.4'
driver: docker
start args: '--addons=ingress'

- name: Run Integration Tests
run: |-
./integration-test/akka-sample-cluster-kubernetes-scala/test.sh
- name: Print logs on failure
if: ${{ failure() }}
run: find . -name "*.log" -exec ./scripts/cat-log.sh {} \;
1 change: 1 addition & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ jobs:

- name: Publish
run: |-
scripts/prepare-downloads.sh
eval "$(ssh-agent -s)"
echo $AKKA_RSYNC_GUSTAV | base64 -d > .github/id_rsa
chmod 600 .github/id_rsa
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,6 @@ target/

.metals
.vscode

# attachments created by scripts/prepare-downloads.sh
docs/src/main/paradox/attachments
4 changes: 2 additions & 2 deletions docs/release-train-issue-template.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Variables to be expanded in this template:

- [ ] Check that open PRs and issues assigned to the milestone are reasonable
- [ ] Update the Change date and version in the LICENSE file.
- [ ] Update the Akka Management version in the samples to $VERSION$, otherwise the published zip files of the samples will have the old version.
- [ ] Create a new milestone for the [next version](https://github.com/akka/akka-management/milestones)
- [ ] Close the [$VERSION$ milestone](https://github.com/akka/akka-management/milestones?direction=asc&sort=due_date)
- [ ] Make sure all important PRs have been merged
Expand Down Expand Up @@ -46,7 +47,6 @@ For important patch releases, and only if critical issues have been fixed:
- [ ] Send a release notification to [Lightbend discuss](https://discuss.akka.io)
- [ ] Tweet using the [@akkateam](https://twitter.com/akkateam/) account (or ask someone to) about the new release
- [ ] Announce on [Gitter akka/akka](https://gitter.im/akka/akka)
- [ ] Announce internally (with links to Tweet, discuss)
For minor or major releases:
Expand All @@ -56,6 +56,6 @@ For minor or major releases:
### Afterwards
- [ ] Update [akka-dependencies bom](https://github.com/lightbend/akka-dependencies) and version for [Akka module versions](https://doc.akka.io/docs/akka-dependencies/current/) in [akka-dependencies repo](https://github.com/akka/akka-dependencies)
- [ ] Update [Akka Guide samples](https://github.com/akka/akka-platform-guide)
- [ ] Update [Akka Guide samples](https://github.com/lightbend/akka-guide)
- Close this issue
10 changes: 4 additions & 6 deletions docs/src/main/paradox/bootstrap/recipes.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,6 @@
A set of integration tests projects can be found in [integration-test folder of the Akka Management project](https://github.com/akka/akka-management/tree/main/integration-test).
These test various Akka management features together in various environments such as Kubernetes.

The following samples exist as standalone projects:

* [Akka Cluster bootstrap using the Kubernetes API with Java/Maven](https://github.com/akka/akka-sample-cluster-kubernetes-java)
* [Akka Cluster bootstrap using DNS in Kubernetes](https://github.com/akka/akka-sample-cluster-kubernetes-dns-java)

## Local

To run Bootstrap locally without any dependencies such as DNS or Kubernetes see the @ref[`local` example](local-config.md)
Expand All @@ -25,7 +20,10 @@ The recommended approach is to:

### Example project

To get started, it might be helpful to have a look at the [Akka Cluster on Kubernetes](https://developer.lightbend.com/start/?group=akka&project=akka-sample-cluster-kubernetes-java) example project.
To get started, it might be helpful to have a look at the example projects.

* [Akka Cluster bootstrap using the Kubernetes API with Java/Maven](../attachments/akka-sample-cluster-kubernetes-java.zip)
* [Akka Cluster bootstrap using the Kubernetes API with Scala/sbt](../attachments/akka-sample-cluster-kubernetes-scala.zip)

### Kubernetes Deployment

Expand Down
4 changes: 2 additions & 2 deletions docs/src/main/paradox/kubernetes-deployment/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
For this guide we will be using the Akka Cluster in Kubernetes sample.
It is available for both:

* [Java](https://developer.lightbend.com/start/?group=akka&project=akka-sample-cluster-kubernetes-java)
* [Scala](https://developer.lightbend.com/start/?group=akka&project=akka-sample-cluster-kubernetes-scala)
* [Java](../attachments/akka-sample-cluster-kubernetes-java.zip)
* [Scala](../attachments/akka-sample-cluster-kubernetes-scala.zip)

@@toc { depth=2 }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ In preparation for production, we need to do two main things:
The final configuration file and deployment spec are in the sample application.
In this guide we will show snippets. Locations of the samples:

* [Java](https://developer.lightbend.com/start/?group=akka&project=akka-sample-cluster-kubernetes-java)
* [Scala](https://developer.lightbend.com/start/?group=akka&project=akka-sample-cluster-kubernetes-scala)
* [Java](../attachments/akka-sample-cluster-kubernetes-java.zip)
* [Scala](../attachments/akka-sample-cluster-kubernetes-scala.zip)

## Deployment Spec

Expand Down
63 changes: 63 additions & 0 deletions integration-test/akka-sample-cluster-kubernetes-scala/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#!/bin/bash

set -exu

export NAMESPACE=appka-1
export APP_NAME=appka
export PROJECT_DIR=samples/akka-sample-cluster-kubernetes-scala
export DEPLOYMENT=kubernetes/akka-cluster.yml

eval $(minikube -p minikube docker-env)
cd $PROJECT_DIR
sbt Docker/publishLocal

docker images | head

kubectl create namespace $NAMESPACE || true
kubectl -n $NAMESPACE apply -f $DEPLOYMENT

for i in {1..10}
do
echo "Waiting for pods to get ready..."
kubectl get pods -n $NAMESPACE
[ `kubectl get pods -n $NAMESPACE | grep Running | wc -l` -eq 3 ] && break
sleep 4
done

if [ $i -eq 10 ]
then
echo "Pods did not get ready"
kubectl -n $NAMESPACE events $APP_NAME
kubectl -n $NAMESPACE describe deployment $APP_NAME
exit -1
fi

POD=$(kubectl get pods -n $NAMESPACE | grep $APP_NAME | grep Running | head -n1 | awk '{ print $1 }')

for i in {1..15}
do
echo "Checking for MemberUp logging..."
kubectl logs $POD -n $NAMESPACE | grep MemberUp || true
[ `kubectl logs -n $NAMESPACE $POD | grep MemberUp | wc -l` -eq 3 ] && break
sleep 3
done

echo "Logs"
echo "=============================="
for POD in $(kubectl get pods -n $NAMESPACE | grep $APP_NAME | grep Running | awk '{ print $1 }')
do
echo "Logging for $POD"
kubectl logs $POD -n $NAMESPACE
done


if [ $i -eq 15 ]
then
echo "No 3 MemberUp log events found"
echo "=============================="

exit -1
fi



2 changes: 1 addition & 1 deletion integration-test/scripts/kubernetes-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ sbt $PROJECT_NAME/Docker/publishLocal

docker images | head

kubectl create namespace akka-bootstrap-demo-ns || true
kubectl create namespace $NAMESPACE || true
kubectl -n $NAMESPACE apply -f $DEPLOYMENT

for i in {1..10}
Expand Down
58 changes: 58 additions & 0 deletions samples/akka-sample-cluster-kubernetes-java/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# akka-sample-cluster-kubernetes-java
akka sample cluster with kubernetes discovery in scala

This is an example SBT project showing how to create an Akka Cluster on
Kubernetes.

## Kubernetes Instructions

## Starting

First, package the application and make it available locally as a docker image:

mvn clean package docker:build

Then `akka-cluster.yml` should be sufficient to deploy a 2-node Akka Cluster, after
creating a namespace for it:

kubectl apply -f kubernetes/namespace.json
kubectl config set-context --current --namespace=appka-1
kubectl apply -f kubernetes/akka-cluster.yml

To check what you have done in Kubernetes so far, you can do:

kubectl get deployments
kubectl get pods
kubectl get replicasets
kubectl cluster-info dump
kubectl logs appka-79c98cf745-abcdee # pod name

Finally, create a service so that you can then test [http://127.0.0.1:8080](http://127.0.0.1:8080)
for 'hello world':

kubectl expose deployment appka --type=LoadBalancer --name=appka-service
kubectl port-forward svc/appka-service 8080:8080

To wipe everything clean and start over, do:

kubectl delete namespaces appka-1

## Running in a real Kubernetes cluster

#### Publish to a registry the cluster can access e.g. Dockerhub with the kubakka user

The app image must be in a registry the cluster can see. The build.sbt uses DockerHub by default.
Use `mvn -Ddocker.registry=$DOCKER_REPO_URL/$NAMESPACE` if your cluster can't access DockerHub.

To push an image to docker hub run:

mvn -am -pl bootstrap-demo-kubernetes-api package docker:push

And remove the `imagePullPolicy: Never` from the deployments. Then you can use the same `kubectl` commands
as described in the [Starting](#starting) section.

## How it works

This example uses [Akka Cluster Bootstrap](https://doc.akka.io/docs/akka-management/current/bootstrap/index.html)
to initialize the cluster, using the [Kubernetes API discovery mechanism](https://doc.akka.io/docs/akka-management/current/discovery/index.html#discovery-method-kubernetes-api)
to find peer nodes.
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: appka
name: appka
namespace: appka-1
spec:
replicas: 3
selector:
matchLabels:
app: appka
template:
metadata:
labels:
app: appka
actorSystemName: appka
spec:
containers:
- name: appka
image: akka-sample-cluster-kubernetes:latest
# remove for real clusters, useful for minikube
imagePullPolicy: Never
readinessProbe:
httpGet:
path: /ready
port: management
periodSeconds: 10
failureThreshold: 3
initialDelaySeconds: 10
livenessProbe:
httpGet:
path: "/alive"
port: management
periodSeconds: 10
failureThreshold: 5
initialDelaySeconds: 20
ports:
# akka remoting
- name: remoting
containerPort: 2552
protocol: TCP
# akka-management and bootstrap
- name: management
containerPort: 8558
protocol: TCP
- name: http
containerPort: 8080
protocol: TCP
env:
- name: NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: REQUIRED_CONTACT_POINT_NR
value: "2"

---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: pod-reader
namespace: appka-1
rules:
- apiGroups: [""] # "" indicates the core API group
resources: ["pods"]
verbs: ["get", "watch", "list"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: read-pods
namespace: appka-1
subjects:
# Note the `name` line below. The first default refers to the namespace. The second refers to the service account name.
# For instance, `name: system:serviceaccount:myns:default` would refer to the default service account in namespace `myns`
- kind: User
name: system:serviceaccount:appka-1:default
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"kind": "Namespace",
"apiVersion": "v1",
"metadata": {
"name": "appka-1",
"labels": {
"name": "appka-1"
}
}
}

Loading

0 comments on commit 6b744c2

Please sign in to comment.