Upgrading to v1.0

We have officially released Gloo Portal 1.0.0! This major version bump comes with a number of breaking changes that you will have to keep in mind as you upgrade from Gloo Portal 0.x to 1.0.0+. While the easiest upgrade process is to just start with a totally fresh installation of Gloo Portal, many users are running Gloo Portal in production on older versions; this guide is intended for users like them who would like to update to our latest and greatest Gloo Portal without any downtime.

Breaking Changes From v0.x to v1.0.0

These breaking changes are common pain points that most users will have to address, and which we specifically would like to draw attention to. For a complete list of all breaking changes, see please refer to our changelog reference.

Example Upgrade Process

In this section, we will walk through the process of upgrading a very simple Gloo Portal installation from 0.7.6 to 1.0.0 that is configured to integrate with Gloo Edge without any downtime. While this will not cover everyone's use case, it will be useful to see how to resolve the most common breakages.

The upgrade process described in this guide consists of the following steps:

Let's go through all the above steps in greater detail.

Starting setup

We will start from with a Kubernetes cluster with Gloo Edge Enterprise v1.8.0 and Gloo Portal v0.7.6 installed in the gloo-system and dev-portal namespaces, respectively. We will be routing to an instance of the petstore application, which you can install by running:

kubectl apply -n default -f https://raw.githubusercontent.com/solo-io/gloo/v1.9.0-beta8/example/petstore/petstore.yaml

The collapsible section below shows a set of Gloo Portal resources (in the pre-v1.0.0 format) that publish the documentation for the petstore API in a Portal and configure Gloo Edge to route to the API backend.

Click to see the complete list of Gloo Portal resources

With the above resources in place, Gloo Portal should have generated the following Gloo Edge VirtualServices:

kubectl get virtualservices.gateway.solo.io -n dev-portal

NAME          AGE
development   45s
pet-portal    46s

Assuming that you have a Gateway resource set up to select these VirtualServices, you should be able to reach the petstore service:

curl "$(glooctl proxy url)/api/pets" -H "Host: petstore.example.com"

[{"id":1,"name":"Dog","status":"available"},{"id":2,"name":"Cat","status":"pending"}]

Ensure Gateway setup will not lead to conflicts

As part of the upgrade process we will install and configure a separate Gloo Portal deployment (running version v1.0.0) in a dedicated namespace (in our case it will be gloo-portal) and configure it to mirror the existing one. The v1.0.0 deployment will generate Gloo Edge resources in its namespace, so we have to make sure that Gloo Edge does not pick them up until we want it to. This can be ensured by configuring the existing Gateway resources so that they will not select any resources in the v1.0.0 namespace. In our example setup this means updating the default Gateway as follows:

apiVersion: gateway.solo.io/v1
kind: Gateway
metadata:
  name: gateway-proxy
  namespace: gloo-system
spec:
  bindAddress: '::'
  bindPort: 8080
  httpGateway:
    # Only select the VS created by the `v0.7.6` Gloo Portal deployment
    virtualServiceNamespaces:
    - dev-portal
  proxyNames:
  - gateway-proxy 

Let's also create a new Gateway that will select VirtualServices in the gloo-portal namespace and expose their routes on port 8099 of the default gateway-proxy proxy deployment.

cat <<EOF | kubectl apply -f-
apiVersion: gateway.solo.io/v1
kind: Gateway
metadata:
  name: portal-gateway-proxy
  namespace: gloo-system
spec:
  bindAddress: '::'
  bindPort: 8099
  httpGateway:
    virtualServiceNamespaces:
    - gloo-portal
  proxyNames:
  - gateway-proxy
EOF

Install Gloo Portal 1.0.0

Now we are ready to install Gloo Portal 1.0.0! First, let's create the gloo-portal namespace:

kubectl create namespace gloo-portal

Now we can install Gloo Portal using Helm:

helm repo add gloo-portal https://storage.googleapis.com/dev-portal-helm
helm repo update
helm install gloo-portal gloo-portal/gloo-portal --version v1.0.0 -n gloo-portal --values values.yaml

Where values.yaml has the following content:

licenseKey:
  # Use the Gloo Edge license key
  secretRef:
    name: license
    namespace: gloo-system
    key: license-key
glooEdge:
  enabled: true

The helm install command should complete without errors, and you should see the Gloo Portal pods running:

kubectl get pods -n gloo-portal

NAME                                        READY   STATUS    RESTARTS   AGE
gloo-portal-admin-server-79448bf45b-cg754   3/3     Running   0          60s
gloo-portal-controller-75fddccfc8-hlv28     1/1     Running   0          60s

Migrate Gloo Portal resources

Now we can start migrating the existing Gloo Portal resources to the new installation. This will involve adapting all the existing resources to the v1.0.0 API and applying them to the gloo-portal namespace. The collapsible section below shows the example resources we have defined earlier after being modified to use the v1.0.0 API.

Click to see the complete list of v1 Gloo Portal resources

Details about resource updates

This section highlight the differences between the 0.7.6 and 1.0.0 resources.

Keep in mind that this is not a complete list of all the breaking API changes, but only shows the changes that we need to apply to our example resources. Please refer to our changelog reference for a complete list of API changes.

The APIDoc spec has remained the same, we just need to update the apiVersion:

apiVersion: devportal.solo.io/v1alpha1
kind: APIDoc
metadata:
  name: petstore-api-spec
  namespace: dev-portal
spec:
  openApi:
    content:
      fetchUrl: "http://petstore.default:8080/swagger.json"
apiVersion: portal.gloo.solo.io/v1beta1
kind: APIDoc
metadata:
  name: petstore-api-spec
  namespace: gloo-portal
spec:
  openApi:
    content:
      fetchUrl: "http://petstore.default:8080/swagger.json"

In the APIProduct the defaultRoute field has been removed in favor of the gatewayConfig.route field.

apiVersion: devportal.solo.io/v1alpha1
kind: APIProduct
metadata:
  name: petstore
  namespace: dev-portal
  labels:
    app: petstore
spec:
  versions:
  - name: v1
    apis:
    - apiDoc:
        name: petstore-api-spec
        namespace: dev-portal
      openApi:
        operations:
        - id: findPets
        - id: findPetById
    defaultRoute:
      inlineRoute:
        backends:
        - kube:
            name: petstore
            namespace: default
            port: 8080
apiVersion: portal.gloo.solo.io/v1beta1
kind: APIProduct
metadata:
  name: petstore
  namespace: gloo-portal
  labels:
    app: petstore
spec:
  versions:
  - name: v1
    apis:
    - apiDoc:
        name: petstore-api-spec
        namespace: gloo-portal
      openApi:
        operations:
        - id: findPets
        - id: findPetById
    gatewayConfig:
      route:
        inlineRoute:
          backends:
          - kube:
              name: petstore
              namespace: default
              port: 8080

In the Environment, API Products are no longer selected one by one. Instead, we need to use the new selector-based API. Here we chose to select all the versions of all APIProducts that define the app: petstore label.

apiVersion: devportal.solo.io/v1alpha1
kind: Environment
metadata:
  name: development
  namespace: dev-portal
spec:
  domains:
  - petstore.example.com
  apiProducts:
  - name: petstore
    namespace: dev-portal
    publishedVersions:
    - name: v1
apiVersion: portal.gloo.solo.io/v1beta1
kind: Environment
metadata:
  name: development
  namespace: gloo-portal
spec:
  domains:
  - petstore.example.com
  apiProducts:
  - namespaces:
    - "*"
    labels:
    - key: app
      operator: In
      values:
      - petstore

On the User (and Group) resources, the accessLevel.apiProducts field has been replaced by the accessLevel.apis field, which implements a selector-based approach, similar to the change to specifying API Products in an Environment.

apiVersion: devportal.solo.io/v1alpha1
kind: User
metadata:
  name: alice
  namespace: dev-portal
spec:
  username: alice
  basicAuth:
    passwordSecretKey: password
    passwordSecretName: alice-password
    passwordSecretNamespace: dev-portal
  accessLevel:
    portals:
    - name: pet-portal
      namespace: dev-portal
    apiProducts:
    - name: petstore
      namespace: dev-portal
      environments:
      - name: development
        namespace: dev-portal
apiVersion: portal.gloo.solo.io/v1beta1
kind: User
metadata:
  name: alice
  namespace: gloo-portal
spec:
  username: alice
  basicAuth:
    passwordSecretKey: password
    passwordSecretName: alice-password
    passwordSecretNamespace: gloo-portal
  accessLevel:
    portals:
    - name: pet-portal
      namespace: gloo-portal
    apis:
    - products:
        namespaces:
        - "*"
        labels:
        - key: app
          operator: In
          values:
          - petstore
      environments:
        names:
        - development
        namespaces:
        - gloo-portal

Although there have been breaking changes to the Portal spec, none of those apply to our simple example, so we can just update the apiVersion:

apiVersion: devportal.solo.io/v1alpha1
kind: Portal
metadata:
  name: pet-portal
  namespace: dev-portal
spec:
  displayName: Petstore Developer Portal
  domains:
  - localhost
  - localhost:8080
  enableIngress: true
  publishedEnvironments:
  - name: development
    namespace: dev-portal
apiVersion: portal.gloo.solo.io/v1beta1
kind: Portal
metadata:
  name: pet-portal
  namespace: gloo-portal
spec:
  displayName: Petstore Developer Portal
  domains:
  - localhost
  - localhost:8080
  enableIngress: true
  publishedEnvironments:
  - name: development
    namespace: gloo-portal

Verify that the new resources have been correctly processed

Now that we have applied the modified resources in the gloo-portal namespace, let's verify that everything works as expected.

You should have 2 VirtualServices and 1 RouteTable in the gloo-portal namespace:

kubectl get virtualservices -n gloo-portal

NAME          AGE
development   2m11s
pet-portal    2m12s
kubectl get routetables -n gloo-portal

NAME                      AGE
development.petstore.v1   3m3s

If you check your Gloo Edge Proxy resource, you should also see that the corresponding routes have been added to the listener on port 8099. Let's verify that we can reach the petstore service through that listener. Let's do that by port-forwarding the 8099 port on the gateway-proxy deployment:

kubectl port-forward -n gloo-system deployment/gateway-proxy 8099

Now, in a separate shell, we can curl the gateway and should get back the expected response from the petstore service:

curl "http://localhost:8099/api/pets" -H "Host: petstore.example.com"

[{"id":1,"name":"Dog","status":"available"},{"id":2,"name":"Cat","status":"pending"}]

Update your Gloo Edge configuration to use the newly generated resources

Now that we have verified that the new gateway works as expected, we can update the gateway-proxy one to select the resources in the gloo-portal namespace and delete the portal-gateway-proxy gateway:

cat <<EOF | kubectl apply -f-
apiVersion: gateway.solo.io/v1
kind: Gateway
metadata:
  name: gateway-proxy
  namespace: gloo-system
spec:
  bindAddress: '::'
  bindPort: 8080
  httpGateway:
    virtualServiceNamespaces:
    - gloo-portal
  proxyNames:
  - gateway-proxy
EOF
kubectl delete gateway -n gloo-system portal-gateway-proxy

Uninstall Gloo Portal 0.7.6

Lastly, let's uninstall the 0.7.6 Gloo Portal deployment. Assuming the name of the Helm release is dev-portal you can run:

helm uninstall dev-portal -n dev-portal

Congratulations, you just upgraded to Gloo Portal v1.0.0 without any downtime!