kube_cluster 0.3.2 → 0.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -0
  3. data/Gemfile.lock +20 -12
  4. data/examples/01-basic-redis-pod/Gemfile +5 -0
  5. data/examples/01-basic-redis-pod/README.md +30 -0
  6. data/examples/01-basic-redis-pod/bin/dev +8 -0
  7. data/examples/01-basic-redis-pod/docker-compose.yml +14 -0
  8. data/examples/01-basic-redis-pod/manifest.rb +1 -1
  9. data/examples/01-basic-redis-pod/redis.conf +2 -0
  10. data/examples/02-manifest-with-middleware/Dockerfile +19 -0
  11. data/examples/02-manifest-with-middleware/Gemfile +5 -0
  12. data/examples/02-manifest-with-middleware/README.md +34 -0
  13. data/examples/02-manifest-with-middleware/bin/dev +9 -0
  14. data/examples/02-manifest-with-middleware/config.ru +3 -0
  15. data/examples/02-manifest-with-middleware/docker-compose.yml +25 -0
  16. data/examples/02-manifest-with-middleware/falcon.rb +11 -0
  17. data/examples/02-manifest-with-middleware/manifest.rb +1 -1
  18. data/examples/02-manifest-with-middleware/registries.yaml +4 -0
  19. data/examples/03-app-with-database/Gemfile +5 -0
  20. data/examples/04-pod-with-ingress/Dockerfile +20 -0
  21. data/examples/04-pod-with-ingress/Gemfile +10 -0
  22. data/examples/04-pod-with-ingress/README.md +42 -0
  23. data/examples/04-pod-with-ingress/bin/dev +10 -0
  24. data/examples/04-pod-with-ingress/config.ru +3 -0
  25. data/examples/04-pod-with-ingress/docker-compose.yml +35 -0
  26. data/examples/04-pod-with-ingress/falcon.rb +11 -0
  27. data/examples/04-pod-with-ingress/manifest.rb +15 -0
  28. data/examples/04-pod-with-ingress/pod_with_ingress.rb +60 -0
  29. data/examples/04-pod-with-ingress/registries.yaml +4 -0
  30. data/examples/05-helm-chart-to-manifest/Gemfile +5 -0
  31. data/examples/05-helm-chart-to-manifest/README.md +44 -0
  32. data/examples/05-helm-chart-to-manifest/bin/dev +6 -0
  33. data/examples/05-helm-chart-to-manifest/docker-compose.yml +16 -0
  34. data/examples/05-helm-chart-to-manifest/manifest.rb +18 -0
  35. data/examples/06-nginx-with-cert-manager/Gemfile +5 -0
  36. data/examples/06-nginx-with-cert-manager/README.md +57 -0
  37. data/examples/06-nginx-with-cert-manager/bin/dev +6 -0
  38. data/examples/06-nginx-with-cert-manager/docker-compose.yml +16 -0
  39. data/examples/06-nginx-with-cert-manager/manifest.rb +45 -0
  40. data/examples/06-nginx-with-cert-manager/resources/namespace.rb +7 -0
  41. data/examples/06-nginx-with-cert-manager/resources/nginx.rb +156 -0
  42. data/examples/06-nginx-with-cert-manager/resources/self_signed_issuer.rb +11 -0
  43. data/examples/README.md +3 -0
  44. data/kube_cluster.gemspec +0 -1
  45. data/lib/kube/cluster/connection.rb +2 -1
  46. data/lib/kube/cluster/resource/extensions/README.md +15 -0
  47. data/lib/kube/cluster/resource/extensions/custom_resource_definition.rb +35 -0
  48. data/lib/kube/cluster/resource/persistence.rb +16 -3
  49. data/lib/kube/cluster/resource.rb +9 -0
  50. data/lib/kube/cluster/version.rb +1 -1
  51. data/lib/kube/cluster.rb +7 -4
  52. data/lib/kube/helm/chart.rb +203 -0
  53. data/lib/kube/helm/endpoint.rb +75 -0
  54. data/lib/kube/helm/repo.rb +121 -0
  55. metadata +44 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 143c409d80b81ee281ed0b8a11fcfedc2d1ae76aa15bae26cbf5a6a1e4d820df
4
- data.tar.gz: 8866e6cecdca078a5ceb6df8003b3c0433c915bf97ca0b9650e6d0e07a2decd6
3
+ metadata.gz: 0b71ea6fab00cdb1604ed20b2e243d9a07213354bbfd34a7a7223039a2291cc0
4
+ data.tar.gz: 5d81264cb2608fc78a24f81fa34117f7a2192a63f20952b7e1bd483aeb59e21c
5
5
  SHA512:
6
- metadata.gz: 8d35f3da0f04b39e204a4a2df015ce7723537d7cf08f3cecd30d6a2532ec1cb1ce7005ae00173e7549a6223ce7312b67353e3aa20dc4693fbf1f75f66bb0de43
7
- data.tar.gz: 497038c1324cff9eab76b0b15e1ab6e6cd91d88526af313db21bca45387b48efb2b35827f5320be8f13465a2b45c8b2a09880c66e36200ea5dccdcc8762d3863
6
+ metadata.gz: 54bb18e16d86e240ec4b58c62ee223dbf75aaec7c1597a04791111436dbb59b4b49a07f5e726326d1dd3d4cd0cc56b67fd5f631645645f730179074599753397
7
+ data.tar.gz: 11a41bf7917ed4972ddc00bbda95df024eb76d48d4c806d12bf0ac77f463688376a299f40c9666db3943d86746c7b5316f091853c2f1928e07f7f0858129e382
data/Gemfile CHANGED
@@ -3,3 +3,6 @@
3
3
  source "https://rubygems.org"
4
4
 
5
5
  gemspec
6
+
7
+ gem "kube_schema", path: "../schema"
8
+ gem "kube_kubectl", path: "../ctl"
data/Gemfile.lock CHANGED
@@ -1,8 +1,24 @@
1
+ PATH
2
+ remote: ../ctl
3
+ specs:
4
+ kube_kubectl (2.0.8)
5
+ debug (~> 1.11)
6
+ json_schemer (~> 2.5)
7
+ rubyshell (~> 1.5)
8
+ shellwords (~> 0.2.2)
9
+ string_builder (~> 1.2.0)
10
+
11
+ PATH
12
+ remote: ../schema
13
+ specs:
14
+ kube_schema (1.3.4)
15
+ json_schemer (~> 2.5.0)
16
+ rubyshell (~> 1.5.0)
17
+
1
18
  PATH
2
19
  remote: .
3
20
  specs:
4
- kube_cluster (0.3.1)
5
- kube_kit (> 0)
21
+ kube_cluster (0.3.4)
6
22
  kube_kubectl (~> 2.0.0)
7
23
  kube_schema (~> 1.3.0)
8
24
 
@@ -29,16 +45,6 @@ GEM
29
45
  hana (~> 1.3)
30
46
  regexp_parser (~> 2.0)
31
47
  simpleidn (~> 0.2)
32
- kube_kit (0.2.0)
33
- kube_kubectl (2.0.2)
34
- debug (~> 1.11)
35
- json_schemer (~> 2.5)
36
- rubyshell (~> 1.5)
37
- shellwords (~> 0.2.2)
38
- string_builder (~> 1.2.0)
39
- kube_schema (1.3.1)
40
- json_schemer (~> 2.5.0)
41
- rubyshell (~> 1.5.0)
42
48
  language_server-protocol (3.17.0.5)
43
49
  lint_roller (1.1.0)
44
50
  minitest (5.27.0)
@@ -94,6 +100,8 @@ PLATFORMS
94
100
 
95
101
  DEPENDENCIES
96
102
  kube_cluster!
103
+ kube_kubectl!
104
+ kube_schema!
97
105
  minitest (~> 5.0)
98
106
  rake (~> 13.0)
99
107
  rubocop (~> 1.21)
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "falcon", "~> 0.55.3"
@@ -0,0 +1,30 @@
1
+ # 01 — Basic Redis Pod
2
+
3
+ A single Redis pod defined with `Kube::Cluster['Pod']`, demonstrating the resource DSL and block overrides.
4
+
5
+ ## Prerequisites
6
+
7
+ - Docker (with Compose)
8
+ - `kubectl`
9
+ - `bundle install` (from project root)
10
+
11
+ ## Run
12
+
13
+ ```
14
+ bin/dev
15
+ ```
16
+
17
+ ## Verify
18
+
19
+ ```
20
+ kubectl logs my-redis-1
21
+ kubectl exec -it my-redis-1 -- redis-cli ping
22
+ ```
23
+
24
+ ## Files
25
+
26
+ | File | Purpose |
27
+ |---|---|
28
+ | `manifest.rb` | Defines `RedisPod` class and generates YAML |
29
+ | `redis.conf` | Redis config mounted into the pod |
30
+ | `docker-compose.yml` | Local k3s cluster |
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+
3
+ docker compose up -d
4
+
5
+ kubectl create configmap example-redis-config --from-file=redis.conf --dry-run=client -o yaml | kubectl apply -f -
6
+
7
+ bundle exec ruby manifest.rb > manifest.yaml
8
+ kubectl apply -f manifest.yaml
@@ -0,0 +1,14 @@
1
+ services:
2
+ cluster:
3
+ image: "rancher/k3s:latest"
4
+ command: server
5
+ privileged: true
6
+ restart: always
7
+ environment:
8
+ - K3S_TOKEN=change-me-or-face-the-consequences
9
+ - K3S_KUBECONFIG_OUTPUT=/output/kubeconfig.yaml
10
+ - K3S_KUBECONFIG_MODE=666
11
+ volumes:
12
+ - .:/output
13
+ ports:
14
+ - 6443:6443
@@ -3,7 +3,7 @@ require "kube/cluster"
3
3
 
4
4
  class RedisPod < Kube::Cluster['Pod']
5
5
  def initialize(container_name: 'my-redis-container', **options, &block)
6
- super(**options) {
6
+ super {
7
7
  spec.containers = [
8
8
  {
9
9
  name: container_name,
@@ -0,0 +1,2 @@
1
+ maxmemory 2mb
2
+ maxmemory-policy allkeys-lru
@@ -0,0 +1,19 @@
1
+ FROM ruby:3.4-slim
2
+
3
+ WORKDIR /app
4
+
5
+ RUN apt-get update -qq && \
6
+ apt-get install -y --no-install-recommends \
7
+ build-essential \
8
+ libyaml-dev \
9
+ libssl-dev \
10
+ pkg-config && \
11
+ rm -rf /var/lib/apt/lists/*
12
+
13
+ COPY Gemfile ./
14
+ RUN bundle install
15
+
16
+ COPY config.ru falcon.rb ./
17
+
18
+ EXPOSE 3000
19
+ CMD ["bundle", "exec", "falcon", "host"]
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "falcon", "~> 0.55.3"
@@ -0,0 +1,34 @@
1
+ # 02 — Manifest with Middleware
2
+
3
+ A full app deployment (Deployment, Service, Ingress, ConfigMap, HPA) assembled with `Kube::Cluster::Manifest` and transformed by middleware (Namespace, Labels).
4
+
5
+ ## Prerequisites
6
+
7
+ - Docker (with Compose)
8
+ - `kubectl`
9
+ - `bundle install` (from project root)
10
+
11
+ ## Run
12
+
13
+ ```
14
+ bin/dev
15
+ ```
16
+
17
+ ## Verify
18
+
19
+ ```
20
+ kubectl get pods -n my-app
21
+ kubectl logs -n my-app -l app=my-app
22
+ curl -H "Host: app.example.com" http://localhost
23
+ ```
24
+
25
+ ## Files
26
+
27
+ | File | Purpose |
28
+ |---|---|
29
+ | `manifest.rb` | Assembles resources and applies middleware |
30
+ | `templates/` | Resource classes (Deployment, Service, Ingress, ConfigMap, HPA) |
31
+ | `middleware/` | Namespace and Labels middleware |
32
+ | `config.ru` | Falcon hello-world app |
33
+ | `Dockerfile` | Container image |
34
+ | `docker-compose.yml` | Local k3s cluster + registry |
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env bash
2
+
3
+ docker compose up -d
4
+
5
+ docker build -t localhost:5000/my-app:latest .
6
+ docker push localhost:5000/my-app:latest
7
+
8
+ bundle exec ruby manifest.rb > manifest.yaml
9
+ kubectl apply -f manifest.yaml
@@ -0,0 +1,3 @@
1
+ run do |env|
2
+ [200, {'Content-Type' => 'text/plain'}, ['Hello, World!']]
3
+ end
@@ -0,0 +1,25 @@
1
+ services:
2
+ registry:
3
+ image: registry:2
4
+ ports:
5
+ - "5000:5000"
6
+ restart: unless-stopped
7
+
8
+ cluster:
9
+ image: "rancher/k3s:latest"
10
+ command: server
11
+ privileged: true
12
+ restart: always
13
+ environment:
14
+ - K3S_TOKEN=change-me-or-face-the-consequences
15
+ - K3S_KUBECONFIG_OUTPUT=/output/kubeconfig.yaml
16
+ - K3S_KUBECONFIG_MODE=666
17
+ volumes:
18
+ - .:/output
19
+ - ./registries.yaml:/etc/rancher/k3s/registries.yaml:ro
20
+ ports:
21
+ - 6443:6443
22
+ - 80:80
23
+ - 443:443
24
+ depends_on:
25
+ - registry
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env falcon-host
2
+
3
+ require "falcon/environment/rack"
4
+
5
+ service "rack" do
6
+ include Falcon::Environment::Rack
7
+
8
+ endpoint do
9
+ Async::HTTP::Endpoint.parse('http://0.0.0.0:3000')
10
+ end
11
+ end
@@ -3,7 +3,7 @@ require "kube/cluster"
3
3
 
4
4
  APP_NAME = "my-app"
5
5
  FULLNAME = "my-app"
6
- IMAGE = "my-app:latest"
6
+ IMAGE = "registry:5000/my-app:latest"
7
7
  MATCH_LABELS = { app: APP_NAME }
8
8
  STANDARD_LABELS = { app: APP_NAME, version: "1.0" }
9
9
  RESOURCES = { requests: { cpu: "100m", memory: "128Mi" }, limits: { cpu: "500m", memory: "256Mi" } }
@@ -0,0 +1,4 @@
1
+ mirrors:
2
+ "registry:5000":
3
+ endpoint:
4
+ - "http://registry:5000"
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "falcon", "~> 0.55.3"
@@ -0,0 +1,20 @@
1
+ FROM ruby:3.4-slim
2
+
3
+ WORKDIR /app
4
+
5
+ # Install build dependencies and OpenSSL headers
6
+ RUN apt-get update -qq && \
7
+ apt-get install -y --no-install-recommends \
8
+ build-essential \
9
+ libyaml-dev \
10
+ libssl-dev \
11
+ pkg-config && \
12
+ rm -rf /var/lib/apt/lists/*
13
+
14
+ COPY Gemfile Gemfile.lock ./
15
+ RUN bundle install
16
+
17
+ COPY . .
18
+
19
+ EXPOSE 3000
20
+ CMD ["bundle", "exec", "falcon", "host"]
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+
6
+ gem "metatron", "~> 0.11.3"
7
+ gem "falcon", "~> 0.55.3"
8
+ gem "logger", "~> 1.7"
9
+
10
+ gem "kube_cluster", "~> 0.3.2"
@@ -0,0 +1,42 @@
1
+ # 04 — Pod with Ingress
2
+
3
+ A hello-world Falcon app deployed as a Pod + Service + Ingress using `PodWithIngress`, a composite `Kube::Cluster::Manifest`.
4
+
5
+ ## Prerequisites
6
+
7
+ - Docker (with Compose)
8
+ - `kubectl`
9
+ - `bundle install`
10
+
11
+ ## Run
12
+
13
+ ```
14
+ bin/dev
15
+ ```
16
+
17
+ This starts a local k3s cluster with a container registry, builds and pushes the app image, generates the Kubernetes manifest from `manifest.rb`, and applies it.
18
+
19
+ ## Verify
20
+
21
+ ```
22
+ kubectl logs my-app
23
+ curl -H "Host: localhost" http://localhost
24
+ ```
25
+
26
+ ## What it does
27
+
28
+ `manifest.rb` produces three resources from a single `PodWithIngress` declaration:
29
+
30
+ - **Pod** — runs the Falcon hello-world server on port 3000
31
+ - **Service** — routes traffic to the pod
32
+ - **Ingress** — exposes the service at `http://localhost`
33
+
34
+ ## Files
35
+
36
+ | File | Purpose |
37
+ |---|---|
38
+ | `manifest.rb` | Generates Kubernetes YAML |
39
+ | `pod_with_ingress.rb` | Composite manifest: Pod + Service + Ingress |
40
+ | `config.ru` | Falcon rack app |
41
+ | `Dockerfile` | Container image |
42
+ | `docker-compose.yml` | Local k3s cluster + registry |
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env bash
2
+
3
+ docker compose up -d
4
+
5
+ docker build -t localhost:5000/myapp:v1 .
6
+ docker push localhost:5000/myapp:v1
7
+
8
+ kubectl delete pod my-app
9
+ bundle exec ruby manifest.rb > manifest.yaml
10
+ kubectl apply -f manifest.yaml
@@ -0,0 +1,3 @@
1
+ run do |env|
2
+ [200, {'Content-Type' => 'text/plain'}, ['Hello, World!']]
3
+ end
@@ -0,0 +1,35 @@
1
+ # to run define K3S_TOKEN, K3S_VERSION is optional, eg:
2
+ # K3S_TOKEN=${RANDOM}${RANDOM}${RANDOM} docker-compose up
3
+ services:
4
+ registry:
5
+ image: registry:2
6
+ ports:
7
+ - "5000:5000"
8
+ restart: unless-stopped
9
+
10
+ cluster:
11
+ image: "rancher/k3s:latest"
12
+ command: server
13
+ privileged: true
14
+ restart: always
15
+ environment:
16
+ - K3S_TOKEN=change-me-or-face-the-consequences
17
+ - K3S_KUBECONFIG_OUTPUT=/output/kubeconfig.yaml
18
+ - K3S_KUBECONFIG_MODE=666
19
+ volumes:
20
+ - .:/output
21
+ - ./registries.yaml:/etc/rancher/k3s/registries.yaml:ro
22
+ ports:
23
+ - 6443:6443 # Kubernetes API Server
24
+ - 80:80 # Ingress controller port 80
25
+ - 443:443 # Ingress controller port 443
26
+ depends_on:
27
+ - registry
28
+ #tmpfs:
29
+ # - /run
30
+ # - /var/run
31
+ #ulimits:
32
+ # nproc: 65535
33
+ # nofile:
34
+ # soft: 65535
35
+ # hard: 65535
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env falcon-host
2
+
3
+ require "falcon/environment/rack"
4
+
5
+ service "rack" do
6
+ include Falcon::Environment::Rack
7
+
8
+ endpoint do
9
+ Async::HTTP::Endpoint.parse('http://0.0.0.0:3000')
10
+ end
11
+ end
@@ -0,0 +1,15 @@
1
+ require "bundler/setup"
2
+ require "kube/cluster"
3
+
4
+ require_relative "pod_with_ingress"
5
+
6
+ manifest = Kube::Cluster::Manifest.new(
7
+ PodWithIngress.new(
8
+ name: "my-app",
9
+ image: "registry:5000/myapp:v1",
10
+ port: 3000,
11
+ host: "localhost",
12
+ ),
13
+ )
14
+
15
+ puts manifest.to_yaml
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ class PodWithIngress < Kube::Cluster::Manifest
4
+ def initialize(name:, image:, port:, host:, &block)
5
+ match_labels = { app: name }
6
+
7
+ super(
8
+ Kube::Cluster["Pod"].new {
9
+ metadata.name = name
10
+ metadata.labels = match_labels
11
+
12
+ spec.containers = [
13
+ {
14
+ name: name,
15
+ image: image,
16
+ imagePullPolicy: "Always",
17
+ ports: [
18
+ { name: "http", containerPort: port }
19
+ ],
20
+ }
21
+ ]
22
+ },
23
+
24
+ Kube::Cluster["Service"].new {
25
+ metadata.name = name
26
+
27
+ spec.selector = match_labels
28
+ spec.ports = [
29
+ { port: port, targetPort: "http" }
30
+ ]
31
+ },
32
+
33
+ Kube::Cluster["Ingress"].new {
34
+ metadata.name = name
35
+
36
+ spec.rules = [
37
+ {
38
+ host: host,
39
+ http: {
40
+ paths: [
41
+ {
42
+ path: "/",
43
+ pathType: "Prefix",
44
+ backend: {
45
+ service: {
46
+ name: name,
47
+ port: { number: port },
48
+ },
49
+ },
50
+ },
51
+ ],
52
+ },
53
+ },
54
+ ]
55
+ },
56
+ )
57
+
58
+ instance_exec(&block) if block
59
+ end
60
+ end
@@ -0,0 +1,4 @@
1
+ mirrors:
2
+ "registry:5000":
3
+ endpoint:
4
+ - "http://registry:5000"
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "kube_cluster", "~> 0.3.2"
@@ -0,0 +1,44 @@
1
+ # 05 — Helm Chart to Manifest
2
+
3
+ Fetches a Helm chart from a repository, renders it with custom values, and converts the output into typed Ruby `Kube::Schema::Resource` objects.
4
+
5
+ No running cluster is required — `helm template` renders everything locally.
6
+
7
+ ## Prerequisites
8
+
9
+ - `helm` CLI installed
10
+ - `bundle install`
11
+
12
+ ## Run
13
+
14
+ ```
15
+ bin/dev
16
+ ```
17
+
18
+ ## What it does
19
+
20
+ `manifest.rb` demonstrates the full Helm → Ruby pipeline:
21
+
22
+ 1. **Registers a Helm repo** — `Kube::Helm::Repo.new("bitnami", url: "...")`
23
+ 2. **Gets a chart reference** — `repo.chart("nginx", version: "18.1.0")`
24
+ 3. **Inspects default values** — `chart.show_values` returns a Ruby hash
25
+ 4. **Renders with custom values** — `chart.template(release:, namespace:, values:)` returns a `Kube::Schema::Manifest`
26
+ 5. **Iterates typed resources** — each item is a real `Resource` with `.kind`, `.metadata.name`, `.spec.replicas`, etc.
27
+ 6. **Applies middleware** — the rendered resources pass through the same middleware stack as hand-written resources
28
+ 7. **Writes YAML** — `manifest.write("manifest.yaml")`
29
+
30
+ ## OCI Registry Example
31
+
32
+ For OCI-based registries, no `repo.add` is needed:
33
+
34
+ ```ruby
35
+ repo = Kube::Helm::Repo.new("ghcr", url: "oci://ghcr.io/my-org/charts")
36
+ chart = repo.chart("my-app", version: "1.0.0")
37
+ manifest = chart.template(release: "my-app", namespace: "production")
38
+ ```
39
+
40
+ ## Files
41
+
42
+ | File | Purpose |
43
+ |---|---|
44
+ | `manifest.rb` | Fetches chart, renders with values, outputs YAML |
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env bash
2
+
3
+ docker compose up -d
4
+
5
+ bundle exec ruby manifest.rb
6
+ kubectl apply -f manifest.yaml
@@ -0,0 +1,16 @@
1
+ services:
2
+ cluster:
3
+ image: "rancher/k3s:latest"
4
+ command: server
5
+ privileged: true
6
+ restart: always
7
+ environment:
8
+ - K3S_TOKEN=change-me-or-face-the-consequences
9
+ - K3S_KUBECONFIG_OUTPUT=/output/kubeconfig.yaml
10
+ - K3S_KUBECONFIG_MODE=666
11
+ volumes:
12
+ - .:/output
13
+ ports:
14
+ - 6443:6443
15
+ - 80:80
16
+ - 443:443
@@ -0,0 +1,18 @@
1
+ require "bundler/setup"
2
+ require "kube/cluster"
3
+
4
+ # Helm Chart → Manifest
5
+ #
6
+ # Fetches the Bitnami nginx chart, renders it with values,
7
+ # and writes the result as YAML.
8
+
9
+ manifest =
10
+ Kube::Helm::Repo
11
+ .new("bitnami", url: "https://charts.bitnami.com/bitnami")
12
+ .fetch("nginx", version: "18.1.0")
13
+ .apply_values({
14
+ "replicaCount" => 3,
15
+ "service" => { "type" => "ClusterIP" },
16
+ })
17
+
18
+ puts manifest.to_yaml
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "kube_cluster", "~> 0.3.2"
@@ -0,0 +1,57 @@
1
+ # 06 — Nginx with cert-manager
2
+
3
+ Deploys a stock **nginx** Deployment (configured via ConfigMap) with a self-signed TLS certificate from **cert-manager**. Uses k3s's built-in Traefik as the ingress controller.
4
+
5
+ ## Architecture
6
+
7
+ ```
8
+ Internet
9
+
10
+
11
+ ┌─────────────────────────────────────┐
12
+ │ Traefik (k3s built-in) │ ← terminates TLS
13
+ └──────────────┬──────────────────────┘
14
+
15
+
16
+ ┌─────────────────────────────────────┐
17
+ │ Ingress → Service → Deployment │ ← nginx:1.27-alpine
18
+ │ nginx-app namespace │
19
+ └─────────────────────────────────────┘
20
+
21
+
22
+ ┌─────────────────────────────────────┐
23
+ │ cert-manager (Helm) │ ← provisions self-signed cert
24
+ │ ClusterIssuer (selfsigned) │
25
+ └─────────────────────────────────────┘
26
+ ```
27
+
28
+ ## Prerequisites
29
+
30
+ - Docker (with Compose)
31
+ - `helm` CLI installed
32
+ - `kubectl`
33
+ - `bundle install`
34
+
35
+ ## Run
36
+
37
+ ```
38
+ bin/dev
39
+ ```
40
+
41
+ ## Verify
42
+
43
+ ```
44
+ kubectl get pods -n nginx-app
45
+ kubectl get ingress -n nginx-app
46
+ kubectl get certificate -n nginx-app
47
+ curl -H "Host: app.example.com" http://localhost
48
+ ```
49
+
50
+ ## Files
51
+
52
+ | File | Purpose |
53
+ |---|---|
54
+ | `manifest.rb` | Assembles cert-manager chart + application resources |
55
+ | `nginx_app.rb` | `NginxApp` — Namespace + ConfigMap + Deployment + Service + Ingress |
56
+ | `self_signed_issuer.rb` | `SelfSignedIssuer` — self-signed ClusterIssuer |
57
+ | `docker-compose.yml` | Local k3s cluster |