erlang
abap
adonis
+
+
+=
css
+
vue
+
fortran
+
+
+
redis
+
+
arch
dask
+
+
+
+
+
+
+
+
+
jax
ray
==
+
htmx
+
+
intellij
+
+
haskell
+
+
emacs
+
0b
+
+
+
+
react
windows
mvn
+
+
+
+
windows
?
+
+
azure
yaml
tcl
+
go
+
chef
scala
kotlin
+
vb
+
eclipse
circle
+
+
suse
elementary
+
+
firebase
+
+
+
+
+
+
+
+
terraform
+
Back to Blog
Setting Up Serverless Platform with Knative on Rocky Linux
rocky-linux knative serverless

Setting Up Serverless Platform with Knative on Rocky Linux

Published Jul 15, 2025

Deploy a complete serverless platform using Knative on Rocky Linux. Learn autoscaling, event-driven architecture, function deployment, and enterprise serverless patterns

20 min read
0 views
Table of Contents

Serverless computing has revolutionized application deployment by abstracting infrastructure management and enabling automatic scaling. This comprehensive guide demonstrates setting up a production-ready Knative serverless platform on Rocky Linux, covering serving, eventing, and advanced deployment patterns.

Understanding Knative Architecture

Knative extends Kubernetes to provide a serverless platform with two main components:

Knative Serving

  • Request-driven compute: Scale to zero and from zero
  • Automatic scaling: Based on concurrent requests or CPU
  • Traffic management: Blue-green deployments and canary releases
  • Revision management: Immutable snapshots of code and configuration

Knative Eventing

  • Event sources: Connect to various event producers
  • Event delivery: Reliable event routing and delivery
  • Event processing: Filter, transform, and route events
  • CloudEvents: Standard event format support

Prerequisites

Before deploying Knative:

  • Rocky Linux 9 with Kubernetes 1.24+
  • kubectl and helm installed
  • Minimum 4 nodes with 8GB RAM each
  • LoadBalancer or Ingress controller
  • Container registry access
  • DNS configuration for custom domains

Setting Up Kubernetes Cluster

Installing Kubernetes with kubeadm

# Disable swap and SELinux
sudo swapoff -a
sudo sed -i '/swap/d' /etc/fstab
sudo setenforce 0
sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config

# Configure kernel modules
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

sudo modprobe overlay
sudo modprobe br_netfilter

# Configure sysctl
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
EOF

sudo sysctl --system

# Install container runtime (containerd)
sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo dnf install -y containerd.io
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
sudo systemctl restart containerd
sudo systemctl enable containerd

# Install Kubernetes components
cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el9-x86_64
enabled=1
gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOF

sudo dnf install -y kubelet kubeadm kubectl
sudo systemctl enable --now kubelet

# Initialize cluster (on master node)
sudo kubeadm init --pod-network-cidr=10.244.0.0/16

# Configure kubectl
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

# Install Calico network plugin
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.0/manifests/tigera-operator.yaml
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.0/manifests/custom-resources.yaml

Installing Istio (Required for Knative)

# Download and install Istio
curl -L https://istio.io/downloadIstio | sh -
cd istio-*
export PATH=$PWD/bin:$PATH

# Install Istio with Knative configuration
istioctl install --set values.pilot.env.PILOT_ENABLE_WORKLOAD_ENTRY_AUTOREGISTRATION=true \
  --set values.gateways.istio-ingressgateway.runAsRoot=true \
  --set values.global.proxy.clusterDomain="cluster.local" \
  --set values.global.proxy.autoInject=disabled

# Label default namespace for injection
kubectl label namespace default istio-injection=enabled

# Verify Istio installation
kubectl get pods -n istio-system

Installing Knative Serving

Core Components

# Install Knative Serving CRDs
kubectl apply -f https://github.com/knative/serving/releases/download/knative-v1.12.0/serving-crds.yaml

# Install Knative Serving core
kubectl apply -f https://github.com/knative/serving/releases/download/knative-v1.12.0/serving-core.yaml

# Verify installation
kubectl get pods -n knative-serving

# Install Knative Istio controller
kubectl apply -f https://github.com/knative/net-istio/releases/download/knative-v1.12.0/net-istio.yaml

# Configure DNS for Knative
kubectl apply -f https://github.com/knative/serving/releases/download/knative-v1.12.0/serving-default-domain.yaml

Configuring Knative Serving

# knative-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: config-domain
  namespace: knative-serving
data:
  # Configure your domain
  example.com: |
    selector:
      app: my-app
  # Default domain template
  _example: |
    {{.Name}}.{{.Namespace}}.{{.Domain}}
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: config-autoscaler
  namespace: knative-serving
data:
  # Autoscaling configuration
  container-concurrency-target-default: "100"
  container-concurrency-target-percentage: "0.7"
  enable-scale-to-zero: "true"
  max-scale-up-rate: "1000"
  max-scale-down-rate: "2"
  panic-window-percentage: "10"
  panic-threshold-percentage: "200"
  scale-to-zero-grace-period: "30s"
  scale-to-zero-pod-retention-period: "0s"
  stable-window: "60s"
  target-burst-capacity: "200"
  requests-per-second-target-default: "200"
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: config-deployment
  namespace: knative-serving
data:
  # Revision timeout configuration
  revision-timeout-seconds: "300"
  max-revision-timeout-seconds: "600"
  revision-cpu-request: "25m"
  revision-memory-request: "50Mi"
  revision-cpu-limit: "1000m"
  revision-memory-limit: "1024Mi"

Installing Knative Eventing

Core Components

# Install Knative Eventing CRDs
kubectl apply -f https://github.com/knative/eventing/releases/download/knative-v1.12.0/eventing-crds.yaml

# Install Knative Eventing core
kubectl apply -f https://github.com/knative/eventing/releases/download/knative-v1.12.0/eventing-core.yaml

# Install default channel (InMemoryChannel)
kubectl apply -f https://github.com/knative/eventing/releases/download/knative-v1.12.0/in-memory-channel.yaml

# Install MT-Channel-Based Broker
kubectl apply -f https://github.com/knative/eventing/releases/download/knative-v1.12.0/mt-channel-broker.yaml

# Verify installation
kubectl get pods -n knative-eventing

Configuring Event Sources

# kafka-source.yaml
apiVersion: sources.knative.dev/v1beta1
kind: KafkaSource
metadata:
  name: kafka-source
  namespace: default
spec:
  consumerGroup: knative-group
  bootstrapServers:
  - kafka-broker-1.kafka:9092
  - kafka-broker-2.kafka:9092
  - kafka-broker-3.kafka:9092
  topics:
  - events-topic
  sink:
    ref:
      apiVersion: eventing.knative.dev/v1
      kind: Broker
      name: default
---
# github-source.yaml
apiVersion: sources.knative.dev/v1alpha1
kind: GitHubSource
metadata:
  name: github-source
  namespace: default
spec:
  eventTypes:
  - push
  - pull_request
  ownerAndRepository: myorg/myrepo
  accessToken:
    secretKeyRef:
      name: github-secret
      key: token
  secretToken:
    secretKeyRef:
      name: github-secret
      key: webhook-secret
  sink:
    ref:
      apiVersion: eventing.knative.dev/v1
      kind: Broker
      name: default

Deploying Serverless Applications

Basic Knative Service

# hello-service.yaml
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: hello
  namespace: default
spec:
  template:
    metadata:
      annotations:
        # Autoscaling annotations
        autoscaling.knative.dev/target: "50"
        autoscaling.knative.dev/metric: "concurrency"
        autoscaling.knative.dev/scale-down-delay: "0s"
        autoscaling.knative.dev/window: "60s"
    spec:
      containerConcurrency: 100
      timeoutSeconds: 300
      containers:
      - image: gcr.io/knative-samples/helloworld-go
        ports:
        - containerPort: 8080
        env:
        - name: TARGET
          value: "Knative"
        resources:
          requests:
            cpu: 100m
            memory: 128Mi
          limits:
            cpu: 1000m
            memory: 512Mi
        livenessProbe:
          httpGet:
            path: /healthz
          initialDelaySeconds: 5
        readinessProbe:
          httpGet:
            path: /ready
          initialDelaySeconds: 5

Advanced Service with Traffic Splitting

# canary-deployment.yaml
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: canary-app
  namespace: default
spec:
  template:
    metadata:
      name: canary-app-v2
    spec:
      containers:
      - image: myregistry/app:v2
        env:
        - name: VERSION
          value: "v2"
  traffic:
  - latestRevision: false
    revisionName: canary-app-v1
    percent: 80
    tag: stable
  - latestRevision: true
    percent: 20
    tag: canary

Event-Driven Architecture

Creating Event Flows

# event-display-service.yaml
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: event-display
  namespace: default
spec:
  template:
    spec:
      containers:
      - image: gcr.io/knative-samples/event-display
---
# broker-trigger.yaml
apiVersion: eventing.knative.dev/v1
kind: Broker
metadata:
  name: default
  namespace: default
  annotations:
    eventing.knative.dev/broker.class: MTChannelBasedBroker
spec:
  config:
    apiVersion: v1
    kind: ConfigMap
    name: config-br-defaults
    namespace: knative-eventing
---
apiVersion: eventing.knative.dev/v1
kind: Trigger
metadata:
  name: event-display-trigger
  namespace: default
spec:
  broker: default
  filter:
    attributes:
      type: dev.knative.samples.helloworld
      source: dev.knative.samples/helloworldsource
  subscriber:
    ref:
      apiVersion: serving.knative.dev/v1
      kind: Service
      name: event-display

Complex Event Processing

# sequence-example.yaml
apiVersion: flows.knative.dev/v1
kind: Sequence
metadata:
  name: event-processing-sequence
  namespace: default
spec:
  channelTemplate:
    apiVersion: messaging.knative.dev/v1
    kind: InMemoryChannel
  steps:
  - ref:
      apiVersion: serving.knative.dev/v1
      kind: Service
      name: event-transformer
  - ref:
      apiVersion: serving.knative.dev/v1
      kind: Service
      name: event-filter
  - ref:
      apiVersion: serving.knative.dev/v1
      kind: Service
      name: event-logger
  reply:
    ref:
      apiVersion: serving.knative.dev/v1
      kind: Service
      name: event-display

Creating Custom Functions

Go Function Example

// main.go
package main

import (
    "context"
    "fmt"
    "log"
    "net/http"
    "os"
    
    cloudevents "github.com/cloudevents/sdk-go/v2"
)

type EventData struct {
    Message string `json:"message"`
    Time    string `json:"time"`
}

func handler(ctx context.Context, event cloudevents.Event) (*cloudevents.Event, error) {
    log.Printf("Received event: %s", event)
    
    var data EventData
    if err := event.DataAs(&data); err != nil {
        return nil, fmt.Errorf("failed to parse event data: %w", err)
    }
    
    // Process the event
    response := EventData{
        Message: fmt.Sprintf("Processed: %s", data.Message),
        Time:    event.Time().String(),
    }
    
    responseEvent := cloudevents.NewEvent()
    responseEvent.SetType("com.example.processed")
    responseEvent.SetSource("knative-function")
    responseEvent.SetData(cloudevents.ApplicationJSON, response)
    
    return &responseEvent, nil
}

func main() {
    ctx := context.Background()
    p, err := cloudevents.NewHTTP()
    if err != nil {
        log.Fatalf("failed to create protocol: %s", err.Error())
    }
    
    c, err := cloudevents.NewClient(p)
    if err != nil {
        log.Fatalf("failed to create client: %s", err.Error())
    }
    
    port := os.Getenv("PORT")
    if port == "" {
        port = "8080"
    }
    
    log.Printf("Starting server on port %s", port)
    if err := c.StartReceiver(ctx, handler); err != nil {
        log.Fatalf("failed to start receiver: %s", err.Error())
    }
}

Dockerfile for Function

FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o function .

FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /
COPY --from=builder /app/function .
EXPOSE 8080
CMD ["./function"]

Advanced Autoscaling Configuration

Custom Metrics Autoscaling

# hpa-custom-metrics.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: function-hpa
  namespace: default
spec:
  scaleTargetRef:
    apiVersion: serving.knative.dev/v1
    kind: Service
    name: my-function
  minReplicas: 1
  maxReplicas: 100
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80
  - type: Pods
    pods:
      metric:
        name: http_requests_per_second
      target:
        type: AverageValue
        averageValue: "1000"
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
      - type: Percent
        value: 50
        periodSeconds: 60
    scaleUp:
      stabilizationWindowSeconds: 0
      policies:
      - type: Percent
        value: 100
        periodSeconds: 15
      - type: Pods
        value: 4
        periodSeconds: 15
      selectPolicy: Max

Configuring Class-Based Autoscaling

# autoscaling-class.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: config-autoscaler
  namespace: knative-serving
data:
  # Class-specific configuration
  autoscaling-class-config: |
    performance:
      container-concurrency-target-default: "50"
      container-concurrency-target-percentage: "0.5"
      max-scale-up-rate: "1000"
      panic-window-percentage: "5"
      panic-threshold-percentage: "150"
      target-burst-capacity: "300"
    
    economy:
      container-concurrency-target-default: "200"
      container-concurrency-target-percentage: "0.8"
      max-scale-up-rate: "10"
      panic-window-percentage: "20"
      panic-threshold-percentage: "300"
      target-burst-capacity: "50"

Security Best Practices

Network Policies

# knative-network-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: knative-serving-ingress
  namespace: knative-serving
spec:
  podSelector:
    matchLabels:
      app: activator
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: istio-system
    ports:
    - protocol: TCP
      port: 8012
    - protocol: TCP
      port: 9090
  egress:
  - to:
    - podSelector: {}
  - to:
    - namespaceSelector:
        matchLabels:
          name: kube-system
    ports:
    - protocol: TCP
      port: 53
    - protocol: UDP
      port: 53

Service Authentication

# auth-policy.yaml
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: default
  namespace: default
spec:
  mtls:
    mode: STRICT
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: require-jwt
  namespace: default
spec:
  selector:
    matchLabels:
      serving.knative.dev/service: my-secure-service
  action: ALLOW
  rules:
  - from:
    - source:
        requestPrincipals: ["*"]
    when:
    - key: request.auth.claims[iss]
      values: ["https://auth.example.com"]

Monitoring and Observability

Prometheus Configuration

# prometheus-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: prometheus-config
  namespace: knative-monitoring
data:
  prometheus.yml: |
    global:
      scrape_interval: 30s
      evaluation_interval: 30s
    
    scrape_configs:
    - job_name: 'knative-serving'
      kubernetes_sd_configs:
      - role: pod
        namespaces:
          names:
          - knative-serving
      relabel_configs:
      - source_labels: [__meta_kubernetes_pod_label_app]
        action: keep
        regex: (activator|autoscaler|controller|webhook)
      - source_labels: [__meta_kubernetes_pod_container_port_name]
        action: keep
        regex: metrics
    
    - job_name: 'knative-eventing'
      kubernetes_sd_configs:
      - role: pod
        namespaces:
          names:
          - knative-eventing
      relabel_configs:
      - source_labels: [__meta_kubernetes_pod_label_app]
        action: keep
        regex: (eventing-controller|eventing-webhook|imc-controller)

Custom Dashboards

{
  "dashboard": {
    "title": "Knative Serverless Metrics",
    "panels": [
      {
        "title": "Request Rate",
        "targets": [
          {
            "expr": "sum(rate(activator_request_count[5m])) by (namespace, service_name)"
          }
        ]
      },
      {
        "title": "Request Latency P95",
        "targets": [
          {
            "expr": "histogram_quantile(0.95, sum(rate(activator_request_latencies_bucket[5m])) by (namespace, service_name, le))"
          }
        ]
      },
      {
        "title": "Active Instances",
        "targets": [
          {
            "expr": "sum(autoscaler_actual_pod_count) by (namespace, service_name)"
          }
        ]
      },
      {
        "title": "Scale to Zero Events",
        "targets": [
          {
            "expr": "sum(rate(activator_request_count{response_code=\"503\"}[5m])) by (namespace, service_name)"
          }
        ]
      }
    ]
  }
}

Performance Optimization

Cold Start Optimization

# optimized-service.yaml
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: optimized-function
  namespace: default
  annotations:
    # Keep minimum instances warm
    autoscaling.knative.dev/min-scale: "1"
spec:
  template:
    metadata:
      annotations:
        # Faster pod startup
        autoscaling.knative.dev/initial-scale: "5"
        # Reduce cold start impact
        autoscaling.knative.dev/scale-down-delay: "15m"
        autoscaling.knative.dev/scale-to-zero-pod-retention-period: "15m"
    spec:
      # Init containers for pre-warming
      initContainers:
      - name: warm-up
        image: busybox
        command: ['sh', '-c', 'echo "Warming up..." && sleep 2']
      containers:
      - image: myregistry/optimized-function:latest
        ports:
        - containerPort: 8080
        # Startup probe for readiness
        startupProbe:
          httpGet:
            path: /ready
          periodSeconds: 1
          failureThreshold: 30
        resources:
          requests:
            cpu: 100m
            memory: 128Mi
          limits:
            cpu: 1000m
            memory: 512Mi

Resource Optimization

# Create priority classes
cat <<EOF | kubectl apply -f -
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: knative-high-priority
value: 1000
globalDefault: false
description: "High priority class for Knative services"
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: knative-low-priority
value: 100
globalDefault: false
description: "Low priority class for batch Knative services"
EOF

# Configure node affinity for Knative workloads
kubectl label nodes node1 node2 node3 workload-type=serverless

Multi-Tenancy Configuration

Namespace Isolation

# tenant-namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: tenant-a
  labels:
    serving.knative.dev/release: v1.12.0
---
apiVersion: v1
kind: ResourceQuota
metadata:
  name: tenant-quota
  namespace: tenant-a
spec:
  hard:
    requests.cpu: "10"
    requests.memory: 20Gi
    services.knative.dev: "50"
    persistentvolumeclaims: "0"
---
apiVersion: v1
kind: LimitRange
metadata:
  name: tenant-limits
  namespace: tenant-a
spec:
  limits:
  - max:
      cpu: "2"
      memory: 2Gi
    min:
      cpu: 50m
      memory: 64Mi
    default:
      cpu: 100m
      memory: 128Mi
    type: Container

Conclusion

Setting up a serverless platform with Knative on Rocky Linux provides a powerful foundation for modern cloud-native applications. The combination of automatic scaling, event-driven architecture, and seamless Kubernetes integration enables developers to focus on business logic while the platform handles infrastructure concerns.

By following the configurations and best practices outlined in this guide, you can build a production-ready serverless platform that scales efficiently, maintains security, and provides excellent observability for your applications.