Skip to content

Commit

Permalink
feat(pod): pod dns settings (#497) (#636)
Browse files Browse the repository at this point in the history
Resolves #362

(cherry picked from commit d377378)
Signed-off-by: Eli Polonsky <epolon@amazon.com>

# Conflicts:
#	docs/java.md
#	docs/python.md
#	docs/typescript.md
#	src/deployment.ts
  • Loading branch information
iliapolo committed Apr 24, 2022
1 parent f0133c7 commit 924350a
Show file tree
Hide file tree
Showing 12 changed files with 2,588 additions and 6 deletions.
779 changes: 779 additions & 0 deletions docs/java.md

Large diffs are not rendered by default.

797 changes: 797 additions & 0 deletions docs/python.md

Large diffs are not rendered by default.

585 changes: 585 additions & 0 deletions docs/typescript.md

Large diffs are not rendered by default.

6 changes: 5 additions & 1 deletion src/daemon-set.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Construct } from 'constructs';
import { Resource, ResourceProps } from './base';
import { Container, ContainerProps } from './container';
import * as k8s from './imports/k8s';
import { HostAlias, IPodTemplate, PodSecurityContext, PodTemplate, PodTemplateProps, RestartPolicy } from './pod';
import { HostAlias, IPodTemplate, PodSecurityContext, PodTemplate, PodTemplateProps, RestartPolicy, PodDns } from './pod';
import { IServiceAccount } from './service-account';
import { Volume } from './volume';

Expand Down Expand Up @@ -123,6 +123,10 @@ export class DaemonSet extends Resource implements IPodTemplate {
return this._podTemplate.securityContext;
}

public get dns(): PodDns {
return this._podTemplate.dns;
}

public addContainer(container: ContainerProps): Container {
return this._podTemplate.addContainer(container);
}
Expand Down
6 changes: 5 additions & 1 deletion src/deployment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Resource, ResourceProps } from './base';
import { Container, ContainerProps } from './container';
import * as k8s from './imports/k8s';
import { IngressV1Beta1 } from './ingress-v1beta1';
import { RestartPolicy, PodTemplate, IPodTemplate, PodTemplateProps, PodSecurityContext, HostAlias } from './pod';
import { RestartPolicy, PodTemplate, IPodTemplate, PodTemplateProps, PodSecurityContext, HostAlias, PodDns } from './pod';
import { ExposeServiceViaIngressOptions, Protocol, Service, ServiceType } from './service';
import { IServiceAccount } from './service-account';
import { Volume } from './volume';
Expand Down Expand Up @@ -197,6 +197,10 @@ export class Deployment extends Resource implements IPodTemplate {
return this._podTemplate.securityContext;
}

public get dns(): PodDns {
return this._podTemplate.dns;
}

/**
* Configure a label selector to this deployment.
* Pods that have the label will be selected by deployments configured with this spec.
Expand Down
6 changes: 5 additions & 1 deletion src/job.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Construct } from 'constructs';
import { Resource, ResourceProps } from './base';
import { Container, ContainerProps } from './container';
import * as k8s from './imports/k8s';
import { RestartPolicy, PodTemplateProps, IPodTemplate, PodTemplate, PodSecurityContext, HostAlias } from './pod';
import { RestartPolicy, PodTemplateProps, IPodTemplate, PodTemplate, PodSecurityContext, HostAlias, PodDns } from './pod';
import { IServiceAccount } from './service-account';
import { Volume } from './volume';

Expand Down Expand Up @@ -124,6 +124,10 @@ export class Job extends Resource implements IPodTemplate {
return this._podTemplate.securityContext;
}

public get dns(): PodDns {
return this._podTemplate.dns;
}

public addContainer(container: ContainerProps): Container {
return this._podTemplate.addContainer(container);
}
Expand Down
268 changes: 267 additions & 1 deletion src/pod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,16 @@ export interface IPodSpec {
*/
readonly hostAliases: HostAlias[];

/**
* The pod's DNS settings.
*/
readonly dns: PodDns;

/**
* The pod's security context.
*/
readonly securityContext: PodSecurityContext;

/**
* Add a container to the pod.
*
Expand Down Expand Up @@ -95,6 +105,7 @@ export class PodSpec implements IPodSpec {
public readonly restartPolicy?: RestartPolicy;
public readonly serviceAccount?: IServiceAccount;
public readonly securityContext: PodSecurityContext;
public readonly dns: PodDns;
public readonly dockerRegistryAuth?: DockerConfigSecret;

private readonly _containers: Container[] = [];
Expand All @@ -106,6 +117,7 @@ export class PodSpec implements IPodSpec {
this.restartPolicy = props.restartPolicy;
this.serviceAccount = props.serviceAccount;
this.securityContext = new PodSecurityContext(props.securityContext);
this.dns = new PodDns(props.dns);
this.dockerRegistryAuth = props.dockerRegistryAuth;

if (props.containers) {
Expand Down Expand Up @@ -229,6 +241,8 @@ export class PodSpec implements IPodSpec {
volumes.set(volume.name, volume);
}

const dns = this.dns._toKube();

return {
restartPolicy: this.restartPolicy,
serviceAccountName: this.serviceAccount?.name,
Expand All @@ -237,6 +251,11 @@ export class PodSpec implements IPodSpec {
initContainers: initContainers,
hostAliases: this.hostAliases,
volumes: Array.from(volumes.values()).map(v => v._toKube()),
dnsPolicy: dns.policy,
dnsConfig: dns.config,
hostname: dns.hostname,
subdomain: dns.subdomain,
setHostnameAsFqdn: dns.hostnameAsFQDN,
imagePullSecrets: this.dockerRegistryAuth ? [{ name: this.dockerRegistryAuth.name }] : undefined,
};

Expand Down Expand Up @@ -439,13 +458,24 @@ export interface PodSpecProps {
*/
readonly hostAliases?: HostAlias[];

/**
* DNS settings for the pod.
*
* @see https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/
*
* @default
*
* policy: DnsPolicy.CLUSTER_FIRST
* hostnameAsFQDN: false
*/
readonly dns?: PodDnsProps;

/**
* A secret containing docker credentials for authenticating to a registry.
*
* @default - No auth. Images are assumed to be publicly available.
*/
readonly dockerRegistryAuth?: DockerConfigSecret;

}

/**
Expand Down Expand Up @@ -500,6 +530,10 @@ export class Pod extends Resource implements IPodSpec {
return this._spec.hostAliases;
}

public get dns(): PodDns {
return this._spec.dns;
}

public addContainer(container: ContainerProps): Container {
return this._spec.addContainer(container);
}
Expand All @@ -518,6 +552,186 @@ export class Pod extends Resource implements IPodSpec {

}

/**
* Properties for `PodDns`.
*/
export interface PodDnsProps {

/**
* Specifies the hostname of the Pod.
*
* @default - Set to a system-defined value.
*/
readonly hostname?: string;

/**
* If specified, the fully qualified Pod hostname will be "<hostname>.<subdomain>.<pod namespace>.svc.<cluster domain>".
*
* @default - No subdomain.
*/
readonly subdomain?: string;

/**
* If true the pod's hostname will be configured as the pod's FQDN, rather than the leaf name (the default).
* In Linux containers, this means setting the FQDN in the hostname field of the kernel (the nodename field of struct utsname).
* In Windows containers, this means setting the registry value of hostname for the registry
* key HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters to FQDN.
* If a pod does not have FQDN, this has no effect.
*
* @default false
*/
readonly hostnameAsFQDN?: boolean;

/**
* Set DNS policy for the pod.
*
* If policy is set to `None`, other configuration must be supplied.
*
* @default DnsPolicy.CLUSTER_FIRST
*/
readonly policy?: DnsPolicy;

/**
* A list of IP addresses that will be used as DNS servers for the Pod. There can be at most 3 IP addresses specified.
* When the policy is set to "NONE", the list must contain at least one IP address,
* otherwise this property is optional.
* The servers listed will be combined to the base nameservers generated from
* the specified DNS policy with duplicate addresses removed.
*/
readonly nameservers?: string[];

/**
* A list of DNS search domains for hostname lookup in the Pod.
* When specified, the provided list will be merged into the base
* search domain names generated from the chosen DNS policy.
* Duplicate domain names are removed.
*
* Kubernetes allows for at most 6 search domains.
*/
readonly searches?: string[];

/**
* List of objects where each object may have a name property (required)
* and a value property (optional). The contents in this property
* will be merged to the options generated from the specified DNS policy.
* Duplicate entries are removed.
*/
readonly options?: DnsOption[];
}

/**
* Holds dns settings of the pod.
*/
export class PodDns {

/**
* The DNS policy of this pod.
*/
public readonly policy: DnsPolicy;

/**
* The configured hostname of the pod. Undefined means its set to a system-defined value.
*/
public readonly hostname?: string;

/**
* The configured subdomain of the pod.
*/
public readonly subdomain?: string;

/**
* Whether or not the pods hostname is set to its FQDN.
*/
public readonly hostnameAsFQDN: boolean;

private readonly _nameservers: string[];
private readonly _searches: string[];
private readonly _options: DnsOption[];

constructor(props: PodDnsProps = {}) {
this.hostname = props.hostname;
this.subdomain = props.subdomain;
this.policy = props.policy ?? DnsPolicy.CLUSTER_FIRST;
this.hostnameAsFQDN = props.hostnameAsFQDN ?? false;
this._nameservers = props.nameservers ?? [];
this._searches = props.searches ?? [];
this._options = props.options ?? [];
}

/**
* Nameservers defined for this pod.
*/
public get nameservers(): string[] {
return [...this._nameservers];
}

/**
* Search domains defined for this pod.
*/
public get searches(): string[] {
return [...this._searches];
}

/**
* Custom dns options defined for this pod.
*/
public get options(): DnsOption[] {
return [...this._options];
}

/**
* Add a nameserver.
*/
public addNameserver(...nameservers: string[]) {
this._nameservers.push(...nameservers);
}

/**
* Add a search domain.
*/
public addSearch(...searches: string[]) {
this._searches.push(...searches);
}

/**
* Add a custom option.
*/
public addOption(...options: DnsOption[]) {
this._options.push(...options);
}

/**
* @internal
*/
public _toKube(): { hostname?: string; subdomain?: string; hostnameAsFQDN: boolean; policy: string; config: k8s.PodDnsConfig } {

if (this.policy === DnsPolicy.NONE && this.nameservers.length === 0) {
throw new Error('When dns policy is set to NONE, at least one nameserver is required');
}

if (this.nameservers.length > 3) {
throw new Error('There can be at most 3 nameservers specified');
}

if (this.searches.length > 6) {
throw new Error('There can be at most 6 search domains specified');
}

return {
hostname: this.hostname,
subdomain: this.subdomain,
hostnameAsFQDN: this.hostnameAsFQDN,
policy: this.policy,
config: {
nameservers: this.nameservers,
searches: this.searches,
options: this.options,
},
};
}

}

/**
* Holds pod-level security attributes and common container settings.
*/
Expand Down Expand Up @@ -599,6 +813,58 @@ export enum FsGroupChangePolicy {
ALWAYS = 'Always'
}

/**
* Custom DNS option.
*/
export interface DnsOption {

/**
* Option name.
*/
readonly name: string;

/**
* Option value.
*
* @default - No value.
*/
readonly value?: string;
}

/**
* Pod DNS policies.
*/
export enum DnsPolicy {

/**
* Any DNS query that does not match the configured cluster domain suffix,
* such as "www.kubernetes.io", is forwarded to the
* upstream nameserver inherited from the node.
* Cluster administrators may have extra stub-domain and upstream DNS servers configured.
*/
CLUSTER_FIRST = 'ClusterFirst',

/**
* For Pods running with hostNetwork, you should
* explicitly set its DNS policy "ClusterFirstWithHostNet".
*/
CLUSTER_FIRST_WITH_HOST_NET = 'ClusterFirstWithHostNet',

/**
* The Pod inherits the name resolution configuration
* from the node that the pods run on.
*/
DEFAULT = 'Default',

/**
* It allows a Pod to ignore DNS settings from the Kubernetes environment.
* All DNS settings are supposed to be provided using the dnsConfig
* field in the Pod Spec.
*/
NONE = 'None',

}

/**
* HostAlias holds the mapping between IP and hostnames that will be injected as
* an entry in the pod's /etc/hosts file.
Expand Down

0 comments on commit 924350a

Please sign in to comment.