Skip to content

Commit

Permalink
Implementing a generic Ingress based on Lua
Browse files Browse the repository at this point in the history
Signed-off-by: liheng.zms <liheng.zms@alibaba-inc.com>
  • Loading branch information
zmberg committed Nov 10, 2022
1 parent a335a7f commit b8531f8
Show file tree
Hide file tree
Showing 31 changed files with 2,366 additions and 431 deletions.
5 changes: 5 additions & 0 deletions .lift.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Ignore results from vendor directories
ignoreFiles = """
vendor/
lua_configuration/
"""
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -o manager main.go
FROM gcr.io/distroless/static:nonroot
WORKDIR /
COPY --from=builder /workspace/manager .
COPY lua_configuration /lua_configuration
USER 65532:65532

ENTRYPOINT ["/manager"]
1 change: 1 addition & 0 deletions Dockerfile_multiarch
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ RUN GOOS=${TARGETOS} GOARCH=${TARGETARCH} CGO_ENABLED=0 GOOS=linux GOARCH=amd64
FROM gcr.io/distroless/static:nonroot
WORKDIR /
COPY --from=builder /workspace/manager .
COPY lua_configuration /lua_configuration
USER 65532:65532

ENTRYPOINT ["/manager"]
42 changes: 8 additions & 34 deletions api/v1alpha1/rollout_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
)

// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
Expand Down Expand Up @@ -65,11 +66,6 @@ type WorkloadRef struct {
Name string `json:"name"`
}

/*type ControllerRevisionRef struct {
TargetRevisionName string `json:"targetRevisionName"`
SourceRevisionName string `json:"sourceRevisionName"`
}*/

// RolloutStrategy defines strategy to apply during next rollout
type RolloutStrategy struct {
// Paused indicates that the Rollout is paused.
Expand Down Expand Up @@ -112,42 +108,19 @@ type CanaryStep struct {
Pause RolloutPause `json:"pause,omitempty"`
// Matches define conditions used for matching the incoming HTTP requests to canary service.
// Each match is independent, i.e. this rule will be matched if **any** one of the matches is satisfied.
Matches []RouteMatch `json:"matches,omitempty"`
// If Gateway API, current only support one match.
// And cannot support both weight and matches, if both are configured, then matches takes precedence.
Matches []HttpRouteMatch `json:"matches,omitempty"`
}

type RouteMatch struct {
type HttpRouteMatch struct {
// Headers specifies HTTP request header matchers. Multiple match values are
// ANDed together, meaning, a request must match all the specified headers
// to select the route.
// +kubebuilder:validation:MaxItems=16
Headers []HeaderMatch `json:"headers"`
}

// HeaderMatch describes how to select a route by matching request
// headers.
type HeaderMatch struct {
// Type specifies how to match against the value of the header.
// +optional
// +kubebuilder:default=Exact
Type *HeaderMatchType `json:"type,omitempty"`
// Name is the name of the HTTP Header to be matched. Name matching MUST be
// case insensitive.
Name string `json:"name"`
// Value is the value of HTTP Header to be matched.
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:MaxLength=4096
Value string `json:"value"`
Headers []gatewayv1alpha2.HTTPHeaderMatch `json:"headers,omitempty"`
}

// +kubebuilder:validation:Enum=Exact;RegularExpression
type HeaderMatchType string

// HeaderMatchType constants.
const (
HeaderMatchExact HeaderMatchType = "Exact"
HeaderMatchRegularExpression HeaderMatchType = "RegularExpression"
)

// RolloutPause defines a pause stage for a rollout
type RolloutPause struct {
// Duration the amount of time to wait before moving to the next step.
Expand All @@ -170,7 +143,8 @@ type TrafficRouting struct {

// IngressTrafficRouting configuration for ingress controller to control traffic routing
type IngressTrafficRouting struct {
// ClassType refers to the class type of an `Ingress`, e.g. Nginx. Default is Nginx
// ClassType refers to the type of `Ingress`.
// current support nginx, aliyun-alb, aliyun-mse. default is nginx.
// +optional
ClassType string `json:"classType,omitempty"`
// Name refers to the name of an `Ingress` resource in the same namespace as the `Rollout`
Expand Down
55 changes: 18 additions & 37 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

49 changes: 38 additions & 11 deletions config/crd/bases/rollouts.kruise.io_rollouts.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,10 @@ spec:
description: Matches define conditions used for matching
the incoming HTTP requests to canary service. Each
match is independent, i.e. this rule will be matched
if **any** one of the matches is satisfied.
if **any** one of the matches is satisfied. If Gateway
API, current only support one match. And cannot support
both weight and matches, if both are configured, then
matches takes precedence.
items:
properties:
headers:
Expand All @@ -111,18 +114,43 @@ spec:
meaning, a request must match all the specified
headers to select the route.
items:
description: HeaderMatch describes how to select
a route by matching request headers.
description: HTTPHeaderMatch describes how to
select a HTTP route by matching HTTP request
headers.
properties:
name:
description: Name is the name of the HTTP
description: "Name is the name of the HTTP
Header to be matched. Name matching MUST
be case insensitive.
be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2).
\n If multiple entries specify equivalent
header names, only the first entry with
an equivalent name MUST be considered
for a match. Subsequent entries with an
equivalent header name MUST be ignored.
Due to the case-insensitivity of header
names, \"foo\" and \"Foo\" are considered
equivalent. \n When a header is repeated
in an HTTP request, it is implementation-specific
behavior as to how this is represented.
Generally, proxies should follow the guidance
from the RFC: https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2
regarding processing a repeated header,
with special handling for \"Set-Cookie\"."
maxLength: 256
minLength: 1
pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$
type: string
type:
default: Exact
description: Type specifies how to match
against the value of the header.
description: "Type specifies how to match
against the value of the header. \n Support:
Core (Exact) \n Support: Custom (RegularExpression)
\n Since RegularExpression HeaderMatchType
has custom conformance, implementations
can support POSIX, PCRE or any other dialects
of regular expressions. Please read the
implementation's documentation to determine
the supported dialect."
enum:
- Exact
- RegularExpression
Expand All @@ -139,8 +167,6 @@ spec:
type: object
maxItems: 16
type: array
required:
- headers
type: object
type: array
pause:
Expand Down Expand Up @@ -199,8 +225,9 @@ spec:
to route traffic, e.g. Nginx, Alb.
properties:
classType:
description: ClassType refers to the class type
of an `Ingress`, e.g. Nginx. Default is Nginx
description: ClassType refers to the type of `Ingress`.
current support nginx, aliyun-alb, aliyun-mse.
default is nginx.
type: string
name:
description: Name refers to the name of an `Ingress`
Expand Down
8 changes: 8 additions & 0 deletions config/rbac/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,14 @@ rules:
- get
- patch
- update
- apiGroups:
- ""
resources:
- configmaps
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
Expand Down
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ go 1.16

require (
github.com/davecgh/go-spew v1.1.1
github.com/evanphx/json-patch v4.11.0+incompatible
github.com/onsi/ginkgo v1.16.5
github.com/onsi/gomega v1.17.0
github.com/openkruise/kruise-api v1.0.0
github.com/spf13/pflag v1.0.5
github.com/yuin/gopher-lua v0.0.0-20220504180219-658193537a64
gopkg.in/yaml.v2 v2.4.0
k8s.io/api v0.22.6
k8s.io/apiextensions-apiserver v0.22.6
Expand All @@ -16,6 +18,7 @@ require (
k8s.io/component-base v0.22.6
k8s.io/klog/v2 v2.10.0
k8s.io/utils v0.0.0-20210820185131-d34e5cb4466e
layeh.com/gopher-json v0.0.0-20201124131017-552bb3c4c3bf
sigs.k8s.io/controller-runtime v0.10.3
sigs.k8s.io/gateway-api v0.4.3
sigs.k8s.io/yaml v1.2.0
Expand Down
5 changes: 5 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,8 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/gopher-lua v0.0.0-20220504180219-658193537a64 h1:5mLPGnFdSsevFRFc9q3yYbBkB6tsm4aCwwQV/j1JQAQ=
github.com/yuin/gopher-lua v0.0.0-20220504180219-658193537a64/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
Expand Down Expand Up @@ -675,6 +677,7 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
Expand Down Expand Up @@ -1031,6 +1034,8 @@ k8s.io/utils v0.0.0-20210722164352-7f3ee0f31471/go.mod h1:jPW/WVKK9YHAvNhRxK0md/
k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
k8s.io/utils v0.0.0-20210820185131-d34e5cb4466e h1:ldQh+neBabomh7+89dTpiFAB8tGdfVmuIzAHbvtl+9I=
k8s.io/utils v0.0.0-20210820185131-d34e5cb4466e/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
layeh.com/gopher-json v0.0.0-20201124131017-552bb3c4c3bf h1:rRz0YsF7VXj9fXRF6yQgFI7DzST+hsI3TeFSGupntu0=
layeh.com/gopher-json v0.0.0-20201124131017-552bb3c4c3bf/go.mod h1:ivKkcY8Zxw5ba0jldhZCYYQfGdb2K6u9tbYK1AwMIBc=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
Expand Down
35 changes: 35 additions & 0 deletions lua_configuration/trafficrouting_ingress/aliyun-alb.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
annotations = {}
if ( obj.annotations )
then
annotations = obj.annotations
end
annotations["alb.ingress.kubernetes.io/canary"] = "true"
annotations["alb.ingress.kubernetes.io/canary-by-cookie"] = nil
annotations["alb.ingress.kubernetes.io/canary-by-header"] = nil
annotations["alb.ingress.kubernetes.io/canary-by-header-pattern"] = nil
annotations["alb.ingress.kubernetes.io/canary-by-header-value"] = nil
annotations["alb.ingress.kubernetes.io/canary-weight"] = nil
if ( obj.weight ~= "-1" )
then
annotations["alb.ingress.kubernetes.io/canary-weight"] = obj.weight
end
if ( not obj.matches )
then
return annotations
end
for _,match in ipairs(obj.matches) do
local header = match.headers[1]
if ( header.name == "canary-by-cookie" )
then
annotations["alb.ingress.kubernetes.io/canary-by-cookie"] = header.value
else
annotations["alb.ingress.kubernetes.io/canary-by-header"] = header.name
if ( header.type == "RegularExpression" )
then
annotations["alb.ingress.kubernetes.io/canary-by-header-pattern"] = header.value
else
annotations["alb.ingress.kubernetes.io/canary-by-header-value"] = header.value
end
end
end
return annotations
Loading

0 comments on commit b8531f8

Please sign in to comment.