Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Beyond Kubernetes - Knative, riff, and Spring Cloud Function

Ray Tsang
November 13, 2018

Beyond Kubernetes - Knative, riff, and Spring Cloud Function

From function source code to running in Kubernetes in 5 minutes. That's the power some of the latest open source projects can bring to your fingertips. This perceived simplicity actually hides layers of abstractions underneath. In this deep dive, we'll explore all the technology behind the scenes, from Kubernetes, Istio, Knative, to riff and Spring Cloud function.

We'll explore how Istio and Knative extend Kubernetes via Custom Resource Definitions to provide support for higher level developer concerns such as microservices autoscaling, routing across revisions of an application, and a unified eventing bus to compose event-driven workloads. Building on top of this, we'll take a look at how riff has been replatformed to run on top of Knative, while preserving its scale-on-demand Function as a Service ease of use. Finally, to tie the platform from top to bottom, we'll dive into Spring Cloud Function to see how to use Function interface to create a function that can process both synchronous HTTP requests as well as event-based messages using riff and Knative.

Presented at 2018 Devoxx Belgium: https://www.youtube.com/watch?v=HEWb1IWqT30

Ray Tsang

November 13, 2018
Tweet

More Decks by Ray Tsang

Other Decks in Technology

Transcript

  1. Beyond Kubernetes Managing Applications and Functions with Knative, riff, and

    Spring Cloud Functions Eric Bottard @ebottard Pivotal Ray Tsang @saturnism Google
  2. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio Ray

    Tsang Developer Advocate Google Cloud Platform Spring Cloud GCP cloud.spring.io/spring-cloud-gcp/ JHipster, JDeferred Java Champion @saturnism | saturnism.me
  3. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio Eric

    Bottard Sr Software Engineer Pivotal Spring Cloud DataFlow cloud.spring.io/spring-cloud-dataflow/ Project riff https://projectriff.io/ @ebottard
  4. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio Kubernetes

    - Looking under the hood Knative - Why and How riff - A FaaS on top of Knative Serving - via a manual deployment Build - via riff function create Eventing - via riff function chaining Spring Cloud Function - platform agnostic functions End to End - everything we've learned Things We'll Cover
  5. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio apiVersion:

    app/v1 kind: Deployment metadata: name: helloworld ... spec: replicas: 2 template: ... spec: containers: - name: helloworld image: saturnism/helloworld:v1
  6. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio web

    browsers Scheduler kubectl web browsers scheduler Kubelet Kubelet Kubelet Kubelet Config file Kubernetes Master Container Image
  7. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio Deployment

    apiVersion: app/v1 kind: Deployment metdatdata: name: nginx spec: replicas: 2 template: ... spec: containers: - name: nginx image: nginx
  8. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio Deployment

    Deployment Controller apiVersion: app/v1 kind: Deployment metdatdata: name: nginx spec: replicas: 2 template: ... spec: containers: - name: nginx image: nginx
  9. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio ReplicaSet

    Deployment Deployment Controller Create apiVersion: app/v1 kind: ReplicaSet metadata: name: nginx-1234 spec: replicas: 2 template: ... spec: containers: - name: nginx image: nginx
  10. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio ReplicaSet

    Deployment Deployment Controller Replication Controller Create apiVersion: app/v1 kind: ReplicaSet metadata: name: nginx-1234 spec: replicas: 2 template: ... spec: containers: - name: nginx image: nginx
  11. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio Pod

    ReplicaSet Deployment Deployment Controller apiVersion: app/v1 kind: Pod metadata: name: nginx-1234-k5jv spec: ... containers: - name: nginx image: nginx Replication Controller Create Create Pod apiVersion: app/v1 kind: Pod metadata: name: nginx-1234-q7jd spec: ... containers: - name: nginx image: nginx
  12. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio Pod

    ReplicaSet Deployment Deployment Controller Replication Controller Create Create Scheduler Pod apiVersion: app/v1 kind: Pod metadata: name: nginx-1234-k5jv spec: ... containers: - name: nginx image: nginx apiVersion: app/v1 kind: Pod metadata: name: nginx-1234-q7jd spec: ... containers: - name: nginx image: nginx
  13. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio Pod

    ReplicaSet Deployment Deployment Controller Replication Controller Create Create Scheduler Assign to Node Pod apiVersion: app/v1 kind: Pod metadata: name: nginx-1234-k5jv spec: ... containers: - name: nginx image: nginx nodeName: node-1 apiVersion: app/v1 kind: Pod metadata: name: nginx-1234-q7jd spec: ... containers: - name: nginx image: nginx nodeName: node-2
  14. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio Pod

    ReplicaSet Deployment Deployment Controller Replication Controller Create Create Scheduler Assign to Node Pod Kubelet apiVersion: app/v1 kind: Pod metadata: name: nginx-1234-k5jv spec: ... containers: - name: nginx image: nginx nodeName: node-1 apiVersion: app/v1 kind: Pod metadata: name: nginx-1234-q7jd spec: ... containers: - name: nginx image: nginx nodeName: node-2
  15. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio Pod

    ReplicaSet Deployment Deployment Controller Replication Controller Create Create Scheduler Assign to Node Pod Kubelet Start the container! apiVersion: app/v1 kind: Pod metadata: name: nginx-1234-k5jv spec: ... containers: - name: nginx image: nginx nodeName: node-1 status: ... apiVersion: app/v1 kind: Pod metadata: name: nginx-1234-q7jd spec: ... containers: - name: nginx image: nginx nodeName: node-2 status: ...
  16. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio Pod

    ReplicaSet Deployment Deployment Controller Replication Controller Create Create Scheduler Assign to Node Pod Kubelet Update Status Start the container! apiVersion: app/v1 kind: Pod metadata: name: nginx-1234-k5jv spec: ... containers: - name: nginx image: nginx nodeName: node-1 status: ... apiVersion: app/v1 kind: Pod metadata: name: nginx-1234-q7jd spec: ... containers: - name: nginx image: nginx nodeName: node-2 status: ...
  17. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio apiVersion:

    apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition metadata: name: gameservers.stable.agones.dev spec: group: stable.agones.dev version: v1alpha1 scope: Namespaced names: kind: GameServer plural: gameservers shortNames: - gs singular: gameserver Custom Resource Definition https://github.com/GoogleCloudPlatform/agones
  18. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio apiVersion:

    apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition metadata: name: gameservers.stable.agones.dev spec: group: stable.agones.dev version: v1alpha1 scope: Namespaced names: kind: GameServer plural: gameservers shortNames: - gs singular: gameserver Custom Resource Definition apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition metadata: name: gameservers.stable.agones.dev spec: group: stable.agones.dev version: v1alpha1 scope: Namespaced names: ... validation: openAPIV3Schema: required: - spec properties: spec: required: - template ... With Validation
  19. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio apiVersion:

    "stable.agones.dev/v1alpha1" kind: GameServer metadata: name: "simple-udp" spec: ports: - name: default portPolicy: "dynamic" containerPort: 7654 template: spec: containers: - name: simple-udp image: gcr.io/agones-images/udp-server:0.4 Custom Resource
  20. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio apiVersion:

    "stable.agones.dev/v1alpha1" kind: GameServer metadata: name: "simple-udp" spec: ports: - name: default portPolicy: "dynamic" containerPort: 7654 template: spec: containers: - name: simple-udp image: gcr.io/agones-images/udp-server:0.4 Custom Resource Controller Game Server Controller
  21. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio apiVersion:

    "stable.agones.dev/v1alpha1" kind: GameServer metadata: name: "simple-udp" spec: ports: - name: default portPolicy: "dynamic" containerPort: 7654 template: spec: containers: - name: simple-udp image: gcr.io/agones-images/udp-server:0.4 Custom Resource Controller Game Server Controller Deployment Create
  22. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio apiVersion:

    "stable.agones.dev/v1alpha1" kind: GameServer metadata: name: "simple-udp" spec: ports: - name: default portPolicy: "dynamic" containerPort: 7654 template: spec: containers: - name: simple-udp image: gcr.io/agones-images/udp-server:0.4 Custom Resource Controller Game Server Controller ReplicaSet Deployment Create
  23. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio apiVersion:

    "stable.agones.dev/v1alpha1" kind: GameServer metadata: name: "simple-udp" spec: ports: - name: default portPolicy: "dynamic" containerPort: 7654 template: spec: containers: - name: simple-udp image: gcr.io/agones-images/udp-server:0.4 Custom Resource Controller Game Server Controller Pod ReplicaSet Deployment Pod Create
  24. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio Zero

    to Kubernetes Kubernetes Write code Build docker image Upload image to registry Deploy with Deployment Expose to the internet HTTP Load Balancing Scale workload
  25. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio Higher

    Level Abstraction Kubernetes Write code Build docker image Upload image to registry Deploy with Deployment Expose to the internet HTTP Load Balancing Scale workload Would Be Nice... Write code :D Deploy!
  26. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio Introducing

    Knative Kubernetes-based building blocks for serverless workloads
  27. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio •

    Set of primitives (Build, Events, Serving) • Solves for modern development patterns • Implements learnings from Google, partners • Ingredient or platform for OSS FaaS frameworks github.com/knative Introducing Knative Kubernetes-based building blocks for serverless workloads
  28. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio The

    Knative stack Kubernetes Platform Istio Service Mesh Build Primitives Serving Events
  29. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio Event

    driven Function as a Service Opinionated experience built atop Knative, Kubernetes and Istio Functions practice Inversion of Control No servers, ports or HTTP, just your logic Pick your language runtime: Java/Spring JavaScript/Node executable commands more from the community riff is for functions
  30. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio riff

    on Knative Community-driven ecosystem of Sources, Channels, Functions, Invokers, BuildTemplates, etc. Kubernetes BuildTemplates Channels CLI Invokers CLI Invokers Build Topics
  31. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio The

    Knative Serving project provides middleware primitives that enable: Automatic scaling up and down to zero Routing and network programming for Istio components Point-in-time snapshots of deployed code and configurations Knative Serving
  32. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio Knative

    Serving defines principled objects Knative defines primitives with clear separation of concerns So far, we used Service, a lite version of Knative objects spec: container: image: gcr.io/knative-samples/simple-app:latest env: - name: SIMPLE_MSG value: "Hello GCP Next 2018!" Service
  33. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio Knative

    Serving defines principled objects Knative defines primitives with clear separation of concerns Configuration Current/desired state for your application Code & configuration (separated, ala 12 factor) Configuration Service
  34. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio Knative

    Serving defines principled objects Knative defines primitives with clear separation of concerns Configuration Current/desired state for your application Code & configuration (separated, ala 12 factor) Revision Point in time snapshots for your code and configuration Revision Configuration Service
  35. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio Knative

    Serving defines principled objects Revision Knative defines primitives with clear separation of concerns Configuration Current/desired state for your application Code & configuration (separated, ala 12 factor) Revision Point in time snapshots for your code and configuration Route Maps traffic to a revisions Supports fractional, named routing Route Configuration Service
  36. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio Revision

    Route Configuration Knative Service Deployment Kubernetes Service
  37. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio Revision

    Route Configuration Knative Service ReplicaSet Deployment Kubernetes Service
  38. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio Revision

    Route Configuration Knative Service Pod ReplicaSet Deployment Pod Kubernetes Service
  39. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio Revision

    Route Configuration Knative Service Pod ReplicaSet Deployment Pod Istio Virtual Service Kubernetes Service
  40. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio ServiceCRD

    - creates route and configuration, for either latest or pinned revision RouteCRD - maps a network endpoint to one or more revisions, enabling traffic policy management across revisions ConfigurationCRD - mutable desired state for your deployment, with each modification creating a new revision RevisionCRD - immutable point-in-time snapshot for each modification made to the workload code/config Knative Serving CRDs
  41. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio Demo:

    Deploying and updating live service Blue-green deployment model Route 100% Revision 0001 Configuration kind: Route ... spec: traffic: - revisionName: blue-green-00001 percent: 100
  42. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio Blue-green

    deployment model kind: Route ... spec: traffic: - revisionName: blue-green-00001 percent: 100 - revisionName: blue-green-00002 percent: 0 name: v2 Deploy updated version of the service • Blue continues to take 100% of traffic • Named route (v2) to green version Revision 00002 Route 100% Revision 00001 0% v2 Configuration Configuration
  43. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio Blue-green

    deployment model Update service configuration • Send % of traffic to green • Still have explicit v2 route kind: Route ... spec: traffic: - revisionName: blue-green-00001 percent: 50 - revisionName: blue-green-00002 percent: 50 name: v2 Revision 00002 Route 98% Revision 00001 2% (Experiment) Configuration Configuration
  44. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio Blue-green

    deployment model Update service configuration • Incrementally add %, until all traffic is on green • Keep explicit named route to blue Secured with RBAC-based ACL kind: Route ... spec: traffic: - revisionName: blue-green-00001 percent: 0 name: v1 - revisionName: blue-green-00002 percent: 100 Revision 00002 Route 0% v1 Revision 00001 100% Configuration Configuration
  45. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio A

    Build is a custom resource in Knative that allows you to define a process that runs to completion and can provide status. For example, fetch, build, and package your code by using a Knative Build that communicates whether the process succeeds. A Knative Build runs on-cluster [...] to build the source code of your apps into container images, which you can then run on Knative serving. Knative Build https://github.com/knative/docs/tree/master/build
  46. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio a

    BuildCRD = specific instance of a process made of steps runs a sequence of images, aka Builders a BuildTemplateCRD = a recipe for instantiating BuildsCRD. accepts parameters runs under a given ServiceAccount can hold credentials Key Concepts of Knative Build
  47. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio Knative

    Events is a system which is designed to address a common need for cloud native development: 1. Services are loosely coupled during development and deployed independently on a variety of platforms (Kubernetes, VMs, SaaS or FaaS). 2. A producer can generate events before a consumer is listening, and a consumer can express an interest in an event or class of events that is not yet being produced. 3. Services can be connected to create new applications without modifying producer or consumer. With the ability to select a specific subset of events from a particular producer Knative Eventing https://github.com/knative/docs/tree/master/eventing
  48. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio ChannelCRD

    is a network endpoint which receives (and optionally persists) events using a Bus-specific implementation. SubscriptionCRD connects events received on a Channel to an interested target, represented as a DNS name. There may be multiple Subscriptions on a single channel. Bus* defines the adaptation layers needed to implement channels and subscriptions using a specific persistence strategy (such as delivery of events to a Kafka topic). Knative Eventing Also: Sources, Flows source channel function flow subscription
  49. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio A

    Loosely Coupled Example square correlator riff service create correlator --image projectriff/correlator:fats
  50. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio A

    Loosely Coupled Example numbers square correlator riff channel create numbers --cluster-bus stub
  51. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio A

    Loosely Coupled Example numbers square correlator squares riff channel create squares --cluster-bus stub
  52. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio riff

    subscription create --channel numbers --subscriber square --reply-to squares A Loosely Coupled Example numbers square correlator squares
  53. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio A

    Loosely Coupled Example numbers square greet correlator squares riff function create command greet \ --image gcr.io/$GCP_PROJECT/riff-sample-greet \ --git-repo https://github.com/projectriff-samples/command-hello \ --artifact greet.sh \ --verbose
  54. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio A

    Loosely Coupled Example numbers square replies greet correlator squares riff channel create replies --cluster-bus stub
  55. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio riff

    subscription create -c squares -s greet -r replies A Loosely Coupled Example numbers square replies greet correlator squares
  56. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio riff

    subscription create -c replies -s correlator A Loosely Coupled Example numbers square replies greet correlator squares
  57. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio A

    Loosely Coupled Example numbers square replies greet correlator squares /numbers
  58. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio Kubernetes

    is extensible Knative is a platform for platforms Serving scale to/from zero. Route traffic Build optionally build from source Eventing decouple workloads in space / time riff is a FaaS on top of Knative Let's Recap
  59. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio Working

    with Spring Cloud Function Serverless Functions the Spring way • Promote the implementation of business logic via functions • Abstract away the target runtime ◦ Supports multiple Function as a Service platform • Support a uniform programming model across serverless providers ◦ Run standalone (locally or in a PaaS). • Enable Spring Boot features on serverless providers ◦ Auto-configuration ◦ Dependency injection ◦ Metrics
  60. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio A

    serverless function by itself is ... • kind of pointless ... we need a way to deploy it and to invoke it • include the function in an app • invoke it via a standalone invoker app • deploy it to a FaaS
  61. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio A

    function package com.springdeveloper.demo.functionapp; import java.util.function.Function; public class Upper implements Function<String, String> { public String apply(String name) { return name.toUpperCase(); } }
  62. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio A

    function invoker package com.springdeveloper.demo.functionapp; import java.util.function.Function; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; @SpringBootApplication public class FunctionAppApplication { @Bean public Function<String, String> uppercase() { return s -> s.toUpperCase(); } public static void main(String[] args) { SpringApplication.run(FunctionAppApplication.class, args); } }
  63. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio Spring

    Cloud GCP Goals Provide integration between GCP services and Spring Meet developers where they are Cut down on boilerplate code +
  64. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio Feature

    GCP Service Spring Framework Authentication Auto credential discovery. Service Accounts. Configuration Cloud Runtime Config Spring Cloud Config Messaging Cloud Pub/Sub Spring Integration Spring Cloud Stream Spring Dataflow Database Cloud SQL Cloud Spanner Spring Data Spring Data Spanner Storage Cloud Storage Spring Resource Logging Stackdriver Logging Logback Trace Stackdriver Trace Spring Cloud Sleuth
  65. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio Vision

    API • Analyze what's inside of an image • Feature detection such as ◦ labels (is there a cat?) ◦ text extraction ◦ facial features and emotion ◦ Landmarks ◦ Logos ◦ safe search ◦ ...
  66. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio Kubernetes

    Basics Knative - Why and How riff - A FaaS on top of Knative Serving - via a manual deployment Build - via riff function create Eventing - via riff function chaining End to End - everything we've learned Things We Saw
  67. @saturnism @gcpcloud / @ebottard @pivotal / @projectriff @knativeproject @kubernetesio Thanks!

    Give it a try! Project riff projectriff.io Install, Samples, Docs github.com/knative/docs Spring Cloud Function, Knative, Riff Code Lab bit.ly/spring-riff-lab Want to contribute? knative/docs/community Have questions? knative.slack.com