Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion Sources/ContainerK8s/Commands/K8sCreate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ public struct K8sCreate: AsyncParsableCommand {
@Option(name: .long, help: "Optional path to a CNI manifest to apply.")
var cni: String?

@Option(name: [.customLong("volume"), .short], help: "Bind mount a volume into the cluster node (format: [source:]destination[:options])")
var volumes: [String] = []

@Option(name: .customLong("mount"), help: "Add a mount to the cluster node (format: type=<>,source=<>,target=<>,readonly)")
var mounts: [String] = []

public func run() async throws {
LoggingSystem.bootstrap { _ in StderrLogHandler() }
let log = Logger(label: K8sHelper.pluginName)
Expand Down Expand Up @@ -95,7 +101,9 @@ public struct K8sCreate: AsyncParsableCommand {
registryScheme: registryFlags.scheme,
maxConcurrentDownloads: imageFetchFlags.maxConcurrentDownloads,
remove: remove,
fqdn: fqdn
fqdn: fqdn,
volumes: volumes,
mounts: mounts
)

progress.set(description: "Starting cluster")
Expand Down
12 changes: 9 additions & 3 deletions Sources/ContainerK8s/Provisioners/LinuxNodeProvisioner.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ public struct LinuxNodeProvisioner: NodeProvisioner {
private let maxConcurrentDownloads: Int
private let remove: Bool
private let fqdn: String?
private let volumes: [String]
private let mounts: [String]

public init(
clusterName: String,
Expand All @@ -42,7 +44,9 @@ public struct LinuxNodeProvisioner: NodeProvisioner {
registryScheme: String = "https",
maxConcurrentDownloads: Int = 3,
remove: Bool = false,
fqdn: String? = nil
fqdn: String? = nil,
volumes: [String] = [],
mounts: [String] = []
) throws {
guard !roles.isEmpty else {
throw ContainerizationError(.invalidArgument, message: "LinuxNode roles must not be empty")
Expand All @@ -63,6 +67,8 @@ public struct LinuxNodeProvisioner: NodeProvisioner {
self.maxConcurrentDownloads = maxConcurrentDownloads
self.remove = remove
self.fqdn = fqdn
self.volumes = volumes
self.mounts = mounts
}

public func provision(name: String, log: Logger) async throws {
Expand Down Expand Up @@ -90,7 +96,7 @@ public struct LinuxNodeProvisioner: NodeProvisioner {
"\(ResourceLabelKeys.role)=\(roles.joined(separator: ","))",
],
maskedPaths: [],
mounts: [],
mounts: mounts,
name: name,
networks: [],
os: "linux",
Expand All @@ -107,7 +113,7 @@ public struct LinuxNodeProvisioner: NodeProvisioner {
tmpFs: [],
useInit: false,
virtualization: false,
volumes: []
volumes: volumes
)

let updatedResource = K8sHelper.defaultedResourceFlags(Flags.Resource(cpus: cpus, memory: memory))
Expand Down
13 changes: 12 additions & 1 deletion docs/command-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -1610,7 +1610,7 @@ Creates and starts a local Kubernetes cluster. Pulls the node image if needed, r
**Usage**

```bash
container k8s create [--name <name>] [--node-image <image>] [--cni <path>] [--rm] [<resource options>] [--debug]
container k8s create [--name <name>] [--node-image <image>] [--cni <path>] [--rm] [--volume <volume>] [--mount <mount>] [<resource options>] [--debug]
```

**Options**
Expand All @@ -1619,6 +1619,8 @@ container k8s create [--name <name>] [--node-image <image>] [--cni <path>] [--rm
* `--node-image <image>`: Node image reference (default: `docker.io/kindest/node:v1.35.5`)
* `--cni <path>`: Optional path to a CNI manifest to apply. If not provided, the bundled kindnet CNI is used.
* `--rm`: Remove the cluster container after it stops
* `--volume, -v <volume>`: Bind mount a host directory or named volume into the cluster node (format: `[source:]destination[:options]`, repeatable). Uses the same syntax as `container run --volume`.
* `--mount <mount>`: Add a mount to the cluster node (format: `type=<>,source=<>,target=<>,readonly`, repeatable). Uses the same syntax as `container run --mount`.

**Resource Options**

Expand Down Expand Up @@ -1647,6 +1649,15 @@ container k8s create --name temp-cluster --rm

# create a cluster using a custom CNI manifest instead of the bundled kindnet
container k8s create --cni ./my-cni.yaml

# create a cluster with a host directory bind-mounted into the node
container k8s create --volume /Users/me/data:/mnt/data

# create a cluster with a named, managed volume mounted read-only
container k8s create --volume mydata:/mnt/data:ro

# create a cluster with an explicit mount using type=/source=/target= syntax
container k8s create --mount type=bind,source=/Users/me/data,target=/mnt/data,readonly
```

### `container k8s start`
Expand Down