mirror of
https://git.sr.ht/~goorzhel/turboprop
synced 2024-12-14 11:37:37 +00:00
Continue writing README; add template
This commit is contained in:
parent
34e00f2b30
commit
a052d499df
5 changed files with 219 additions and 68 deletions
190
README.rst
190
README.rst
|
@ -22,22 +22,22 @@ Turboprop templates your Helm charts for you, making an individual Nix derivatio
|
||||||
Acknowledgments
|
Acknowledgments
|
||||||
***************
|
***************
|
||||||
|
|
||||||
Without `Vladimir Pouzanov`_'s "`Nix and Kubernetes\: Deployments Done Right`_" (and `its notes`_), this project would not exist.
|
- `Vladimir Pouzanov`_'s "`Nix and Kubernetes\: Deployments Done Right`_" (and `its notes`_) is the reason this project exists.
|
||||||
|
- Early on, I used `heywoodlh's Kubernetes flake`_ as a starting point.
|
||||||
I also used `heywoodlh's Kubernetes flake`_ as a starting point early on.
|
- Once I discovered `Haumea`_, Turboprop *really* started coming together.
|
||||||
|
|
||||||
.. _Vladimir Pouzanov: https://github.com/farcaller
|
.. _Vladimir Pouzanov: https://github.com/farcaller
|
||||||
.. _Nix and Kubernetes\: Deployments Done Right: https://media.ccc.de/v/nixcon-2023-35290-nix-and-kubernetes-deployments-done-right
|
.. _Nix and Kubernetes\: Deployments Done Right: https://media.ccc.de/v/nixcon-2023-35290-nix-and-kubernetes-deployments-done-right
|
||||||
.. _its notes: https://gist.github.com/farcaller/c87c03fbb55eaeaeb840b938455f37ff
|
.. _its notes: https://gist.github.com/farcaller/c87c03fbb55eaeaeb840b938455f37ff
|
||||||
.. _heywoodlh's Kubernetes flake: https://github.com/heywoodlh/flakes/blob/aa5a52a/kube/flake.nix
|
.. _heywoodlh's Kubernetes flake: https://github.com/heywoodlh/flakes/blob/aa5a52a/kube/flake.nix
|
||||||
|
.. _Haumea: https://github.com/nix-community/haumea
|
||||||
|
|
||||||
|
********
|
||||||
|
Tutorial
|
||||||
|
********
|
||||||
|
|
||||||
**********************
|
Installation
|
||||||
Usage and architecture
|
============
|
||||||
**********************
|
|
||||||
|
|
||||||
Getting started
|
|
||||||
===============
|
|
||||||
|
|
||||||
To start, add this flake to your flake's inputs, along with ``nixpkgs`` and ``flake-utils``:
|
To start, add this flake to your flake's inputs, along with ``nixpkgs`` and ``flake-utils``:
|
||||||
|
|
||||||
|
@ -64,17 +64,30 @@ Next, put it to use in your flake's output:
|
||||||
<...>
|
<...>
|
||||||
outputs = {self, nixpkgs, flake-utils, turboprop}:
|
outputs = {self, nixpkgs, flake-utils, turboprop}:
|
||||||
flake-utils.lib.eachDefaultSystem (system: let
|
flake-utils.lib.eachDefaultSystem (system: let
|
||||||
pkgs = import nixpkgs {
|
pkgs = import nixpkgs {inherit system;};
|
||||||
inherit system;
|
|
||||||
overlays = [devshell.overlays.default];
|
turbo = turboprop.lib.${system};
|
||||||
|
|
||||||
|
mkDerivation = turbo.mkDerivation {
|
||||||
|
user = {
|
||||||
|
# We'll get to this
|
||||||
|
app-template = turbo.app-template;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
t = turboprop.lib.${system};
|
|
||||||
|
|
||||||
mkDerivation = t.mkDerivation {};
|
|
||||||
in {
|
in {
|
||||||
packages.default = turbo.mkDerivation {
|
packages.default = let
|
||||||
# This too
|
pname = "my-k8s-flake";
|
||||||
|
in
|
||||||
|
mkDerivation {
|
||||||
|
inherit pname;
|
||||||
|
version = "rolling";
|
||||||
|
src = builtins.path {
|
||||||
|
path = ./.;
|
||||||
|
name = pname;
|
||||||
|
};
|
||||||
|
|
||||||
|
serviceRoot = ./services;
|
||||||
|
nsMetadata = {};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -115,14 +128,15 @@ This is a module that defines a *service derivation*:
|
||||||
spec.ca.secretName = user.vars.k8sCert.name;
|
spec.ca.secretName = user.vars.k8sCert.name;
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
1. The module takes as input:
|
1. The module takes as input:
|
||||||
|
|
||||||
#. A tree of *chart derivations*;
|
#. A tree of *chart derivations*;
|
||||||
#. the Turboprop library; and
|
#. the Turboprop library; and
|
||||||
#. user data specific to your flake. You may `omit any of these input variables`_ if they're not used.
|
#. the Nixpkgs for the current system (``pkgs``); and
|
||||||
|
#. user data specific to your flake. You may `omit any of these input variables`_.
|
||||||
|
|
||||||
2. The module has the output signature ``{builder, args, extraObjects}``.
|
2. The module has the output signature ``{builder, args, extraObjects}``.
|
||||||
|
|
||||||
|
@ -135,75 +149,89 @@ This is a module that defines a *service derivation*:
|
||||||
.. _single remote YAML file: https://git.sr.ht/~goorzhel/kubernetes/tree/f3cba6831621288228581b7ad7b6762d6d58a966/item/system/gateway-system/gateway-api/default.nix#L2
|
.. _single remote YAML file: https://git.sr.ht/~goorzhel/kubernetes/tree/f3cba6831621288228581b7ad7b6762d6d58a966/item/system/gateway-system/gateway-api/default.nix#L2
|
||||||
.. _define your own builder: https://git.sr.ht/~goorzhel/kubernetes/tree/f3cba6831621288228581b7ad7b6762d6d58a966/item/services/svc/breezewiki/default.nix#L6
|
.. _define your own builder: https://git.sr.ht/~goorzhel/kubernetes/tree/f3cba6831621288228581b7ad7b6762d6d58a966/item/services/svc/breezewiki/default.nix#L6
|
||||||
|
|
||||||
Trees of Nix modules
|
Creating a service tree
|
||||||
====================
|
=======================
|
||||||
|
|
||||||
Turboprop's operates on *trees* of Nix modules, both in the filesystem sense (nested directories) and the Nix sense (nested attrsets). A service tree, then, consists of
|
Turboprop operates on *trees* of Nix modules, both in the filesystem sense (nested directories) and the Nix sense (nested attrsets), and uses `Haumea`_ to do so. A service tree consists of
|
||||||
|
|
||||||
#. an arbitrarily-named root, such as ``./services``, which contains
|
#. an arbitrarily-named root, such as ``./services``, which contains
|
||||||
#. zero or more intermediate directories (we'll get to this), which each contain
|
#. zero or more intermediate directories (we'll get to this), which each contain
|
||||||
#. directories representing Kubernetes namespaces, which each contain
|
#. directories representing Kubernetes namespaces, which each contain
|
||||||
#. Nix modules representing a templated deployment.
|
#. Nix modules representing a templated deployment.
|
||||||
|
|
||||||
This metaphor extends to charts. Both Turboprop and nixhelm, from which Turboprop borrows heavily, contain a chart tree:
|
We'll start with building a flake containing two applications:
|
||||||
|
|
||||||
#. an arbitrarily-named root, ``./charts``, which contains
|
- the `Gateway API`_, and
|
||||||
#. directories representing Helm repositories, which each contain
|
- `Breezewiki`_ (through `app-template`_).
|
||||||
#. Nix modules representing a(n untemplated) chart.
|
|
||||||
|
|
||||||
In practice::
|
.. _Gateway API: https://gateway-api.sigs.k8s.io/
|
||||||
|
.. _Breezewiki: https://gateway-api.sigs.k8s.io/
|
||||||
|
.. _app-template: https://bjw-s.github.io/helm-charts/docs/app-template/
|
||||||
|
|
||||||
$ nix run nixpkgs#tree -- ~/src/kubernetes/{chart,service}s --noreport
|
Normally, one would also deploy a Gateway controller, but this suffices for the example.
|
||||||
/home/ag/src/kubernetes/charts
|
|
||||||
├── kubernetes-dashboard
|
|
||||||
│ └── kubernetes-dashboard
|
|
||||||
│ └── default.nix
|
|
||||||
<...>
|
|
||||||
/home/ag/src/kubernetes/services
|
|
||||||
<...>
|
|
||||||
├── istio-system
|
|
||||||
│ ├── 1-18-1
|
|
||||||
│ │ └── default.nix
|
|
||||||
│ └── kiali
|
|
||||||
│ └── default.nix
|
|
||||||
└── svc
|
|
||||||
├── breezewiki
|
|
||||||
│ └── default.nix
|
|
||||||
<...>
|
|
||||||
└── vaultwarden
|
|
||||||
└── default.nix
|
|
||||||
|
|
||||||
You may have noticed that, if neither Nixhelm nor Turboprop provide a chart you need, you may define it within your flake. (PRs welcome, though.)
|
.. code-block:: nix
|
||||||
|
|
||||||
Builders
|
# services/gateway-system/gateway-api/default.nix
|
||||||
===========================
|
{lib, ...}: {
|
||||||
|
builder = lib.builders.derivation;
|
||||||
|
args = {
|
||||||
|
src = lib.fetchers.remoteYAMLFile rec {
|
||||||
|
version = "1.0.0";
|
||||||
|
url = "https://github.com/kubernetes-sigs/gateway-api/releases/download/v${version}/experimental-install.yaml";
|
||||||
|
hash = "sha256-bGAdzteHKpQNdvpmeuEmunGMtMbblw0Lq0kSjswRkqM=";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
*Builders* are Nix functions that build a derivation, be it of a chart, a service, or a service's extra objects.
|
.. code-block:: nix
|
||||||
|
|
||||||
|
# services/default/breezewiki/default.nix
|
||||||
|
{charts, lib, user, ...}: {
|
||||||
|
builder = user.app-template.build;
|
||||||
|
args = {
|
||||||
|
mainImage = "quay.io/pussthecatorg/breezewiki:latest";
|
||||||
|
values = {
|
||||||
|
service.main.ports.http.port = 10416;
|
||||||
|
route.main = {
|
||||||
|
enabled = true;
|
||||||
|
hostnames = ["breezewiki.example.com"];
|
||||||
|
parentRefs = [
|
||||||
|
{
|
||||||
|
name = "gateway";
|
||||||
|
namespace = "default";
|
||||||
|
sectionName = "https";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
rules = [
|
||||||
|
{
|
||||||
|
backendRefs = [
|
||||||
|
{
|
||||||
|
name = "breezewiki";
|
||||||
|
namespace = "default";
|
||||||
|
port = 10416;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Ordering services by provided APIs
|
||||||
|
==================================
|
||||||
|
|
||||||
Services and system services
|
|
||||||
============================
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. TODO
|
|
||||||
- Helm cannot see your cluster from inside the sandbox.
|
|
||||||
- Custom APIs must be gathered and passed explicitly.
|
|
||||||
- This can't be done in one step due to infinite recursion.
|
|
||||||
|
|
||||||
Finally: your flake's output
|
|
||||||
============================
|
|
||||||
|
|
||||||
*********
|
*********
|
||||||
Reference
|
Reference
|
||||||
*********
|
*********
|
||||||
|
|
||||||
Utilities
|
Library
|
||||||
=========
|
=======
|
||||||
|
|
||||||
Charts
|
mkDerivation
|
||||||
======
|
------------
|
||||||
|
|
||||||
Turboprop overlays `its own charts`_ atop `Nixhelm's`_.
|
Turboprop overlays `its own charts`_ atop `Nixhelm's`_.
|
||||||
|
|
||||||
|
@ -211,6 +239,15 @@ Turboprop overlays `its own charts`_ atop `Nixhelm's`_.
|
||||||
.. _Nixhelm's: https://github.com/farcaller/nixhelm/tree/master/charts
|
.. _Nixhelm's: https://github.com/farcaller/nixhelm/tree/master/charts
|
||||||
|
|
||||||
|
|
||||||
|
app-template
|
||||||
|
------------
|
||||||
|
|
||||||
|
mkCharts
|
||||||
|
--------
|
||||||
|
|
||||||
|
mkChartsWithNixhelm
|
||||||
|
-------------------
|
||||||
|
|
||||||
Fetchers
|
Fetchers
|
||||||
========
|
========
|
||||||
|
|
||||||
|
@ -277,7 +314,7 @@ helmChart
|
||||||
Wrapped re-export of `kubelib.fromHelm`_ that sets ``metadata.namespace`` on all templated objects lacking it. As such, its signature is identical to `kubelib.buildHelmChart`_.
|
Wrapped re-export of `kubelib.fromHelm`_ that sets ``metadata.namespace`` on all templated objects lacking it. As such, its signature is identical to `kubelib.buildHelmChart`_.
|
||||||
|
|
||||||
- **chart** (derivation): The chart from which to build.
|
- **chart** (derivation): The chart from which to build.
|
||||||
- **values** (attrset, default: ``{}``): Values to pass into the chart.
|
- **values** (attrs, default: ``{}``): Values to pass into the chart.
|
||||||
- **includeCRDs** (bool, default: ``true``): Whether to include CustomResourceDefinitions in the template output.
|
- **includeCRDs** (bool, default: ``true``): Whether to include CustomResourceDefinitions in the template output.
|
||||||
- **kubeVersion** (str, default: ``pkgs.kubernetes.version``): The Kubernetes version to target.
|
- **kubeVersion** (str, default: ``pkgs.kubernetes.version``): The Kubernetes version to target.
|
||||||
- **apiVersions** ([str], default: ``[]``): Sets `Capabilities.APIVersions`_.
|
- **apiVersions** ([str], default: ``[]``): Sets `Capabilities.APIVersions`_.
|
||||||
|
@ -286,6 +323,9 @@ Wrapped re-export of `kubelib.fromHelm`_ that sets ``metadata.namespace`` on all
|
||||||
.. _kubelib.buildHelmChart: https://github.com/farcaller/nix-kube-generators/blob/cdb5810a8d5d553cdd0d04fa53378d5105b529b2/lib/default.nix#L82-L90
|
.. _kubelib.buildHelmChart: https://github.com/farcaller/nix-kube-generators/blob/cdb5810a8d5d553cdd0d04fa53378d5105b529b2/lib/default.nix#L82-L90
|
||||||
.. _Capabilities.APIVersions: https://helm.sh/docs/chart_template_guide/builtin_objects/#helm
|
.. _Capabilities.APIVersions: https://helm.sh/docs/chart_template_guide/builtin_objects/#helm
|
||||||
|
|
||||||
|
app-template.build
|
||||||
|
------------------
|
||||||
|
|
||||||
|
|
||||||
.. _SRI-style hash: https://nixos.wiki/wiki/Nix_Hash
|
.. _SRI-style hash: https://nixos.wiki/wiki/Nix_Hash
|
||||||
|
|
||||||
|
@ -295,3 +335,17 @@ Assign extra metadata in ``namespaces.nix``. For example,
|
||||||
``svc = {labels."istio.io/rev" = "1-18-1"}``
|
``svc = {labels."istio.io/rev" = "1-18-1"}``
|
||||||
is the equivalent of
|
is the equivalent of
|
||||||
``k label ns/svc istio.io/rev=1-18-1``
|
``k label ns/svc istio.io/rev=1-18-1``
|
||||||
|
|
||||||
|
Modules
|
||||||
|
=======
|
||||||
|
|
||||||
|
Service (unbuilt)
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
``{charts, lib, pkg, user} -> {builder, args, extraObjects}``
|
||||||
|
|
||||||
|
|
||||||
|
Service (loaded)
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
``{kubeVersion, apiVersion} -> {out, extra}``
|
||||||
|
|
|
@ -61,5 +61,9 @@
|
||||||
};
|
};
|
||||||
# TODO: make a template
|
# TODO: make a template
|
||||||
formatter = pkgs.alejandra;
|
formatter = pkgs.alejandra;
|
||||||
|
templates.default = {
|
||||||
|
path = ./templates/default;
|
||||||
|
description = "Example Turboprop flake";
|
||||||
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
45
templates/default/flake.nix
Normal file
45
templates/default/flake.nix
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
{
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:NixOS/nixpkgs";
|
||||||
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
|
turboprop = {
|
||||||
|
url = "sourcehut:~goorzhel/turboprop";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = {
|
||||||
|
self,
|
||||||
|
nixpkgs,
|
||||||
|
flake-utils,
|
||||||
|
turboprop,
|
||||||
|
}:
|
||||||
|
flake-utils.lib.eachDefaultSystem (
|
||||||
|
system: let
|
||||||
|
pkgs = import nixpkgs {inherit system;};
|
||||||
|
|
||||||
|
turbo = turboprop.lib.${system};
|
||||||
|
|
||||||
|
mkDerivation = turbo.mkDerivation {
|
||||||
|
user = {
|
||||||
|
app-template = turbo.app-template;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
in {
|
||||||
|
packages.default = let
|
||||||
|
pname = "my-k8s-flake";
|
||||||
|
in
|
||||||
|
mkDerivation {
|
||||||
|
inherit pname;
|
||||||
|
version = "rolling";
|
||||||
|
src = builtins.path {
|
||||||
|
path = ./.;
|
||||||
|
name = pname;
|
||||||
|
};
|
||||||
|
|
||||||
|
serviceRoot = ./services;
|
||||||
|
nsMetadata = {};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
38
templates/default/services/default/breezewiki/default.nix
Normal file
38
templates/default/services/default/breezewiki/default.nix
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
{
|
||||||
|
charts,
|
||||||
|
lib,
|
||||||
|
user,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
|
builder = user.app-template.build;
|
||||||
|
args = {
|
||||||
|
mainImage = "quay.io/pussthecatorg/breezewiki:latest";
|
||||||
|
values = let
|
||||||
|
port = 10416;
|
||||||
|
in {
|
||||||
|
service.main.ports.http.port = port;
|
||||||
|
route.main = {
|
||||||
|
enabled = true;
|
||||||
|
hostnames = ["breezewiki.example.com"];
|
||||||
|
parentRefs = [
|
||||||
|
{
|
||||||
|
name = "gateway";
|
||||||
|
namespace = "default";
|
||||||
|
sectionName = "https";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
rules = [
|
||||||
|
{
|
||||||
|
backendRefs = [
|
||||||
|
{
|
||||||
|
name = "breezewiki";
|
||||||
|
namespace = "default";
|
||||||
|
inherit port;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
{lib, ...}: {
|
||||||
|
builder = lib.builders.derivation;
|
||||||
|
args = {
|
||||||
|
src = lib.fetchers.remoteYAMLFile rec {
|
||||||
|
version = "1.0.0";
|
||||||
|
url = "https://github.com/kubernetes-sigs/gateway-api/releases/download/v${version}/experimental-install.yaml";
|
||||||
|
hash = "sha256-bGAdzteHKpQNdvpmeuEmunGMtMbblw0Lq0kSjswRkqM=";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in a new issue