Guest Blog: Deploying JFrog Artifactory with Nutanix Karbon

Anyone working with containers and Kubernetes knows the value of a rock-solid container registry. We’ll show you how to deploy JFrog Artifactory Enterprise in a highly available configuration as a Kubernetes Docker registry with Nutanix Karbon.

This enterprise-grade Kubernetes Certified distribution by Nutanix simplifies the provisioning, operations and lifecycle management of Kubernetes with a native K8s experience. Karbon makes it simple to deploy a highly available Kubernetes cluster and operate web-scale workloads.

One of the most challenging aspects of any stateful K8s application is managing persistent storage. However, with Nutanix Karbon and integrated CSI Volume Driver, managing persistent storage is extremely simple. In this walk-through we’ll be using the default Storage Class created with every Karbon cluster deployment, which uses Nutanix Volumes on the backend.

Before You Start

We’ll be installing Artifactory Enterprise in HA mode via a Helm chart, so basic knowledge of Helm is recommended, but not required. If you’re just getting started with Helm, take a look at this Nutanix Community forum post which runs through using Tillerless Helm with Nutanix Karbon.

You’ll also need an Artifactory Enterprise license. If you haven’t purchased one, you can get a free trial of Artifactory, and be sure to select the “I want a multi-server trial…” checkbox for an Artifactory Enterprise setup.

The default Artifactory HA Helm chart installs an NGINX server, which utilizes the built-in LoadBalancer Kubernetes resource. For NGINX to be assigned an External IP, MetalLB in Layer 2 mode is required. To install MetalLB, first apply the MetalLB manifest, then create a Config Map with a pool of IP addresses available for MetalLB to hand out.

$ kubectl apply -f>
$ kubectl apply -f
$ cat metallb-config.yaml 
apiVersion: v1
kind: ConfigMap
  namespace: metallb-system
  name: config
  config: |
    - name: default
      protocol: layer2
      - # Substitute your IPs here
$ kubectl apply -f metallb-config.yaml

Steps to Follow

To deploy Artifactory on Nutanix and create a Kubernetes Docker registry for containers on Karbon, perform these procedures.

Deploy Artifactory

To start the Artifactory deployment, open up a terminal from a MacOS or Linux machine that has Helm installed. For more info, please see our Tillerless Helm on Karbon blog post. We’ll first initialize our tillerless helm, and then start the service.

$ helm init --client-only
$ helm tiller start

Next, we’ll add the JFrog repo to helm, and then install Artifactory HA, with one simple command. Since every Karbon cluster has a default Storage Class based on Nutanix Volumes automatically created at cluster creation, there’s no need to configure storage, which typically is the most challenging aspect of K8s.

$ helm repo add jfrog
$ helm install --name artifactory-demo jfrog/artifactory-ha

Next, monitor the pods, services, and persistent volume claims. Ensure that all pods change to a Running state, the NGINX Service gets an External-IP, and all volume claims are Bound.

$ kubectl get pods
NAME                                           READY   STATUS    RESTARTS   AGE
artifactory-demo-artifactory-ha-member-0       1/1     Running   0          4m52s
artifactory-demo-artifactory-ha-member-1       1/1     Running   0          2m14s
artifactory-demo-artifactory-ha-primary-0      1/1     Running   0          4m52s
artifactory-demo-nginx-548c7b744d-czngv        1/1     Running   0          4m52s
artifactory-demo-postgresql-6f66bb8c8b-k5zkf   1/1     Running   0          4m52s

$ kubectl get svc
NAME                                      TYPE           CLUSTER-IP       EXTERNAL-IP    PORT(S)                      AGE
artifactory-demo-artifactory-ha           ClusterIP            8081/TCP                     4m52s
artifactory-demo-artifactory-ha-primary   ClusterIP            8081/TCP                     4m52s
artifactory-demo-nginx                    LoadBalancer   80:31895/TCP,443:30121/TCP   4m52s
artifactory-demo-postgresql               ClusterIP            5432/TCP                     4m52s
kubernetes                                ClusterIP                443/TCP                      16m

$ kubectl get pvc
NAME                                               STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS           AGE
artifactory-demo-postgresql                        Bound    pvc-22558e21-4042-11e9-aafc-506b8d53468e   50Gi       RWO            default-storageclass   4m53s
volume-artifactory-demo-artifactory-ha-member-0    Bound    pvc-227e62e2-4042-11e9-aafc-506b8d53468e   200Gi      RWO            default-storageclass   4m52s
volume-artifactory-demo-artifactory-ha-member-1    Bound    pvc-80ca05f3-4042-11e9-aafc-506b8d53468e   200Gi      RWO            default-storageclass   2m14s
volume-artifactory-demo-artifactory-ha-primary-0   Bound    pvc-2282341f-4042-11e9-aafc-506b8d53468e   200Gi      RWO            default-storageclass   4m52s

Take note that all of the Persistent Volume Claims are created from our default Storage Class that gets created with every Karbon cluster. You’ll also see the matching Volumes in the Karbon UI:

You’ll note that the default size of the Persistent Volume Claims are 200GiB. If this is not enough for your environment, you have several options. One option is to set the size of the PVC to a larger number at deployment:

$ helm install --name artifactory-demo --set artifactory.persistence.size="1Ti" jfrog/artifactory-ha

Another option would be to add NFS storage, like Nutanix Files, or S3 compliant Object storage, like Nutanix Buckets. These are also set via helm settings, and can be defined before initial deployment or later with a helm upgrade command. For more information, please see the Artifactory storage section of the helm chart.

If for any reason you need to view the logs of a pod, in order to troubleshoot or verify configuration, you can do so with the following command.

$ kubectl logs  | less

Once all of your pods are running, and PVCs are bound, you can access Artifactory HA via the LoadBalancer External IP listed above, or by running the following two commands.

$ export SERVICE_IP=$(kubectl get svc --namespace default artifactory-demo-nginx -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
$ echo https://$SERVICE_IP/

It is recommended that you add this IP to your company’s domain server.

Set Up Artifactory

Enter the domain name, or IP that was just gathered into a web browser, where you should see a “Welcome to JFrog Artifactory” message.

Artifactory Welcome Screen
JFrog Artifactory: Welcome

Click Next, where you’ll be prompted for your license keys.

Artifactory Add Licenses
Artifactory: Add Licenses

Paste your keys in, and click next, where you’ll be prompted to set a new admin password.

Artifactory Set Password
JFrog Artifactory: Set Password

After entering a strong password, click Next. Depending on your environment, a proxy server may be required to access the internet. If so, enter your proxy server information on the page that appears. If a proxy server is not required, click Skip.

On the next page, you have the option of selecting the package type(s) that you want repositories created for. Choose your package(s) and click Create.

Artifactory Create Repositories
JFrog Artifactory: Create Repositories

Finally, you should get a notification stating “Artifactory on-boarding complete!”  Click Finish to start using Artifactory.

Create the Kubernetes Docker registry

For each repository added in the previous step, you’ll find an entry in the Set Me Up box in the middle of the homepage. We’ll be walking through setting up docker, but for any other registry, we recommend starting here.

Artifactory Repository Set Up
Artifactory: Repository Set Up

As an example, we’re going to walk through configuring Artifactory as a Kubernetes Docker registry for containers. If you did not add docker in the previous step, and wish to follow along, navigate to Admin > Repositories > Local, and then click the + New button in the upper right.

Artifactory Add Repository
JFrog Artifactory: Add Repository

In order to use Artifactory as Docker registry it’s mandatory to use a Reverse Proxy. Luckily the default helm chart deploys an NGINX server that we can use. As outlined in , there are a couple of steps to take within Artifactory.

Navigate to Admin > Configuration > HTTP Settings, and change or fill in the following fields, leaving all others as default:

  • Docker Access Method: Repository Path
  • Reverse Proxy Server Provider: NGINX
  • Internal Hostname: Name of the Artifactory Kubernetes Service, in my case artifactory-demo-artifactory-ha
Docker Access Method
HTTP Settings: Docker Access Method

HTTP Settings: Reverse Proxy SettingsClick Save, upon which the changes will automatically be pushed to the NGINX server. Back in your MacOS or Linux terminal, we’re going to push a Docker image to our new repository. In the event you do not have a local image, let’s pull one first.

$ docker pull python:3.5

Next, we’ll set a variable to make copy and pasting easier (be sure to substitute our hostname for your hostname or IP), and then log in to our new repository with docker login. At the password prompt, enter your Artifactory credentials from the previous step.

$ export ARTIFACTORY="" 
$ docker login -u admin ${ARTIFACTORY}
Login Succeeded

Finally, we’ll tag our python image, and push our image to our Artifactory repository.

$ docker tag python:3.5 ${ARTIFACTORY}/docker/python:3.5
$ docker push ${ARTIFACTORY}/docker/python:3.5
The push refers to repository []
a83742433b45: Pushed 
319fab820b58: Pushed 
3c74ba240996: Pushed 
526dede64623: Pushed 
7de462056991: Pushed 
3443d6cf0f1f: Pushed 
f3a38968d075: Pushed 
a327787b3c73: Pushed 
5bb0785f2eee: Pushed 
3.5: digest: sha256:4c257cd3a276806e90aacd7d470b361869178ee023613b2d942fdc292a3068b4 size: 2218

Back in the Artifactory UI, we should see our new image:

Artifact Repository Browser
Artifact Repository Browser


In this blog, we showed how easy it is to deploy Artifactory HA on Nutanix Karbon by utilizing JFrog’s Helm Chart and the built-in Nutanix CSI driver. We then stepped through an example use case of creating an Artifactory Docker Repository, and pushing a Docker image. However, Docker is just one type of dozens of different packages that Artifactory can manage. Thanks for your time today!