Microsoft Azure Container Service

This guide article will walk you through the steps for deploying PSPDFKit Server to the Microsoft Azure Container Service with Kubernetes.

Setting Up Azure CLI

To be able to deploy PSPDFKit Server to the Microsoft Azure Container Service with Kubernetes, you have to set up the Azure CLI utility to manage your Kubernetes cluster in the command line.

To install Azure CLI, follow the installation instructions from the Azure CLI installation guide.

After you’ve installed Azure CLI, run the following command to log in to Microsoft Azure:

1
az login

This command will print the URL https://microsoft.com/devicelogin and the code for signing in. Open the URL in your browser and enter the code to sign in to your Microsoft Azure account.

Sign in Page

Creating a Resource Group

To create a resource group, run the following:

1
az group create -l eastus -n pspdfkitresourcegroup

In this example, we created the resource group in the eastus region with the name pspdfkitresourcegroup. An overview of available regions can be found here.

Creating and Logging In To an Azure Container Registry

You’ll probably want a private registry to upload your Docker images, so let’s create an Azure Container Registry instance. To be able to upload Docker images to Microsoft Azure, you need to create a private Azure Container Registry. You can create a Azure Container Registry with the name pspdfkitconainerregistry with the following:

1
az acr create -g pspdfkitresourcegroup -n pspdfkitcontainerregistry --sku Basic --admin-enabled

After the Azure Container Registry is created, you can log in to it by executing this:

1
az acr login -n pspdfkitcontainerregistry

Alternatively, you can also log in to the Azure Container Registry with Docker:

Copy
1
2
3
az acr credential show -n pspdfkitcontainerregistry

docker login -u pspdfkitcontainerregistry -p [PASSWORD FROM PREVIOUS COMMAND] pspdfkitcontainerregistry.azurecr.io

Uploading the PSPDFKit Image to the Azure Container Registry

Before you can upload the PSPDFKit image to the Azure Container Registry, you have to download it to your local machine.

First make sure you have Docker installed and running.

To log in to the private PSPDFKit Docker registry and pull the pspdfkit image, run the following:

Copy
1
2
docker login -u YOUR_DOCKER_USERNAME_GOES_HERE -p YOUR_DOCKER_PASSWORD_GOES_HERE docker.pspdfkit.com
docker pull docker.pspdfkit.com/pspdfkit:latest

Now that the image is built, you need to create a separate tag that will represent the destination in the Azure Container Registry.

To publish a Docker image to the Azure Container Registry, you have to create a tag, which will represent where this image will be saved in the Azure Container Registry. To create the tag with the name pspdfkitcontainerregistry.azurecr.io/pspdfkit:latest for the Docker image, run:

1
docker tag docker.pspdfkit.com/pspdfkit:latest pspdfkitcontainerregistry.azurecr.io/pspdfkit:latest

After you tag the image, you can publish it to the Azure Container Registry with this:

1
docker push pspdfkitcontainerregistry.azurecr.io/pspdfkit:latest

Make sure to also replace the tag with the tag you created in the step above.

Creating the Kubernetes Cluster

To be able to manage the Kubernetes cluster from the command line, you have to install kubectl:

1
az aks install-cli

To create a Kubernetes cluster with the name pspdfkitAKScluster, run the following:

1
az aks create -g pspdfkitresourcegroup --name pspdfkitAKScluster --generate-ssh-keys

To connect kubectl with your cluster, execute:

1
az aks get-credentials -g pspdfkitresourcegroup -n pspdfkitAKScluster

Creating a ConfigMap

ConfigMaps allow you to decouple configuration artifacts from image content. To create the pspdfkit-config ConfigMap, run the following command:

1
kubectl create configmap pspdfkit-config

After the ConfigMap is created, you can edit it with the following:

1
kubectl edit configmap pspdfkit-config

This should open the created ConfigMap in your editor. Edit the file to match the following file and replace activation_key with your activation key:

Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving,
# this file will be reopened with the relevant failures.
#
apiVersion: v1
data:
  activation_key: YOUR_ACTIVATION_KEY_GOES_HERE
  api_auth_token: secret
  dashboard_password: secret
  dashboard_username: dashboard
  jwt_algorithm: RS256
  jwt_public_key: |
    -----BEGIN PUBLIC KEY-----
    MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALd41vG5rMzG26hhVxE65kzWC+bYQ94t
    OxsSxIQZMOc1GY8ubuqu2iku5/5isaFfG44e+VAe+YIdVeQY7cUkaaUCAwEAAQ==
    -----END PUBLIC KEY-----
  pgdata: /var/lib/postgresql/data/pgdata
  pgdatabase: pspdfkit
  pghost: pspdfkitdb
  pgpassword: examplepassword
  pgport: "5432"
  pguser: pspdfkit
  secret_key_base: secret-key-base
kind: ConfigMap

Don’t change anything that comes after the kind: ConfigMap line, because that part is autogenerated.

Creating a Secret That Holds the Registry Credentials

Kubernetes Secrets are intended to hold sensitive information. In this guide, we use them to store the credentials for the Azure Container Registry. To get the password for the Azure Container Registry, run:

1
az acr credential show -n pspdfkitcontainerregistry

You can create the secrets with this:

Copy
1
kubectl create secret docker-registry pspdfkitsecret --docker-server=pspdfkitcontainerregistry.azurecr.io --docker-username=pspdfkitcontainerregistry --docker-password=PASSWORD_FROM_COMMAND_ABOVE --docker-email=YOUR_EMAIL_ADDRESS

Make sure to replace PASSWORD_FROM_COMMAND_ABOVE with the password you got from the command above and YOUR_EMAIL_ADDRESS with your email address.

Creating an Azure Disk Volume

To create the Azure Disk Volume where the database saves the data, run:

1
az group list --output table

This will print a list of resource groups. Copy the name of the resource group that starts with MC — for example, MC_pspdfkitresourcegroup_pspdfkitAKScluster_eastus — and insert it into the following command after --resource-group:

Copy
1
2
3
4
5
az disk create \
  --resource-group MC_pspdfkitresourcegroup_pspdfkitAKScluster_eastus \
  --name postgres-disk\
  --size-gb 50 \
  --query id --output tsv

This will print the disk ID of the created disk. For example:

Copy
1
/subscriptions/12345abc-def1-2345-6789-abcdef123456/resourceGroups/MC_pspdfkitresourcegroup_pspdfkitAKScluster_eastus/providers/Microsoft.Compute/disks/postgres-disk

Creating Services and Deployments

Kubernetes Services and Deployments can be configured in a file. To run PSPDFKit Server, you have to define a Service and a Deployment for the database and a Service and a Deployment for PSPDFKit Server. First, create the file that configures the database Service and Deployment. To do this, create the pspdfkitdb.yml file in the current directory:

Copy
pspdfkitdb.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
apiVersion: v1
kind: Service
metadata:
  name: pspdfkitdb
spec:
  ports:
    - port: 5432
  selector:
    app: pspdfkitdb
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: pspdfkitdb
spec:
  template:
    metadata:
      labels:
        app: pspdfkitdb
    spec:
      containers:
        - image: "postgres:9.6.6"
          name: pspdfkitdb
          env:
            - name: POSTGRES_USER
              valueFrom:
                configMapKeyRef:
                  name: pspdfkit-config
                  key: pguser
            - name: POSTGRES_PASSWORD
              valueFrom:
                configMapKeyRef:
                  name: pspdfkit-config
                  key: pgpassword
            - name: PGDATA
              valueFrom:
                configMapKeyRef:
                  name: pspdfkit-config
                  key: pgdata
          ports:
            - containerPort: 5432
              name: pspdfkitdb
          volumeMounts:
            - name: postgres-storage
              mountPath: /var/lib/postgresql/data
      volumes:
        - name: postgres-storage
          azureDisk:
            kind: Managed
            diskName: postgres-disk
            diskURI: /subscriptions/12345abc-def1-2345-6789-abcdef123456/resourceGroups/MC_pspdfkitresourcegroup_pspdfkitAKScluster_eastus/providers/Microsoft.Compute/disks/postgres-disk

Make sure to replace diskURI in the last line with the disk ID you got from the command before.

After you’ve created the configuration file for the database, create the configuration for PSPDFKit Server (pspdfkit.yml) and replace the image pspdfkitcontainerregistry.azurecr.io/pspdfkit:latest with the PSPDFKit Docker image you uploaded to the Azure Container Registry in an earlier step:

Copy
pspdfkit.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
apiVersion: v1
kind: Service
metadata:
  name: pspdfkit
spec:
  ports:
    - protocol: TCP
      port: 5000
      targetPort: 5000
  selector:
    app: pspdfkit
  type: LoadBalancer
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: pspdfkit
spec:
  template:
    metadata:
      labels:
        app: pspdfkit
    spec:
      containers:
        - image: "pspdfkitcontainerregistry.azurecr.io/pspdfkit:latest"
          name: pspdfkit
          env:
            - name: PGUSER
              valueFrom:
                configMapKeyRef:
                  name: pspdfkit-config
                  key: pguser
            - name: PGPASSWORD
              valueFrom:
                configMapKeyRef:
                  name: pspdfkit-config
                  key: pgpassword
            - name: PGDATABASE
              valueFrom:
                configMapKeyRef:
                  name: pspdfkit-config
                  key: pgdatabase
            - name: PGHOST
              valueFrom:
                configMapKeyRef:
                  name: pspdfkit-config
                  key: pghost
            - name: PGPORT
              valueFrom:
                configMapKeyRef:
                  name: pspdfkit-config
                  key: pgport
            - name: ACTIVATION_KEY
              valueFrom:
                configMapKeyRef:
                  name: pspdfkit-config
                  key: activation_key
            - name: API_AUTH_TOKEN
              valueFrom:
                configMapKeyRef:
                  name: pspdfkit-config
                  key: api_auth_token
            - name: SECRET_KEY_BASE
              valueFrom:
                configMapKeyRef:
                  name: pspdfkit-config
                  key: secret_key_base
            - name: JWT_ALGORITHM
              valueFrom:
                configMapKeyRef:
                  name: pspdfkit-config
                  key: jwt_algorithm
            - name: JWT_PUBLIC_KEY
              valueFrom:
                configMapKeyRef:
                  name: pspdfkit-config
                  key: jwt_public_key
            - name: DASHBOARD_USERNAME
              valueFrom:
                configMapKeyRef:
                  name: pspdfkit-config
                  key: dashboard_username
            - name: DASHBOARD_PASSWORD
              valueFrom:
                configMapKeyRef:
                  name: pspdfkit-config
                  key: dashboard_password
          ports:
            - containerPort: 5000
              name: pspdfkit
      imagePullSecrets:
      - name: pspdfkitsecret

To create all Services and Deployments needed to run PSPDFKit Server, execute:

1
kubectl create -f ./pspdfkitdb.yml
1
kubectl create -f ./pspdfkit.yml

View the Dashboard

To be able to access the server, you have to get the external IP address that was assigned to the server. Run the following command to view all the Services in your cluster, along with their assigned external IP addresses:

1
kubectl get services

This will show something like the following:

Copy
1
2
3
4
NAME         TYPE           CLUSTER-IP      EXTERNAL-IP      PORT(S)          AGE
kubernetes   ClusterIP      10.15.240.1     <none>           443/TCP          54m
pspdfkit     LoadBalancer   10.15.247.197   12.345.678.910   5000:32393/TCP   1m
pspdfkitdb   ClusterIP      10.15.244.127   <none>           5432/TCP         4m

Copy the EXTERNAL-IP address from the pspdfkit column and access the dashboard with the port 5000 and the /dashboard path in your web browser. In this example, you would access the dashboard with http://12.345.678.910:5000/dashboard.

Limitations

Be aware that this is just an example setup, and we recommend looking deeper into the Microsoft Azure Container Service for a production-ready setup.