Of course there are many ways to install BWS in a Kubernetes cluster. Here we give an example using an Azure Kubernetes service cluster. Before you begin, please read through the prerequisites for BWS on-premises installations.
In the example we start with an existing Azure Kubernetes service cluster, that has some additional controllers installed (only required for secure connections):
For this example we need to configure two secrets, containing the MongoDB connection string and the Base64 encoded byte array used to encrypt/decrypt the internally used RSA private key. The YAML file (secrets.yaml) defining these secrets might look as follows:
apiVersion: v1
kind: Secret
metadata:
name: bws-secrets
namespace: bws
type: Opaque
stringData:
mongodb_connectionstring: "mongodb://username:password@mongodb.mydomain.com:27017/bws?ssl=true"
key_secret: "key encryption secret - Base64 encoded byte array"
kubectl create namespace bws
kubectl apply -f secrets.yaml
The BWS Service opionally logs images and some generated output to a mounted volume (/mnt/bwslogging
by default).
To mount this volume later, we specify a PersistentVolumeClaim (here we use a Azure File store):
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: bwslogging
namespace: bws
spec:
storageClassName: azurefile-csi
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Gi
EOF
Now you need access to the BWS Portal container image as described in the prerequisites. To deploy the image, apply the following YAML configuration, after you have changed the image container registry and version to your registry and the latest version:
apiVersion: apps/v1
kind: Deployment
metadata:
name: bws-portal
namespace: bws
spec:
replicas: 1
selector:
matchLabels:
app: bws-portal
template:
metadata:
labels:
app: bws-portal
spec:
containers:
- name: bwsportal
image: bioidcr.azurecr.io/bws/bwsportal-onprem:3.4.24309.2
ports:
- containerPort: 5001
name: bws-portal-svc
env:
- name: ASPNETCORE_URLS
value: "http://+:5001"
- name: MongoDB__ConnectionString
valueFrom:
secretKeyRef:
name: bws-secrets
key: mongodb_connectionstring
- name: KeyEncryption__Secret
valueFrom:
secretKeyRef:
name: bws-secrets
key: key_secret
resources:
requests:
cpu: 10m
memory: 128Mi
limits:
cpu: 500m
memory: 256Mi
volumeMounts:
- mountPath: /mnt/bwslogging
name: logging
volumes:
- name: logging
persistentVolumeClaim:
claimName: bwslogging
---
apiVersion: v1
kind: Service
metadata:
name: bws-portal-service
namespace: bws
spec:
selector:
app: bws-portal
ports:
- name: bws-portal-port
protocol: TCP
port: 80
targetPort: bws-portal-svc
type: LoadBalancer
If secure connections are not required in your setup, you can use LoadBalancer as service type above
to expose the service externally and you should now be able to access the on-prem BWS Portal using the assigned IP address:
$ip = $(kubectl get services bws-portal-service -n bws --output 'jsonpath={..status.loadBalancer.ingress[0].ip}')
Otherwise, if you want to secure the connection to the BWS Portal with TLS, use the ClusterIP service type and create an ingress to route external traffic to the BWS Portal. In this example we use a TLS certificate as issued by Let's Encrypt for the host bws-portal.yourdomain.com. Of course you can create a route without TLS if desired (by removing the annotations and the tls section).
The generated external IP address for this host needs to be added to the yourdomain.com DNS server of course.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
cert-manager.io/cluster-issuer: letsencrypt
name: portal-tls
namespace: bws
spec:
ingressClassName: nginx
rules:
- host: bws-portal.yourdomain.com
http:
paths:
- backend:
service:
name: bws-portal-service
port:
name: bws-portal-port
path: /
pathType: Prefix
tls:
- hosts:
- bws-portal.yourdomain.com
secretName: portal-cert
Now, as you have the BWS Portal up and running, go ahead and configure your BWS installation by using a browser and navigating to bws-portal.yourdomain.com.
When you navigate to the BWS Portal web site for the first time, you have to register as a new user, or, if you have configured an OpenID Connect provider, you can login with your OpenID Connect account.
If the BWS Portal detects that the database does not contain a BWS configuration yet, an initialization process is started.
The user enters a name for the new BWS on-prem installation, e.g. the company name and click on 'Create On-Prem version'.
The following steps are now carried out automatically:
For the communication with BioID, the public key needs to be exported/copied and imported/pasted into the pre-configured on-prem installation client at the BioID BWS Portal (Cloud).
Import your public key by clicking on the 'Create initial protection key' button. The dialog opens, put your public key here and click on the button 'Send Public RSA Key to BioID …'. After a short moment your protection key is generated. Click the button 'Copy Protection Key' and go back to your local BWS Portal.
Copy your Protection Key and finalize the BWS Configuration inside the BWS Portal.
The initial version of BWS should be configured now and you can continue to configure and start the BWSgRPC service.
Please note, that the newly created subscription has no permissions assigned yet. At least one user needs to have owner permissions to this subscription. Therefore you have to add yourself or another responsible person (which has to register at the on-prem BWS Portal first) as Owner to the subscription permissions.
To install the BWS gRPC service, you need access to the BWS gRPC service container image as described in the prerequisites. To deploy the image, apply the following YAML configuration, after you have changed the image container registry and version to your registry and the latest version:
apiVersion: apps/v1
kind: Deployment
metadata:
name: bws-grpc
namespace: bws
spec:
replicas: 2
selector:
matchLabels:
app: bws-grpc
template:
metadata:
labels:
app: bws-grpc
spec:
containers:
- name: bws
image: bioidcr.azurecr.io/bws/bwsgrpc-onprem:3.4.24309.2
resources: # TODO
requests:
memory: "2Gi"
cpu: "1"
limits:
memory: "4Gi"
cpu: "4"
ports:
- containerPort: 50051
name: bws-grpc-svc
- containerPort: 8080
name: bws-http1-svc
livenessProbe:
grpc:
port: 50051
service: liveness
initialDelaySeconds: 10
periodSeconds: 20
readinessProbe:
grpc:
port: 50051
service: readiness
initialDelaySeconds: 10
periodSeconds: 5
env:
- name: Kestrel__Endpoints__gRPC__Protocols
value: Http2
- name: Kestrel__Endpoints__gRPC__Url
value: http://*:50051
- name: Kestrel__Endpoints__RESTful__Protocols
value: Http1
- name: Kestrel__Endpoints__RESTful__Url
value: http://*:8080
- name: MongoDB__ConnectionString
valueFrom:
secretKeyRef:
name: bws-secrets
key: mongodb_connectionstring
- name: ClientService__Secret
valueFrom:
secretKeyRef:
name: bws-secrets
key: key_secret
volumeMounts:
- mountPath: /mnt/bwslogging
name: logging
volumes:
- name: logging
persistentVolumeClaim:
claimName: bwslogging
---
apiVersion: v1
kind: Service
metadata:
name: bws-service
namespace: bws
spec:
selector:
app: bws-grpc
ports:
- name: bws-grpc-port
protocol: TCP
port: 50051
targetPort: bws-grpc-svc
- name: bws-http1-port
protocol: TCP
port: 80
targetPort: bws-http1-svc
type: ClusterIP
Again, if a secure connection to the BWS on-prem service is required, you can create an ingress and route external traffic to the BWS gRPC service. Please take notice of the first two annotations, which instructs NGINX to communicate with the BWS backend service using gRPC via HTTP/2 and sets the maximum allowed size of the client request to the 50MB as also used by the BWS. If you plan to use the RESTful API only, you can remove these annotations and use the bws-http1-port.
In this example again we use a TLS certificate as issued by Let's Encrypt for the host bws.yourdomain.com. The generated external IP address for this host needs to be added to the yourdomain.com DNS server of course.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/backend-protocol: GRPC
nginx.ingress.kubernetes.io/proxy-body-size: 50M
nginx.ingress.kubernetes.io/ssl-redirect: "true"
cert-manager.io/cluster-issuer: letsencrypt
name: bws-tls
namespace: bws
spec:
ingressClassName: nginx
rules:
- host: bws.yourdomain.com
http:
paths:
- backend:
service:
name: bws-service
port:
name: bws-grpc-port
path: /
pathType: Prefix
tls:
- hosts:
- bws.yourdomain.com
secretName: bws-cert
As the BWS service allows RESTful API calls and also utilizes the gRPC framework, which uses HTTP/2 based transport, the service supports the HTTP/2 and the HTTP/1.1 protocols by default. Therefore it might come to problems when using unsecure connections (plain http), that cannot negotiate the connection protocol, in contrast to TLS clients that run ALPN (Application-Layer Protocol Negotiation).
When you come across those kind of problems, consider to explicitely use the ports configured for the specific protocols (bws-grpc-svc and bws-http1-svc above).
The BWS gRPC service supports the gRPC health checking protocol (health/v1) and also some classic Docker health checks:
When everything went fine, we can now test our BWS installation using the BWS 3 command line interface (as downloadable here), e.g.
bws healthcheck --host https://bws.yourdomain.com