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
|
||||
***************
|
||||
|
||||
Without `Vladimir Pouzanov`_'s "`Nix and Kubernetes\: Deployments Done Right`_" (and `its notes`_), this project would not exist.
|
||||
|
||||
I also used `heywoodlh's Kubernetes flake`_ as a starting point early on.
|
||||
- `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.
|
||||
- Once I discovered `Haumea`_, Turboprop *really* started coming together.
|
||||
|
||||
.. _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
|
||||
.. _its notes: https://gist.github.com/farcaller/c87c03fbb55eaeaeb840b938455f37ff
|
||||
.. _heywoodlh's Kubernetes flake: https://github.com/heywoodlh/flakes/blob/aa5a52a/kube/flake.nix
|
||||
.. _Haumea: https://github.com/nix-community/haumea
|
||||
|
||||
********
|
||||
Tutorial
|
||||
********
|
||||
|
||||
**********************
|
||||
Usage and architecture
|
||||
**********************
|
||||
|
||||
Getting started
|
||||
===============
|
||||
Installation
|
||||
============
|
||||
|
||||
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}:
|
||||
flake-utils.lib.eachDefaultSystem (system: let
|
||||
pkgs = import nixpkgs {
|
||||
inherit system;
|
||||
overlays = [devshell.overlays.default];
|
||||
pkgs = import nixpkgs {inherit system;};
|
||||
|
||||
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 {
|
||||
packages.default = turbo.mkDerivation {
|
||||
# This too
|
||||
packages.default = let
|
||||
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;
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
1. The module takes as input:
|
||||
|
||||
#. A tree of *chart derivations*;
|
||||
#. 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}``.
|
||||
|
||||
|
@ -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
|
||||
.. _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
|
||||
#. zero or more intermediate directories (we'll get to this), which each contain
|
||||
#. directories representing Kubernetes namespaces, which each contain
|
||||
#. 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
|
||||
#. directories representing Helm repositories, which each contain
|
||||
#. Nix modules representing a(n untemplated) chart.
|
||||
- the `Gateway API`_, and
|
||||
- `Breezewiki`_ (through `app-template`_).
|
||||
|
||||
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
|
||||
/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
|
||||
Normally, one would also deploy a Gateway controller, but this suffices for the example.
|
||||
|
||||
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
|
||||
*********
|
||||
|
||||
Utilities
|
||||
=========
|
||||
Library
|
||||
=======
|
||||
|
||||
Charts
|
||||
======
|
||||
mkDerivation
|
||||
------------
|
||||
|
||||
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
|
||||
|
||||
|
||||
app-template
|
||||
------------
|
||||
|
||||
mkCharts
|
||||
--------
|
||||
|
||||
mkChartsWithNixhelm
|
||||
-------------------
|
||||
|
||||
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`_.
|
||||
|
||||
- **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.
|
||||
- **kubeVersion** (str, default: ``pkgs.kubernetes.version``): The Kubernetes version to target.
|
||||
- **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
|
||||
.. _Capabilities.APIVersions: https://helm.sh/docs/chart_template_guide/builtin_objects/#helm
|
||||
|
||||
app-template.build
|
||||
------------------
|
||||
|
||||
|
||||
.. _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"}``
|
||||
is the equivalent of
|
||||
``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
|
||||
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