cleanup codebase and add documentation

This commit is contained in:
dev 2019-06-28 14:23:34 -04:00
parent d9e05a0a02
commit cb1fbe77d9
10 changed files with 84 additions and 170 deletions

View File

@ -1,6 +1,3 @@
build:
@mkdir -p bin
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o ./bin/ingress-controller ./cmd/caddy
publish-docker:
@echo 'TODO :- not implemented'
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o ./bin/ingress-controller ./cmd/caddy

View File

@ -47,3 +47,54 @@ View the pod logs:
```sh
kubectl logs <pod-name> -n caddy-system
```
## Automatic HTTPS
By default, any hosts defined in an ingress resource will configure caddy to automatically get certificates from let's encrypt and
will serve your side over HTTPS.
To disable automattic https you can set the argument `tls` on the caddy ingress controller to `false`.
Example:
Add args `tls=false` to the deployment.
```
args:
- -tls=false
```
## Bringing Your Own Certificates
If you would like to disable automatic HTTPS for a specific host and use your own certificates you can create a new TLS secret in Kubernetes and define
what certificates to use when serving your application on the ingress resource.
Example:
Create TLS secret `mycerts`, where `./tls.key` and `./tls.crt` are valid certificates for `test.com`.
```
kubectl create secret tls mycerts --key ./tls.key --cert ./tls.crt
```
```
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: example
annotations:
kubernetes.io/ingress.class: caddy
spec:
rules:
- host: test.com
http:
paths:
- path: /
backend:
serviceName: test
servicePort: 8080
tls:
- hosts:
- test.com
secretName: mycerts # use mycerts for host test.com
```

View File

@ -12,7 +12,7 @@ func parseFlags() caddy.ControllerConfig {
flag.StringVar(&email, "email", "", "the email address to use for requesting tls certificates if automatic https is enabled.")
var namespace string
flag.StringVar(&namespace, "observe-namespace", "", "the namespace that you would like to observe kubernetes ingress resources in.")
flag.StringVar(&namespace, "namespace", "", "the namespace that you would like to observe kubernetes ingress resources in.")
var enableAutomaticTLS bool
flag.BoolVar(&enableAutomaticTLS, "tls", false, "defines if automatic tls should be enabled for hostnames defined in ingress resources.")

View File

@ -37,22 +37,14 @@ func main() {
// get client to access the kubernetes service api
kubeClient, err := createApiserverClient()
if err != nil {
msg := `
Error while initiating a connection to the Kubernetes API server.
This could mean the cluster is misconfigured (e.g. it has invalid
API server certificates or Service Accounts configuration)
`
msg := "Could not establish a connection to the Kubernetes API Server."
logrus.Fatalf(msg, err)
}
restClient := kubeClient.ExtensionsV1beta1().RESTClient()
// start ingress controller
c := controller.NewCaddyController(kubeClient, restClient, cfg)
reg := prometheus.NewRegistry()
reg.MustRegister(prometheus.NewGoCollector())
reg.MustRegister(prometheus.NewProcessCollector(prometheus.ProcessCollectorOpts{
PidFn: func() (int, error) { return os.Getpid(), nil },
@ -69,6 +61,7 @@ func main() {
logrus.Info("Starting the caddy ingress controller")
go c.Run(stopCh)
// TODO :- listen to sigterm
select {}
}
@ -103,12 +96,11 @@ func createApiserverClient() (*kubernetes.Clientset, error) {
return nil, err
}
logrus.Infof("Creating API client for %s", cfg.Host)
cfg.QPS = defaultQPS
cfg.Burst = defaultBurst
cfg.ContentType = "application/vnd.kubernetes.protobuf"
logrus.Infof("Creating API client for %s", cfg.Host)
client, err := kubernetes.NewForConfig(cfg)
if err != nil {
return nil, err
@ -143,13 +135,9 @@ func createApiserverClient() (*kubernetes.Clientset, error) {
return nil, lastErr
}
// this should not happen, warn the user
if retries > 0 {
logrus.Warningf("Initial connection to the Kubernetes API server was retried %d times.", retries)
}
msg := "Running in Kubernetes cluster version v%v.%v (%v) - git (%v) commit %v - platform %v"
logrus.Infof(msg, v.Major, v.Minor, v.GitVersion, v.GitTreeState, v.GitCommit, v.Platform)
return client, nil
}

View File

@ -1,94 +0,0 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: example
labels:
app: example
spec:
replicas: 1
selector:
matchLabels:
app: example
template:
metadata:
labels:
app: example
spec:
containers:
- name: httpecho
image: hashicorp/http-echo
args:
- "-listen=:8080"
- "-text=hello world"
ports:
- containerPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: example2
labels:
app: example2
spec:
replicas: 1
selector:
matchLabels:
app: example2
template:
metadata:
labels:
app: example2
spec:
containers:
- name: httpecho
image: hashicorp/http-echo
args:
- "-listen=:8080"
- "-text=hello world 2"
ports:
- containerPort: 8080
---
kind: Service
apiVersion: v1
metadata:
name: example
spec:
type: ClusterIP
selector:
app: example
ports:
- protocol: TCP
port: 80
targetPort: 8080
---
kind: Service
apiVersion: v1
metadata:
name: example2
spec:
type: ClusterIP
selector:
app: example2
ports:
- protocol: TCP
port: 80
targetPort: 8080
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: example
annotations:
kubernetes.io/ingress.class: caddy
spec:
rules:
- host: caddy2.kubed.co
http:
paths:
- path: /hello2
backend:
serviceName: example2
servicePort: 8080
- backend:
serviceName: example
servicePort: 8080

View File

@ -12,12 +12,10 @@ import (
// This is not used when this ingress controller is configured with a config map, so that we don't
// override user defined routes.
func ConvertToCaddyConfig(ings []*v1beta1.Ingress) (caddyhttp.RouteList, error) {
// ~~~~
// TODO :-
// when setting the upstream url we should should bypass kube-dns and get the ip address of
// the pod for the deployment we are proxying to so that we can proxy to that ip address port.
// this is good for session affinity and increases performance.
// ~~~~
// create a server route for each ingress route
var routes caddyhttp.RouteList
@ -46,6 +44,7 @@ func ConvertToCaddyConfig(ings []*v1beta1.Ingress) (caddyhttp.RouteList, error)
return routes, nil
}
// TODO :- configure log middleware for all routes
func baseRoute(upstream string) caddyhttp.ServerRoute {
return caddyhttp.ServerRoute{
// Apply: []json.RawMessage{

View File

@ -148,12 +148,11 @@ func (r ResourceDeletedAction) handle(c *CaddyController) error {
return nil
}
// TODO :- Cleanup This Fn
// updateConfig updates internal caddy config with new ingress info
// updateConfig updates internal caddy config with new ingress info.
func updateConfig(c *CaddyController) error {
// if certs are defined on an ingress resource start a shared informer factory
// to listen to any changes for these certs. If the certs are updated, reload
// them into the caddy instance.
apps := c.resourceStore.CaddyConfig.Apps
// if certs are defined on an ingress resource we need to handle them.
tlsCfg, err := c.HandleOwnCertManagement(c.resourceStore.Ingresses)
if err != nil {
return errors.Wrap(err, "caddy config reload")
@ -161,38 +160,20 @@ func updateConfig(c *CaddyController) error {
// after TLS secrets are synched we should load them in the cert pool.
if tlsCfg != nil {
if c, exists := c.resourceStore.CaddyConfig.Apps["tls"]; exists {
if cfg, ok := c.(caddytls.TLS); ok {
cfg.Certificates["load_folders"] = tlsCfg["load_folders"].(json.RawMessage)
}
}
apps["tls"].(caddytls.TLS).Certificates["load_folders"] = tlsCfg["load_folders"].(json.RawMessage)
} else {
// reset cert loading
if c, exists := c.resourceStore.CaddyConfig.Apps["tls"]; exists {
if cfg, ok := c.(caddytls.TLS); ok {
cfg.Certificates["load_folders"] = json.RawMessage(`[]`)
}
}
apps["tls"].(caddytls.TLS).Certificates["load_folders"] = json.RawMessage(`[]`)
}
// skip auto https for hosts with certs provided
if tlsCfg != nil {
if skipHosts, exists := tlsCfg["hosts"]; exists {
if hosts, ok := skipHosts.([]string); ok {
if httpCfg, exists := c.resourceStore.CaddyConfig.Apps["http"]; exists {
if cfg, ok := httpCfg.(caddyhttp.App); ok {
cfg.Servers["ingress_server"].AutoHTTPS.Skip = hosts
}
}
}
if hosts, ok := tlsCfg["hosts"].([]string); ok {
apps["http"].(caddyhttp.App).Servers["ingress_server"].AutoHTTPS.Skip = hosts
}
} else {
// reset any skipped hosts set
if httpCfg, exists := c.resourceStore.CaddyConfig.Apps["http"]; exists {
if cfg, ok := httpCfg.(caddyhttp.App); ok {
cfg.Servers["ingress_server"].AutoHTTPS.Skip = make([]string, 0)
}
}
apps["http"].(caddyhttp.App).Servers["ingress_server"].AutoHTTPS.Skip = make([]string, 0)
}
if !c.usingConfigMap {
@ -202,11 +183,7 @@ func updateConfig(c *CaddyController) error {
}
// set the http server routes
if httpCfg, exists := c.resourceStore.CaddyConfig.Apps["http"]; exists {
if cfg, ok := httpCfg.(caddyhttp.App); ok {
cfg.Servers["ingress_server"].Routes = serverRoutes
}
}
apps["http"].(caddyhttp.App).Servers["ingress_server"].Routes = serverRoutes
}
// reload caddy with new config

View File

@ -31,10 +31,7 @@ func (c *CaddyController) syncStatus(ings []*v1beta1.Ingress) error {
return err
}
// this happens about every 30 seconds and can pollute the logs, so we
// only want to log on higher verbosity levels.
logrus.Info("Synching Ingress resource source addresses")
c.updateIngStatuses(sliceToLoadBalancerIngress(addrs), ings)
return nil

View File

@ -2,7 +2,6 @@ package controller
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"path/filepath"
@ -73,8 +72,6 @@ func (c *CaddyController) HandleOwnCertManagement(ings []*v1beta1.Ingress) (map[
go informer.Run(c.stopChan)
}
fmt.Printf("\nCERTS: %+v - %+v\n", len(certs), certs)
if len(certs) > 0 {
return getTLSConfig(hosts), nil
}

View File

@ -28,24 +28,26 @@ func NewStore(kubeClient *kubernetes.Clientset, namespace string, cfg c.Controll
Ingresses: []*v1beta1.Ingress{},
}
if cfgMapConfig == nil {
s.CaddyConfig = c.NewConfig(namespace, cfg)
} else {
// set cert-magic storage provider
cfgMapConfig.Storage = c.Storage{
System: "secret_store",
StorageValues: c.StorageValues{
Namespace: namespace,
},
}
s.CaddyConfig = cfgMapConfig
}
for _, i := range ingresses.Items {
s.Ingresses = append(s.Ingresses, &i)
}
// not using cfg map to configure the ingress controller
if cfgMapConfig == nil {
s.CaddyConfig = c.NewConfig(namespace, cfg)
return s
}
// set cert-magic storage provider
cfgMapConfig.Storage = c.Storage{
System: "secret_store",
StorageValues: c.StorageValues{
Namespace: namespace,
},
}
s.CaddyConfig = cfgMapConfig
return s
}