Add healthz endpoint (#107)

This commit is contained in:
Xinbin Huang 2022-12-06 02:45:32 -08:00 committed by GitHub
parent 9dba87b050
commit 6e28cb2cb3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 151 additions and 16 deletions

1
.gitignore vendored
View File

@ -3,3 +3,4 @@ bin
vendor
.idea/
dist/
ingress-controller

View File

@ -27,7 +27,7 @@ kind export kubeconfig
## Setup development env
Replace also the domain name to use in `hack/test/example-ingress.yaml` from `kubernetes.localhost` to your domain (ensure also that the subdomain `example1` and `example2` are resolved to the server public IP)
Replace also the domain name to use in `kubernetes/sample/example-ingress.yaml` from `kubernetes.localhost` to your domain (ensure also that the subdomain `example1` and `example2` are resolved to the server public IP)
Create a namespace to host the caddy ingress controller:
```
@ -36,7 +36,7 @@ kubectl create ns caddy-system
Then we can start skaffold using:
```
skaffold dev --port-forward
make dev
```
this will automatically:

View File

@ -1,3 +1,6 @@
build:
@mkdir -p bin
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o ./bin/ingress-controller ./cmd/caddy
dev: build
skaffold dev --port-forward

View File

@ -87,7 +87,7 @@ spec:
periodSeconds: 10
httpGet:
port: 9765
path: /metrics
path: /healthz
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}

8
go.mod
View File

@ -16,6 +16,11 @@ require (
k8s.io/client-go v0.23.6
)
require (
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/stretchr/objx v0.4.0 // indirect
)
require (
filippo.io/edwards25519 v1.0.0-rc.1 // indirect
github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 // indirect
@ -100,6 +105,7 @@ require (
github.com/spf13/cast v1.4.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stoewer/go-strcase v1.2.0 // indirect
github.com/stretchr/testify v1.8.0
github.com/tailscale/tscert v0.0.0-20220125204807-4509a5fbaf74 // indirect
github.com/urfave/cli v1.22.5 // indirect
go.etcd.io/bbolt v1.3.6 // indirect
@ -128,7 +134,7 @@ require (
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
howett.net/plist v1.0.0 // indirect
k8s.io/klog/v2 v2.30.0 // indirect
k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65 // indirect

6
go.sum
View File

@ -1074,6 +1074,8 @@ github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5J
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/testify v0.0.0-20170130113145-4d4bfba8f1d1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
@ -1083,6 +1085,8 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/tailscale/tscert v0.0.0-20220125204807-4509a5fbaf74 h1:uFx5aih29p2IaRUF0lJwtVViCXStlvnPPE3NEmM4Ivs=
github.com/tailscale/tscert v0.0.0-20220125204807-4509a5fbaf74/go.mod h1:hL4gB6APAasMR2NNi/JHzqKkxW3EPQlFgLEq9PMi2t0=
@ -1862,6 +1866,8 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

View File

@ -0,0 +1,37 @@
package caddy
import (
"encoding/json"
"os"
"testing"
"github.com/stretchr/testify/require"
"github.com/caddyserver/ingress/pkg/store"
)
func TestConvertToCaddyConfig(t *testing.T) {
tests := []struct {
name string
expectedConfigPath string
}{
{
name: "default",
expectedConfigPath: "./test_data/default.json",
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
cfg, err := Converter{}.ConvertToCaddyConfig(store.NewStore(store.Options{}, &store.PodInfo{}))
require.NoError(t, err)
cfgJson, err := json.Marshal(cfg)
require.NoError(t, err)
expectedCfg, err := os.ReadFile(test.expectedConfigPath)
require.NoError(t, err)
require.JSONEq(t, string(expectedCfg), string(cfgJson))
})
}
}

View File

@ -0,0 +1,48 @@
package global
import (
"encoding/json"
"net/http"
"strconv"
"github.com/caddyserver/caddy/v2"
"github.com/caddyserver/caddy/v2/caddyconfig"
"github.com/caddyserver/caddy/v2/modules/caddyhttp"
"github.com/caddyserver/ingress/pkg/converter"
"github.com/caddyserver/ingress/pkg/store"
)
type HealthzPlugin struct{}
func (p HealthzPlugin) IngressPlugin() converter.PluginInfo {
return converter.PluginInfo{
Name: "healthz",
Priority: -20,
New: func() converter.Plugin { return new(HealthzPlugin) },
}
}
func init() {
converter.RegisterPlugin(HealthzPlugin{})
}
func (p HealthzPlugin) GlobalHandler(config *converter.Config, store *store.Store) error {
healthzHandler := caddyhttp.StaticResponse{StatusCode: caddyhttp.WeakString(strconv.Itoa(http.StatusOK))}
healthzRoute := caddyhttp.Route{
HandlersRaw: []json.RawMessage{
caddyconfig.JSONModuleObject(healthzHandler, "handler", healthzHandler.CaddyModule().ID.Name(), nil),
},
MatcherSetsRaw: []caddy.ModuleMap{{
"path": caddyconfig.JSON(caddyhttp.MatchPath{"/healthz"}, nil),
}},
}
config.GetMetricsServer().Routes = append(config.GetMetricsServer().Routes, healthzRoute)
return nil
}
// Interface guards
var (
_ = converter.GlobalMiddleware(HealthzPlugin{})
)

View File

@ -23,20 +23,15 @@ func init() {
}
func (p MetricsPlugin) GlobalHandler(config *converter.Config, store *store.Store) error {
httpApp := config.Apps["http"].(*caddyhttp.App)
if store.ConfigMap.Metrics {
httpApp.Servers[converter.MetricsServer] = &caddyhttp.Server{
Listen: []string{":9765"},
AutoHTTPS: &caddyhttp.AutoHTTPSConfig{Disabled: true},
Routes: []caddyhttp.Route{{
HandlersRaw: []json.RawMessage{json.RawMessage(`{ "handler": "metrics" }`)},
MatcherSetsRaw: []caddy.ModuleMap{{
"path": caddyconfig.JSON(caddyhttp.MatchPath{"/metrics"}, nil),
}},
metricsRoute := caddyhttp.Route{
HandlersRaw: []json.RawMessage{json.RawMessage(`{ "handler": "metrics" }`)},
MatcherSetsRaw: []caddy.ModuleMap{{
"path": caddyconfig.JSON(caddyhttp.MatchPath{"/metrics"}, nil),
}},
}
config.GetMetricsServer().Routes = append(config.GetMetricsServer().Routes, metricsRoute)
}
return nil
}

View File

@ -0,0 +1,27 @@
{
"admin": {},
"storage": { "module": "secret_store", "namespace": "", "leaseId": "" },
"apps": {
"http": {
"servers": {
"ingress_server": {
"listen": [":80", ":443"],
"tls_connection_policies": [{}],
"automatic_https": {}
},
"metrics_server": {
"listen": [":9765"],
"routes": [
{
"match": [{ "path": ["/healthz"] }],
"handle": [{ "handler": "static_response", "status_code": 200 }]
}
],
"automatic_https": { "disable": true }
}
}
},
"tls": {}
},
"logging": {}
}

View File

@ -30,6 +30,10 @@ func (c Config) GetHTTPServer() *caddyhttp.Server {
return c.Apps["http"].(*caddyhttp.App).Servers[HttpServer]
}
func (c Config) GetMetricsServer() *caddyhttp.Server {
return c.Apps["http"].(*caddyhttp.App).Servers[MetricsServer]
}
func (c Config) GetTLSApp() *caddytls.TLS {
return c.Apps["tls"].(*caddytls.TLS)
}
@ -50,6 +54,10 @@ func NewConfig() *Config {
&caddytls.ConnectionPolicy{},
},
},
MetricsServer: {
Listen: []string{":9765"},
AutoHTTPS: &caddyhttp.AutoHTTPSConfig{Disabled: true},
},
},
},
},

View File

@ -1,4 +1,4 @@
apiVersion: skaffold/v2beta3
apiVersion: skaffold/v2beta29
kind: Config
metadata:
name: caddy-ingress-controller
@ -12,6 +12,10 @@ deploy:
namespace: caddy-system
chartPath: charts/caddy-ingress-controller
recreatePods: true
artifactOverrides:
image: caddy/ingress
imageStrategy:
helm: {}
kubectl:
manifests:
- kubernetes/sample/*.yaml