Skip to content

Commit

Permalink
nix-intro: 2024.05.15-1
Browse files Browse the repository at this point in the history
  • Loading branch information
codgician committed May 15, 2024
1 parent 4a1cf2e commit ae2a56d
Show file tree
Hide file tree
Showing 3 changed files with 175 additions and 16 deletions.
12 changes: 5 additions & 7 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,11 @@
};

# Development shells
devShells = {
default = pkgs.mkShell {
buildInputs = with pkgs; [
pandoc
httplz
];
};
devShells.default = pkgs.mkShell {
buildInputs = with pkgs; [
pandoc
httplz
];
};

# Formatter: `nix fmt`
Expand Down
2 changes: 1 addition & 1 deletion slides/nix-intro/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ lib.seelies.mkRevealJs {

name = "nix-intro";
title = "Introducing Nix: declarative builds and deployments";
version = "2024.05.14-1";
version = "2024.05.15-1";
src = ./.;
license = lib.licenses.cc-by-nc-sa-40;

Expand Down
177 changes: 169 additions & 8 deletions slides/nix-intro/slides.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,34 @@ subtitle: Declarative builds and deployments
date: 2024.05.20
---

# Problem
# Software deployment

::: { .incremental }
- Source deployment
$$
\begin{CD}
\text{get source} @>>> \text{build} @>>> \text{install} \\
\end{CD}
$$
- Binary deployment
$$
\begin{CD}
\text{get binary} @>>> \text{install} \\
\end{CD}
$$
:::

## Problems

- Software should be reproducible when copied among machines.
- Challenges:
* Most software today is not self-contained.
* As they scale, deployment process becomes increasingly complex.
- We deal with these everyday at Deployment Team 🤪.

## Environment issues
---

### Environment issues

- Software today is almost **never self-contained**.
- Dependencies, both build time and run time, needs to be **compatible**.
Expand All @@ -29,11 +48,13 @@ date: 2024.05.20

:::

## Manageability issues
---

### Manageability issues

- **Uninstall / Upgrade**: should not induce failures to another part of the system (e.g. *[DLL hell](https://en.wikipedia.org/wiki/DLL_Hell)*).
- **Administrator queries**: file ownership? disk space consumption? source?
- **Incident mitigation**: able to undo / rollback effects of upgrades.
- **Rollbacks**: able to undo effects of upgrades.
- **Variability**: build / deployment configurations may differ.
- **Maintenance**: may have different policies for keeping software up-to-date.
- ... and they scale for a **huge** fleet of machines with **different SKUs**.
Expand All @@ -43,7 +64,7 @@ date: 2024.05.20
- **Uninstall**: also should be as clean as possible.
- **Upgrades**: DLL hell as a typical example, where upgrading or installing one application can cause a failure to another application due to shared dynamic libraries.
- **Administrator queries**
- **Incident migitation**: both reproduce the old package and the old configuration.
- **Rollbacks**: both reproduce the old package and the old configuration.
- **Variability**: software may have different compile options, and may only deploy a subset of components. Especially for OSS, packages with the same name and the same version may be compiled from different source.
- **Maintenance**
- **Heterogeneous network**: different set of components may be deployed to different machines according to hardware differences. Even for the same software, compiler options may differ (e.g. enable AVX512?)
Expand All @@ -52,14 +73,143 @@ Blood pressure rising? That's what we are dealing with on a daily basis :P

:::

# Solutions?
# Industry solutions?

## Idea #1. Let's go monolithic!

Bundle everything to increase reproducibility at runtime.

::: { .incremental }
- **Dependencies**? Self-contained packaging!
- **Isolation**? Sandbox technologies!
- **Environment issues**? Containers!
- **Different hardware**? Virtualization!
:::

---

*Wait, this doesn't really simplify build + deployment process.*

::: { .incremental }
- Split build & deployment into *stages* (workflows).
- Manage dependencies between *stages*.
- e.g. GitHub actions, Ansible, etc.
:::

::: { .notes }

Monolithic only solves running the software in a reproducible manner.
Building and deploying monolithic software could still be complex.

:::

---

*Aren't we wasting storage spaces?*

::: { .fragment .incremental }
- Split into layers and share common bases.
- Fetch files on-demand? (e.g. Zero Install System).
- Storage today is getting cheaper anyway...
:::

::: { .notes }

If we habe $N$ apps having $M$ same dependencies, the storage complexity becomes $\mathcal{O}(NM)$ instead of $\mathcal{O}(N + M)$.

Splitting monolithic architecture can never be fine-grained, because its motavation is to prevent management complexity. The more you split, the more you lose benefits of monolithic architecture.

:::

## Idea #2. Package manager

::: { .incremental }
- Each component provide a set of constraints:
- Hard clauses, e.g. dependencies must exist.
- Soft clauses (weighted), e.g. version as new as possible.
- Goal: Satisfy all hard caluses, and maximize satisfied soft clauses.
- MAXSAT solver. e.g. rpm, apt, etc.
- MAXSAT is NP-complete.
:::

::: { .notes }

* Package management is especially critical to UNIX systems because they traditionally insist placing packages in global namespaces, following [Filesystem Hierarchy Standard](https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard).

:::

---

*But most implementations install components in global namespace...*

::: { .incremental }

- Two components dependeing different versions of the same package?
- Two components providing file to the same path?
- Two components may interfere with others in the case of incomplete dependencies and inexact notions of component compatibility.

:::

---

::: { .incremental }

- Desctrucitive upgrading:
* Upgrades are not atomic.
* Files are overwritten, making rollback non-trivial.

:::

## Idea #3?

Let's solve all issues with a **systematic** approach.

Introducing [The Purely Functional Software Deployment Model](https://edolstra.github.io/pubs/phd-thesis.pdf),

and one of its implementation, Nix.

::: { .notes }

Nix is not the only implementation, we also have [Guix](https://guix.gnu.org/nb-NO/blog/2006/purely-functional-software-deployment-model/) inspired by the same thesis.

:::

# Nix: a build system

*Building software is just a function.*

$$
\begin{CD}
\text{Inputs} @> f>> \text{Output}
\end{CD}
$$

::: { .r-stack }
::: { .fragment .fade-out data-fragment-index="0" }
$$
\begin{CD}
x = 1, y = 2 @> f(x, y) = x + y >> 1 + 2 = 3
\end{CD}
$$
:::
::: { .fragment .current-visible data-fragment-index="0" }
$$
\begin{CD}
\text{gcc, libc, source, ...} @> \text{./configure, make, make install} >> \text{binary}
\end{CD}
$$
:::
:::

---


# Nix: as build system

# Nix: as package manager

# NixOS


---

::: { .r-stack }
Expand All @@ -73,4 +223,15 @@ Blood pressure rising? That's what we are dealing with on a daily basis :P
# References

- [Dolstra, Eelco. The purely functional software deployment model. Utrecht University, 2006.](https://edolstra.github.io/pubs/phd-thesis.pdf)


---

Slides are

generated by [pandoc](https://pandoc.org),

rendered by [reveal.js](https://revealjs.com),

and managed by [Nix](https://nixos.org).

Fully [open-sourced](https://github.com/codgician/seelies).

0 comments on commit ae2a56d

Please sign in to comment.