Knative cli with Cloud Run (managed)

2020-02-03

A very limited hack to use Knative CLI cli to do basic operations on Cloud Run (managed)

I was looking at the API calls yesterday to understand how GCP’s gcloud deploys and manages an app on Cloud Run. Cloud Run at the core used Knative so i figured “how hard is it to use knative’s on CLI to manage Cloud Run?”.

Well, you can to a limited degree and with some hacks.


WWGD? (what would gcloud do?)

First lets see the api calls gcloud makes for a simple deployment:

Consider running

gcloud run deploy service \ 
   --image gcr.io/snuffleupagus-420/http_server:$VER \
   --allow-unauthenticated

What you’ll see is a sequece of API calls…the main, unrepeated polling ones are shown below

  1. First a GET to find if the service exists

    GET https://us-central1-run.googleapis.com/apis/serving.knative.dev/v1/namespaces/snuffleupagus-420/services/service
    
  2. Then a POST with payload to create it.

    Note the namespace. THe namespace Cloud Run’s infrastructure uses as aboundary is your own project (in my case, its snuffleupagus-420 )

    POST https://us-central1-run.googleapis.com/apis/serving.knative.dev/v1/namespaces/snuffleupagus-420/services
    
    {
      "apiVersion": "serving.knative.dev/v1",
      "kind": "Service",
      "metadata": {
        "annotations": {
          "client.knative.dev/user-image": "gcr.io/snuffleupagus-420/http_server:1",
          "run.googleapis.com/client-name": "gcloud",
          "run.googleapis.com/client-version": "278.0.0"
        },
        "labels": {},
        "name": "service",
        "namespace": "snuffleupagus-420"
      },
      "spec": {
        "template": {
          "metadata": {
            "annotations": {
              "client.knative.dev/user-image": "gcr.io/snuffleupagus-420/http_server:1"
            }
          }
        }
      },
      "status": {
        "address": {}
      }
    }
  1. Get the IAM Policy first

    GET https://run.googleapis.com/v1/projects/snuffleupagus-420/locations/us-central1/services/service:getIamPolicy
    
  2. Then set the policy

    POST https://run.googleapis.com/v1/projects/snuffleupagus-420/locations/us-central1/services/service:setIamPolicy
    
    {
      "policy": {
        "bindings": [
          {
            "members": [
              "allUsers"
            ],
            "role": "roles/run.invoker"
          }
        ],
        "etag": "ACAB"
      }
    }
  1. Finally poll until its ready

    GET https://us-central1-run.googleapis.com/apis/serving.knative.dev/v1/namespaces/snuffleupagus-420/services/service
    

So, kn should be able to do all of the steps above except 3,4…lets just do the parts we can.

Using kn

Knative cli uses the kuberenets config file in addition to its own. For this tutorial, we’ll only use the kube one.

The config file i used at: $HOME/.kube/config looks like this

apiVersion: v1
kind: Config
preferences: {}

current-context: gse

clusters:
- cluster:
    certificate-authority: /path/to/ca.crt
    server: https://us-central1-run.googleapis.com:443
  name: gse
contexts:
- context:
    cluster: gse
    namespace: snuffleupagus-420
    user: gcp
  name: gse

users:
- name: gcp
  user:
    auth-provider:
      config:
        access-token: ya29.redacted
        cmd-args: config config-helper --format=json
        cmd-path: gcloud
        expiry: "2020-02-04T15:21:41Z"
        expiry-key: '{.credential.token_expiry}'
        token-key: '{.credential.access_token}'
      name: gcp

So lets look at it a bit more…

Q1 what is this config file?

its just the v1.Config file

Q2:

whats /path/to/ca.crt?

Thats the public cert chain for Google. You can get that by running openssl s_client --connect us-central1-run.googleapis.com:443 --showcerts or here

Q3: why is the namespace snuffleupagus-420?

Cloud Run uses your project as the namespace.


ok, now download knative binaries here

Then deploy any sample app you’ve uploaded to your container registry on that project.

For example, upload the files as shown in Cloud Run Quickstart

Once the image is uploaded, use kn to deploy:

./kn-linux-amd64 service create test --image=gcr.io/snuffleupagus-420/http_server:1 --namespace=snuffleupagus-420
Using kn config file: /home/srashid/.kn/config.yaml
Creating service 'test' in namespace 'snuffleupagus-420':

  1.568s Deploying Revision...
  5.630s Revision deployment finished. Waiting for health check to begin.
  6.415s Waiting for container to become healthy.
 24.526s Ready to serve.

Service 'test' created to latest revision 'test-xcydd-1' is available at URL:
https://test-6w42z6vi3q-uc.a.run.app
$ ./kn-linux-amd64 service list
Using kn config file: /home/srashid/.kn/config.yaml
NAME         URL                                          LATEST                 AGE     CONDITIONS   READY   REASON
test         https://test-6w42z6vi3q-uc.a.run.app         test-xcydd-1           2m59s   3 OK / 3     True 

By default Cloud Run enables authentication. TO make this image public, follow the instructions here

now you can access the endpoint…

again, please be aware this isn’t supported and many things in knative specs don’t work in Cloud Run (managed)…(eg, tags)

This site supports webmentions. Send me a mention via this form.