Skip to content

Kubernetes Installation#

Advanced

Posit End User License Agreement

This page includes instructions for downloading Posit professional products. Download and/or use of these products is governed under the terms of the Posit End User License Agreement. By downloading, you agree to the terms posted there.

These instructions describe how to install Posit Package Manager in a Kubernetes cluster. For alternative installation instructions, see our Linux server installation instructions or Install Posit Professional Products overview.

Posit Package Manager can be run in a Kubernetes cluster, where Package Manager runs in a pod or, in the case of replicas, multiple pods. Leveraging a container-based Kubernetes infrastructure can ease the management of resource constraints, maximize process isolation, and improve reproducibility.

Important

The following sections of this guide assume that the reader has a working knowledge of Kubernetes and Helm.

Posit requires using the Package Manager Helm chart to install and run Package Manager in a Kubernetes cluster.

For help with any other topology or deployment options, please contact your Posit Customer Success Representative and request an architecture review session with Posit Solutions Engineering.

Feature requirements#

Planning and preparation#

There are several planning and preparation steps that should be performed ahead of the deployment sequence.

Pull the Helm charts used in this guide#

# Add the rstudio Repository
helm repo add rstudio https://helm.rstudio.com

# Pull the latest versions of the Helm charts
helm repo update

Network connectivity verification#

Verify that the Kubernetes cluster has connectivity to your:

  • shared storage or AWS S3.
  • PostgreSQL database.

Storage verification#

When running Package Manager in Kubernetes, persistent data can be stored in AWS S3 or shared storage. For more information on these requirements, see the Shared Data Directory Requirements section.

Amazon S3#

Posit Package Manager will need credentials with certain permissions to use Amazon S3 as a storage backend. For more details on credential types and permissions, see the AWS Simple Cloud Storage Server (S3) section of this guide.

If you are running your cluster in Amazon Elastic Kubernetes Service (EKS), we recommend using IAM Roles for Service Accounts to manage the credentials needed to access your S3 bucket. Once created, the IAM role can be supplied as an annotation for the service account, as shown in the Using AWS S3 with EKS example.

If you are unable to use IAM Roles for Service Accounts, then you must use an alternative method to add the required AWS credentials to the Package Manager container.

Shared storage#

Shared storage must be POSIX-compliant and accessible to your cluster. Before beginning the installation, ensure you have enough space in your shared storage. We recommend 100+ GB of storage in our Recommended system requirements.

Posit Package Manager license validation#

A valid Package Manager license is required to run Package Manager in Kubernetes. If you use an existing Package Manager license, you must also confirm that you have enough license activations available.

Check your license status using the steps outlined in the Licensing section. If you have questions, reach out to your Posit Customer Success representative before proceeding.

To request a separate evaluation license, you can email Customer Success or sales@posit.co and specify that you are trialing this feature.

Kubernetes cluster preparation#

Note

Before continuing with the steps below, please ensure that your Kubernetes cluster is configured according to your provider's instructions. For example, your Kubernetes cluster might need to have Container Storage Interface (CSI) drivers installed to support a ReadWriteMany compatible StorageClass if using shared storage.

Create a namespace for Package Manager#

You need a Kubernetes namespace for Package Manager. We recommend creating a new one called posit-pm or having a cluster administrator create one on your behalf.

This can be accomplished with the following commands:

# Create the new namespace
kubectl create namespace posit-pm

# Switch to the new namespace in your current context
kubectl config set-context --current --namespace=posit-pm

Create a StorageClass with ReadWriteMany access (optional)#

If you are not using AWS S3 as a storage backend, your cluster must have a StorageClass backed by POSIX-compliant PersistentVolume (PV) storage that supports symlinks and ReadWriteMany access. This storage class is used by PVC objects to either dynamically provision PV objects or use static PV objects for Package Manager shared storage.

Create a Secret containing a license file#

We recommend storing a license file as a Secret and setting the license.file.secret and license.file.secretKey values accordingly as shown in the values.yaml in the next section.

Create the Secret declaratively with YAML or imperatively using the following command:

kubectl create secret generic rstudio-pm-license --from-file=licenses/rstudio-pm.lic

Create a Secret containing a PostgreSQL database password#

We recommend storing a PostgreSQL database password in a Secret and making it available to the container as an environment variable, as shown in the values.yaml in the next section.

Create the secret declaratively with YAML or imperatively using the following command (replacing <YOURPASSWORDHERE> with your own password):

kubectl create secret generic rstudio-pm-database --from-literal=password=YOURPASSWORDHERE

Configure Helm chart values#

Posit maintains a Helm chart that is recommended for deploying Package Manager on Kubernetes. It is highly configurable and supports multiple deployment options to meet your organization's requirements.

The values.yaml file is used to override defaults specified within the Helm chart. The steps below will help you set the values for the initial deployment.

The config section of your values.yaml allows for setting application configuration options in one section so that they are converted to the correct format and mounted to the right location.

Create your initial values.yaml file#

Using AWS S3 with EKS#

Create a file called values.yaml with the following contents:

# Controls how many instances of Posit Package Manager are created.
replicas: 1

# Mounts the license file appropriately from the Secret
license:
  file:
    secret: rstudio-pm-license
    secretKey: rstudio-pm.lic

# Adds an environment variable containing the PostgreSQL password from a Secret
pod:
  env:
    - name: PACKAGEMANAGER_POSTGRES_PASSWORD
      valueFrom:
        secretKeyRef:
          name: rstudio-pm-database
          key: password

serviceAccount:
  annotations:
    # Specify your specific IAM role below
    # https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html
    eks.amazonaws.com/role-arn: arn:aws:iam::123456789000:role/iam-role-name-here

# The config section is converted into the correct configuration files and mounted.
config:
  Storage:
    Default: s3
  S3Storage:
    # Specify your bucket name and region below
    Bucket: posit-pm
    Region: us-east-1
  Database:
    Provider: postgres
  Postgres:
    URL: "postgres://<USERNAME>@<HOST>:<PORT>/<DATABASE>"
    # While it is possible to set a Postgres password here in the values file,
    # we recommend adding it from a Secret as an environment variable as shown in pod.env

Using shared storage#

Create a file called values.yaml with the following contents:

# Controls how many instances of Posit Package Manager are created.
replicas: 1

# Mounts the license file appropriately from the Secret
license:
  file:
    secret: rstudio-pm-license
    secretKey: rstudio-pm.lic

# Adds an environment variable containing the PostgreSQL password from a Secret
pod:
  env:
    - name: PACKAGEMANAGER_POSTGRES_PASSWORD
      valueFrom:
        secretKeyRef:
          name: rstudio-pm-database
          key: password

# Configures Package Manager shared storage
sharedStorage:
  create: true
  mount: true

  # The name of the PVC created for Package Managers's shared storage directory.
  name: package-manager-shared-pvc

  # The storageClass to use for Package Manager's shared storage directory. Must support RWX.
  # Replace with your storage class name.
  storageClassName: nfs-rwx
  requests:
    storage: 100G

# The config section is converted into the correct configuration files and mounted.
config:
  Database:
    Provider: postgres
  Postgres:
    URL: "postgres://<USERNAME>@<HOST>:<PORT>/<DATABASE>"
    # While it is possible to set a Postgres password here in the values file,
    # we recommend adding it from a Secret as an environment variable as shown in pod.env

Replace the sample values#

You must modify the initial values.yaml file to match the needs of your environment. For example, fill in the placeholder values for the PostgreSQL connection string, specify the name of your storage class that supports ReadWriteMany access (replace nfs-rwx with your specific storage class name) or IAM role, specify the name of the secret containing your license file and specify the name of the secret containing your PostgreSQL database password.

If you would like to view the chart's entire set of default values, use the command:

helm show values rstudio/rstudio-pm

Kubernetes deployment#

Installing Posit Package Manager within Kubernetes#

To complete your installation of Package Manager within Kubernetes, run the following commands:

helm upgrade --install rstudio-pm-prod \
  rstudio/rstudio-pm \
  --values values.yaml

To ensure a stable production deployment, please:

  • Ensure you "pin" the version of the Helm chart that you are using. You can do this using the helm dependency command and the associated "Chart.lock" files or the --version flag. This protects you from breaking changes. For example, to pin the release to version 0.5.11 add the --version=0.5.11 flag to your helm upgrade --install command.
  • Use helm diff upgrade before upgrading, to avoid breaking changes. This requires the helm-diff plugin.
  • Pay close attention to the Helm chart NEWS.md for updates on changes.

Use the following command to check the status of Package Manager:

kubectl get pod -l app.kubernetes.io/name=rstudio-pm

Output similar to the following displays:

NAME                               READY   STATUS    RESTARTS   AGE
rstudio-pm-prod-695684d7b5-bz8mm   1/1     Running   0          92s

If your Package Manager pod is failing to start, see the Debugging Package Manager in Kubernetes section for details on how to diagnose and fix problems with your deployment.

Access Package Manager and validate your installation#

Now, Package Manager should be running. To confirm the successful completion of this phase, log in to the application and validate the correct functionality as described below.

Note

Manual port-forwarding is appropriate for local testing and validation of the installation. Once you have validated the installation, configure an Ingress and public DNS records for Package Manager. See the configure external access section for more details.

To interact with your new Package Manager installation, temporarily enable port-forwarding. For example, to use local port 4242:

kubectl port-forward svc/rstudio-pm-prod 4242:80

You can now point your browser to http://localhost:4242 and access Package Manager.

Post-deployment considerations#

This section will guide you through the post-deployment steps for your Kubernetes installation of Package Manager.

Updating and changing the deployment#

If you have made changes to your values file and wish to update an existing installation, edit your values.yaml and run the same helm upgrade command again.

Set up repositories#

R and/or Python repositories need to be created on Package Manager before users can utilize Package Manager. After Package Manager is installed, commands must be run inside a Package Manager container to set up these repositories.

For example, to serve CRAN packages for R users, follow the steps as outlined in the serving CRAN packages section of the Quick Start guide. Replace rstudio-pm-prod-5f9fb55444-q9fc6 with the name of your pod.

kubectl exec -it rstudio-pm-prod-5f9fb55444-q9fc6 -c rspm -- /bin/bash
rspm create repo --name=cran --description='Access CRAN packages'
rspm subscribe --repo=cran --source=cran

See the Quick Start section for walkthroughs on setting up different types of sources and repositories.

Custom container image preparation#

Some organizations want control over the Docker images used, rather than using the public images Posit makes available. rstudio-package-manager is used for the Package Manager pods, which can be extended and used in the Helm chart.

rstudio-package-manager image#

The Helm chart uses ubuntu2204 images from the rstudio/rstudio-package-manager repository by default for Package Manager containers, which are controlled by the image. settings in the values.yaml file.

Docker Hub: https://hub.docker.com/r/rstudio/rstudio-package-manager GitHub: https://github.com/rstudio/rstudio-docker-products/tree/dev/package-manager

Using custom images#

To change the image used to create the Package Manager pods, set the following values:

image:
  repository: "yourprivateregistry.com/rstudio-package-manager"
  tag: "ubuntu2204-2023.04.0-custom"

Implement load balancing#

With the Helm Chart values.yaml file created earlier, the deployment of Package Manager was configured with one replica so that traffic for a single connection is always routed to the same Package Manager pod.

To implement multiple replicas of the Package Manager pod, update the replicas count in your values.yaml file and then run helm upgrade. For example, the following change would enable three running replicas:

# Controls how many instances of Package Manager are created.
replicas: 3

Configure external access#

For users to access your installation of Package Manager running in Kubernetes, you need to configure an Ingress. There are many different ways to accomplish this, and the steps may vary depending on the requirements of your organization.

In this guide, we use the Traefik v2 Ingress Controller to configure external access to our Package Manager instance using locally managed TLS certificates. We use the value packagemanager.posit.co as our public domain name in this example, but you must modify this everywhere it occurs to use your own domain.

If you prefer not to manage local certificates, it is also possible to use external certificate management tools such as cert-manager, Amazon ACM, etc. The configurations for these tools varies depending on the Ingress Controller and certificate manager used.

Step 1: Install the Traefik Ingress Controller#

The Traefik documentation contains detailed installation instructions, but the simplest installation steps are:

helm repo add traefik https://helm.traefik.io/traefik
helm repo update
helm install traefik traefik/traefik

Step 2: Create TLS Secrets#

Replace packagemanager.crt and packagemanager.key with the local path to your TLS certificate files.

kubectl create secret tls packagemanager-tls \
    --cert packagemanager.crt \
    --key packagemanager.key

Step 3: Configure the Ingress in your Helm chart values#

ingress:
  enabled: true
  annotations:
    kubernetes.io/ingress.class: traefik

  hosts:
    - host: packagemanager.posit.co
      paths:
        - /

  # Tell the ingress controller to use your TLS secret
  tls:
    - secretName: packagemanager-tls
      hosts:
        - packagemanager.posit.co

Step 4: Apply the changes to your installation#

See the updating and changing the deployment section to see how to apply these changes to an existing installation.

Step 5: Create DNS records for your installation#

To access your Package Manager installation via an Ingress, you must create a DNS record. There are many different DNS service providers to choose from, or you can host your own DNS servers. Creating the DNS records is out of scope for this guide, as the process most likely varies for each organization.

Note

A common way to do this in Kubernetes is to automate the provisioning of DNS records using a tool like external-dns.

For this guide, the EXTERNAL-IP of the Traefik Ingress Controller Service must resolve to packagemanager.posit.co. To obtain the EXTERNAL-IP of the Ingress Controller, inspect the Service that was created by the Traefik Helm chart.

kubectl get svc traefik

You should see output like the following:

NAME      TYPE           CLUSTER-IP      EXTERNAL-IP       PORT(S)                      AGE
traefik   LoadBalancer   10.110.77.164   <xx.xx.xx.xx>     80:31869/TCP,443:31047/TCP   20s

Once your DNS records are in place, you can use netcat to make sure your new DNS records resolve to the correct host. In the example below, update your host path for packagemanager.posit.co:

nc -vz packagemanager.posit.co 443

Output:

Connection to packagemanager.posit.co port 443 [tcp/https] succeeded!

Step 6: Connect to the Package Manager homepage#

If you have successfully installed Package Manager, you can visit Package Manager's homepage through your web browser.

Debugging Package Manager in Kubernetes#

Startup failure#

If your Package Manager pod is failing to start, use the kubectl describe command to get its diagnostic information:

kubectl describe pod -l app.kubernetes.io/name=rstudio-pm

It is possible the pod's Events may indicate an error. In this case, we can see that the Package Manager pod is failing to start and Kubernetes is repeatedly attempting to restart it:

Name:                 rstudio-pm-prod-695684d7b5-bz8mm
...
Events:
  Type     Reason     Age                 From               Message
  ----     ------     ----                ----               -------
  Normal   Scheduled  102s                default-scheduler  Successfully assigned posit-pm/rstudio-pm-prod-79576c58d9-svgmr to ip-172-25-17-186.ec2.internal
  Normal   Started    101s                kubelet            Started container rspm
  Warning  Unhealthy  42s (x19 over 96s)  kubelet            Readiness probe failed: HTTP probe failed with statuscode: 503
  Normal   Pulled     39s (x2 over 101s)  kubelet            Container image "rstudio/rstudio-package-manager:bionic-2023.04.0" already present on machine
  Normal   Created    39s (x2 over 101s)  kubelet            Created container rspm
  Warning  Unhealthy  39s                 kubelet            Readiness probe failed: Get "http://172.25.22.214:4242/__ping__": dial tcp 172.25.22.214:4242: connect: connection refused

If the container fails, you can check the logs of the failed container. This can be done with the following command:

kubectl logs -f --tail 50 \
    -l app.kubernetes.io/name=rstudio-pm \
    --container rspm

In Package Manager's logs, we can see the container is failing to start because Package Manager cannot reach our Postgres database:

2023/07/07 17:27:01 Error running services: Error: Unable to initialize a connection to the database: Unable to connect to DB: failed to connect to `host=packagemanager.posit.co user=packagemanager database=packagemanager`: dial error (timeout: dial tcp 34.194.154.154:5432: i/o timeout)
2023/07/07 17:27:01 Gracefully shutting down, received signal to terminate
2023/07/07 17:27:01 Stopping: signal dumper...
2023/07/07 17:27:01 Done Stopping: signal dumper
2023/07/07 17:27:01 Exited Posit Package Manager
+ deactivate
+ echo 'Deactivating license ...'

Opening a support ticket#

If you need additional help with your Package Manager deployment on Kubernetes, please review the Support Agreement to verify that you qualify. Then, execute the following script and attach the diagnostics to your ticket.

Using this script requires that the deployment was created with the helm upgrade --install command as outlined in the Installing Posit Package Manager within Kubernetes section.

#!/usr/bin/env bash
# Copyright (C) 2023 by Posit Software, PBC.

set -euxo pipefail

NAMESPACE="${1:-posit-pm}"
RELEASE_NAME=$(helm list -n $NAMESPACE -o yaml | grep "chart: rstudio-pm-[0-9]" -A1 | grep name | awk '{print $2}')

echo "### Kubernetes version ###"
kubectl version
echo

echo "### Helm version ###"
helm version
echo

echo "### Helm releases (namespace: $NAMESPACE) ###"
helm list -n $NAMESPACE
echo

echo "### values.yaml (release: $RELEASE_NAME) ###"
helm get values -n $NAMESPACE $RELEASE_NAME | grep -v "Password:"
echo

echo "### Posit Package Manager Pod describe ###"
kubectl describe pod -n $NAMESPACE -l app.kubernetes.io/name=rstudio-pm
echo

echo "### Posit Package Manager server logs ###"
kubectl logs -n $NAMESPACE $(kubectl get pod -n $NAMESPACE -l app.kubernetes.io/name=rstudio-pm -o=jsonpath='{.items[0].metadata.name}') -c rspm

To produce a diagnostic file for your support ticket:

  1. Save the above script to a file called posit-pm-run-diagnostics-k8s.sh

  2. Make the script executable:

    chmod 750 ./posit-pm-run-diagnostics-k8s.sh
    
  3. Invoke the script and save the output to a file:

    ./posit-pm-run-diagnostics-k8s.sh > posit-pm-diagnostic-info-k8s.txt
    
  4. Attach the output file posit-pm-diagnostic-info-k8s.txt to your support ticket.

    Note

    posit-pm-run-diagnostics-k8s.sh accepts an optional argument that can be used to provide a namespace other than posit-pm. This allows you to invoke the script with a non-default namespace:

    ./posit-pm-run-diagnostics-k8s.sh my-custom-namespace > posit-pm-diagnostic-info-k8s.txt