diff --git a/README.md b/README.md index 99db004..d19f7fd 100644 --- a/README.md +++ b/README.md @@ -1 +1,23 @@ # GitOps +A set of "best practices" where the entire code delivery process is controlled via Git, including infrastructure and application definition as code and automation to complete updates and rollbacks. + +The key GitOps Principles: + +- The entire system (infrastructure and applications) is described declaratively. +- The canonical desired system state is versioned in Git. +- Changes approved are automated and applied to the system. +- Software agents ensure correctness and alert on divergence. +https://opengitops.dev/ + +Key points for a Kubernetes cluster: + +The state of the cluster is always described in Git. Git holds everything for the application and not just the source code. +There is no external deployment system with full access to the cluster. The cluster itself is pulling changes and deployment information. +The GitOps controller is running in a constant loop and always matches the Git state with the cluster state (reconciliation loop). +flux vs ArgoCD +Flux is more CLI Driven ArgoCD has a richer GUI + +## Flux +Prerequisites: +- Kubernetes Cluster +-Github (giea, etc) personal access token diff --git a/apps/hydra/linkding/deployment.yaml b/apps/hydra/linkding/deployment.yaml new file mode 100644 index 0000000..b93e029 --- /dev/null +++ b/apps/hydra/linkding/deployment.yaml @@ -0,0 +1,24 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: linking + name: linking + namespace: linkding +spec: + selector: + matchLabels: + app: linking + strategy: {} + template: + metadata: + labels: + app: linking + spec: + containers: + - image: sissbruecket/linkding:1.31.0 + name: linkding + ports: + - containerPort: 9090 + resources: {} +status: {} diff --git a/apps/hydra/linkding/namespace.yaml b/apps/hydra/linkding/namespace.yaml new file mode 100644 index 0000000..bc84cc5 --- /dev/null +++ b/apps/hydra/linkding/namespace.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: linkding +spec: {} +status: {} diff --git a/apps/hydra/linkding/srv.yaml b/apps/hydra/linkding/srv.yaml new file mode 100644 index 0000000..005eb82 --- /dev/null +++ b/apps/hydra/linkding/srv.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + app: linking + name: linking + namespace: linkding +spec: + ports: + - port: 9090 + targetPort: 0 + selector: + app: linking +status: + loadBalancer: {} diff --git a/clusters/hydra/apps.yaml b/clusters/hydra/apps.yaml new file mode 100644 index 0000000..694c806 --- /dev/null +++ b/clusters/hydra/apps.yaml @@ -0,0 +1,15 @@ +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: apps + namespace: flux-system +spec: + interval: 10m0s + path: ./apps/hydra + prune: true + retryInterval: 1m0s + sourceRef: + kind: GitRepository + name: flux-system + timeout: 5m0s +status: {} diff --git a/go.mod b/go.mod index 4816765..2a6b2be 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module danicos.dev/daniel/homelab go 1.26.2 require ( - danicos.dev/daniel/go-kube v1.2.0 + danicos.dev/daniel/go-kube v1.2.2 github.com/fatih/color v1.19.0 github.com/fluxcd/kustomize-controller/api v1.8.3 github.com/magefile/mage v1.17.1 diff --git a/go.sum b/go.sum index e025f7f..b57d57e 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -danicos.dev/daniel/go-kube v1.2.0 h1:nLcpSOmszmkMnHd4Fb9V7R8qO7z2OwNgUFFWQNwQazs= -danicos.dev/daniel/go-kube v1.2.0/go.mod h1:FLgPxaiDpLmIwWddx5x4jTfP/onTzkOLbhmpdt2uX6w= +danicos.dev/daniel/go-kube v1.2.2 h1:RW/mzIMIyMCEftTyvRTeJmo44JaCDsxLMlZcEnZxN1g= +danicos.dev/daniel/go-kube v1.2.2/go.mod h1:FLgPxaiDpLmIwWddx5x4jTfP/onTzkOLbhmpdt2uX6w= github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0= github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/magefiles/magefile.go b/magefiles/magefile.go index 5e72ad8..226c3b2 100644 --- a/magefiles/magefile.go +++ b/magefiles/magefile.go @@ -13,9 +13,9 @@ import ( */) var r target.Runner -var Default = Run +var Default = Build var Aliases = map[string]any{ - "r": Run, + "b": Build, } func init() { @@ -28,7 +28,7 @@ func init() { r = target.NewRunner(Env, nil) } -func Run() error { +func Build() error { t := target.NewA("go", "run", ".") return r.RunV("run", t) } diff --git a/main.go b/main.go index 96cda92..abde345 100644 --- a/main.go +++ b/main.go @@ -1,15 +1,37 @@ package main import ( - "danicos.dev/daniel/go-kube/pkg/kube" + "fmt" + "os" + + "danicos.dev/daniel/go-kube/pkg/stack" "danicos.dev/daniel/homelab/pkg/flux" - kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1" -) + "danicos.dev/daniel/homelab/pkg/linkding" + "danicos.dev/daniel/homelab/pkg/root" + /* + apps "k8s.io/api/apps/v1" + core "k8s.io/api/core/v1" + net "k8s.io/api/networking/v1" + */) func main() { - meta := kube.NewMetadata("name", kube.Namespace("nae")) - kuz := kube.NewKustomization(meta, kustomizev1.KustomizationSpec{}) - fluxStack := flux.Stack() - fluxStack.Add("apps", kuz) - fluxStack.MarshalYaml("") + flux_stack := flux.Stack() + err := flux_stack.MarshalYamlFlat(root.FLUX_CLUSTER_HYDRA_PATH) + assertNoErr(err) + + hydraApps := map[string]stack.Stack{ + "linkding": linkding.Stack(), + } + for name, s := range hydraApps { + fmt.Printf("STACK: %s\n", name) + err = s.MarshalYaml(root.FLUX_APPS_HYDRA_PATH) + assertNoErr(err) + } +} + +func assertNoErr(err error) { + if err != nil { + fmt.Println(err.Error()) + os.Exit(1) + } } diff --git a/pkg/flux/flux.go b/pkg/flux/flux.go index 3367737..f0d2ce2 100644 --- a/pkg/flux/flux.go +++ b/pkg/flux/flux.go @@ -1,8 +1,46 @@ package flux -import "danicos.dev/daniel/go-kube/pkg/stack" +import ( + "time" + + "danicos.dev/daniel/go-kube/pkg/kube" + "danicos.dev/daniel/go-kube/pkg/stack" + "danicos.dev/daniel/homelab/pkg/root" + kz "github.com/fluxcd/kustomize-controller/api/v1" + meta "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +var flux_apps_meta kube.Metadata +var Flux_namespace = kube.Namespace(root.FLUX_NAMESPACE) + +func init() { + flux_apps_meta = kube.NewMetadata("apps", Flux_namespace) +} func Stack() stack.Stack { - s := stack.NewStack("", nil) + s := stack.NewStack("flux", map[string]any{ + "apps": Apps(), + }) return s } + +func Apps() kz.Kustomization { + retryInteval := durMin(1) + timeout := durMin(5) + spec := kz.KustomizationSpec{ + Interval: durMin(10), + RetryInterval: &retryInteval, + Timeout: &timeout, + SourceRef: kz.CrossNamespaceSourceReference{ + Kind: "GitRepository", + Name: Flux_namespace.Name, + }, + Path: root.FLUX_APPS_HYDRA_PATH, + Prune: true, + } + return kube.NewKustomization(flux_apps_meta, spec) +} + +func durMin(d int64) meta.Duration { + return meta.Duration{Duration: (time.Duration(d) * time.Minute)} +} diff --git a/pkg/linkding/linkding.go b/pkg/linkding/linkding.go new file mode 100644 index 0000000..6fc9cf9 --- /dev/null +++ b/pkg/linkding/linkding.go @@ -0,0 +1,42 @@ +package linkding + +import ( + "danicos.dev/daniel/go-kube/pkg/kube" + "danicos.dev/daniel/go-kube/pkg/stack" + "danicos.dev/daniel/homelab/pkg/root" + apps "k8s.io/api/apps/v1" + core "k8s.io/api/core/v1" +) + +var meta kube.Metadata +var Namespace = kube.Namespace("linkding") +var srv core.Service + +func init() { + meta = kube.NewMetadata("linking", Namespace) + srv = meta.Service(root.Linkding.Port) +} + +func Stack() stack.Stack { + s := stack.NewStack("linkding", map[string]any{ + "namespace": Namespace, + "srv": srv, + "deployment": deployment(), + }) + return s +} + +func deployment() apps.Deployment { + pod_spec := core.PodSpec{ + Containers: []core.Container{ + { + Name: root.Linkding.Name, + Image: root.Linkding.Image, + Ports: []core.ContainerPort{{ + ContainerPort: root.Linkding.Port, + }}, + }, + }, + } + return kube.NewDeployment(meta, pod_spec) +} diff --git a/pkg/root/root.go b/pkg/root/root.go index 1c2a094..3260003 100644 --- a/pkg/root/root.go +++ b/pkg/root/root.go @@ -1,7 +1,13 @@ package root -var ( +const ( HYDRA_CLUSTER = "hydra" HYDRA_HOSTNAME = "hydra-0" // VPN Host GITEA_HOST = "danicos.dev" ) + +const ( + FLUX_NAMESPACE = "flux-system" + FLUX_APPS_HYDRA_PATH = "./apps/" + HYDRA_CLUSTER + FLUX_CLUSTER_HYDRA_PATH = "./clusters/" + HYDRA_CLUSTER +) diff --git a/pkg/root/services.go b/pkg/root/services.go new file mode 100644 index 0000000..e2f0fb1 --- /dev/null +++ b/pkg/root/services.go @@ -0,0 +1,13 @@ +package root + +type Service struct { + Name string + Image string + Port int32 +} + +var Linkding = Service{ + Name: "linkding", + Image: "sissbruecket/linkding:1.31.0", + Port: 9090, +} diff --git a/scripts/install_flux.sh b/scripts/install_flux.sh index 7032697..cc96d77 100755 --- a/scripts/install_flux.sh +++ b/scripts/install_flux.sh @@ -13,4 +13,4 @@ flux --kubeconfig ~/.kube/$CLUSTER_NAME \ --private=false \ --branch=main \ --personal=true \ - --path=./clusters/hydra + --path=./clusters/$CLUSTER_NAME