Skip to content

Commit

Permalink
Merge pull request #52 from bancolombia/feature/add-samples-and-docs
Browse files Browse the repository at this point in the history
added manifests and readme's
  • Loading branch information
gabheadz authored Jul 31, 2023
2 parents 35ca997 + c15aea2 commit 0137f77
Show file tree
Hide file tree
Showing 17 changed files with 957 additions and 0 deletions.
20 changes: 20 additions & 0 deletions channel-sender/deploy_samples/k8s/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# K8S Templates

This folder contains templates to deploy channel sender in a kubernetes environment and specific configurations to build an erlang cluster with several nodes.

## Libcluster for cluster erlang configuration

The demo templates rely on [libcluster](https://hexdocs.pm/libcluster/readme.html), which is a dependency used in Sender to configure the Erlang cluster.

## Istio

These templates also asume istio is installed and enforcing mtls cluster-wide.

## Folders

a. [libcluster-kubernetes](./libcluster-kubernetes/README.md): Templates for deploying sender using `libcluster` strategy `Cluster.Strategy.Kubernetes`.

b. [libcluster-kubernetes-dns](./libcluster-kubernetes-dns/README.md): Similar to (A), but using the `Cluster.Strategy.Kubernetes.DNS` strategy.

c. [libcluster-kubernetes-dnssrv](./libcluster-kubernetes-dnssrv/README.md): Similar to (A) but using the
`Cluster.Strategy.Kubernetes.DNSSRV` strategy.
159 changes: 159 additions & 0 deletions channel-sender/deploy_samples/k8s/libcluster-kubernetes-dns/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
# K8S Templates and libcluster strategy Cluster.Strategy.Kubernetes.DNS

## Istio Gateway and VirtualService configuration

Gateway:

```yaml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: adfsender-gw
namespace: sendernm
spec:
selector:
istio: ingressgateway
servers:
- port:
name: secure-port
number: 443
protocol: HTTPS
tls:
## this is a cert and key created as a secret in istio-system namespace
mode: SIMPLE
credentialName: adfsender-credential
hosts:
- adfsender.example.com
```
VirtualService, exposing websocket port:
```yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: adfsender-vs-socket
namespace: sendernm
spec:
hosts:
- adfsender.example.com
gateways:
- adfsender-gw
http:
- match:
- uri:
prefix: /ext/socket
rewrite:
uri: /ext/socket
route:
- destination:
host: adfsender
port:
number: 8082
```
VirtualService, exposing rest endpoints:
```yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: adfsender-vs-rest
namespace: sendernm
spec:
hosts:
- adfsender.example.com
gateways:
- adfsender-gw
http:
- match:
- uri:
prefix: /ext/socket
rewrite:
uri: /ext/socket
route:
- destination:
host: adfsender
port:
number: 8082
```
VirtualService por EPMD port:
```yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: adfsender-vs-epmd
namespace: sendernm
spec:
hosts:
- adfsender-headless
tcp:
- match:
- port: 4369
route:
- destination:
host: adfsender-headless
port:
number: 4369
```
## Erlang cluster configuration
Building an Erlang Cluster with `libcluster` strategy named: [`Cluster.Strategy.Kubernetes.DNS`](https://hexdocs.pm/libcluster/Cluster.Strategy.Kubernetes.DNS.html). You'll need:

- A headless service: This is a kubernetes service without an IP address. This one instead returns pod IP, allowing pods to comunicate each other. See service named `adfsender-headless` in [app.yaml](./app.yaml).

**NOTE**: Unlike strategy `Cluster.Strategy.Kubernetes`, a service-account it is not required.

### 2.1. ADF Sender configuration

a. **Topology config**

You can set topology related configuration in `config\runtime.exs`:

```elixir
import Config
config :logger, level: :info
config :channel_sender_ex,
secret_base:
{"aV4ZPOf7T7HX6GvbhwyBlDM8B9jfeiwi+9qkBnjXxUZXqAeTrehojWKHkV3U0kGc", "socket auth"},
socket_port: 8082,
initial_redelivery_time: 900,
socket_idle_timeout: 30000,
rest_port: 8081,
max_age: 900,
topology: [
strategy: Elixir.Cluster.Strategy.Kubernetes.DNS,
config: [
service: "adfsender-headless"
application_name: "channel_sender_ex"
namespace: "sendernm"
polling_interval: 5000
]
]
```
where:

- `service` it's the headless service name defined in `app.yaml`.
- `application_name` it's the elixir release name. See `mix.exs`. Default release name is `channel_sender_ex`.
- `namespace`: namespace where sender is being deployed.

b. **Define related env vars for release**

via `rel/env.sh.eex` file:

```elixir
export RELEASE_DISTRIBUTION=name
export RELEASE_NODE=<%= @release.name %>@${POD_IP}
```

check env var POD_IP being injected in `app.yaml`.

This will form a node name like: `channel_sender_ex@10.1.2.3`

This pair of files can be mounted as a volume and passed to the container. See `configmap.yaml` and volume mount definition in `app.yaml`.
101 changes: 101 additions & 0 deletions channel-sender/deploy_samples/k8s/libcluster-kubernetes-dns/app.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
apiVersion: v1
kind: Service
metadata:
name: adfsender
namespace: sendernm
labels:
app: adfsender
spec:
selector:
app: adfsender
ports:
- name: socket-http
targetPort: 8082
port: 8082
- name: rest-http
targetPort: 8081
port: 8081
---
##
## headless-service to define EPMD 4369 port, to allow pods to form Erlang cluster.
##
apiVersion: v1
kind: Service
metadata:
name: adfsender-headless
namespace: sendernm
spec:
type: ClusterIP
clusterIP: None
selector:
app: adfsender
ports:
- name: epmd-tcp
port: 4369
targetPort: 4369
protocol: TCP
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: adfsender
namespace: sendernm
labels:
app: adfsender
spec:
replicas: 2
selector:
matchLabels:
app: adfsender
cluster: beam
serviceName: "adfsender-headless"
template:
metadata:
## annotations required for istio-proxy to detect ports
annotations:
traffic.sidecar.istio.io/includeOutboundPorts: "4369"
traffic.sidecar.istio.io/includeInboundPorts: "4369, 8081, 8082"
labels:
app: adfsender
cluster: beam
spec:
containers:
- name: adfsender
image: bancolombia/async-dataflow-channel-sender:0.1.3
env:
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: ERLANG_COOKIE
value: "secret"
- name: RELEASE_COOKIE
value: "secret"
ports:
- name: rest-http
protocol: TCP
containerPort: 8081
- name: socket-http
protocol: TCP
containerPort: 8082
- name: epmd-tcp
protocol: TCP
containerPort: 4369
resources:
requests:
cpu: 250m
memory: 150M
limits:
cpu: 250m
memory: 250M
volumeMounts:
- name: config-volume
mountPath: /app/releases/0.1.3/env.sh
subPath: env.sh
- name: config-volume
mountPath: /app/releases/0.1.3/runtime.exs
subPath: runtime.exs
volumes:
- name: config-volume
configMap:
name: adfsender-config
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: adfsender-config
namespace: sendernm
data:
env.sh: |-
#!/bin/sh
export RELEASE_DISTRIBUTION=name
export RELEASE_NODE=channel_sender_ex@${POD_IP}
runtime.exs: |-
import Config
config :channel_sender_ex,
secret_base:
{"aV4ZPOf7T7HX6GvbhwyBlDM8B9jfeiwi+9qkBnjXxUZXqAeTrehojWKHkV3U0kGc", "socket auth"},
socket_port: 8082,
initial_redelivery_time: 900,
socket_idle_timeout: 30000,
rest_port: 8091,
max_age: 900,
# libcluster topology for this demostration.
# To see other topologies supported by libcluster
# see library documentation.
topology: [
strategy: Cluster.Strategy.Kubernetes.DNS,
config: [
service: "adfsender-headless",
application_name: "channel_sender_ex",
namespace: "sendernm",
polling_interval: 5000
]
]
Loading

0 comments on commit 0137f77

Please sign in to comment.