Ingress Exposure
TinySystems components can expose HTTP endpoints to the internet via Kubernetes Ingress. This guide covers ingress configuration and common patterns.
Overview
+-----------------------------------------------------------------------------+
| INGRESS EXPOSURE |
+-----------------------------------------------------------------------------+
Internet Ingress Controller Module Pods
| | |
| https://api.example.com | |
| ----------------------> | |
| | |
| | Route to Service |
| | -----------------------> |
| | |
| | Load Balance |
| | +------------------------->| Pod 1
| | | |
| | +------------------------->| Pod 2
| | | |
| | +------------------------->| Pod 3
| | |Basic Ingress Setup
Exposing a Port
go
func (s *Server) exposeHTTP(ctx context.Context, rm resource.Manager) error {
return rm.ExposePort(ctx, resource.ExposePortRequest{
Port: s.currentPort,
Hostnames: []string{"api.example.com"},
TLS: true,
})
}Generated Resources
Service:
yaml
apiVersion: v1
kind: Service
metadata:
name: http-server-abc123
namespace: tinysystems
spec:
type: ClusterIP
selector:
app: http-module
ports:
- port: 8080
targetPort: 8080Ingress:
yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: http-server-abc123
namespace: tinysystems
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
ingressClassName: nginx
tls:
- hosts:
- api.example.com
secretName: http-server-abc123-tls
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: http-server-abc123
port:
number: 8080TLS Configuration
Automatic Certificates
With cert-manager, certificates are provisioned automatically:
go
rm.ExposePort(ctx, resource.ExposePortRequest{
Port: 8080,
Hostnames: []string{"api.example.com"},
TLS: true, // Triggers cert-manager
})Custom Certificate
Use existing certificate:
go
rm.ExposePort(ctx, resource.ExposePortRequest{
Port: 8080,
Hostnames: []string{"api.example.com"},
TLS: true,
TLSSecretName: "my-existing-cert",
})No TLS (HTTP only)
go
rm.ExposePort(ctx, resource.ExposePortRequest{
Port: 8080,
Hostnames: []string{"internal.example.com"},
TLS: false,
})Multiple Hostnames
Expose same service on multiple domains:
go
rm.ExposePort(ctx, resource.ExposePortRequest{
Port: 8080,
Hostnames: []string{
"api.example.com",
"api.example.org",
"api.example.net",
},
TLS: true,
})Generated Ingress:
yaml
spec:
tls:
- hosts:
- api.example.com
- api.example.org
- api.example.net
secretName: http-server-abc123-tls
rules:
- host: api.example.com
http:
paths:
- path: /
backend:
service:
name: http-server-abc123
- host: api.example.org
http:
paths:
- path: /
backend:
service:
name: http-server-abc123
- host: api.example.net
http:
paths:
- path: /
backend:
service:
name: http-server-abc123Path-Based Routing
Route different paths to different components:
yaml
# Manual ingress for advanced routing
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: multi-path-ingress
spec:
rules:
- host: api.example.com
http:
paths:
- path: /users
pathType: Prefix
backend:
service:
name: user-service
port:
number: 8080
- path: /orders
pathType: Prefix
backend:
service:
name: order-service
port:
number: 8080Ingress Annotations
NGINX Ingress Controller
yaml
metadata:
annotations:
# Timeouts
nginx.ingress.kubernetes.io/proxy-connect-timeout: "60"
nginx.ingress.kubernetes.io/proxy-send-timeout: "60"
nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
# Body size
nginx.ingress.kubernetes.io/proxy-body-size: "10m"
# WebSocket support
nginx.ingress.kubernetes.io/websocket-services: "http-server-abc123"
# Rate limiting
nginx.ingress.kubernetes.io/limit-rps: "100"
# CORS
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-origin: "*"Custom Annotations via Settings
go
type Settings struct {
Hostnames []string `json:"hostnames"`
TLS bool `json:"tls"`
IngressAnnotations map[string]string `json:"ingressAnnotations,omitempty"`
}
rm.ExposePort(ctx, resource.ExposePortRequest{
Port: 8080,
Hostnames: s.settings.Hostnames,
TLS: s.settings.TLS,
Annotations: s.settings.IngressAnnotations,
})WebSocket Support
Enable WebSocket upgrade:
yaml
metadata:
annotations:
nginx.ingress.kubernetes.io/proxy-http-version: "1.1"
nginx.ingress.kubernetes.io/upstream-hash-by: "$request_uri"
nginx.ingress.kubernetes.io/configuration-snippet: |
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";Health Checks
Readiness Probe
Ensure pods are ready before receiving traffic:
yaml
# In module Helm chart
spec:
containers:
- name: module
readinessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 5
periodSeconds: 10Backend Health
NGINX ingress checks backend health:
yaml
metadata:
annotations:
nginx.ingress.kubernetes.io/upstream-vhost: "api.example.com"
nginx.ingress.kubernetes.io/health-check-path: "/healthz"Load Balancing
Default (Round Robin)
Kubernetes Service distributes traffic evenly.
Session Affinity
Sticky sessions for stateful applications:
yaml
metadata:
annotations:
nginx.ingress.kubernetes.io/affinity: "cookie"
nginx.ingress.kubernetes.io/session-cookie-name: "route"
nginx.ingress.kubernetes.io/session-cookie-expires: "172800"Monitoring Ingress
Check Ingress Status
bash
kubectl get ingress -n tinysystems
kubectl describe ingress http-server-abc123 -n tinysystemsView Logs
bash
# NGINX Ingress Controller logs
kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginxMetrics
bash
# Prometheus metrics from ingress controller
curl http://ingress-controller:10254/metricsTroubleshooting
Certificate Not Ready
bash
# Check cert-manager
kubectl get certificates -n tinysystems
kubectl describe certificate http-server-abc123-tls -n tinysystems
# Check challenges
kubectl get challenges -n tinysystems502 Bad Gateway
- Check pod readiness
- Verify service selector matches pods
- Check pod logs for errors
bash
kubectl get pods -n tinysystems -l app=http-module
kubectl logs -n tinysystems -l app=http-moduleDNS Not Resolving
- Verify DNS record exists
- Check ingress host configuration
- Ensure ingress controller has external IP
bash
kubectl get svc -n ingress-nginx
nslookup api.example.comBest Practices
1. Use TLS in Production
go
rm.ExposePort(ctx, resource.ExposePortRequest{
TLS: true, // Always enable in production
})2. Configure Timeouts
Match timeouts to your processing time:
yaml
nginx.ingress.kubernetes.io/proxy-read-timeout: "300" # 5 minutes for long operations3. Enable Rate Limiting
Protect against abuse:
yaml
nginx.ingress.kubernetes.io/limit-rps: "50"
nginx.ingress.kubernetes.io/limit-connections: "10"4. Monitor Certificate Expiry
Set up alerts for certificate expiration:
yaml
# Prometheus rule
- alert: CertificateExpiringSoon
expr: certmanager_certificate_expiration_timestamp_seconds - time() < 604800
for: 1hNext Steps
- Resource Manager - Resource management
- Multi-Replica Coordination - Server patterns
- Observability - Monitoring