Hello World - Golang

    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. import (
      2. "context"
      3. "log"
      4. cloudevents "github.com/cloudevents/sdk-go/v2"
      5. "github.com/google/uuid"
      6. )
      7. func receive(ctx context.Context, event cloudevents.Event) (*cloudevents.Event, cloudevents.Result) {
      8. // Here is where your code to process the event will go.
      9. // In this example we will log the event msg
      10. log.Printf("Event received. \n%s\n", event)
      11. data := &HelloWorld{}
      12. if err := event.DataAs(data); err != nil {
      13. log.Printf("Error while extracting cloudevent Data: %s\n", err.Error())
      14. return nil, cloudevents.NewHTTPResult(400, "failed to convert data: %s", err)
      15. }
      16. log.Printf("Hello World Message from received event %q", data.Msg)
      17. // Respond with another event (optional)
      18. // This is optional and is intended to show how to respond back with another event after processing.
      19. // The response will go back into the knative eventing system just like any other event
      20. newEvent := cloudevents.NewEvent()
      21. newEvent.SetID(uuid.New().String())
      22. newEvent.SetSource("knative/eventing/samples/hello-world")
      23. newEvent.SetType("dev.knative.samples.hifromknative")
      24. if err := newEvent.SetData(cloudevents.ApplicationJSON, HiFromKnative{Msg: "Hi from helloworld-go app!"}); err != nil {
      25. return nil, cloudevents.NewHTTPResult(500, "failed to set response data: %s", err)
      26. }
      27. log.Printf("Responding with event\n%s\n", newEvent)
      28. return &newEvent, nil
      29. }
      30. func main() {
      31. log.Print("Hello world sample started.")
      32. c, err := cloudevents.NewDefaultClient()
      33. if err != nil {
      34. log.Fatalf("failed to create client, %v", err)
      35. }
      36. log.Fatal(c.StartReceiver(context.Background(), receive))
      37. }
    2. Create a new file named eventschemas.go and paste the following code. This defines the data schema of the CloudEvents.

      1. package main
      2. // HelloWorld defines the Data of CloudEvent with type=dev.knative.samples.helloworld
      3. type HelloWorld struct {
      4. // Msg holds the message from the event
      5. Msg string `json:"msg,omitempty,string"`
      6. }
      7. // HiFromKnative defines the Data of CloudEvent with type=dev.knative.samples.hifromknative
      8. type HiFromKnative struct {
      9. // Msg holds the message from the event
      10. Msg string `json:"msg,omitempty,string"`
      11. }
    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. # Use the official Golang image to create a build artifact.
      2. # This is based on Debian and sets the GOPATH to /go.
      3. # https://hub.docker.com/_/golang
      4. FROM golang:1.14 as builder
      5. # Copy local code to the container image.
      6. WORKDIR /app
      7. # Retrieve application dependencies using go modules.
      8. # Allows container builds to reuse downloaded dependencies.
      9. COPY go.* ./
      10. RUN go mod download
      11. # Copy local code to the container image.
      12. COPY . ./
      13. # Build the binary.
      14. # -mod=readonly ensures immutable go.mod and go.sum in container builds.
      15. RUN CGO_ENABLED=0 GOOS=linux go build -mod=readonly -v -o helloworld
      16. # Use a Docker multi-stage build to create a lean production image.
      17. # https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds
      18. FROM alpine:3
      19. RUN apk add --no-cache ca-certificates
      20. # Copy the binary to the production image from the builder stage.
      21. COPY --from=builder /app/helloworld /helloworld
      22. # Run the web service on container startup.
      23. CMD ["/helloworld"]
    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
      2. kind: Namespace
      3. metadata:
      4. name: knative-samples
      5. ---
      6. apiVersion: eventing.knative.dev/v1
      7. kind: Broker
      8. metadata:
      9. name: default
      10. namespace: knative-samples
      11. spec: {}
      12. ---
      13. # Helloworld-go app deploment
      14. apiVersion: apps/v1
      15. kind: Deployment
      16. metadata:
      17. name: helloworld-go
      18. namespace: knative-samples
      19. spec:
      20. replicas: 1
      21. selector:
      22. matchLabels: &labels
      23. app: helloworld-go
      24. template:
      25. metadata:
      26. labels: *labels
      27. spec:
      28. containers:
      29. - name: helloworld-go
      30. image: docker.io/{username}/helloworld-go
      31. ---
      32. # Service that exposes helloworld-go app.
      33. # This will be the subscriber for the Trigger
      34. kind: Service
      35. apiVersion: v1
      36. metadata:
      37. name: helloworld-go
      38. namespace: knative-samples
      39. spec:
      40. selector:
      41. app: helloworld-go
      42. ports:
      43. - protocol: TCP
      44. port: 80
      45. targetPort: 8080
      46. ---
      47. # Knative Eventing Trigger to trigger the helloworld-go service
      48. apiVersion: eventing.knative.dev/v1
      49. kind: Trigger
      50. metadata:
      51. name: helloworld-go
      52. namespace: knative-samples
      53. spec:
      54. broker: default
      55. filter:
      56. attributes:
      57. type: dev.knative.samples.helloworld
      58. source: dev.knative.samples/helloworldsource
      59. subscriber:
      60. ref:
      61. apiVersion: v1
      62. kind: Service
      63. name: helloworld-go
    5. Use the go tool to create a manifest.

      1. go mod init github.com/knative/docs/docs/serving/samples/hello-world/helloworld-go

    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-go .
      3. # Push the container to docker registry
      4. docker push {username}/helloworld-go
    2. After the build has completed and the container is pushed to docker hub, you can deploy the sample application into your cluster. Ensure that the container image value in sample-app.yaml matches the container you built in the previous step. Apply the configuration using kubectl:

        1. kubectl get broker --namespace knative-samples

        Note: you can also use injection based on labels with the Eventing sugar controller. For how to install the Eventing sugar controller, see Install optional Eventing extensions.

      1. It deployed the helloworld-go app as a K8s Deployment and created a K8s service names helloworld-go. Verify using the following command.

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

        1. kubectl --namespace knative-samples get trigger helloworld-go

    Send and verify CloudEvents

    Once you have deployed the application and verified that the namespace, sample application and trigger are ready, let’s send a CloudEvent.

    We can send an http request directly to the Broker with correct CloudEvent headers set.

    1. Deploy a curl pod and SSH into it

      1. kubectl --namespace knative-samples run curl --image=radial/busyboxplus:curl -it
    2. Get the Broker URL

      1. kubectl --namespace knative-samples get broker default
    3. Run the following in the SSH terminal. Please replace the URL with the URL of the default broker.

      1. curl -v "http://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: 1.0" \
      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-go app

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

    1. Display helloworld-go app logs

      1. Event received.
      2. Validation: valid
      3. specversion: 1.0
      4. type: dev.knative.samples.helloworld
      5. source: dev.knative.samples/helloworldsource
      6. id: 536808d3-88be-4077-9d7a-a3f162705f79
      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. Data,
      13. {"msg":"Hello World from the curl pod."}
      14. Hello World Message "Hello World from the curl pod."
      15. Responded with event
      16. Validation: valid
      17. Context Attributes,
      18. specversion: 1.0
      19. type: dev.knative.samples.hifromknative
      20. source: knative/eventing/samples/hello-world
      21. id: 37458d77-01f5-411e-a243-a459bbf79682
      22. datacontenttype: application/json
      23. Data,
      24. {"msg":"Hi from Knative!"}

      Play around with the CloudEvent attributes in the curl command and the trigger specification to understand how Triggers work.

    helloworld-go app replies back with an event of type= dev.knative.samples.hifromknative, and source=knative/eventing/samples/hello-world. This event enters the eventing mesh via the Broker and can be delivered to other services using a Trigger

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

      1. kubectl --namespace knative-samples apply --filename - << END
      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-go
      19. # Source code: https://github.com/knative/eventing/tree/main/cmd/event_display
      20. image: gcr.io/knative-releases/knative.dev/eventing/cmd/event_display
      21. ---
      22. # Service that exposes event-display app.
      23. # This will be the subscriber for the Trigger
      24. kind: Service
      25. apiVersion: v1
      26. metadata:
      27. name: event-display
      28. namespace: knative-samples
      29. spec:
      30. selector:
      31. app: event-display
      32. ports:
      33. - protocol: TCP
      34. port: 80
      35. targetPort: 8080
      36. END
    2. Create a trigger to deliver the event to the above service

      1. kubectl --namespace knative-samples apply --filename - << END
      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. END
    3. Check the logs of event-display service

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

      You should see something similar to:

      1. cloudevents.Event
      2. Validation: valid
      3. Context Attributes,
      4. specversion: 1.0
      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-go app!"

    Note: You could use the above approach to test your applications too.

    Removing the sample app deployment

    To remove the sample app from your cluster, delete the service record:

    Table of contents