Publish
1
.envrc
Normal file
|
@ -0,0 +1 @@
|
|||
use flake
|
4
.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
.direnv/
|
||||
result
|
||||
ideas.txt
|
||||
notes.txt
|
BIN
assets/cat-chewing-cable.jpg
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
assets/helm-example/base.png
Normal file
After Width: | Height: | Size: 215 KiB |
BIN
assets/helm-example/highlight.png
Normal file
After Width: | Height: | Size: 210 KiB |
BIN
assets/helm-example/watermark.png
Normal file
After Width: | Height: | Size: 430 KiB |
BIN
assets/helm.png
Normal file
After Width: | Height: | Size: 135 KiB |
BIN
assets/kubenix-example/base.png
Normal file
After Width: | Height: | Size: 276 KiB |
BIN
assets/kubenix-example/highlight1.png
Normal file
After Width: | Height: | Size: 281 KiB |
BIN
assets/kubenix-example/highlight2.png
Normal file
After Width: | Height: | Size: 284 KiB |
BIN
assets/kubenix-example/highlight3.png
Normal file
After Width: | Height: | Size: 281 KiB |
BIN
assets/kubenix-example/highlight4.png
Normal file
After Width: | Height: | Size: 283 KiB |
BIN
assets/kubenix-github.png
Normal file
After Width: | Height: | Size: 182 KiB |
162
assets/kubenix.svg
Normal file
|
@ -0,0 +1,162 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="722.8457"
|
||||
height="701.96637"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
|
||||
sodipodi:docname="logo2.svg"
|
||||
inkscape:export-filename="/home/thockin/src/kubernetes/new.png"
|
||||
inkscape:export-xdpi="460.95001"
|
||||
inkscape:export-ydpi="460.95001"
|
||||
xml:space="preserve"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"><defs
|
||||
id="defs4"><linearGradient
|
||||
inkscape:collect="always"
|
||||
id="main"><stop
|
||||
style="stop-color:#ffffff;stop-opacity:0"
|
||||
offset="0"
|
||||
id="stop915" /><stop
|
||||
id="stop917"
|
||||
offset="0.23168644"
|
||||
style="stop-color:#ffffff;stop-opacity:1" /><stop
|
||||
style="stop-color:#ffffff;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop919" /></linearGradient><linearGradient
|
||||
y2="880.37714"
|
||||
x2="-414.38654"
|
||||
y1="782.33563"
|
||||
x1="-584.19934"
|
||||
gradientTransform="translate(864.69589,-1491.3405)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient1299"
|
||||
xlink:href="#main"
|
||||
inkscape:collect="always" /><linearGradient
|
||||
y2="460.51822"
|
||||
x2="389.57562"
|
||||
y1="351.41116"
|
||||
x1="200.59668"
|
||||
gradientTransform="translate(210.82018,-765.27605)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient1713"
|
||||
xlink:href="#main"
|
||||
inkscape:collect="always" /></defs><sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.69351872"
|
||||
inkscape:cx="390.03994"
|
||||
inkscape:cy="303.52461"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="g3052"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1248"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:snap-global="false"
|
||||
fit-margin-top="10"
|
||||
fit-margin-left="10"
|
||||
fit-margin-right="10"
|
||||
fit-margin-bottom="10"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1" /><metadata
|
||||
id="metadata7"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-6.3260942,-174.7524)"><g
|
||||
id="g3052"><path
|
||||
style="fill:#326ce5;fill-opacity:1;stroke:#ffffff;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 365.31239,184.81252 a 46.724621,46.342246 0 0 0 -17.90625,4.53125 l -244.34375,116.75 a 46.724621,46.342246 0 0 0 -25.281248,31.4375 l -60.28125,262.25 a 46.724621,46.342246 0 0 0 6.34375,35.53125 46.724621,46.342246 0 0 0 2.65625,3.6875 L 195.62489,849.28127 a 46.724621,46.342246 0 0 0 36.53125,17.4375 l 271.21875,-0.0625 a 46.724621,46.342246 0 0 0 36.53125,-17.40625 l 169.0625,-210.3125 a 46.724621,46.342246 0 0 0 9.03125,-39.21875 l -60.375,-262.25 a 46.724621,46.342246 0 0 0 -25.28125,-31.4375 l -244.375,-116.6875 a 46.724621,46.342246 0 0 0 -22.65625,-4.53125 z"
|
||||
id="path3055"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:export-filename="new.png"
|
||||
inkscape:export-xdpi="250.55"
|
||||
inkscape:export-ydpi="250.55" /><g
|
||||
id="g321"
|
||||
transform="matrix(1.0666666,0,0,1.0666666,100.31931,303.73558)"><g
|
||||
style="display:none"
|
||||
transform="matrix(0.09048806,0,0,0.09048806,-14.15991,84.454917)"
|
||||
inkscape:label="(pdf) background"
|
||||
id="layer1-3"><rect
|
||||
y="-2102.4253"
|
||||
x="-1045.6049"
|
||||
height="7145.4614"
|
||||
width="7947.0356"
|
||||
id="rect995"
|
||||
style="opacity:1;fill:#040404;fill-opacity:1;stroke-width:10.3605" /></g><g
|
||||
transform="translate(-156.48372,537.56136)"
|
||||
style="display:inline;opacity:1"
|
||||
inkscape:label="gradient-logo"
|
||||
id="layer3"><g
|
||||
style="stroke-width:11.0512"
|
||||
transform="matrix(0.09048806,0,0,0.09048806,142.32381,-453.10644)"
|
||||
id="g955"><g
|
||||
transform="matrix(11.047619,0,0,11.047619,-1572.2888,9377.7107)"
|
||||
id="g869"><g
|
||||
transform="rotate(-60,226.35754,-449.37199)"
|
||||
id="g932"
|
||||
style="stroke-width:11.0512"><path
|
||||
sodipodi:nodetypes="cccccccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3336-6"
|
||||
d="m 449.71876,-420.51322 122.19683,211.67512 -56.15706,0.5268 -32.6236,-56.8692 -32.85645,56.5653 -27.90237,-0.011 -14.29086,-24.6896 46.81047,-80.4901 -33.22946,-57.8257 z"
|
||||
style="opacity:1;fill:url(#linearGradient1713);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:33.1535;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /></g><path
|
||||
sodipodi:nodetypes="cccccccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4260-0"
|
||||
d="m 309.54892,-710.38827 122.19683,211.67512 -56.15706,0.5268 -32.6236,-56.8692 -32.85645,56.5653 -27.90237,-0.011 -14.29086,-24.6896 46.81047,-80.4901 -33.22946,-57.8256 z"
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#linearGradient1299);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:33.1535;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /><use
|
||||
x="0"
|
||||
y="0"
|
||||
xlink:href="#path3336-6"
|
||||
inkscape:transform-center-x="124.43045"
|
||||
inkscape:transform-center-y="151.59082"
|
||||
id="use3439-6"
|
||||
transform="rotate(60,728.23563,-692.24036)"
|
||||
width="100%"
|
||||
height="100%"
|
||||
style="stroke-width:11.0512" /><use
|
||||
x="0"
|
||||
y="0"
|
||||
xlink:href="#path3336-6"
|
||||
inkscape:transform-center-x="59.669705"
|
||||
inkscape:transform-center-y="-139.94592"
|
||||
id="use3449-5"
|
||||
transform="rotate(180,477.5036,-570.81898)"
|
||||
width="100%"
|
||||
height="100%"
|
||||
style="stroke-width:11.0512" /><use
|
||||
style="display:inline;stroke-width:11.0512"
|
||||
x="0"
|
||||
y="0"
|
||||
xlink:href="#path4260-0"
|
||||
id="use4354-5"
|
||||
transform="rotate(120,407.33916,-716.08356)"
|
||||
width="100%"
|
||||
height="100%" /><use
|
||||
style="display:inline;stroke-width:11.0512"
|
||||
x="0"
|
||||
y="0"
|
||||
xlink:href="#path4260-0"
|
||||
id="use4362-2"
|
||||
transform="rotate(-120,407.28823,-715.86995)"
|
||||
width="100%"
|
||||
height="100%" /></g></g></g></g></g></g></svg>
|
After Width: | Height: | Size: 7.8 KiB |
BIN
assets/kubernetes.png
Normal file
After Width: | Height: | Size: 239 KiB |
BIN
assets/me.jpg
Normal file
After Width: | Height: | Size: 1.6 MiB |
BIN
assets/nix-snapshotter.png
Normal file
After Width: | Height: | Size: 298 KiB |
BIN
assets/nixng.png
Normal file
After Width: | Height: | Size: 284 KiB |
BIN
assets/openapi-spec-example/base.png
Normal file
After Width: | Height: | Size: 156 KiB |
BIN
assets/openapi-spec-example/highlight1.png
Normal file
After Width: | Height: | Size: 157 KiB |
BIN
assets/openapi-spec-example/highlight2.png
Normal file
After Width: | Height: | Size: 157 KiB |
BIN
assets/openapi-spec-gen.png
Normal file
After Width: | Height: | Size: 52 KiB |
BIN
assets/self-hosting/highlight.png
Normal file
After Width: | Height: | Size: 443 KiB |
BIN
assets/self-hosting/logos.png
Normal file
After Width: | Height: | Size: 360 KiB |
BIN
assets/self-hosting/logos.xcf
Normal file
BIN
assets/servers-k8s-kill.jpg
Normal file
After Width: | Height: | Size: 576 KiB |
BIN
assets/servers-k8s-revive.jpg
Normal file
After Width: | Height: | Size: 580 KiB |
BIN
assets/servers-k8s.jpg
Normal file
After Width: | Height: | Size: 595 KiB |
BIN
assets/servers-kill.jpg
Normal file
After Width: | Height: | Size: 609 KiB |
BIN
assets/servers-services.jpg
Normal file
After Width: | Height: | Size: 635 KiB |
BIN
assets/servers.jpg
Normal file
After Width: | Height: | Size: 1.2 MiB |
BIN
assets/servers.jpg-autosave.kra
Normal file
BIN
assets/yaml-manifest/base.png
Normal file
After Width: | Height: | Size: 104 KiB |
BIN
assets/yaml-manifest/highlight1.png
Normal file
After Width: | Height: | Size: 104 KiB |
BIN
assets/yaml-manifest/highlight2.png
Normal file
After Width: | Height: | Size: 106 KiB |
BIN
assets/yaml-manifest/highlight3.png
Normal file
After Width: | Height: | Size: 108 KiB |
27
flake.lock
Normal file
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"nodes": {
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1730200266,
|
||||
"narHash": "sha256-l253w0XMT8nWHGXuXqyiIC/bMvh1VRszGXgdpQlfhvU=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "807e9154dcb16384b1b765ebe9cd2bba2ac287fd",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
36
flake.nix
Normal file
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
description = "Presentation for NixCon 2024";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs }:
|
||||
let
|
||||
supportedSystems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ];
|
||||
forEachSupportedSystem = f: nixpkgs.lib.genAttrs supportedSystems (system: f {
|
||||
pkgs = import nixpkgs { inherit system; };
|
||||
});
|
||||
in
|
||||
{
|
||||
packages = forEachSupportedSystem ({ pkgs }: {
|
||||
default = pkgs.stdenv.mkDerivation {
|
||||
name = "nixcon-2024-slides";
|
||||
buildInputs = with pkgs; [ marp-cli ];
|
||||
src = self;
|
||||
dontUnpack = true;
|
||||
|
||||
buildPhase = ''
|
||||
marp $src --output $out/presentation.html --html
|
||||
cp -r $src/assets $out/assets
|
||||
'';
|
||||
};
|
||||
});
|
||||
|
||||
devShells = forEachSupportedSystem ({ pkgs }: {
|
||||
default = pkgs.mkShell {
|
||||
packages = with pkgs; [ marp-cli ];
|
||||
};
|
||||
});
|
||||
};
|
||||
}
|
487
presentation.md
Normal file
|
@ -0,0 +1,487 @@
|
|||
---
|
||||
marp: true
|
||||
theme: gaia
|
||||
paginate: true
|
||||
footer: "October 26th, 2024"
|
||||
---
|
||||
|
||||
# Kubenix: Leveraging NixOS modules to generate Kubernetes manifests
|
||||
|
||||
![bg right:35% 100% Kubenix logo](assets/kubenix.svg)
|
||||
|
||||
**Pim Kunis**
|
||||
|
||||
---
|
||||
|
||||
# Agenda
|
||||
|
||||
![bg right:60% 80%](assets/kubenix-github.png)
|
||||
|
||||
|
||||
1. My background
|
||||
2. Kubernetes
|
||||
3. Kubenix
|
||||
|
||||
---
|
||||
|
||||
# `$ whoami`
|
||||
|
||||
![bg right 60% drop-shadow:0,5px,10px,rgba(0,0,0,.7)](assets/me.jpg)
|
||||
|
||||
- Pim Kunis
|
||||
- Matrix: @pim:envs.net
|
||||
- GitHub: @pizzapim
|
||||
- Consultant @ [Sue](https://sue.nl)
|
||||
- Currently doing Linux + Ansible stuff
|
||||
- Relatively new to Nix
|
||||
- Avid self-hoster
|
||||
|
||||
---
|
||||
|
||||
# Self-hosting
|
||||
|
||||
![bg Logos of services I self-host](assets/self-hosting/logos.png)
|
||||
|
||||
---
|
||||
|
||||
# Self-hosting
|
||||
|
||||
3 mini PCs (Gigabyte Brix with Intel Celeron J4105)
|
||||
|
||||
![w:900 My servers in their closet](assets/servers-services.jpg)
|
||||
|
||||
---
|
||||
|
||||
# NixOS for a cluster?
|
||||
|
||||
![w:900 My servers in their closet](assets/servers-kill.jpg)
|
||||
|
||||
---
|
||||
|
||||
# NixOS for a cluster?
|
||||
|
||||
![bg right assets/cat-chewing-cable.jpg](assets/cat-chewing-cable.jpg)
|
||||
|
||||
- Balance services
|
||||
- Maintenance
|
||||
- Services are tied to a particular host
|
||||
- Pets vs cattle
|
||||
|
||||
---
|
||||
|
||||
# Agenda
|
||||
|
||||
1. My background
|
||||
2. **Kubernetes**
|
||||
3. Kubenix
|
||||
|
||||
---
|
||||
|
||||
# Enter: Kubernetes
|
||||
|
||||
![bg left:40% 100% assets/cat-chewing-cable.jpg](assets/kubernetes.png)
|
||||
|
||||
- Abstracts infrastructure
|
||||
- Container orchestration
|
||||
- Workloads are containers (pods)
|
||||
- Distributed state (etcd)
|
||||
- Actual state
|
||||
- Desired state
|
||||
- Reconciliation
|
||||
|
||||
---
|
||||
|
||||
# Kubernetes
|
||||
|
||||
![w:900 My servers in their closet](assets/servers-k8s.jpg)
|
||||
|
||||
---
|
||||
|
||||
# Kubernetes
|
||||
|
||||
![w:900 My servers in their closet](assets/servers-k8s-kill.jpg)
|
||||
|
||||
---
|
||||
|
||||
# Kubernetes
|
||||
|
||||
![w:900 My servers in their closet](assets/servers-k8s-revive.jpg)
|
||||
|
||||
---
|
||||
|
||||
# Mutating state in Kubernetes
|
||||
|
||||
![bg 80% hi](assets/yaml-manifest/base.png)
|
||||
|
||||
---
|
||||
|
||||
# Mutating state in Kubernetes
|
||||
|
||||
![bg 80% hi](assets/yaml-manifest/highlight1.png)
|
||||
|
||||
---
|
||||
|
||||
# Mutating state in Kubernetes
|
||||
|
||||
![bg 80% hi](assets/yaml-manifest/highlight2.png)
|
||||
|
||||
---
|
||||
|
||||
# Mutating state in Kubernetes
|
||||
|
||||
![bg 80% hi](assets/yaml-manifest/highlight3.png)
|
||||
|
||||
---
|
||||
|
||||
# Helm
|
||||
|
||||
![bg right:50% 60%](assets/helm.png)
|
||||
|
||||
- Package manager
|
||||
- Templating YAML
|
||||
- Cursed
|
||||
|
||||
---
|
||||
|
||||
# Helm
|
||||
|
||||
|
||||
![bg 80% hi](assets/helm-example/base.png)
|
||||
|
||||
---
|
||||
|
||||
# Helm
|
||||
|
||||
|
||||
![bg 80% hi](assets/helm-example/highlight.png)
|
||||
|
||||
---
|
||||
|
||||
# Helm
|
||||
|
||||
![bg 80% hi](assets/helm-example/watermark.png)
|
||||
|
||||
---
|
||||
|
||||
# Agenda
|
||||
|
||||
1. My background
|
||||
2. Kubernetes
|
||||
3. **Kubenix**
|
||||
|
||||
---
|
||||
|
||||
# Kubenix ✨
|
||||
|
||||
- Generate manifests using NixOS modules!
|
||||
- Benefits:
|
||||
- No ugly YAML templates
|
||||
- Functional language
|
||||
- Type and structure checking
|
||||
- Modularity
|
||||
|
||||
---
|
||||
|
||||
# How Kubenix works
|
||||
|
||||
1. My background
|
||||
2. Kubernetes
|
||||
3. **Kubenix**
|
||||
- **OpenAPI specification**
|
||||
- Generate NixOS module
|
||||
- Use generated module
|
||||
- Generate manifest
|
||||
|
||||
---
|
||||
|
||||
|
||||
# The OpenAPI spec
|
||||
|
||||
- Standard for describing APIs
|
||||
- YAML or JSON
|
||||
- Specifies how to interact with Kubernetes API
|
||||
|
||||
---
|
||||
|
||||
# The OpenAPI spec
|
||||
|
||||
|
||||
![bg 75% hi](assets/openapi-spec-example/base.png)
|
||||
|
||||
---
|
||||
|
||||
# The OpenAPI spec
|
||||
|
||||
![bg 75% hi](assets/openapi-spec-example/highlight1.png)
|
||||
|
||||
---
|
||||
|
||||
# The OpenAPI spec
|
||||
|
||||
![bg 75% hi](assets/openapi-spec-example/highlight2.png)
|
||||
|
||||
---
|
||||
|
||||
# How Kubenix works
|
||||
|
||||
1. My background
|
||||
2. Kubernetes
|
||||
3. **Kubenix**
|
||||
- OpenAPI specification
|
||||
- **Generate NixOS module**
|
||||
- Use generated module
|
||||
- Generate manifest
|
||||
|
||||
---
|
||||
|
||||
# Generating the NixOS module
|
||||
|
||||
- Generate Nix code
|
||||
- Templating?
|
||||
|
||||
---
|
||||
|
||||
# Generating the NixOS module
|
||||
|
||||
```nix
|
||||
''
|
||||
definitions = {
|
||||
# Here we loop over each "definition"
|
||||
${concatStrings (mapAttrsToList (name: value: ''
|
||||
"${name}" = {
|
||||
${optionalString (hasAttr "options" value) "
|
||||
options = {${concatStrings (mapAttrsToList (name: value: ''
|
||||
"${name}" = ${value};
|
||||
'')
|
||||
value.options)}};
|
||||
"}
|
||||
|
||||
${optionalString (hasAttr "config" value) ''
|
||||
config = {${concatStrings (mapAttrsToList (name: value: ''
|
||||
"${name}" = ${value};
|
||||
'')
|
||||
value.config)}};
|
||||
''}
|
||||
};
|
||||
'')
|
||||
definitions)}
|
||||
};
|
||||
''
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# The generated NixOS module
|
||||
|
||||
```nix
|
||||
"io.k8s.api.core.v1.Pod" = {
|
||||
options = {
|
||||
"apiVersion" = mkOption {
|
||||
description = "...";
|
||||
type = (types.nullOr types.str);
|
||||
};
|
||||
"kind" = mkOption {
|
||||
description = "...";
|
||||
type = (types.nullOr types.str);
|
||||
};
|
||||
"metadata" = mkOption {
|
||||
description = "...";
|
||||
type = (types.nullOr (submoduleOf "io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta"));
|
||||
};
|
||||
"spec" = mkOption {
|
||||
description = "...";
|
||||
type = (types.nullOr (submoduleOf "io.k8s.api.core.v1.PodSpec"));
|
||||
};
|
||||
"status" = mkOption {
|
||||
description = "...";
|
||||
type = (types.nullOr (submoduleOf "io.k8s.api.core.v1.PodStatus"));
|
||||
};
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# How Kubenix works
|
||||
|
||||
1. My background
|
||||
2. Kubernetes
|
||||
3. **Kubenix**
|
||||
- OpenAPI specification
|
||||
- Generate NixOS module
|
||||
- **Use generated module**
|
||||
- Generate manifest
|
||||
|
||||
---
|
||||
|
||||
# Using the module
|
||||
|
||||
![bg 70% hi](assets/kubenix-example/base.png)
|
||||
|
||||
---
|
||||
|
||||
# Using the module
|
||||
|
||||
![bg 70% hi](assets/kubenix-example/highlight1.png)
|
||||
|
||||
---
|
||||
|
||||
# Using the module
|
||||
|
||||
![bg 70% hi](assets/kubenix-example/highlight2.png)
|
||||
|
||||
---
|
||||
|
||||
# Using the module
|
||||
|
||||
![bg 70% hi](assets/kubenix-example/highlight3.png)
|
||||
|
||||
---
|
||||
|
||||
# Using the module
|
||||
|
||||
![bg 70% hi](assets/kubenix-example/highlight4.png)
|
||||
|
||||
---
|
||||
|
||||
# Example of type checking
|
||||
|
||||
```nix
|
||||
{
|
||||
kubernetes.resources.pods.example-pod = {
|
||||
spec.containers.jellyfin-container = {
|
||||
image = "jellyfin/jellyfin:latest";
|
||||
ports = [{ containerPort = "foo"; }];
|
||||
};
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
```
|
||||
error: A definition for option `kubernetes.(...).containerPort' is not of type `signed integer'.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# An undefined option
|
||||
|
||||
```nix
|
||||
{
|
||||
kubernetes.resources = {
|
||||
foo.bar = "baz";
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
error: The option `kubernetes.api.resources.foo' does not exist.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# How Kubenix works
|
||||
|
||||
1. My background
|
||||
2. Kubernetes
|
||||
3. **Kubenix**
|
||||
- OpenAPI specification
|
||||
- Generate NixOS module
|
||||
- Use generated module
|
||||
- **Generate manifest**
|
||||
|
||||
---
|
||||
|
||||
# `kubenix.evalModules`
|
||||
|
||||
```nix
|
||||
{
|
||||
inputs.kubenix.url = "github:hall/kubenix";
|
||||
outputs = {self, kubenix, ... }@inputs: let
|
||||
system = "x86_64-linux";
|
||||
in {
|
||||
packages.${system}.default = (kubenix.evalModules.${system} {
|
||||
module = { kubenix, ... }: {
|
||||
imports = [ kubenix.modules.k8s ];
|
||||
kubernetes.resources.pods.example.spec.containers.jellyfin.image = "jellyfin/jellyfin:latest";
|
||||
};
|
||||
}).config.kubernetes.result;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# `kubenix.evalModules`
|
||||
|
||||
|
||||
```json
|
||||
{
|
||||
"apiVersion": "v1",
|
||||
"items": [
|
||||
{
|
||||
"apiVersion": "v1",
|
||||
"kind": "Pod",
|
||||
"metadata": {
|
||||
"annotations": {
|
||||
"kubenix/k8s-version": "1.30",
|
||||
"kubenix/project-name": "kubenix"
|
||||
},
|
||||
"labels": {
|
||||
"kubenix/hash": "84130bb6a26b9066eb2bdcaf2e68148a6e0648b0"
|
||||
},
|
||||
"name": "example"
|
||||
},
|
||||
"spec": {
|
||||
"containers": [
|
||||
{
|
||||
"image": "jellyfin/jellyfin:latest",
|
||||
"name": "jellyfin"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"kind": "List",
|
||||
"labels": {
|
||||
"kubenix/hash": "84130bb6a26b9066eb2bdcaf2e68148a6e0648b0",
|
||||
"kubenix/k8s-version": "1.30",
|
||||
"kubenix/project-name": "kubenix"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Summary
|
||||
|
||||
- Kubenix generates Kubernetes manifests
|
||||
- Converts OpenAPI spec to a NixOS module
|
||||
- Build Kubernetes deployments with:
|
||||
- No ugly YAML templates
|
||||
- Modularity
|
||||
- In a functional language
|
||||
- Type and structure checking
|
||||
|
||||
---
|
||||
|
||||
# Terraform: OpenAPI Provider Spec Generator
|
||||
|
||||
![hoi](assets/openapi-spec-gen.png)
|
||||
|
||||
---
|
||||
|
||||
# Bonus: nix-snapshotter
|
||||
|
||||
![bg right:50% 100%](assets/nix-snapshotter.png)
|
||||
|
||||
- Images are in Nix store
|
||||
- Fully declarative
|
||||
|
||||
---
|
||||
|
||||
# Bonus: NixNG
|
||||
|
||||
![bg right:50% 100%](assets/nixng.png)
|
||||
|
||||
- Nix~~OS~~ in a container
|
||||
- init-system independent
|