Hello World - Python

    We will deploy the app as a Kubernetes Deployment along with a . However, you can also deploy the app as a Knative Serving Service.

    Follow the steps below to create the sample code and then deploy the app to your cluster. You can also download a working copy of the sample, by running the following commands:

    • A Kubernetes cluster with installed.
    • Docker installed and running on your local machine, and a Docker Hub account configured (we’ll use it for a container registry).

    Recreating the sample code

    1. Create a new file named and paste the following code. This code creates a basic web server which listens on port 8080:

      1. from flask import Flask, request, make_response
      2. import uuid
      3. app = Flask(__name__)
      4. @app.route('/', methods=['POST'])
      5. def hello_world():
      6. app.logger.warning(request.data)
      7. # Respond with another event (optional)
      8. response = make_response({
      9. "msg": "Hi from helloworld-python app!"
      10. })
      11. response.headers["Ce-Id"] = str(uuid.uuid4())
      12. response.headers["Ce-specversion"] = "0.3"
      13. response.headers["Ce-Source"] = "knative/eventing/samples/hello-world"
      14. response.headers["Ce-Type"] = "dev.knative.samples.hifromknative"
      15. return response
      16. if __name__ == '__main__':
      17. app.run(debug=True, host='0.0.0.0', port=8080)
    2. Add a requirements.txt file containing the following contents:

      1. Flask==1.1.1
    3. In your project directory, create a file named Dockerfile and copy the code block below into it. For detailed instructions on dockerizing a Go app, see Deploying Go servers with Docker.

      1. FROM python:alpine3.7
      2. COPY . /app
      3. WORKDIR /app
      4. RUN pip install -r requirements.txt
      5. EXPOSE 8080
      6. ENTRYPOINT [ "python" ]
      7. CMD [ "helloworld.py" ]
    4. Create a new file, sample-app.yaml and copy the following service definition into the file. Make sure to replace {username} with your Docker Hub username.

      1. # Namespace for sample application with eventing enabled
      2. apiVersion: v1
      3. kind: Namespace
      4. metadata:
      5. name: knative-samples
      6. labels:
      7. eventing.knative.dev/injection: enabled
      8. ---
      9. # A default broker
      10. apiVersion: eventing.knative.dev/v1
      11. kind: Broker
      12. metadata:
      13. name: default
      14. namespace: knative-samples
      15. annotations:
      16. # Note: you can set the eventing.knative.dev/broker.class annotation to change the class of the broker.
      17. # The default broker class is MTChannelBasedBroker, but Knative also supports use of the other class.
      18. eventing.knative.dev/broker.class: MTChannelBasedBroker
      19. spec: {}
      20. ---
      21. # Helloworld-python app deployment
      22. apiVersion: apps/v1
      23. kind: Deployment
      24. metadata:
      25. name: helloworld-python
      26. namespace: knative-samples
      27. spec:
      28. replicas: 1
      29. selector:
      30. matchLabels: &labels
      31. app: helloworld-python
      32. template:
      33. labels: *labels
      34. spec:
      35. containers:
      36. - name: helloworld-python
      37. image: docker.io/{username}/helloworld-python
      38. ---
      39. # Service that exposes helloworld-python app.
      40. # This will be the subscriber for the Trigger
      41. apiVersion: v1
      42. kind: Service
      43. metadata:
      44. name: helloworld-python
      45. namespace: knative-samples
      46. spec:
      47. selector:
      48. app: helloworld-python
      49. ports:
      50. - protocol: TCP
      51. port: 80
      52. targetPort: 8080
      53. ---
      54. # Knative Eventing Trigger to trigger the helloworld-python service
      55. apiVersion: eventing.knative.dev/v1
      56. kind: Trigger
      57. metadata:
      58. name: helloworld-python
      59. namespace: knative-samples
      60. spec:
      61. broker: default
      62. filter:
      63. attributes:
      64. type: dev.knative.samples.helloworld
      65. source: dev.knative.samples/helloworldsource
      66. subscriber:
      67. ref:
      68. apiVersion: v1
      69. kind: Service
      70. name: helloworld-python

    Once you have recreated the sample code files (or used the files in the sample folder) you’re ready to build and deploy the sample app.

    1. Use Docker to build the sample code into a container. To build and push with Docker Hub, run these commands replacing {username} with your Docker Hub username:

      1. # Build the container on your local machine
      2. docker build -t {username}/helloworld-python .
      3. # Push the container to docker registry
      4. docker push {username}/helloworld-python
    2. The previous command creates a namespace knative-samples and labels it with knative-eventing-injection=enabled, to enable eventing in the namespace. Verify using the following command:

      1. kubectl get ns knative-samples --show-labels
    3. It deployed the helloworld-python app as a K8s Deployment and created a K8s service names helloworld-python. Verify using the following command:

      1. kubectl --namespace knative-samples get deployments helloworld-python
      2. kubectl --namespace knative-samples get svc helloworld-python
    4. It created a Knative Eventing Trigger to route certain events to the helloworld-python application. Make sure that Ready=true:

      1. kubectl -n knative-samples get trigger helloworld-python

    Send and verify CloudEvents

    After you have deployed the application, and have verified that the namespace, sample application and trigger are ready, you can send a CloudEvent.

    You can send an HTTP request directly to the Knative broker if the correct CloudEvent headers are set.

    1. Deploy a curl pod and SSH into it:

      1. kubectl --namespace knative-samples run curl --image=radial/busyboxplus:curl -it
    2. Run the following command in the SSH terminal:

      1. curl -v "broker-ingress.knative-eventing.svc.cluster.local/knative-samples/default" \
      2. -X POST \
      3. -H "Ce-Id: 536808d3-88be-4077-9d7a-a3f162705f79" \
      4. -H "Ce-specversion: 0.3" \
      5. -H "Ce-Type: dev.knative.samples.helloworld" \
      6. -H "Ce-Source: dev.knative.samples/helloworldsource" \
      7. -H "Content-Type: application/json" \
      8. -d '{"msg":"Hello World from the curl pod."}'
      9. exit

    Verify that event is received by helloworld-python app

    Helloworld-python app logs the context and the msg of the above event, and replies back with another event.

    1. You should see something similar to:

      1. Event received. Context: Context Attributes,
      2. specversion: 0.3
      3. type: dev.knative.samples.helloworld
      4. source: dev.knative.samples/helloworldsource
      5. id: 536808d3-88be-4077-9d7a-a3f162705f79
      6. time: 2019-10-04T22:35:26.05871736Z
      7. datacontenttype: application/json
      8. Extensions,
      9. knativearrivaltime: 2019-10-04T22:35:26Z
      10. knativehistory: default-kn2-trigger-kn-channel.knative-samples.svc.cluster.local
      11. traceparent: 00-971d4644229653483d38c46e92a959c7-92c66312e4bb39be-00
      12. Hello World Message "Hello World from the curl pod."
      13. Responded with event Validation: valid
      14. Context Attributes,
      15. type: dev.knative.samples.hifromknative
      16. source: knative/eventing/samples/hello-world
      17. Data,
      18. {"msg":"Hi from Knative!"}

      Try the CloudEvent attributes in the curl command and the trigger specification to understand how triggers work.

    The helloworld-python app replies with an event type type= dev.knative.samples.hifromknative, and source source=knative/eventing/samples/hello-world. The event enters the eventing mesh through the broker, and can be delivered to event sinks using a trigger

    1. Deploy a pod that receives any CloudEvent and logs the event to its output:

      1. kubectl -n knative-samples apply -f - <<EOF
      2. # event-display app deploment
      3. apiVersion: apps/v1
      4. kind: Deployment
      5. metadata:
      6. name: event-display
      7. namespace: knative-samples
      8. spec:
      9. replicas: 1
      10. selector:
      11. matchLabels: &labels
      12. app: event-display
      13. template:
      14. metadata:
      15. labels: *labels
      16. spec:
      17. containers:
      18. - name: helloworld-python
      19. image: gcr.io/knative-releases/knative.dev/eventing/cmd/event_display
      20. ---
      21. # Service that exposes event-display app.
      22. # This will be the subscriber for the Trigger
      23. kind: Service
      24. apiVersion: v1
      25. metadata:
      26. name: event-display
      27. namespace: knative-samples
      28. spec:
      29. selector:
      30. app: event-display
      31. ports:
      32. - protocol: TCP
      33. port: 80
      34. targetPort: 8080
      35. EOF
    2. Create a trigger to deliver the event to the previously created service:

      1. kubectl -n knative-samples apply -f - <<EOF
      2. apiVersion: eventing.knative.dev/v1
      3. kind: Trigger
      4. metadata:
      5. name: event-display
      6. namespace: knative-samples
      7. spec:
      8. broker: default
      9. filter:
      10. attributes:
      11. type: dev.knative.samples.hifromknative
      12. source: knative/eventing/samples/hello-world
      13. subscriber:
      14. ref:
      15. apiVersion: v1
      16. kind: Service
      17. name: event-display
      18. EOF
    3. Check the logs of event-display Service:

      1. kubectl -n knative-samples logs -l app=event-display --tail=50

      Example output:

      1. cloudevents.Event
      2. Validation: valid
      3. Context Attributes,
      4. specversion: 0.3
      5. type: dev.knative.samples.hifromknative
      6. source: knative/eventing/samples/hello-world
      7. id: 8a7384b9-8bbe-4634-bf0f-ead07e450b2a
      8. time: 2019-10-04T22:53:39.844943931Z
      9. datacontenttype: application/json
      10. Extensions,
      11. knativearrivaltime: 2019-10-04T22:53:39Z
      12. knativehistory: default-kn2-ingress-kn-channel.knative-samples.svc.cluster.local
      13. traceparent: 00-4b01db030b9ea04bb150b77c8fa86509-2740816590a7604f-00
      14. Data,
      15. {
      16. "msg": "Hi from helloworld- app!"

    Removing the sample app deployment