Commit e6d3d0a5 authored by Pierre Ozoux's avatar Pierre Ozoux
Browse files

First commit.

parent 257d9ec7
Pipeline #180 passed with stages
in 1 minute and 4 seconds
\ No newline at end of file
\ No newline at end of file
- build
- deploy
stage: build
entrypoint: [""]
- /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --no-push
- master
stage: build
entrypoint: [""]
- cp $DOCKER_SECRET_CONFIG /kaniko/.docker/config.json
- /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination indiepaas/website:$CI_COMMIT_SHORT_SHA
- master
stage: deploy
- deploy
name: lachlanevenson/k8s-kubectl
entrypoint: [""]
- cat $CI_PROJECT_DIR/k8s.yml | sed "s/latest/$CI_COMMIT_SHORT_SHA/" | kubectl apply -f -
- master
\ No newline at end of file
[submodule "hugo-theme-learn"]
path = themes/hugo-theme-learn
url =
FROM unteem/nginx:1.16
RUN apt-get update && apt-get install -y wget \
&& wget${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_Linux-64bit.tar.gz \
&& tar xzf hugo_extended_${HUGO_VERSION}_Linux-64bit.tar.gz \
&& rm -r hugo_extended_${HUGO_VERSION}_Linux-64bit.tar.gz \
&& mv hugo /usr/bin/hugo \
&& rm -rf /var/lib/apt/lists/*
COPY . /usr/src/site
RUN cd /usr/src/site \
&& hugo -d /var/www
CMD 'nginx'
CC0 1.0 Universal
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related Rights (defined below) upon the creator and subsequent owner(s) (each and all, an "owner") of an original work of authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a commons of creative, cultural and scientific works ("Commons") that the public can reliably and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse and redistribute as freely as possible in any form whatsoever and for any purposes, including without limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a free culture and the further production of creative, cultural and scientific works, or to gain reputation or greater distribution for their Work in part through the use and efforts of others.
For these and/or other purposes and motivations, and without any expectation of additional consideration or compensation, the person associating CC0 with a Work (the "Affirmer"), to the extent that he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be protected by copyright and related or neighboring rights ("Copyright and Related Rights"). Copyright and Related Rights include, but are not limited to, the following:
the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work;
moral rights retained by the original author(s) and/or performer(s);
publicity and privacy rights pertaining to a person's image or likeness depicted in a Work;
rights protecting against unfair competition in regards to a Work, subject to the limitations in paragraph 4(a), below;
rights protecting the extraction, dissemination, use and reuse of data in a Work;
database rights (such as those arising under Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, and under any national implementation thereof, including any amended or successor version of such directive); and
other similar, equivalent or corresponding rights throughout the world based on applicable law or treaty, and any national implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention of, applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, and surrenders all of Affirmer's Copyright and Related Rights and associated claims and causes of action, whether now known or unknown (including existing as well as future claims and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each member of the public at large and to the detriment of Affirmer's heirs and successors, fully intending that such Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other legal or equitable action to disrupt the quiet enjoyment of the Work by the public as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason be judged legally invalid or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent permitted taking into account Affirmer's express Statement of Purpose. In addition, to the extent the Waiver is so judged Affirmer hereby grants to each affected person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and unconditional license to exercise Affirmer's Copyright and Related Rights in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "License"). The License shall be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of the License for any reason be judged legally invalid or ineffective under applicable law, such partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and causes of action with respect to the Work, in either case contrary to Affirmer's express Statement of Purpose.
4. Limitations and Disclaimers.
No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed or otherwise affected by this document.
Affirmer offers the Work as-is and makes no representations or warranties of any kind concerning the Work, express, implied, statutory or otherwise, including without limitation warranties of title, merchantability, fitness for a particular purpose, non infringement, or the absence of latent or other defects, accuracy, or the present or absence of errors, whether or not discoverable, all to the greatest extent permissible under applicable law.
Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work.
Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work.
title: "{{ replace .Name "-" " " | title }}"
date: {{ .Date }}
draft: true
#baseURL = ""
baseURL = ""
languageCode = "en-us"
title = " - Kubernetes the libre way."
theme = "hugo-theme-learn"
# For search functionality
home = [ "HTML", "RSS", "JSON"]
name = "<i class='fas fa-heart'></i> Contribute"
url = "/contribute"
weight = 10
name = "<i class='fab fa-discourse'></i> Forum"
url = ""
weight = 11
name = "<i class='fas fa-comments'></i> Matrix Channel"
url = "!"
weight = 20
name = "<i class='fas fa-donate'></i> Sponsor"
url = ""
weight = 28
name = "<i class='fas fa-gift'></i> Free mentoring"
url = "/mentoring"
weight = 25
name = "<i class='fas fa-calendar-alt'></i> Roadmap"
url = "/roadmap"
weight = 26
name = "<i class='fab fa-creative-commons-zero'></i> License"
url = "/License"
weight = 28
name = "<i class='fas fa-bullhorn'></i> Credits"
url = "/credits"
weight = 30
editURL = ""
themeVariant = "blue"
\ No newline at end of file
title: Comparison to
pre: "<b>5. </b>"
weight: 5
- yunohost
- cloudron
- freedombox
- v1
title: Further reading
pre: "<b>6. </b>"
weight: 6
- [The Illustrated Children's Guide to Kubernetes]( - a nice getting started
- [Julia Evan's blog]( - a great resource to understand internals of kubernetes
- [CoreOS cluster OSI model]( - one of the really inspiring article that started to make me dreaming
- [Kubernetes Resource Management]( - a beautiful, almost academic paper - on how to run a distributed cluster that is in reallity kubernetes ;)
- [Airbnb synapse - Registration Discovery pattern]( - Discovery/Registration pattern
- [Kubernetes The hard way]( - a deep dive on what is needed to build a kubernetes cluster - this would help you understand the deep internals
- [Kubernetes the not so hard way with ansible]( - a alternative to the previous link - wiht ansible
title: "Layers"
## Layer 0 - infra
Create 9 machines on your favorite place. We'll not details the steps here. We use hetzner cloud. Deploy a debian or ubuntu or your favorite distrib.
## Layer 1 - network
Then we need to prepare the Network:
### wireguard
In term of network topology, we'll use 3 networks, all secured by wireguard:
- management
- Ceph backend
- Kubernetes overlay
Management will be used by kubernetes and ceph components.
The ceph backend will be used for data heavy part of ceph.
And the overlay to allow services running on top of kubernetes to discuss together.
In this step, we'll only install The 2 first one. The overlay will be installed later.
## Layer 2 - kubespray
Use [kubespray]( to deploy your components.
It is a set of ansible roles to deploy an HA kubernetes cluster.
We personnaly use the following:
- containerd - It is the container runtime. Nowadays, the industry is moving from Docker to containerd, so do we.
- kubeadm - It ss developed Upstream Under kubernetes namespace. It is aimed at becoming the defacto installation tool for kubernetes.
- canal with wireguard - it is the Kubernetes overlay network.
- nginx-ingress
- cert-manager
## Layer 3 - storage
Storage with [ceph]( (Or [rook]( if you are bold ;), it is almost production ready)
## Layer 4 - backing services
This term is a reference to [12 factor app](, and it is not a coincidence! (If you don't know it, get there and read it!)
This is our curated list of operators:
- [Postgres operator](
- [Redis operator](
- [Stash]( for backups/restore
## Layer 5 - upstream operators
## Layer 6 - operator
## Layer 7 - web UI
UI to let people self serve. The status of this is clearly [vaporware](, but we hope to release an alpha by begining of 2021 (Except if you have skills and want to work on it already, this would be amazing ;) ).
\ No newline at end of file
title: "Getting started"
pre: "<b>3. </b>"
weight: 3
## A layered and modular architecture
Hopefully this becomes a Quickstart ;)
(The idea is to build [a terraform template]( with kubespray to automate this part)
This is what we'll deploy:
The reference architecture needs 9 machines:
- 3 masters
- 3 ingresses
- 3 compute
Masters are used to coordinate the cluster. They store the state in etcd. They make sure nodes are healthy. They schedule work on the nodes. They are the brain of your cluster. If they are down, the three of them, your workload still functions properly, but you could't change the state of you cluster.
Ingresses are where https is terminated. They need to also be highly available. Depending on your hardware setup, you have to find a way to balance traffic. You could use MettalLB for instance. On Hetzner VMs, we use floating IPs.
Compute nodes are where your workload is running. This is where your databases and application servers will run.
\ No newline at end of file
title: Backing services
weight: 1
[Backing services]( are necessary to any web application you deploy.
In our example, we'll need a prostgres database.
So, we'll need to deploy a postgres database on kubernetes. For that we'll use an operator. There are currently [around 5 different postgres operators]( curated one for you, the one developped by [Zalando](
Once you have [the operator running]( in your cluster, we can deploy a postgres instance.
With the kubernetes API that is declarative, this is how you'd do:
cat << EOF | kubectl apply -f -
apiVersion: ""
kind: postgresql
name: nexctloud-postgres
namespace: fight-marketing
teamId: "nextcloud"
size: 1Gi
numberOfInstances: 2
nextcloud: # database owner
- superuser
- createdb
nextcloud: nextcloud # dbname: owner
version: "11"
After some minutes, you get a highly available Postgres cluster running. Nice right? Now let's deploy Nextcloud.
\ No newline at end of file
title: operator
weight: 20
As explained at the begining, is a distribution where services are curated and integrated together.
We assume that you use the zalando postgres operator. We also know the domain name from the annotation in the namespace.
So then we can build a Nextcloud operator (still to be built).
And deploying a Nextcloud instance would look like this:
cat << EOF | kubectl -f -
apiVersion: ""
kind: cloud
name: fight-marketing
namespace: fight-marketing
Or put differently:
curl https://yourkubernetes.cluster/ -k -H "Content-Type: application/json" -XPOST -d '
"apiVersion": "",
"kind": "cloud",
"metadata": {
"name": "fight-marketing",
"namespace": "fight-marketing",
And yes, you can use an OpenIdConnect provider with RuleBasedAccessControl in front of the kubernetes api if you see where we are going ;)
You could also imagine adding a spec, like `size: L`, and it would translate into a price and cpu and memory request for the different components.
\ No newline at end of file
title: Upstream operator
weight: 10
Now that Postgres is running, we can deploy our Nextcloud.
But first we need to deploy the nextcloud upstream operator. This operator is low level because it would need every information about the backing services. It is a nice building block for projects like
Here is the version alpha we are developing. The goal is to move it's development upstream. We think that this belongs to Nextcloud community to own this. And we'll help bootstrap that. The same way we did with [some]( [official]( [docker]( [images](
Here is how the Nextcloud instance object would look like:
cat << EOF | kubectl apply -f -
apiVersion: ""
kind: nextcloud
name: cloud
namespace: fight-marketing
endpoint: nextcloud-postgres
secret: nextcloud-postgres-secret
size: 1Gi
numberOfInstances: 2
After some minutes, you'd get an up and running Nextcloud instance. behind the scene it would have provisionned the following:
- the deployment with 2 pods with a php container with Nextcloud code
- a cron job
- a web container to serve static assets
- an ingress with a Let's Encrypt certificate
- installed Nextcloud
Upstream operators are already nice you'd say. But keep in mind that we are discussing about 7 backing services. So for each Nextcloud instance, you'd need to do the plumbing manually of each backing service manually. Let's go now to the operator.
\ No newline at end of file
title: Wrap Up
weight: 100
This concept of upstream and operators enables us to build nice and reusable code upstream and also have a really tailored operator for our needs.
Once the 2 levels are built, it is not difficult to add a UI on top of it.
You might also be frustrated by this need of 2 level operators, there must be a better solution for it. We do think so too, but it is a [long term goal that we have to work with the kubernetes community](
\ No newline at end of file
title: Kubernetes Operators
pre: "<b>2. </b>"
weight: 2
For a more in depth view of what is kubernetes or what are opertators, you should read the [why kubernetes](/whykubernetes/).
But first let's move on with our example to start to get a taste of what is our solution.
\ No newline at end of file
title: IndieHosters tale
weight: 1
## Once upon a time in Lisboa
a young guy started to host WordPresses for his friends on a Raspberry. Then he teamed with a new friend to create IndieHosters. This project was about hosting free software for people. Little by little, they gained popularity and bigger and bigger organisations trusted them to host there software. There was some up and some down about how to pay the rent with this service. A new team member came along. And eventually, they finally managed to secure a bigger client and some nice smaller one. The rent was mostly paid.
At this point, they realized that hosting for people is just not profitable at all, or they would need some volume.
If they were capitalistic and rational, IndieHosters would have stop hosting for the people and focus on the bigger clients. Some people say that startup start B2C and end up doing B2B, it is just plain easier. But IndieHosters was not a startup and the tale didn't end up like this.
We think that this tale is what most small free software hosters are experiencing. We want to change this, and here it is how:
\ No newline at end of file
title: Nextcloud example
weight: 3
Heard about [Nextcloud]( Let's say that we want to deploy a Nextcloud instance for a nice association fighting marketing.
Before deploying the Nextlcoud, we'll need to list the backing services that would be necessary:
- postgres database
- redis cache
- smtp relay to send email notification
- S3 compatible API for object store
- OpenIdConnect provider for Single Sign On
- libre office online
- nextant
This is to deploy a reliable and scalable Nextcloud instance. For the sake of simplicity, let's say that we just need Postgres. But keep in mind, that we have the other backing services in mind too, and that we can use the same paradigms.
We'll assume for the rest of the example that you already got a kubernetes cluster running.
The domain name of the association is ``. You already created a namespace `fight-marketing` and added the annotation `domaine-name:`.
Let's now see how we solve our problem with the [kubernetes operators](/kubernetesoperators/).
\ No newline at end of file
title: Problem to solve
pre: "<b>1. </b>"
weight: 1
What is the problem to solve? It is always a great question to ask before starting a project.
For, since version 1, the problem to solve is the same, How do we :
- host free software at scale?
- make it cheaper in term of admin time?
- improve reliability of our platform?
- share our SysAdmin recipes?
These are the questions we think we found answers in 2 words, [kubernetes](/whykubernetes/) operators.
Let's detail what we envision about operators and why it is so great. But first, let's start with a little tale.
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment