A minimal deployment of the Fury Kubernetes Distribution using the GitOps paradigm.
For a regular deployment in a minikube environment without GitOps go here.
- fluxcd v2
>= 0.9
(installation guide) - minikube
>= v1.18
(installation guide)
There are various others GitOps tools available (e.g. Argo CD), for this demo I choose Flux v2.
Create a GitHub personal access token following this guide.
Remember to grant all repo
permissions.
Once created save the token in an environment variable:
export GITHUB_TOKEN=<TOKEN_ID>
export GITHUB_USER=<MY_GITHUB_USER> (e.g. nikever)
At the root level of this repository, execute:
export REPO_DIR=$(PWD)
Start a minikube cluster:
cd $REPO_DIR/minikube
make setup
By default, it will spin up a one node Kubernetes cluster of version v1.19.4
in a VirtualBox VM (CPUs=4, Memory=8192MB, Disk=20000MB).
You can pass additional parameters to change the default values:
make setup cpu=2 memory=2048
If you reduce the memory
and cpu
of the node, remember to adjust resources requests and limits in the patches of the fury-distribution-minimal.
Please referer to this Makefile for additional details on the cluster creation.
We are going to bootstrap flux via the cli:
flux bootstrap github \
--owner $GITHUB_USER \
--repository fury-flux-fleet \
--branch main \
--path ./clusters/fury-minimal-cluster \
--personal
The bootstrap command creates a repository if one doesn't exist, commits the manifests for the Flux components to the default branch at the specified path, and installs the Flux components. Then it configures the target cluster to synchronize with the specified path inside the repository.
Wait for the pods to be up and running:
kubectl -n flux-system get pods -w
mkdir $REPO_DIR/demo
cd $REPO_DIR/demo
git clone https://github.com/$GITHUB_USER/fury-flux-fleet
cd fury-flux-fleet
Create a folder for the Fury distribution:
mkdir -p ./clusters/fury-minimal-cluster/fury/
Create a GitRepository
manifest pointing to Fury Distribution Minimal repository's master branch:
flux create source git fury-distribution \
--url https://github.com/nikever/fury-distribution-minimal \
--branch main \
--interval 1m \
--export \
> ./clusters/fury-minimal-cluster/fury/fury-distribution-source.yaml
Create a Flux Kustomization
manifest for the Fury distribution. This configures Flux to build and apply the kustomize directory located in the Fury Distribution Minimal repository under the fury
folder.
flux create kustomization fury-distribution \
--source=fury-distribution \
--path="./fury" \
--prune=true \
--interval=5m \
--export \
> ./clusters/fury-minimal-cluster/fury/fury-distribution-kustomization.yaml
We don't perform any validation
(neither on client nor server) due to some race-condition on Custom Resource Definitions (CRDs). This happens because CRDs are referenced before they are created, resulting in an error. Without the validation we force the kustomize apply
until the actual state matches the desired state.
Commit and push to deploy the Fury Distribution in the cluster:
git add -A && git commit -m "Add Fury Minimal Distribution GitRepository and Kustomization"
git push
Wait for Flux to reconcile everything:
watch flux get sources git
watch flux get kustomizations
Wait for pods to be up and running:
kubectl get pods -A -w
Use minikube ip
to get the external IP of the cluster:
$ minikube ip
192.168.99.113
Add ingresses to /etc/hosts
file by adding the following line to the bottom of the file:
192.168.99.113 directory.fury.info alertmanager.fury.info goldpinger.fury.info grafana.fury.info prometheus.fury.info >> /etc/hosts
Replace 192.168.99.113
with your actual IP.
If you are adventurous enough, you might want to use this one-liner:
sudo bash -c "echo $(minikube ip) directory.fury.info alertmanager.fury.info goldpinger.fury.info grafana.fury.info prometheus.fury.info >> /etc/hosts"
Now, open a browser and go to directory.fury.info, you should be able to see all the cluster ingresses.
More information of what can you do can be found here.
To conclude we are going to deploy a simple demo app in our cluster. We are going to deploy a sample web application called hello-app
. It is a web server written in Go that responds to all requests with the message Hello, World!
on port 8080
.
The application is available as two Docker images, which respond to requests with different version numbers:
gcr.io/google-samples/hello-app:1.0
gcr.io/google-samples/hello-app:2.0
We are going to deploy gcr.io/google-samples/hello-app:1.0
first, and then update to gcr.io/google-samples/hello-app:2.0
.
Let's create a new directory first for our app:
mkdir -p ./clusters/fury-minimal-cluster/hello-app/
Now, we can create a GitRepository
manifest pointing to the Hello App. We will point to the branch hello-app-1.0
that uses the gcr.io/google-samples/hello-app:1.0
image.
flux create source git hello-app \
--url https://github.com/nikever/kubernetes-hello-app \
--branch hello-app-1.0 \
--interval 1m \
--export \
> ./clusters/fury-minimal-cluster/hello-app/hello-app-source.yaml
flux create kustomization hello-app \
--source=hello-app \
--path="." \
--prune=true \
--interval=5m \
--export \
> ./clusters/fury-minimal-cluster/hello-app/hello-app-kustomization.yaml
Commit and push to deploy the Hello App:
git add -A && git commit -m "Add hello-app GitRepository and Kustomization"
git push
Wait for Flux to reconcile everything:
watch flux get sources git
watch flux get kustomizations
Wait for pods to be up and running:
kubectl get pods -n logging -w
Add the following line to the bottom of the /etc/hosts
file manually:
<MINIKUBE_IP> hello-world.info
(where <MINIKUBE_IP>
must be replace with output of minikube ip
)
or, again, via:
sudo bash -c "echo $(minikube ip) hello-world.info >> /etc/hosts"
Verify that the Ingress controller is directing traffic:
curl hello-world.info
It should output something similar to:
Hello, world!
Version: 1.0.0
Hostname: hello-app-5c4957dcc4-l4mqz
Ensure that the version is 1.0.0
.
To update the app, we simply going to change the branch of the hello-app
GitRepository from branch: hello-app-1.0
to branch: hello-app-2.0
.
sed -i "" "s/hello-app-1.0/hello-app-2.0/g" clusters/fury-minimal-cluster/hello-app/hello-app-source.yaml
Commit to apply:
git add -A && git commit -m "Update hello-app to v2.0.0"
git push
Wait for Flux to reconcile everything:
watch flux get sources git
watch flux get kustomizations
Now you can retry the app:
curl hello-world.info
It should output Version: 2.0.0
:
Hello, world!
Version: 2.0.0
Hostname: hello-app-5c4957dcc4-l4mqz
To clean up:
- delete the
minikube
cluster:
cd $REPO_DIR/minikube
make delete
-
delete the lines you added in the
/etc/hosts
-
delete the
fury-flux-fleet
repository (optional).
As a side note, in case of private repositories you can:
- Generate SSH Credentials
- Add Deploy key in GitHub
- Create a secret containing SSH credentials
- Specify the secret name in the
secret-ref
parameter when creating GitRepository
This approach is quick but not really "GitOps" since it requires kubectl apply
.
It is okay for a quick demo, consider alternatives in a real setup.
mkdir secrets
ssh-keygen -q -N "" -f ./secrets/identity
ssh-keyscan github.com > ./secrets/known_hosts
Copy the public key:
cat identity.pub
ssh-rsa AAAAB3NzaC1yc2EAA...
Add it to deploy keys under https://github.com/<GITHUB_USER>/<REPOSITORY>/settings/keys
kubectl create secret generic ssh-credentials \
--from-file=./secrets/identity \
--from-file=./secrets/identity.pub \
--from-file=./secrets/known_hosts \
--namespace=flux-system
flux create source git fury-distribution \
--url PRIVATE_REPO/fury-distribution-minimal \
--branch master \
--interval 1m \
--secret-ref ssh-credentials \
--export \
| tee ./clusters/fury-minimal-cluster/fury/fury-distribution-source.yaml
This guide uses: