Skip to content

Commit

Permalink
feat: craft a gitops focused installation
Browse files Browse the repository at this point in the history
Write up a GitOps focused installation of Understack along with some
helper scripts to assist the user with crafting their secrets and their
initial layout of their data.
  • Loading branch information
cardoe committed Mar 22, 2024
1 parent 294c5d3 commit b143b0e
Show file tree
Hide file tree
Showing 5 changed files with 230 additions and 0 deletions.
23 changes: 23 additions & 0 deletions apps/app-of-apps.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: app-of-apps
namespace: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
destination:
namespace: argocd
server: https://kubernetes.default.svc
project: default
source:
path: clusters/${DEPLOY_NAME}
repoURL: ${GIT_URL}
targetRevision: main
directory:
recurse: true
syncPolicy:
automated:
prune: true
selfHeal: true
125 changes: 125 additions & 0 deletions docs/gitops-install.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# GitOps based Install

This guide is not meant to be a definitive guide to [GitOps][gitops] and
how it can be used with UnderStack or even a best practices example
but instead focused on an example development oriented installation.
It will make a few assumptions and some opinionated choices that may
not align with a production best practices installation.
Most notable assumptions are:

- [GitOps][gitops] tooling runs on the same cluster as the deploy
- AIO (All-in-One) configuration
- Your cluster is a blank slate and can be entirely consumed

You will have the source to your deployment and all the pre-deployment
work will occur on your local machine and not on any of the target
machines.

## Getting the source

You must fetch the source to this repo and since we will be using
[GitOps][gitops], you must also have a deployment repo. These
operations can all happen locally on your development machine.

```bash
git clone https://github.com/rackerlabs/understack
# then either
git init my-deploy
# or
git clone https://path/to/my/deploy
```

The remainder of this guide will assume you've set the following
environment variables:

```bash
export US_REPO=$(pwd)/understack
export US_DEPLOY=$(pwd)/uc-deploy
```

## Pre-deployment

Embracing GitOps and declarative configuration, we will define three
distinct pieces of information for your deployment.

- Infrastructure: Where the software will live
- Secrets: What are all the credentials, passwords, etc needed by the software
- Cluster: The actual software that will be deployed

To properly scope this you'll need an environment name. For the
purposes of this document we'll call it `my-k3s`. To create the space to
work from you can run the following:

```bash
mkdir -p ${US_DEPLOY}/infrastructure/my-k3s
mkdir -p ${US_DEPLOY}/secrets/my-k3s
mkdir -p ${US_DEPLOY}/clusters/my-k3s
```

### Populating the infrastructure

TODO: some terraform template examples for building infra

### Generating secrets

Secrets in their very nature are sensitive pieces of data. The ultimate
storage and injection of these in a production environment needs to be
carefully considered. For the purposes of this document no specific
choice has been made but tools like Vault, Sealed Secrets, SOPS, etc
should be considered. This will only generate the necessary secrets
using random data to sucessfully continue the installation.

TODO: probably give at least one secure example

```bash
${US_REPO}/scripts/quick-secrets-gen.sh "${US_DEPLOY}/secrets/my-k3s"
cd ${US_DEPLOY}
git add secrets/my-k3s
git commit -m "my-k3s: secrets generation"
```

### Defining the app deployment

In this section we will use the [App of Apps][app-of-apps] pattern to define
the deployment of all the components of UnderStack.

```bash
${US_REPO}/scripts/gitops-deploy.sh \
some.domain.name \
[email protected]:myuser/uc-deploy.git
"${UC_DEPLOY}" \
my-k3s
```

This will populate `${UC_DEPLOY}/clusters/my-k3s` which can then be committed.

## Final modifications of your deployment

This is point you can make changes to the [ArgoCD][argocd] configs before
you do the deployment.

## Doing the Deployment

At this point we will use our configs to make the actual deployment.
Make sure everything you've committed to your deployment repo is pushed
to your git server so that ArgoCD can access it.

If you do not have ArgoCD deployed then you can use the following:

```bash
kubectl kustomize --enable-helm \
https://github.com/rackerlabs/understack//bootstrap/argocd/ \
| kubectl apply -f -
```

Then run the following:

```bash
kubectl apply -f "${UC_DEPLOY}/clusters/my-k3s/app-of-apps.yaml"
```

At this point ArgoCD will work to deploy Understack.

[gitops]: <https://about.gitlab.com/topics/gitops/>
[app-of-apps]: <https://argo-cd.readthedocs.io/en/stable/operator-manual/cluster-bootstrapping/>
[argocd]: <https://argo-cd.readthedocs.io/en/stable/>
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,4 @@ nav:
- openstack-helm.md
- secrets.md
- install-understack-ubuntu-k3s.md
- gitops-install.md
41 changes: 41 additions & 0 deletions scripts/gitops-deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#!/bin/sh

usage() {
echo "$(basename "$0") <dns-zone> <deploy-git-repo> <local-clone> <deploy-name>" >&2
echo "" >&2
echo "dns-zone: DNS zone where all the ingress endpoints will be hooked to" >&2
echo "deploy-git-repo: URL to your deploy repo" >&2
echo "local-clone: path to the local clone of your repo" >&2
echo "deploy-name: name you are giving your deployment" >&2
exit 1
}

template() {
local subvars
subvars="\$DNS_ZONE \$GIT_URL \$DEPLOY_NAME"
cat "$1" | envsubst "${subvars}" > "$2"
}

if [ $# -ne 4 ]; then
usage
fi

SCRIPTS_DIR="$(dirname "$0")"

OUTPUT_DIR="$3"

export DNS_ZONE="$1"
export GIT_URL="$2"
export DEPLOY_NAME="$4"

for part in operators components; do
echo "Creating ${part} configs"
mkdir -p "${OUTPUT_DIR}/clusters/${DEPLOY_NAME}/${part}"
for tmpl in $(find "${SCRIPTS_DIR}/../apps/${part}" -type f); do
outfile=$(basename "${tmpl}")
template "${tmpl}" "${OUTPUT_DIR}/clusters/${DEPLOY_NAME}/${part}/${outfile}"
done
rm -rf "${OUTPUT_DIR}/clusters/${DEPLOY_NAME}/${part}/kustomization.yaml"
done
echo "Creating app-of-apps config"
template "${SCRIPTS_DIR}/../apps/app-of-apps.yaml" "${OUTPUT_DIR}/clusters/${DEPLOY_NAME}/app-of-apps.yaml"
40 changes: 40 additions & 0 deletions scripts/quick-secrets-gen.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/bin/sh

function usage() {
echo "$(basename "$0") <output-dir>" >&2
echo "" >&2
echo "Generates random secrets needed by the apps in this repo" >&2
exit 1
}

if [ $# -ne 1 ]; then
usage
fi

SCRIPTS_DIR=$(dirname "$0")

kubectl --namespace openstack \
create secret generic mariadb \
--dry-run=client -o yaml \
--type Opaque \
--from-literal=root-password="$(${SCRIPTS_DIR}/pwgen.sh)" \
--from-literal=password="$(${SCRIPTS_DIR}/pwgen.sh)" \
> "$1/secret-mariadb.yaml"

kubectl --namespace nautobot \
create secret generic nautobot-env \
--dry-run=client -o yaml \
--type Opaque \
--from-literal=NAUTOBOT_SECRET_KEY="$(${SCRIPTS_DIR}/pwgen.sh)" \
--from-literal=NAUTOBOT_SUPERUSER_API_TOKEN="$(${SCRIPTS_DIR}/pwgen.sh)" \
--from-literal=NAUTOBOT_SUPERUSER_PASSWORD="$(${SCRIPTS_DIR}/pwgen.sh)" \
> "$1/secret-nautobot-env.yaml"

kubectl --namespace nautobot \
create secret generic nautobot-redis \
--dry-run=client -o yaml \
--type Opaque \
--from-literal=redis-password="$(${SCRIPTS_DIR}/pwgen.sh)" \
> "$1/secret-nautobot-redis.yaml"

"${SCRIPTS_DIR}/gen-os-secrets.sh" "$1/secret-openstack.yaml"

0 comments on commit b143b0e

Please sign in to comment.