-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
526214c
commit 500c5d5
Showing
4 changed files
with
200 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export * from "./ingress-props"; | ||
export * from "./ingress"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
export interface ServiceProps { | ||
readonly name: string; | ||
readonly port: number; | ||
readonly namespace: string; | ||
readonly weight: number; | ||
} | ||
|
||
export interface IngressProps { | ||
/** | ||
* Whether this is an internal service (behind VPN). | ||
* @default false | ||
*/ | ||
readonly internal?: boolean; | ||
|
||
/** | ||
* Custom selector labels, they will be merged with the default app, role, and instance. | ||
* They will be applied to the workload, the pod and the service. | ||
* @default { app: "<app label from chart>", role: "server", instance: "<construct id>" } | ||
*/ | ||
readonly selectorLabels?: { [key: string]: string }; | ||
|
||
/** | ||
* Domain name for TLS certificate discovery. | ||
* @see https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.3/guide/ingress/cert_discovery/ | ||
*/ | ||
readonly tlsDomain?: string | string[]; | ||
|
||
/** | ||
* Overrides for Ingress annotations. | ||
* @see https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.3/guide/ingress/annotations/ | ||
*/ | ||
readonly ingressAnnotations?: { [key: string]: string }; | ||
|
||
/** | ||
* Hostname to add External DNS record for the ingress. | ||
*/ | ||
readonly externalHostname?: string; | ||
|
||
readonly hostnames: string[]; | ||
|
||
readonly serviceRouting: ServiceProps[]; | ||
|
||
readonly ingressClassName: string; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
import { Chart } from "cdk8s"; | ||
import { Construct } from "constructs"; | ||
import { | ||
IngressRule, | ||
IngressTls, | ||
IntOrString, | ||
KubeIngress, | ||
KubeService, | ||
} from "../../imports/k8s"; | ||
import { convertToStringMap } from "../web-service/."; | ||
import { ensureArray } from "../common"; | ||
import { supportsTls } from "./tls-util"; | ||
import { IngressProps } from "."; | ||
import { ServiceSpecType } from "../k8s"; | ||
|
||
export class Ingress extends Construct { | ||
constructor(scope: Construct, id: string, props: IngressProps) { | ||
super(scope, id); | ||
|
||
const chart = Chart.of(this); | ||
const ingressTargetType = "instance"; | ||
const environment = chart.labels.environment; | ||
const app = chart.labels.app ?? props.selectorLabels?.app; | ||
const selectorLabels: { [key: string]: string } = { | ||
app: app, | ||
role: "server", | ||
instance: id, | ||
...props.selectorLabels, | ||
}; | ||
|
||
const labels: { [key: string]: string } = { | ||
...chart.labels, | ||
...selectorLabels, | ||
}; | ||
|
||
const externalDns: Record<string, string> = {}; | ||
const ingressRules: IngressRule[] = []; | ||
const ingressTls: IngressTls[] = []; | ||
const ingressListenPorts: Record<string, number>[] = [{ HTTP: 80 }]; | ||
const ingressTlsAnnotations: Record<string, string> = {}; | ||
if (supportsTls(props)) { | ||
if (props.tlsDomain) { | ||
ingressTls.push({ | ||
hosts: ensureArray(props.tlsDomain), | ||
}); | ||
} | ||
ingressListenPorts.push({ HTTPS: 443 }); | ||
} | ||
|
||
if (props.externalHostname) { | ||
externalDns["external-dns.alpha.kubernetes.io/hostname"] = | ||
props.externalHostname; | ||
} | ||
|
||
const targetGroups: Record<string, string | number>[] = []; | ||
for (const service of props.serviceRouting) { | ||
const serviceName = `${service.name}-${service.namespace}`; | ||
new KubeService(this, `${id}-${serviceName}-service`, { | ||
metadata: { | ||
name: serviceName, | ||
namespace: "application-ingress", | ||
}, | ||
spec: { | ||
type: ServiceSpecType.EXTERNAL_NAME, | ||
externalName: `${service.name}.${service.namespace}.svc.cluster.local`, | ||
ports: [ | ||
{ | ||
port: service.port, | ||
targetPort: IntOrString.fromNumber(service.port), | ||
}, | ||
], | ||
}, | ||
}); | ||
|
||
const targetGroup = { | ||
serviceName: serviceName, | ||
servicePort: service.port, | ||
weight: service.weight, | ||
}; | ||
targetGroups.push(targetGroup); | ||
} | ||
|
||
const ingressAnnotations = { | ||
"alb.ingress.kubernetes.io/listen-ports": | ||
convertToJsonContent(ingressListenPorts), | ||
"alb.ingress.kubernetes.io/success-codes": "200,303", | ||
"alb.ingress.kubernetes.io/target-type": ingressTargetType, | ||
"alb.ingress.kubernetes.io/tags": convertToStringMap({ | ||
service: labels.service ?? app, | ||
instance: id, | ||
environment: environment, | ||
}), | ||
"alb.ingress.kubernetes.io/actions.service-weighting": | ||
convertToJsonContent({ | ||
type: "forward", | ||
forwardConfig: { | ||
targetGroups: targetGroups, | ||
}, | ||
}), | ||
...ingressTlsAnnotations, | ||
...props.ingressAnnotations, | ||
...externalDns, | ||
}; | ||
|
||
for (const hostname of props.hostnames) { | ||
ingressRules.push({ | ||
host: hostname, | ||
http: { | ||
paths: [ | ||
{ | ||
pathType: "Prefix", | ||
path: "/", | ||
backend: { | ||
service: { | ||
name: "service-weighting", | ||
port: { | ||
name: "use-annotation", | ||
}, | ||
}, | ||
}, | ||
}, | ||
], | ||
}, | ||
}); | ||
} | ||
|
||
new KubeIngress(this, `${id}-ingress`, { | ||
metadata: { | ||
annotations: ingressAnnotations, | ||
labels: labels, | ||
}, | ||
spec: { | ||
ingressClassName: props.ingressClassName, | ||
tls: ingressTls.length > 0 ? ingressTls : undefined, | ||
rules: ingressRules.length > 0 ? ingressRules : undefined, | ||
}, | ||
}); | ||
} | ||
} | ||
|
||
function convertToJsonContent(obj: unknown): string { | ||
return JSON.stringify(obj); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { IngressProps } from "."; | ||
|
||
/** | ||
* Whether this web service should support TLS. | ||
*/ | ||
export function supportsTls(props: Partial<IngressProps>): boolean { | ||
return ( | ||
!!props.tlsDomain || | ||
!!props.ingressAnnotations?.["alb.ingress.kubernetes.io/certificate-arn"] | ||
); | ||
} |