diff --git a/deploy/src/main/sandbox-k8s/00-install-k3s.sh b/deploy/src/main/sandbox-k8s/00-install-k3s.sh new file mode 100755 index 0000000000..bc178928f2 --- /dev/null +++ b/deploy/src/main/sandbox-k8s/00-install-k3s.sh @@ -0,0 +1,18 @@ +#!/bin/sh +#******************************************************************************* +# Copyright (c) 2021 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Eclipse Public License 2.0 which is available at +# http://www.eclipse.org/legal/epl-2.0 +# +# SPDX-License-Identifier: EPL-2.0 +#******************************************************************************* + +# This script installs the current version of k3s. It is intended to be only used +# on the Eclipse Foundation's Hono sandbox VM. + +curl -sfL https://get.k3s.io | sh -s - server --node-name hono.eclipseprojects.io diff --git a/deploy/src/main/sandbox-k8s/10-deploy-cert-manager.sh b/deploy/src/main/sandbox-k8s/10-deploy-cert-manager.sh new file mode 100755 index 0000000000..91f93aa839 --- /dev/null +++ b/deploy/src/main/sandbox-k8s/10-deploy-cert-manager.sh @@ -0,0 +1,54 @@ +#!/bin/bash +#******************************************************************************* +# Copyright (c) 2021 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Eclipse Public License 2.0 which is available at +# http://www.eclipse.org/legal/epl-2.0 +# +# SPDX-License-Identifier: EPL-2.0 +#******************************************************************************* + +# This script takes care to provide a public certificate from Let's Encrypt. +# It creates the namespace "hono", deploys the Cert-Manager and requests a certificate. +# The script expects an email address to be used by Let's Encrypt, as the first argument. +# The second argument must be "production" to create a valid certificate. If it is not set, +# the issuer will be configured to use the Let's Encrypt Staging API. This is to avoid +# hitting a limit on Let's Encrypt's productive API. + +SCRIPTPATH="$(cd "$(dirname "$0")" && pwd -P)" +source $SCRIPTPATH/common.sh + +NS_CERT_MANAGER=cert-manager +EMAIL=$1 +LE_API=${2:-"staging"} + + +retry() { + "$@" + while [ $? -ne 0 ]; do + sleep 2s + echo "retrying" "$@" + "$@" + done +} + +kubectl create namespace hono $KUBECONFIG + +# add Helm repo +helm repo add jetstack https://charts.jetstack.io $KUBECONFIG +helm repo update $KUBECONFIG + +echo "" +echo "Deploying cert-manager..." +helm install cert-manager jetstack/cert-manager --namespace $NS_CERT_MANAGER --create-namespace --set installCRDs=true $KUBECONFIG $HELM_WAIT # --version v1.4.0 + +# checking when cert-manager is ready is tricky: https://cert-manager.io/docs/installation/kubernetes/#verifying-the-installation +# we just retry the following command +echo "" +echo "Adding issuer Let's Encrypt to cert-manager with API: $LE_API" +LE_CONFIG=$(helm template ./letsencrypt-chart -f ./letsencrypt-chart/values-$LE_API.yaml --set spec.acme.email=$EMAIL) +retry echo "$LE_CONFIG" | kubectl apply -f - $KUBECONFIG || true # do not abort although '-e' is set diff --git a/deploy/src/main/sandbox-k8s/20-deploy-hono.sh b/deploy/src/main/sandbox-k8s/20-deploy-hono.sh new file mode 100755 index 0000000000..71c51b3727 --- /dev/null +++ b/deploy/src/main/sandbox-k8s/20-deploy-hono.sh @@ -0,0 +1,28 @@ +#!/bin/bash +#******************************************************************************* +# Copyright (c) 2021 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Eclipse Public License 2.0 which is available at +# http://www.eclipse.org/legal/epl-2.0 +# +# SPDX-License-Identifier: EPL-2.0 +#******************************************************************************* + +# This script deploys Hono to the Eclipse Foundation's sandbox at hono.eclipseprojects.io +# It requires that the namespace "hono" already exists and that the secret for the certificate is present. + +SCRIPTPATH="$(cd "$(dirname "$0")" && pwd -P)" +source $SCRIPTPATH/common.sh + + +# add Helm repos +helm repo add eclipse-iot https://eclipse.org/packages/charts $KUBECONFIG +helm repo update $KUBECONFIG + +echo "" +echo "Deploying hono..." +helm install eclipse-hono --dependency-update -f hono-values.yml -n hono eclipse-iot/hono $KUBECONFIG $HELM_WAIT diff --git a/deploy/src/main/sandbox-k8s/common.sh b/deploy/src/main/sandbox-k8s/common.sh new file mode 100644 index 0000000000..471b881326 --- /dev/null +++ b/deploy/src/main/sandbox-k8s/common.sh @@ -0,0 +1,18 @@ +#!/bin/bash +#******************************************************************************* +# Copyright (c) 2021 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Eclipse Public License 2.0 which is available at +# http://www.eclipse.org/legal/epl-2.0 +# +# SPDX-License-Identifier: EPL-2.0 +#******************************************************************************* + +set -ue + +KUBECONFIG="--kubeconfig /etc/rancher/k3s/k3s.yaml" +HELM_WAIT="--wait --timeout 5m0s" diff --git a/deploy/src/main/sandbox-k8s/hono-values.yml b/deploy/src/main/sandbox-k8s/hono-values.yml new file mode 100644 index 0000000000..6a4463fe9d --- /dev/null +++ b/deploy/src/main/sandbox-k8s/hono-values.yml @@ -0,0 +1,243 @@ +# +# Copyright (c) 2021 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Eclipse Public License 2.0 which is available at +# http://www.eclipse.org/legal/epl-2.0 +# +# SPDX-License-Identifier: EPL-2.0 +# + +honoImagesType: "quarkus-native" + +useLoadBalancer: true + +messagingNetworkTypes: + - "amqp" + - "kafka" + +amqpMessagingNetworkExample: + enabled: true + dispatchRouter: + keyFile: "/etc/external-tls/tls.key" + certFile: "/etc/external-tls/tls.crt" + uidFormat: "n" + adapterUids: "hono.eclipseprojects.io" + extraSecretMounts: + sandbox: + secretName: "sandbox-tls" + mountPath: "/etc/external-tls" + +kafkaMessagingClusterExample: + enabled: true + +adapters: + http: + enabled: true + hono: + healthCheck: + port: 8088 + bindAddress: "0.0.0.0" + keyPath: "/etc/external-tls/tls.key" + certPath: "/etc/external-tls/tls.crt" + http: + bindAddress: "0.0.0.0" + keyPath: "/etc/external-tls/tls.key" + certPath: "/etc/external-tls/tls.crt" + insecurePortEnabled: true + insecurePortBindAddress: "0.0.0.0" + jmsVendorPropsEnabled: true + maxPayloadSize: 8096 + tenantIdleTimeout: "1h" + extraSecretMounts: + sandbox: + secretName: "sandbox-tls" + mountPath: "/etc/external-tls" + resources: + requests: + cpu: + memory: "96Mi" + limits: + cpu: + memory: "96Mi" + + mqtt: + enabled: true + hono: + healthCheck: + port: 8088 + bindAddress: "0.0.0.0" + keyPath: "/etc/external-tls/tls.key" + certPath: "/etc/external-tls/tls.crt" + mqtt: + bindAddress: "0.0.0.0" + keyPath: "/etc/external-tls/tls.key" + certPath: "/etc/external-tls/tls.crt" + insecurePortEnabled: true + insecurePortBindAddress: "0.0.0.0" + jmsVendorPropsEnabled: true + maxPayloadSize: 8096 + tenantIdleTimeout: "1h" + maxConnections: 200 + extraSecretMounts: + sandbox: + secretName: "sandbox-tls" + mountPath: "/etc/external-tls" + resources: + requests: + cpu: + memory: "96Mi" + limits: + cpu: + memory: "96Mi" + + amqp: + enabled: true + hono: + healthCheck: + port: 8088 + bindAddress: "0.0.0.0" + keyPath: "/etc/external-tls/tls.key" + certPath: "/etc/external-tls/tls.crt" + amqp: + bindAddress: "0.0.0.0" + keyPath: "/etc/external-tls/tls.key" + certPath: "/etc/external-tls/tls.crt" + insecurePortEnabled: true + insecurePortBindAddress: "0.0.0.0" + tenantIdleTimeout: "1h" + maxConnections: 200 + extraSecretMounts: + sandbox: + secretName: "sandbox-tls" + mountPath: "/etc/external-tls" + resources: + requests: + cpu: + memory: "96Mi" + limits: + cpu: + memory: "96Mi" + + coap: + enabled: true + hono: + healthCheck: + port: 8088 + bindAddress: "0.0.0.0" + keyPath: "/etc/external-tls/tls.key" + certPath: "/etc/external-tls/tls.crt" + coap: + bindAddress: "0.0.0.0" + port: 5684 + insecurePortEnabled: true + keyPath: "/etc/external-tls/tls.key" + certPath: "/etc/external-tls/tls.crt" + tenantIdleTimeout: "1h" + maxConnections: 400 + extraSecretMounts: + sandbox: + secretName: "sandbox-tls" + mountPath: "/etc/external-tls" + resources: + requests: + cpu: + memory: "96Mi" + limits: + cpu: + memory: "96Mi" + + kura: + enabled: false + + lora: + enabled: false + + amqpMessagingNetworkSpec: + keyPath: "/etc/external-tls/tls.key" + certPath: "/etc/external-tls/tls.crt" + hostnameVerificationRequired: false + commandAndControlSpec: + keyPath: "/etc/external-tls/tls.key" + certPath: "/etc/external-tls/tls.crt" + hostnameVerificationRequired: false + +authServer: + resources: + requests: + cpu: + memory: "32Mi" + limits: + cpu: + memory: "32Mi" + +deviceRegistryExample: + type: "embedded" + hono: + registry: + amqp: + bindAddress: "0.0.0.0" + keyPath: "/etc/external-tls/tls.key" + certPath: "/etc/external-tls/tls.crt" + http: + authenticationRequired: false + bindAddress: "0.0.0.0" + keyPath: "/etc/external-tls/tls.key" + certPath: "/etc/external-tls/tls.crt" + insecurePortEnabled: true + insecurePortBindAddress: "0.0.0.0" + extraSecretMounts: + sandbox: + secretName: "sandbox-tls" + mountPath: "/etc/external-tls" + resources: + requests: + cpu: + memory: "300Mi" + limits: + cpu: + memory: "300Mi" + +commandRouterService: + extraSecretMounts: + sandbox: + secretName: "sandbox-tls" + mountPath: "/etc/external-tls" + resources: + requests: + cpu: + memory: "128Mi" + limits: + cpu: + memory: "128Mi" + +kafka: + auth: + clientProtocol: "sasl" # no TLS. That would be "sasl_tls" + persistence: + size: 200Mi + zookeeper: + persistence: + size: 200Mi + externalAccess: + service: + type: "LoadBalancer" + autoDiscovery: + resources: + requests: + cpu: 100m + resources: + requests: + cpu: 100m + +jaegerBackendExample: + enabled: false + +prometheus: + createInstance: false + +grafana: + enabled: false diff --git a/deploy/src/main/sandbox-k8s/letsencrypt-chart/Chart.yaml b/deploy/src/main/sandbox-k8s/letsencrypt-chart/Chart.yaml new file mode 100644 index 0000000000..9ff27f98d3 --- /dev/null +++ b/deploy/src/main/sandbox-k8s/letsencrypt-chart/Chart.yaml @@ -0,0 +1,12 @@ +# This Helm chart is only used for templating not to deploy something. +# It renders the issuer and certificate files for cert-manager depending +# on the Let's Encrypt API to be used and it expects the email to be provided +# on invocation like the following example: +# helm template . -f ./values-staging.yaml --set spec.acme.email=foo@bar.baz + +apiVersion: v2 +name: lets-encrypt-chart +description: A Helm chart used to render issuer and certificate files for cert-manager. +type: application +version: 0.1.0 +appVersion: "0.1.0" diff --git a/deploy/src/main/sandbox-k8s/letsencrypt-chart/templates/letsencrypt-certificate.yml b/deploy/src/main/sandbox-k8s/letsencrypt-chart/templates/letsencrypt-certificate.yml new file mode 100644 index 0000000000..feb1ba4257 --- /dev/null +++ b/deploy/src/main/sandbox-k8s/letsencrypt-chart/templates/letsencrypt-certificate.yml @@ -0,0 +1,22 @@ +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: hono-eclipseprojects-io + namespace: hono +spec: + # Secret names are always required. + secretName: sandbox-tls + duration: 2160h # 90d + renewBefore: 528h # 22d + subject: + organizations: + - "Eclipse Foundation" + commonName: hono.eclipseprojects.io + usages: + - server auth + - client auth + dnsNames: + - hono.eclipseprojects.io + issuerRef: + name: {{ .Values.spec.acme.privateKeySecretRef.name }} + kind: ClusterIssuer diff --git a/deploy/src/main/sandbox-k8s/letsencrypt-chart/templates/letsencrypt-issuer.yml b/deploy/src/main/sandbox-k8s/letsencrypt-chart/templates/letsencrypt-issuer.yml new file mode 100644 index 0000000000..9d3f487cb3 --- /dev/null +++ b/deploy/src/main/sandbox-k8s/letsencrypt-chart/templates/letsencrypt-issuer.yml @@ -0,0 +1,19 @@ +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + name: {{ .Values.metadata.name }} +spec: + acme: + # You must replace this email address with your own. + # Let's Encrypt will use this to contact you about expiring + # certificates, and issues related to your account. + email: {{ required ".Values.spec.acme.email MUST be set" .Values.spec.acme.email }} + server: {{ .Values.spec.acme.server }} + privateKeySecretRef: + # Secret resource that will be used to store the account's private key. + name: {{ .Values.spec.acme.privateKeySecretRef.name }} + # Add a single challenge solver, HTTP01 using traefik + solvers: + - http01: + ingress: + class: traefik diff --git a/deploy/src/main/sandbox-k8s/letsencrypt-chart/values-production.yaml b/deploy/src/main/sandbox-k8s/letsencrypt-chart/values-production.yaml new file mode 100644 index 0000000000..5f0bb2b473 --- /dev/null +++ b/deploy/src/main/sandbox-k8s/letsencrypt-chart/values-production.yaml @@ -0,0 +1,8 @@ +metadata: + name: letsencrypt-prod + +spec: + acme: + server: https://acme-v02.api.letsencrypt.org/directory + privateKeySecretRef: + name: letsencrypt-prod diff --git a/deploy/src/main/sandbox-k8s/letsencrypt-chart/values-staging.yaml b/deploy/src/main/sandbox-k8s/letsencrypt-chart/values-staging.yaml new file mode 100644 index 0000000000..f874a525b0 --- /dev/null +++ b/deploy/src/main/sandbox-k8s/letsencrypt-chart/values-staging.yaml @@ -0,0 +1,8 @@ +metadata: + name: letsencrypt-staging + +spec: + acme: + server: https://acme-staging-v02.api.letsencrypt.org/directory + privateKeySecretRef: + name: letsencrypt-staging diff --git a/deploy/src/main/sandbox-k8s/readme.md b/deploy/src/main/sandbox-k8s/readme.md new file mode 100644 index 0000000000..c117a89132 --- /dev/null +++ b/deploy/src/main/sandbox-k8s/readme.md @@ -0,0 +1,30 @@ +This folder contains scripts and configuration files for setting up a Hono *sandbox* that runs in a Kubernetes cluster with the following properties: + +* Clients can register devices for arbitrary tenants using Device Registry's REST interface (requires registering the device itself as well as corresponding credentials). +* Devices can publish telemetry data and events for the tenant they have been registered with using the deployed protocol adapters. +* Devices can subscribe for receiving commands. +* An AMQP 1.0 based messaging network is provided as well as a Kafka cluster. The messaging type can be configured per tenant. Northbound clients need to use the corresponding API. +* Consumers can receive telemetry data and events for arbitrary tenants using the Telemetry and Event APIs. +* Consumers and devices are required to authenticate with the Dispatch Router and the adapters respectively. + +# Deployment + +The scripts need to be executed in the order of the numbers in the file names: + +1. Install Kubernetes: `sudo ./00-install-k3s.sh`. +2. Deploy the [cert-manager](https://cert-manager.io/) & request a public certificate from Let's Encrypt: `sudo ./10-deploy-cert-manager.sh $LE_EMAIL` (creates the namespace "hono"). +3. Deploy Hono: `sudo ./20-deploy-hono.sh`. + +**NB:** Let's Encrypt has quite strict rate limits. Therefore the script `10-deploy-cert-manager.sh` does not use +the productive Let's Encrypt API by default. After the retrieval of a certificate has been successfully tested, +execute the script again with `production` as the second argument to request a valid certificate from the productive API. + +The scripts need to be executed with `sudo` because the Kube config is only readable by root. + +# Updating the Let's Encrypt certificate + +Cert-Manager automatically renews the public-facing Let's Encrypt certificate. + +Once the certificate has been renewed, the Hono installation need to be upgraded in order to pick up the updated certificate: + +`sudo helm upgrade eclipse-hono -f hono-values.yml -n hono eclipse-iot/hono`