Update to caddy v2.0.0 and fixes (#27)

* Update to caddy v2.0.0

* Fixes from #24

* Update rbac api and move ingresses from extensions api to networking

* Fix matchers

* Allow default backend

* Use caddyconfig.JSON

* Fix issuer

* Use empty image for docker
This commit is contained in:
Marc-Antoine 2020-05-16 13:43:57 +02:00 committed by GitHub
parent 3abf447b47
commit 022ff01309
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 640 additions and 118 deletions

View File

@ -1,26 +1,20 @@
FROM golang:alpine AS build FROM golang:1.14.2-alpine AS builder
WORKDIR /app WORKDIR /app
ADD . /app
COPY go.mod go.sum ./
RUN go mod download
COPY ./cmd ./cmd
COPY ./pkg ./pkg
COPY ./internal ./internal
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o ./bin/ingress-controller ./cmd/caddy RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o ./bin/ingress-controller ./cmd/caddy
FROM alpine:latest as certs FROM alpine:latest as certs
RUN apk --update add ca-certificates RUN apk --update add ca-certificates
FROM golang:1.13.5 as builder
WORKDIR /build
ENV CGO_ENABLED=0
ENV GOOS=linux
ENV GOARCH=amd64
RUN mkdir -p ./bin
COPY go.mod go.sum ./
RUN go mod download
COPY ./cmd ./cmd
COPY ./pkg ./pkg
COPY ./internal ./internal
RUN go build -o ./bin/ingress-controller ./cmd/caddy
FROM scratch FROM scratch
COPY --from=builder /build/bin/ingress-controller . COPY --from=builder /app/bin/ingress-controller .
COPY --from=certs /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt COPY --from=certs /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
EXPOSE 80 443 EXPOSE 80 443
ENTRYPOINT ["/ingress-controller"] ENTRYPOINT ["/ingress-controller"]

View File

@ -41,7 +41,7 @@ func main() {
logrus.Fatalf(msg, err) logrus.Fatalf(msg, err)
} }
restClient := kubeClient.ExtensionsV1beta1().RESTClient() restClient := kubeClient.NetworkingV1beta1().RESTClient()
c := controller.NewCaddyController(kubeClient, restClient, cfg) c := controller.NewCaddyController(kubeClient, restClient, cfg)
reg := prometheus.NewRegistry() reg := prometheus.NewRegistry()

12
go.mod
View File

@ -1,13 +1,13 @@
module github.com/caddyserver/ingress module github.com/caddyserver/ingress
go 1.13 go 1.14
require ( require (
github.com/caddyserver/caddy/v2 v2.0.0-beta11 github.com/caddyserver/caddy/v2 v2.0.0
github.com/mholt/certmagic v0.9.0 github.com/caddyserver/certmagic v0.10.12
github.com/pkg/errors v0.8.1 github.com/pkg/errors v0.9.1
github.com/prometheus/client_golang v1.1.0 github.com/prometheus/client_golang v1.6.0
github.com/sirupsen/logrus v1.4.2 github.com/sirupsen/logrus v1.6.0
gopkg.in/go-playground/assert.v1 v1.2.1 // indirect gopkg.in/go-playground/assert.v1 v1.2.1 // indirect
gopkg.in/go-playground/pool.v3 v3.1.1 gopkg.in/go-playground/pool.v3 v3.1.1
k8s.io/api v0.17.0 k8s.io/api v0.17.0

628
go.sum

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
apiVersion: extensions/v1beta1 apiVersion: networking.k8s.io/v1beta1
kind: Ingress kind: Ingress
metadata: metadata:
name: example name: example
@ -24,7 +24,7 @@ spec:
backend: backend:
serviceName: example2 serviceName: example2
servicePort: 8080 servicePort: 8080
- path: /hello - path: /hello1
backend: backend:
serviceName: example serviceName: example
servicePort: 8080 servicePort: 8080

View File

@ -1,10 +1,8 @@
package caddy package caddy
import ( import (
"encoding/json"
"fmt"
"github.com/caddyserver/caddy/v2" "github.com/caddyserver/caddy/v2"
"github.com/caddyserver/caddy/v2/caddyconfig"
"github.com/caddyserver/caddy/v2/modules/caddyhttp" "github.com/caddyserver/caddy/v2/modules/caddyhttp"
"github.com/caddyserver/caddy/v2/modules/caddytls" "github.com/caddyserver/caddy/v2/modules/caddytls"
) )
@ -36,7 +34,9 @@ type ControllerConfig struct {
// NewConfig returns a plain slate caddy2 config file. // NewConfig returns a plain slate caddy2 config file.
func NewConfig(namespace string, cfg ControllerConfig) *Config { func NewConfig(namespace string, cfg ControllerConfig) *Config {
autoPolicyBytes := json.RawMessage(fmt.Sprintf(`{"module": "acme", "email": "%v"}`, cfg.Email)) acmeIssuer := caddytls.ACMEIssuer{
CA: getCAEndpoint(cfg.TLSUseStaging),
Email: cfg.Email}
return &Config{ return &Config{
Storage: Storage{ Storage: Storage{
@ -48,10 +48,9 @@ func NewConfig(namespace string, cfg ControllerConfig) *Config {
Apps: map[string]interface{}{ Apps: map[string]interface{}{
"tls": caddytls.TLS{ "tls": caddytls.TLS{
Automation: &caddytls.AutomationConfig{ Automation: &caddytls.AutomationConfig{
Policies: []caddytls.AutomationPolicy{ Policies: []*caddytls.AutomationPolicy{
caddytls.AutomationPolicy{ {
Hosts: nil, IssuerRaw: caddyconfig.JSONModuleObject(acmeIssuer, "module", "acme", nil),
ManagementRaw: autoPolicyBytes,
}, },
}, },
}, },
@ -71,3 +70,10 @@ func NewConfig(namespace string, cfg ControllerConfig) *Config {
}, },
} }
} }
func getCAEndpoint(useStaging bool) string {
if useStaging {
return "https://acme-staging-v02.api.letsencrypt.org/directory"
}
return ""
}

View File

@ -3,9 +3,10 @@ package caddy
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/caddyserver/caddy/v2"
"github.com/caddyserver/caddy/v2/caddyconfig"
"github.com/caddyserver/caddy/v2/modules/caddyhttp" "github.com/caddyserver/caddy/v2/modules/caddyhttp"
"k8s.io/api/extensions/v1beta1" "k8s.io/api/networking/v1beta1"
) )
// ConvertToCaddyConfig returns a new caddy routelist based off of ingresses managed by this controller. // ConvertToCaddyConfig returns a new caddy routelist based off of ingresses managed by this controller.
@ -25,18 +26,22 @@ func ConvertToCaddyConfig(ings []*v1beta1.Ingress) (caddyhttp.RouteList, error)
clusterHostName := fmt.Sprintf("%v.%v.svc.cluster.local:%d", path.Backend.ServiceName, ing.Namespace, path.Backend.ServicePort.IntVal) clusterHostName := fmt.Sprintf("%v.%v.svc.cluster.local:%d", path.Backend.ServiceName, ing.Namespace, path.Backend.ServicePort.IntVal)
r := baseRoute(clusterHostName) r := baseRoute(clusterHostName)
r.MatcherSets = caddyhttp.MatcherSets{ match := caddy.ModuleMap{}
{
caddyhttp.MatchHost{rule.Host}, if rule.Host != "" {
caddyhttp.MatchPath{path.Path}, match["host"] = caddyconfig.JSON(caddyhttp.MatchHost{rule.Host}, nil)
},
} }
if path.Path != "" {
match["path"] = caddyconfig.JSON(caddyhttp.MatchPath{path.Path}, nil)
}
r.MatcherSetsRaw = []caddy.ModuleMap{match}
routes = append(routes, r) routes = append(routes, r)
} }
} }
} }
return routes, nil return routes, nil
} }

View File

@ -10,7 +10,7 @@ import (
"github.com/caddyserver/ingress/internal/caddy" "github.com/caddyserver/ingress/internal/caddy"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"k8s.io/api/extensions/v1beta1" "k8s.io/api/networking/v1beta1"
) )
// loadConfigMap runs when a config map with caddy config is loaded on app start. // loadConfigMap runs when a config map with caddy config is loaded on app start.

View File

@ -17,7 +17,7 @@ import (
"github.com/caddyserver/ingress/pkg/storage" "github.com/caddyserver/ingress/pkg/storage"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
apiv1 "k8s.io/api/core/v1" apiv1 "k8s.io/api/core/v1"
"k8s.io/api/extensions/v1beta1" "k8s.io/api/networking/v1beta1"
"k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/util/wait"

View File

@ -9,7 +9,7 @@ import (
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
pool "gopkg.in/go-playground/pool.v3" pool "gopkg.in/go-playground/pool.v3"
apiv1 "k8s.io/api/core/v1" apiv1 "k8s.io/api/core/v1"
"k8s.io/api/extensions/v1beta1" "k8s.io/api/networking/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes"
) )
@ -47,7 +47,7 @@ func runUpdate(ing *v1beta1.Ingress, status []apiv1.LoadBalancerIngress, client
return nil, nil return nil, nil
} }
ingClient := client.ExtensionsV1beta1().Ingresses(ing.Namespace) ingClient := client.NetworkingV1beta1().Ingresses(ing.Namespace)
currIng, err := ingClient.Get(ing.Name, metav1.GetOptions{}) currIng, err := ingClient.Get(ing.Name, metav1.GetOptions{})
if err != nil { if err != nil {

View File

@ -7,7 +7,7 @@ import (
"github.com/caddyserver/ingress/internal/pod" "github.com/caddyserver/ingress/internal/pod"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
apiv1 "k8s.io/api/core/v1" apiv1 "k8s.io/api/core/v1"
"k8s.io/api/extensions/v1beta1" "k8s.io/api/networking/v1beta1"
) )
// dispatchSync is run every syncInterval duration to sync ingress source address fields. // dispatchSync is run every syncInterval duration to sync ingress source address fields.

View File

@ -8,7 +8,7 @@ import (
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
apiv1 "k8s.io/api/core/v1" apiv1 "k8s.io/api/core/v1"
"k8s.io/api/extensions/v1beta1" "k8s.io/api/networking/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
sv1 "k8s.io/client-go/informers/core/v1" sv1 "k8s.io/client-go/informers/core/v1"
"k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes"

View File

@ -3,7 +3,7 @@ package store
import ( import (
c "github.com/caddyserver/ingress/internal/caddy" c "github.com/caddyserver/ingress/internal/caddy"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"k8s.io/api/extensions/v1beta1" "k8s.io/api/networking/v1beta1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes"
) )
@ -18,7 +18,7 @@ type Store struct {
// NewStore returns a new store that keeps track of ingresses and secrets. It will attempt to get // NewStore returns a new store that keeps track of ingresses and secrets. It will attempt to get
// all current ingresses before returning. // all current ingresses before returning.
func NewStore(kubeClient *kubernetes.Clientset, namespace string, cfg c.ControllerConfig, cfgMapConfig *c.Config) *Store { func NewStore(kubeClient *kubernetes.Clientset, namespace string, cfg c.ControllerConfig, cfgMapConfig *c.Config) *Store {
ingresses, err := kubeClient.ExtensionsV1beta1().Ingresses("").List(v1.ListOptions{}) ingresses, err := kubeClient.NetworkingV1beta1().Ingresses("").List(v1.ListOptions{})
if err != nil { if err != nil {
logrus.Errorf("could not get existing ingresses in cluster") logrus.Errorf("could not get existing ingresses in cluster")
return &Store{} return &Store{}

View File

@ -1,4 +1,4 @@
apiVersion: rbac.authorization.k8s.io/v1beta1 apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole kind: ClusterRole
metadata: metadata:
name: caddy-ingress-controller-role name: caddy-ingress-controller-role
@ -6,7 +6,7 @@ metadata:
rules: rules:
- apiGroups: - apiGroups:
- "" - ""
- "extensions" - "networking.k8s.io"
resources: resources:
- ingresses - ingresses
- ingresses/status - ingresses/status

View File

@ -1,5 +1,5 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata: metadata:
name: caddy-ingress-controller-role-binding name: caddy-ingress-controller-role-binding
namespace: caddy-system namespace: caddy-system

View File

@ -1,5 +1,5 @@
{{- if .Values.caddyingresscontroller.rbac.create }} {{- if .Values.caddyingresscontroller.rbac.create }}
apiVersion: rbac.authorization.k8s.io/v1beta1 apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole kind: ClusterRole
metadata: metadata:
name: {{ .Values.name }}-role name: {{ .Values.name }}-role
@ -7,7 +7,7 @@ metadata:
rules: rules:
- apiGroups: - apiGroups:
- "" - ""
- "extensions" - "networking.k8s.io"
resources: resources:
- ingresses - ingresses
- ingresses/status - ingresses/status

View File

@ -1,6 +1,6 @@
{{- if .Values.caddyingresscontroller.rbac.create }} {{- if .Values.caddyingresscontroller.rbac.create }}
kind: ClusterRoleBinding kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1 apiVersion: rbac.authorization.k8s.io/v1
metadata: metadata:
name: {{ .Values.name }}-role-binding name: {{ .Values.name }}-role-binding
namespace: {{ .Release.Namespace }} namespace: {{ .Release.Namespace }}

View File

@ -6,11 +6,12 @@ import (
"strings" "strings"
"github.com/caddyserver/caddy/v2" "github.com/caddyserver/caddy/v2"
"github.com/mholt/certmagic" "github.com/caddyserver/certmagic"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
) )
// matchLabels are attached to each resource so that they can be found in the future. // matchLabels are attached to each resource so that they can be found in the future.
@ -42,6 +43,16 @@ func (SecretStorage) CaddyModule() caddy.ModuleInfo {
} }
} }
// Provisions the SecretStorage instance.
func (s *SecretStorage) Provision(ctx caddy.Context) error {
config, _ := clientcmd.BuildConfigFromFlags("", "")
// creates the clientset
clientset, _ := kubernetes.NewForConfig(config)
s.KubeClient = clientset
return nil
}
// CertMagicStorage returns a certmagic storage type to be used by caddy. // CertMagicStorage returns a certmagic storage type to be used by caddy.
func (s *SecretStorage) CertMagicStorage() (certmagic.Storage, error) { func (s *SecretStorage) CertMagicStorage() (certmagic.Storage, error) {
return s, nil return s, nil