1
0
Fork 0
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:
Antonio Gurgel 2023-12-04 21:32:12 -08:00
parent 34e00f2b30
commit a052d499df
5 changed files with 219 additions and 68 deletions

View file

@ -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}``

View file

@ -61,5 +61,9 @@
};
# TODO: make a template
formatter = pkgs.alejandra;
templates.default = {
path = ./templates/default;
description = "Example Turboprop flake";
};
});
}

View 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 = {};
};
}
);
}

View 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;
}
];
}
];
};
};
};
}

View file

@ -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=";
};
};
}