### Deployment Manifest Example Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/deployment.md This is an example of the Kubernetes Deployment manifest generated by cdk8s-plus, showcasing automatic label selection for pods. ```yaml apiVersion: apps/v1 kind: Deployment metadata: name: deployment-frontends-c8e48310 spec: minReadySeconds: 0 progressDeadlineSeconds: 600 replicas: 2 selector: matchLabels: cdk8s.io/metadata.addr: deployment-FrontEnds-c89e9e97 strategy: rollingUpdate: maxSurge: 25% maxUnavailable: 25% type: RollingUpdate template: metadata: labels: cdk8s.io/metadata.addr: deployment-FrontEnds-c89e9e97 spec: automountServiceAccountToken: false containers: - image: node imagePullPolicy: Always name: main resources: limits: cpu: 1500m memory: 2048Mi requests: cpu: 1000m memory: 512Mi securityContext: allowPrivilegeEscalation: false privileged: false readOnlyRootFilesystem: true runAsGroup: 26000 runAsNonRoot: true runAsUser: 25000 dnsPolicy: ClusterFirst restartPolicy: Always securityContext: fsGroupChangePolicy: Always runAsNonRoot: true setHostnameAsFQDN: false ``` -------------------------------- ### Configure Container Readiness Probe with HTTP Get Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/container.md Configures a readiness probe for a container using an HTTP GET request to a specified path. ```typescript new kplus.Pod(this, 'Pod', { containers: [ { image: 'my-app', readiness: kplus.Probe.fromHttpGet('/ping'), } ] }); ``` -------------------------------- ### Define a Service with Label Selectors Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/service.md Configure a service to select pods based on their labels. This example selects all pods with the label 'run: frontend'. ```typescript import * as k from 'cdk8s'; import * as kplus from 'cdk8s-plus-34'; const app = new k.App(); const chart = new k.Chart(app, 'Chart'); const frontends = new kplus.Service(chart, 'FrontEnds'); // this will cause the service to select all pods with the 'run: frontend' label. frontends.select(kplus.LabelSelector.equals('run', 'frontend')); ``` -------------------------------- ### Configure HPA with Scale Up Strategy and Resource Metrics Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/horizontal-pod-autoscaler.md This example demonstrates configuring an HPA with a specific scale-up strategy (`MAX_CHANGE`) and resource-based metrics (CPU utilization). It shows how to combine policies for scaling up by a fixed number of pods or a percentage. ```typescript const hpa = new kplus.HorizontalPodAutoscaler(chart, 'BookstoreWebsiteHpa', { target: bookstoreWebsite, maxReplicas: 10, metrics: [ kplus.Metric.resourceCpu(kplus.MetricTarget.averageUtilization(70)), ], scaleUp: { strategy: kplus.ScalingStrategy.MAX_CHANGE, stabilizationWindow: 60, policies: [ kplus.PolicyType.pods(4), kplus.PolicyType.percent(200), ], }, }); ``` -------------------------------- ### Deployment and Service Manifest Example Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/deployment.md This YAML output shows a Kubernetes Deployment and its associated ClusterIP Service, configured to route traffic to the deployment's pods using the automatically generated label selector. ```yaml apiVersion: apps/v1 kind: Deployment metadata: name: deployment-frontends-c8e48310 spec: minReadySeconds: 0 progressDeadlineSeconds: 600 replicas: 2 selector: matchLabels: cdk8s.io/metadata.addr: deployment-FrontEnds-c89e9e97 strategy: rollingUpdate: maxSurge: 25% maxUnavailable: 25% type: RollingUpdate template: metadata: labels: cdk8s.io/metadata.addr: deployment-FrontEnds-c89e9e97 spec: automountServiceAccountToken: false containers: - image: node imagePullPolicy: Always name: main ports: - containerPort: 9000 resources: limits: cpu: 1500m memory: 2048Mi requests: cpu: 1000m memory: 512Mi securityContext: allowPrivilegeEscalation: false privileged: false readOnlyRootFilesystem: true runAsGroup: 26000 runAsNonRoot: true runAsUser: 25000 startupProbe: failureThreshold: 3 tcpSocket: port: 9000 dnsPolicy: ClusterFirst restartPolicy: Always securityContext: fsGroupChangePolicy: Always runAsNonRoot: true setHostnameAsFQDN: false --- apiVersion: v1 kind: Service metadata: name: deployment-frontends-service-c8206158 spec: externalIPs: [] ports: - port: 9000 selector: cdk8s.io/metadata.addr: deployment-FrontEnds-c89e9e97 type: ClusterIP ``` -------------------------------- ### Create a HorizontalPodAutoscaler for CPU Utilization Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/horizontal-pod-autoscaler.md This example demonstrates creating an HPA that scales a Deployment based on average CPU utilization. It scales up when CPU exceeds 70% and scales down when it falls below. The maximum number of replicas is set to 10. ```typescript import * as k from 'cdk8s'; import * as kplus from 'cdk8s-plus-34'; const app = new k.App(); const chart = new k.Chart(app, 'Chart'); // Lets create a deployment for our web server const bookstoreWebsite = new kplus.Deployment(chart, 'BookstoreWebsite', { containers: [ { image: 'node' } ], }); // Now define a HorizontalPodAutoscaler const hpa = new kplus.HorizontalPodAutoscaler(chart, 'BookstoreWebsiteHpa', { target: bookstoreWebsite, maxReplicas: 10, metrics: [ kplus.Metric.resourceCpu(kplus.MetricTarget.averageUtilization(70)), ], }); // This will scale our website deployment up when the average CPU utilization // is 70% or higher up to a maximum of 10 replicas. ``` -------------------------------- ### Create and Mount PersistentVolumeClaim Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/pvc.md Define a PersistentVolumeClaim with a specified storage size and mount it to a container within a pod. This snippet demonstrates the basic setup for requesting and utilizing persistent storage. ```typescript import * as kplus from 'cdk8s-plus-34'; import * as cdk8s from 'cdk8s'; const pod = new kplus.Pod(chart, 'Pod'); const container = pod.addContainer({ image: 'node' }); // create the storage request const claim = new kplus.PersistentVolumeClaim(chart, 'Claim', { storage: cdk8s.Size.gibibytes(50), }); // mount a volume based on the request to the container // this will also add the volume itself to the pod spec. container.mount('/data', kplus.Volume.fromPersistentVolumeClaim(claim)); ``` -------------------------------- ### Mutable Collection Add Methods Example Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/CONTRIBUTING.md Shows how to implement 'addXxx' methods for mutating collections like string arrays ('bar') and string-to-string maps ('baz'). ```typescript interface FooProps { readonly bar?: string[]; readonly baz?: { [key: string]: string }; } class Foo extends Construct { public addBar(item: string): void { ... } public addBaz(key: string, value: string): void { ... } } ``` -------------------------------- ### Read-only Primitive Accessor Example Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/CONTRIBUTING.md Illustrates how to define a class with a read-only primitive property 'replicas' that defaults to 10 if not provided. ```typescript interface FooProps { /** * @default 10 **/ readonly replicas?: number; } class Foo extends Construct { public readonly replicas: number; constructor(scope: Construct, id: string, props: FooProps = { }) { super(scope, id); this.replicas = props.replicas ?? 10; } } ``` -------------------------------- ### Tolerate Node Taints Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/pod.md Allow a pod to schedule onto nodes that have specific taints. This example tolerates nodes tainted with 'key1=value1:NoSchedule'. ```typescript import * as k from 'cdk8s'; import * as kplus from 'cdk8s-plus-34'; const app = new k.App(); const chart = new k.Chart(app, 'Chart'); const redis = new kplus.Pod(chart, 'Redis', { containers: [{ image: 'redis' }] }); const node = kplus.Node.tainted(kplus.NodeTaintQuery.is('key1', 'value1', { effect: kplus.TainEffect.NO_SCHEDULE })); redis.scheduling.tolerate(node); ``` -------------------------------- ### Configure Service Ports Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/service.md Define the ports a service listens on and the target ports on the associated containers. This example binds the service to port 9000 and redirects traffic to port 80 on the containers. ```typescript import * as k from 'cdk8s'; import * as kplus from 'cdk8s-plus-34'; const app = new k.App(); const chart = new k.Chart(app, 'Chart'); const frontends = new kplus.Service(chart, 'FrontEnds'); // make the service bind to port 9000 and redirect to port 80 on the associated containers. frontends.bind({port: 9000, targetPort: 80}) ``` -------------------------------- ### Immutable Collection Getter Example Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/CONTRIBUTING.md Demonstrates providing immutable copies of internal collections ('_bar', '_baz') via getter properties to prevent external modification. ```typescript class Foo extends Construct { private readonly _bar: string[]; private readonly _baz: { [k: string]: string }; constructor() { this._bar = props.bar ?? []; this._baz = props.baz ?? {}; } // use spreads to create a copy public get bar() { return [ ...this._bar ]; } public get baz() { return { ...this._baz }; } } ``` -------------------------------- ### Configure Job TTL - TypeScript Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/job.md Define a Kubernetes Job with a TTL to automatically clean up after successful completion. This example sets a 1-second TTL for a job named 'LoadData'. ```typescript import * as kplus from 'cdk8s-plus-34'; import { Construct } from 'constructs'; import { App, Chart, ChartProps, Duration } from 'cdk8s'; export class MyChart extends Chart { constructor(scope: Construct, id: string, props: ChartProps = { }) { super(scope, id, props); // let's define a job spec, and set a 1 second TTL. const job = new kplus.Job(this, 'LoadData', { ttlAfterFinished: Duration.seconds(1) }); // now add a container to all the pods created by this job job.addContainer({ image: 'loader' }); } } const app = new App(); new MyChart(app, 'Job'); app.synth(); ``` -------------------------------- ### Select Pods with labels in a specific namespace Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/pod.md Scopes pod selection to specific namespaces using a namespace selector. This example selects pods with the 'app=store' label in the 'backoffice' namespace. ```typescript import * as kplus from 'cdk8s-plus-34'; const pods = kplus.Pods.select(this, 'Pods', { labels: { app: 'store' }, namespaces: kplus.Namespaces.select(this, 'Backoffice', { names: ['backoffice'] }), }); ``` -------------------------------- ### Create a basic Pod Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/pod.md Instantiate a new Pod in the cluster. Ensure you import the necessary modules. ```typescript import * as kplus from 'cdk8s-plus-34'; import * as k from 'cdk8s'; const app = new k.App(); const chart = new k.Chart(app, 'Chart'); const pod = new kplus.Pod(chart, 'Pod'); ``` -------------------------------- ### Create a Basic Deployment Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/deployment.md Use this snippet to create a basic deployment with a specified container image. The construct automatically handles pod selection using labels. ```typescript import * as kplus from 'cdk8s-plus-34'; import { Construct } from 'constructs'; import { App, Chart, ChartProps } from 'cdk8s'; export class MyChart extends Chart { constructor(scope: Construct, id: string, props: ChartProps = { }) { super(scope, id, props); new kplus.Deployment(this, 'FrontEnds', { containers: [ { image: 'node' } ], }); } } const app = new App(); new MyChart(app, 'deployment'); app.synth(); ``` -------------------------------- ### Create Volume from Directory Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/config-map.md Add all files from a local directory to a ConfigMap, creating a volume that can be mounted into a pod. Only top-level files are supported. ```typescript import * as kplus from 'cdk8s-plus-34'; import * as path from 'path'; import { Construct } from 'constructs'; import { App, Chart, ChartProps } from 'cdk8s'; export class MyChart extends Chart { constructor(scope: Construct, id: string, props?: ChartProps) { super(scope, id, props); const appMap = new kplus.ConfigMap(this, 'Config'); // add the files in the directory to the config map. // this will create a key for each file. // note: this directory needs to exist // note: that only top level files will be included, sub-directories are not yet supported. appMap.addDirectory(path.join(__dirname, 'app')); const appVolume = kplus.Volume.fromConfigMap(this, 'ConfigMap', appMap); const mountPath = '/var/app'; const pod = new kplus.Pod(this, 'Pod'); const container = pod.addContainer({ image: 'node', command: [ 'node', 'app.js' ], workingDir: mountPath, }); // from here, just mount the volume to a container, and run your app! container.mount(mountPath, appVolume); } } const app = new App(); new MyChart(app, 'AppWithDir'); app.synth(); ``` -------------------------------- ### Isolate Initiating Pod (Egress Only) Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/pod.md Creates only an egress policy on the 'web' pod, allowing it to connect to 'redis' but not isolating 'redis' from other potential connections. ```typescript web.connections.allowTo(redis, { isolation: PodConnectionsIsolation.POD }); ``` -------------------------------- ### Create Volume from EmptyDir in TypeScript Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/volume.md Use this to create a temporary, initially empty volume for a pod. Data is preserved for the pod's lifecycle but lost when the pod is deleted. Mount it to a container using `mount()`. ```typescript import * as kplus from 'cdk8s-plus-34'; const data = kplus.Volume.fromEmptyDir(configMap); const pod = new kplus.Pod(this, 'Pod'); const redis = pod.addContainer({ image: 'redis' }) // mount to the redis container. redis.mount('/var/lib/redis', data); ``` -------------------------------- ### Expose Deployment via Service Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/deployment.md This snippet demonstrates how to create a Kubernetes Service that automatically selects pods managed by a cdk8s-plus Deployment, exposing them on a specified port. ```typescript // store the deployment to created in a constant const frontends = new kplus.Deployment(this, 'FrontEnds', { containers: [ { image: 'node', portNumber: 9000, } ], }); // create a ClusterIP service that listens on port 9000 and redirects to port 9000 on the containers. frontends.exposeViaService({ ports: [{ port: 9000, }] }); ``` -------------------------------- ### Import Kubernetes Spec Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/rotate.md Use this script to import a new Kubernetes version specification into the cdk8s repository. Provide the Kubernetes version number as an argument. ```sh tools/import-spec.sh x.xx.x # provide the new version number e.g. 1.25.0 ``` -------------------------------- ### Create Role and Add Rules Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/rbac.md Defines a Role with read/write permissions for Deployments and binds it to a user, group, and service account. ```typescript import * as kplus from 'cdk8s-plus-34'; import { Construct } from 'constructs'; import { App, Chart, ChartProps } from 'cdk8s'; export class MyChart extends Chart { constructor(scope: Construct, id: string, props: ChartProps = { }) { super(scope, id, props); // Creating RBAC Role const role = new kplus.Role(this, 'SampleRole'); // The convenience method here `allowReadWrite` would add // `get, list, watch, create, update, patch, delete, // deletecollection` rules to the role for deployment resources. role.allowReadWrite(kplus.ApiResource.DEPLOYMENTS); const user = kplus.User.fromName(this, 'SampleUser', 'Jane'); const group = kplus.Group.fromName(this, 'SampleGroup', 'sample-group'); const serviceAccount = new kplus.ServiceAccount(this, 'SampleServiceAccount'); // You can bind this role to a specific user, group or service account role.bind(user, group, serviceAccount); } } const app = new App(); new MyChart(app, 'rbac-docs'); app.synth(); ``` -------------------------------- ### Create a CronJob with a Predefined Schedule (Every Minute) Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/cronjob.md Creates a CronJob using the `Cron.everyMinute()` helper function for a concise way to schedule jobs to run every minute. This simplifies common scheduling needs. ```typescript new kplus.CronJob(this, 'CronJob', { containers: [{ image: 'databack/mysql-backup', }], // This would schedule jobs to be scheduled to run every minute schedule: Cron.everyMinute(), }); ``` -------------------------------- ### Create ConfigMap and Add Data Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/config-map.md Create a new ConfigMap and add key-value pairs to it. This is useful for storing simple configuration settings. ```typescript import * as kplus from 'cdk8s-plus-34'; import { Construct } from 'constructs'; import { App, Chart, ChartProps } from 'cdk8s'; export class MyChart extends Chart { constructor(scope: Construct, id: string, props?: ChartProps) { super(scope, id, props); const config = new kplus.ConfigMap(this, 'Config'); config.addData('url', 'https://my-endpoint:8080'); } } const app = new App(); new MyChart(app, 'ConfigMap'); app.synth(); ``` -------------------------------- ### Spread Redis and Web App Deployments and Colocate Them Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/deployment.md Ensures that both Redis and Web app deployments are spread across nodes, and that a web app pod always runs alongside a cache instance. This demonstrates both spreading and colocation strategies. ```typescript const redis = new kplus.Deployment(this, 'Redis', { containers: [{ image: 'redis' }], replicas: 3, }); const web = new kplus.Deployment(this, 'Web', { containers: [{ image: 'web' }], replicas: 3, }); // ensure redis is spread across all nodes redis.scheduling.spread({ topology: kplus.Topology.HOSTNAME }); // ensure web app is spread across all nodes web.scheduling.spread({ topology: kplus.Topology.HOSTNAME }); // ensure a web app pod always runs along side a cache instance web.scheduling.colocate(redis); ``` -------------------------------- ### Create Volume from ConfigMap in TypeScript Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/volume.md Use this to create a volume from an existing Kubernetes ConfigMap. Each key in the ConfigMap will become a file in the volume. ```typescript import * as kplus from 'cdk8s-plus-34'; const configMap = kplus.ConfigMap.fromConfigMapName('redis-config'); const configVolume = kplus.Volume.fromConfigMap(configMap); ``` -------------------------------- ### Simplified Pod Connections Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/network-policy.md Easily allow connections between managed pods using the `connections.allowTo` and `connections.allowFrom` methods. This simplifies bi-directional rule configuration. ```typescript import * as k from 'cdk8s'; import * as kplus from 'cdk8s-plus-34'; const app = new k.App(); const chart = new k.Chart(app, 'Chart'); const web = new kplus.Pod(chart, 'Web', { containers: [{ image: 'web' }], metadata: { namespace: 'n1' }, }); const redis = new kplus.Pod(chart, 'Redis', { containers: [{ image: 'redis', portNumber: 6379 }], metadata: { namespace: 'n2' }, }); web.connections.allowTo(redis); // or redis.connections.allowFrom(web); ``` -------------------------------- ### Select All Namespaces Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/namespace.md Retrieve all namespaces in the cluster using the `Namespaces.all()` method. This can be used to manage or query all available namespaces. ```typescript import * as kplus from 'cdk8s-plus-34'; const all = kplus.Namespaces.all(); ``` -------------------------------- ### Attract Pod to Nodes with Specific Labels Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/pod.md Configure a pod to be scheduled on nodes that match a given label query. This is a required attraction. ```typescript import * as k from 'cdk8s'; import * as kplus from 'cdk8s-plus-34'; const app = new k.App(); const chart = new k.Chart(app, 'Chart'); const redis = new kplus.Pod(chart, 'Redis', { containers: [{ image: 'redis' }] }); const highMemoryNodes = kplus.Node.labeled(kplus.NodeLabelQuery.is('memory', 'high')); redis.scheduling.attract(highMemoryNodes); ``` -------------------------------- ### Prefer Pod Scheduling on Nodes with Specific Labels Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/pod.md Configure a pod to prefer nodes matching a label query, with an adjustable weight for preference strength. This is a preferred attraction. ```typescript redis.scheduling.attract(highMemoryNodes, { weight: 50 }); ``` -------------------------------- ### Preferred Pod Separation with Weight Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/pod.md Requests a preference for 'Web' pod not to be scheduled on the same node as 'Redis', with a weight of 50. ```typescript web.scheduling.separate(redis, { weight: 50 }); ``` -------------------------------- ### Configure HPA with External Metrics Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/horizontal-pod-autoscaler.md Use this snippet to set up an HPA that scales based on an external metric, such as an SQS queue length. Ensure the label selector correctly identifies the target. ```typescript import * as kplus from 'cdk8s-plus-34'; const hpa = new kplus.HorizontalPodAutoscaler(chart, 'BookstoreWebsiteHpa', { target: bookstoreWebsite, maxReplicas: 10, metrics: [ kplus.Metric.external({ labelSelector: kplus.LabelSelector.of({ labels: { app: 'scraper' } }), name: 'sqs-queue', target: kplus.MetricTarget.averageUtilization(50), }), ], }); ``` -------------------------------- ### Create a Namespace Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/namespace.md Use the `Namespace` class to create a new namespace. If a name is not specified, cdk8s will auto-generate one. ```typescript import * as kplus from 'cdk8s-plus-34'; import * as k from 'cdk8s'; const app = new k.App(); const chart = new k.Chart(app, 'Chart'); const namespace = new kplus.Namespace(chart, 'BackOfficeNamespace'); ``` -------------------------------- ### Mutating Pod Spec in cdk8s+ Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/CONTRIBUTING.md Demonstrates how to mutate a Pod's spec after instantiation by adding volumes and containers. Primitive properties like 'replicas' are read-only. ```typescript import * as kplus from 'cdk8s-plus-17'; const pod = new kplus.Pod(parent, 'Pod', { replicas: 4 }); // mutating the pod spec with another volume pod.spec.addVolume(volume); // mutating the pod spec with another container pod.spec.addContainer(container); // returns the resolved value of "replicas" assert(pod.replicas === 4); ``` -------------------------------- ### Configure HPA Scaling Behavior (Scale Up/Down) Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/horizontal-pod-autoscaler.md Customize the scaling behavior of an HPA by defining stabilization windows and policies for both scale-up and scale-down operations. This allows fine-grained control over how quickly the number of pods changes. ```typescript const hpa = new kplus.HorizontalPodAutoscaler(chart, 'BookstoreWebsiteHpa', { target: bookstoreWebsite, maxReplicas: 10, scaleUp: { stabilizationWindow: 60, policies: [ kplus.PolicyType.pods(4), kplus.PolicyType.percent(200), ], }, scaleDown: { stabilizationWindow: 60, policies: [ kplus.PolicyType.pods(2), kplus.PolicyType.percent(100), ], }, }); ``` -------------------------------- ### Co-locate Pods with Preference and Specific Topology Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/pod.md Prefer co-location of pods with a specified weight and topology (e.g., ZONE). ```typescript web.scheduling.colocate(redis, { weight: 50, topology: kplus.Topology.ZONE }); ``` -------------------------------- ### Co-locate Pods on the Same Node (Required) Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/pod.md Require that the 'Web' pod be scheduled on the same node as the 'Redis' pod. This uses the default topology (HOSTNAME). ```typescript import * as k from 'cdk8s'; import * as kplus from 'cdk8s-plus-34'; const app = new k.App(); const chart = new k.Chart(app, 'Chart'); const redis = new kplus.Pod(chart, 'Redis', { containers: [{ image: 'redis' }] }); const web = new kplus.Pod(chart, 'Web', { containers: [{ image: 'web' }] }); web.scheduling.colocate(redis); ``` -------------------------------- ### Populate Environment Variables from a ConfigMap Source Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/container.md Populates environment variables in a container by copying all key-value pairs from a ConfigMap. ```typescript const pod = new kplus.Pod(this, 'Pod'); const cm = new kplus.ConfigMap(this, 'ConfigMap', { data: { key: 'value', } }); const container = pod.addContainer({ image: 'my-app' }); // this will add 'key=value' env variable at runtime. container.env.copyFrom(kplus.Env.fromConfigMap(cm)); ``` -------------------------------- ### Add Environment Variables to a Container Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/container.md Demonstrates adding environment variables to a container from static values, config maps, and secrets. ```typescript import * as kplus from 'cdk8s-plus-34'; import { Construct } from 'constructs'; import { App, Chart, ChartProps } from 'cdk8s'; export class MyChart extends Chart { constructor(scope: Construct, id: string, props: ChartProps = { }) { super(scope, id, props); const pod = new kplus.Pod(this, 'Pod'); const container = pod.addContainer({ image: 'my-app' }); // use a static value. container.env.addVariable('endpoint', kplus.EnvValue.fromValue('value')); // use a specific key from a config map. const backendsConfig = kplus.ConfigMap.fromConfigMapName(this, 'BackendConfig', 'backends'); container.env.addVariable('endpoint', kplus.EnvValue.fromConfigMap(backendsConfig, 'endpoint')); // use a specific key from a secret. const credentials = kplus.Secret.fromSecretName(this, 'Credentials', 'credentials'); container.env.addVariable('password', kplus.EnvValue.fromSecretValue({ secret: credentials, key: 'password' })); } } const app = new App(); new MyChart(app, 'container'); app.synth(); ``` -------------------------------- ### Create Network Policy with Ingress Rule Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/network-policy.md Defines a network policy with an ingress rule at instantiation, allowing traffic from a specific peer and port. An additional ingress rule can be added post-instantiation. ```typescript import * as k from 'cdk8s'; import * as kplus from 'cdk8s-plus-34'; const app = new k.App(); const chart = new k.Chart(app, 'Chart'); const web = new kplus.Pod(chart, 'Web', { containers: [{ image: 'web' }], }); const cache = new kplus.Pod(chart, 'Cache', { containers: [{ image: 'cache', portNumber: 6379 }], }); const db = new kplus.Pod(chart, 'DB', { containers: [{ image: 'db', portNumber: 6378 }], }); // create a policy with an ingress rule at instantiation const dbPolicy = new kplus.NetworkPolicy(chart, 'Policy', { selector: db, ingress: { rule: [{ peer: web, ports: [kplus.NetworkPolicyPort.tcp(6379)]}] }, }); // add an ingress rule post instantiation redis.addIngressRule(cache, [kplus.NetworkPolicyPort.tcp(6379)]); ``` -------------------------------- ### Apply a restart policy to a Pod Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/pod.md Specify the restart policy for a Pod. This can only be set at instantiation time. ```typescript import * as kplus from 'cdk8s-plus-34'; const app = new k.App(); const chart = new k.Chart(app, 'Chart'); const pod = new kplus.Pod(chart, 'Pod', { restartPolicy: kplus.RestartPolicy.NEVER, }); ``` -------------------------------- ### Update cdk8s-plus Version References Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/rotate.md Run these commands within the cdk8s-plus repository on the new branch to update version references in documentation and perform code generation. ```sh yarn projen yarn rotate # updates all version references in documenation yarn run import # codegen the k8s imports file based on the new schema. yarn build ``` -------------------------------- ### HorizontalPodAutoscaler with Object Metric Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/horizontal-pod-autoscaler.md Creates a HorizontalPodAutoscaler that scales based on a custom object metric, 'requests-per-second', associated with an Ingress object. The target average utilization is 50%, with a maximum of 10 replicas. ```typescript import * as kplus from 'cdk8s-plus-34'; const hpa = new kplus.HorizontalPodAutoscaler(chart, 'BookstoreWebsiteHpa', { target: bookstoreWebsite, maxReplicas: 10, metrics: [ kplus.Metric.object({ object: ingress, name: 'requests-per-second', target: kplus.MetricTarget.averageUtilization(50), }), ], }); ``` -------------------------------- ### Pod Separation by Zone Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/pod.md Configures separation between 'Web' and 'Redis' pods, preferring them not to be in the same zone, with a weight of 50. ```typescript web.scheduling.separate(redis, { weight: 50, topology: kplus.Topology.ZONE }); ``` -------------------------------- ### Create a CronJob with a Custom Schedule Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/cronjob.md Instantiates a CronJob with a custom cron schedule defined using the Cron class. Ensures jobs are scheduled according to the specified minute, hour, day, month, and weekday. ```typescript import * as kplus from 'cdk8s-plus-34'; import { Construct } from 'constructs'; import { App, Chart, ChartProps, Cron } from 'cdk8s'; export class MyChart extends Chart { constructor(scope: Construct, id: string, props: ChartProps = { }) { super(scope, id, props); new kplus.CronJob(this, 'CronJob', { containers: [{ image: 'databack/mysql-backup', }], // You can pass a custom cron schedule using our Cron class schedule: Cron.schedule({ minute: '*', hour: '*', day: '*', month: '*', weekDay: '*', }), }); } } const app = new App(); new MyChart(app, 'cronjob-readme'); app.synth(); ``` -------------------------------- ### Create New Branch for cdk8s-plus-go Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/rotate.md Create and publish a new Git branch in the cdk8s-plus-go repository for the new Kubernetes version. This branch will be used for subsequent development. ```sh git checkout -b k8s.xx # e.g. k8s.25 for version 1.25.0 git push --set-upstream origin k8s.xx ``` -------------------------------- ### Bi-directional Network Policy Across Namespaces Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/network-policy.md Configures egress and ingress rules for pods in different namespaces to allow communication. This involves creating separate network policies for each pod and adding rules to permit traffic. ```typescript import * as k from 'cdk8s'; import * as kplus from 'cdk8s-plus-34'; const app = new k.App(); const chart = new k.Chart(app, 'Chart'); const web = new kplus.Pod(chart, 'Web', { containers: [{ image: 'web' }], metadata: { namespace: 'n1' }, }); const redis = new kplus.Pod(chart, 'Redis', { containers: [{ image: 'redis', portNumber: 6379 }], metadata: { namespace: 'n2' }, }); const webPolicy = new kplus.NetworkPolicy(chart, 'WebPolicy', { selector: web, // must be created in the 'web' namespace so it can select it. metadata: { namespace: web.metadata.namespace } }); const redisPolicy = new kplus.NetworkPolicy(chart, 'RedisPolicy', { selector: redis, // must be created in the 'redis' namespace so it can select it. metadata: { namespace: redis.metadata.namespace } }); // allow the 'web' pod to initiate a connection to the 'redis' pod on port 6379 webPolicy.addEgressRule(redis, [kplus.NetworkPolicyPort.tcp(6379)]); // allow the 'redis' pod to accept a connection from the 'web' pod on port 6379 redis.addIngressRule(web, [kplus.NetworkPolicyPort.tcp(6379)]); ``` -------------------------------- ### Create Network Policy with Egress Rule Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/network-policy.md Defines a network policy with an egress rule at instantiation, allowing traffic to a specific peer and port. An additional egress rule can be added post-instantiation. ```typescript import * as k from 'cdk8s'; import * as kplus from 'cdk8s-plus-34'; const app = new k.App(); const chart = new k.Chart(app, 'Chart'); const web = new kplus.Pod(chart, 'Web', { containers: [{ image: 'web' }], }); const cache = new kplus.Pod(chart, 'Cache', { containers: [{ image: 'cache', portNumber: 6379 }], }); const db = new kplus.Pod(chart, 'DB', { containers: [{ image: 'db', portNumber: 6378 }], }); // create a policy with an egress rule at instantiation const webPolicy = new kplus.NetworkPolicy(chart, 'Policy', { selector: web, egress: { rules: [{ peer: cache, ports: [kplus.NetworkPolicyPort.tcp(6379)]}] }, }); // add an egress rule post instantiation webPolicy.addEgressRule(db, [kplus.NetworkPolicyPort.tcp(6378)]); ``` -------------------------------- ### Allow Web Pod to Connect to Redis Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/pod.md Allows the 'web' pod to connect to the 'redis' pod on its defined port (6379). Automatically creates egress policy on 'web' and ingress policy on 'redis'. ```typescript import * as k from 'cdk8s'; import * as kplus from 'cdk8s-plus-34'; const app = new k.App(); const chart = new k.Chart(app, 'Chart'); const redis = new kplus.Pod(chart, 'Redis', { containers: [{ image: 'redis', portNumber: 6379 }] }); const web = new kplus.Pod(chart, 'Web', { containers: [{ image: 'web' }] }); web.connections.allowTo(redis); ``` -------------------------------- ### Select Namespaces by Name Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/namespace.md Select a namespace by its name using the `Namespaces.select` method. This is often used for resource scheduling. ```typescript import * as kplus from 'cdk8s-plus-34'; const backoffice = kplus.Namespaces.select(this, 'Backoffice', { names: ['backoffice'] }); ``` -------------------------------- ### Define HTTP Ingress Rule with cdk8s+ Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/ingress.md Use this snippet to route HTTP requests from a specific URL prefix to a Kubernetes service. Ensure the service is exposed and the Ingress controller is configured. ```typescript import * as kplus from 'cdk8s-plus-34'; import { Construct } from 'constructs'; import { App, Chart, ChartProps } from 'cdk8s'; export class MyChart extends Chart { constructor(scope: Construct, id: string, props: ChartProps = { }) { super(scope, id, props); const helloDeployment = new kplus.Deployment(this, "Deployment", { containers: [ { image: 'hashicorp/http-echo', args: [ '-text', 'hello ingress' ], portNumber: 5678, } ] }); const helloService = helloDeployment.exposeViaService({ ports: [ { port: 5678, } ] }); const ingress = new kplus.Ingress(this, 'ingress'); ingress.addRule('/hello', kplus.IngressBackend.fromService(helloService)); } } const app = new App(); new MyChart(app, 'ingress'); app.synth(); ``` -------------------------------- ### Select Namespaces by Labels Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/namespace.md Select namespaces that have specific labels using the `Namespaces.select` method. This is useful for targeting resources with certain tags. ```typescript import * as kplus from 'cdk8s-plus-34'; const batch = kplus.Namespaces.select(this, 'Batch', { labels: { processing: 'batch'} }); ``` -------------------------------- ### Directly Mount PersistentVolume Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/pv.md Mounts a PersistentVolume directly onto a container. This implicitly reserves the volume and creates a PersistentVolumeClaim. ```typescript const vol = new kplus.AwsElasticBlockStorePersistentVolume(chart, 'Volume', { volumeId: 'vol1234' }); container.mount('/data', vol); ``` -------------------------------- ### Create AWS EBS PersistentVolume Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/pv.md Instantiates an existing AWS EBS volume as a Kubernetes PersistentVolume resource. Ensure the volumeId exists in AWS. This does not create a new volume. ```typescript import * as kplus from 'cdk8s-plus-34'; import * as cdk8s from 'cdk8s'; const vol = new kplus.AwsElasticBlockStorePersistentVolume(chart, 'Volume', { // must exist in aws volumeId: 'vol1234', // assign the volume to small-ebs storage class storageClassName: 'small-ebs', // what is the volume storage storage: cdk8s.Size.gibibytes(50), }); ``` -------------------------------- ### Mount a volume onto a container Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/pod.md Mounts a volume onto a specified path within a container. cdk8s+ automatically adds the volume to the pod definition when a container mounts it. ```typescript import * as kplus from 'cdk8s-plus-34'; const data = kplus.Volume.fromEmptyDir('data'); const pod = new kplus.Pod(chart, 'Pod'); const container = pod.addContainer({ image: 'image' }); // mount the volume onto the container. this is actually enough, and you // don't need to explicitly add the volume to the pod -- cdk8s+ will do that for you. container.mount('/data', data); ``` -------------------------------- ### Select Pods by labels Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/pod.md Selects all pods that have a specific label. This is often used in other cdk8s+ APIs for pod selection. ```typescript import * as kplus from 'cdk8s-plus-34'; const pods = kplus.Pods.select(this, 'Store', { labels: { app: 'store' }}); ``` -------------------------------- ### Create ClusterRole and Add Rules Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/rbac.md Defines a ClusterRole with read/write permissions for Nodes and a non-API resource '/healthz', then binds it to subjects. ```typescript // Creating RBAC ClusterRole const clusterRole = new kplus.ClusterRole(this, 'SampleClusterRole'); // Adding list of rules to the ClusterRole for 'Nodes' and 'URL' non-namespaced resource clusterRole.allowReadWrite(kplus.ApiResource.NODES, kplus.NonApiResource.of('/healthz')); const user = kplus.User.fromName(this, 'SampleUser', 'Jane'); const group = kplus.Group.fromName(this, 'SampleGroup', 'sample-group'); const serviceAccount = new kplus.ServiceAccount(this, 'SampleServiceAccount'); // You can bind this cluster role to a specific user, group or service account clusterRole.bind(user, group, serviceAccount); ``` -------------------------------- ### PersistentVolumeClaim Disabling Dynamic Provisioning Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/pvc.md Create a PersistentVolumeClaim with an empty string for `storageClassName` to disable dynamic provisioning. This requires a pre-existing PersistentVolume that is not assigned to any storage class. ```typescript const claim = new kplus.PersistentVolumeClaim(chart, 'Claim', { storage: cdk8s.Size.gibibytes(50), // disable dynamic provisioning storageClassName: "", }); ``` -------------------------------- ### Spread Redis Deployment Replicas by Hostname Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/deployment.md Ensures that each replica of the Redis deployment is scheduled on a different node. This is useful for high availability. ```typescript const redis = new kplus.Deployment(this, 'Redis', { containers: [{ image: 'redis' }], replicas: 3, }); redis.scheduling.spread({ topology: kplus.Topology.HOSTNAME }); ``` -------------------------------- ### Reference Existing ConfigMap Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/config-map.md Use this when you need to reference an existing ConfigMap by its name. This does not create a new ConfigMap resource. ```typescript import * as kplus from 'cdk8s-plus-34'; import { Construct } from 'constructs'; import { App, Chart, ChartProps } from 'cdk8s'; export class MyChart extends Chart { constructor(scope: Construct, id: string, props?: ChartProps) { super(scope, id, props); const config: kplus.IConfigMap = kplus.ConfigMap.fromConfigMapName(this, 'ConfigMap', 'config'); // the 'config' constant can later be used by API's that require an IConfigMap. // for example when creating a volume. kplus.Volume.fromConfigMap(this, 'Volume', config); } } const app = new App(); new MyChart(app, 'VolumeFromConfigMap'); app.synth(); ``` -------------------------------- ### PersistentVolumeClaim with Specific Storage Class Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/pvc.md Create a PersistentVolumeClaim requesting a specific storage class, 'large-ebs'. This ensures that Kubernetes uses the appropriate provisioner for the requested storage. ```typescript const claim = new kplus.PersistentVolumeClaim(chart, 'Claim', { storage: cdk8s.Size.gibibytes(50), storageClassName: 'large-ebs', }); ``` -------------------------------- ### Mount PersistentVolumeClaim Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/pv.md Mounts a volume onto a container using a PersistentVolumeClaim that has been reserved from a PersistentVolume. ```typescript container.mount('/data', kplus.Volume.fromPersistentVolumeClaim(claim)); ``` -------------------------------- ### Allow Redis Pod to Accept Connections from Web Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/pod.md Allows the 'redis' pod to accept connections from the 'web' pod on its defined port (6379). Automatically creates ingress policy on 'redis' and egress policy on 'web'. ```typescript import * as k from 'cdk8s'; import * as kplus from 'cdk8s-plus-34'; const app = new k.App(); const chart = new k.Chart(app, 'Chart'); const redis = new kplus.Pod(chart, 'Redis', { containers: [{ image: 'redis', portNumber: 6379 }] }); const web = new kplus.Pod(chart, 'Web', { containers: [{ image: 'web' }] }); redis.connections.allowFrom(web); ``` -------------------------------- ### Isolate Peer Pod (Ingress Only) Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/pod.md Creates only an ingress policy on the 'redis' pod, allowing 'web' to connect to it but not isolating 'web' from other potential egress connections. ```typescript web.connections.allowTo(redis, { isolation: PodConnectionsIsolation.PEER }); ``` -------------------------------- ### HorizontalPodAutoscaler with Resource CPU Metric Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/horizontal-pod-autoscaler.md Defines a HorizontalPodAutoscaler targeting a Deployment, configured to scale based on resource CPU utilization. The target average utilization is set to 70%, with a maximum of 10 replicas. ```typescript import * as kplus from 'cdk8s-plus-34'; const hpa = new kplus.HorizontalPodAutoscaler(chart, 'BookstoreWebsiteHpa', { target: bookstoreWebsite, maxReplicas: 10, metrics: [ kplus.Metric.resourceCpu(kplus.MetricTarget.averageUtilization(70)), ], }); ``` -------------------------------- ### Default Deny All Ingress Policy Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/network-policy.md Creates a network policy that denies all ingress traffic by default. This ensures that pods not explicitly allowed by other policies remain isolated for incoming connections. ```typescript import * as k from 'cdk8s'; import * as kplus from 'cdk8s-plus-34'; const app = new k.App(); const chart = new k.Chart(app, 'Chart'); new kplus.NetworkPolicy(chart, 'Policy', { ingress: { default: kplus.NetworkPolicyTrafficDefault.DENY }, }); ``` -------------------------------- ### Add Subjects to an Existing Role Binding Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/rbac.md Demonstrates how to add additional subjects (users, groups, or service accounts) to an existing Role binding. ```typescript const user = kplus.User.fromName(this, 'SampleUser', 'Jane'); const binding = role.bind(user); const anotherUser = kplus.User.fromName(this, 'AnotherSampleUser', 'James'); binding.addSubjects(anotherUser); ``` -------------------------------- ### Create ServiceAccount and Grant Secret Access Source: https://github.com/cdk8s-team/cdk8s-plus/blob/k8s-34/main/docs/plus/service-account.md Create a new ServiceAccount and grant it access to specific secrets. Ensure the necessary imports for cdk8s and cdk8s-plus are included. ```typescript import * as kplus from 'cdk8s-plus-34'; import * as k from 'cdk8s'; const app = new k.App(); const chart = new k.Chart(app, 'Chart'); const awsCreds = kplus.Secret.fromSecretName('aws-creds'); const awsService = new kplus.ServiceAccount(chart, 'AWS'); // give access to the aws creds secret. awsService.addSecret(awsCreds); ```