├── .gitignore ├── bootstrap-resources ├── values.yaml ├── templates │ ├── clusterissuer.yaml │ ├── metallb.yaml │ └── ingress.yaml ├── .helmignore └── Chart.yaml ├── images ├── 1.png ├── 2.png ├── 3.png ├── 4.png ├── 5.png ├── 6.png └── yt.png ├── .helmignore ├── bootstrap.yaml ├── templates ├── application_metallb.yaml ├── application_nginx.yaml ├── application_cats.yaml ├── bootstrap-resources.yaml ├── application_kube-prom-stack-crds.yaml ├── application_tracing.yaml ├── application_logging.yaml ├── application_trivy.yaml ├── application_cert-manager.yaml ├── application_local-path-provisioner.yaml ├── application_kube-state-metrics.yaml └── application_observability.yaml ├── values.yaml ├── scripts ├── generate.sh └── read-only-access.yaml ├── Chart.yaml └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /bootstrap-resources/values.yaml: -------------------------------------------------------------------------------- 1 | domain: 2 | metallb: 3 | addresspool: -------------------------------------------------------------------------------- /images/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloud-native-skunkworks/gitops-kubernetes-bootstrap/HEAD/images/1.png -------------------------------------------------------------------------------- /images/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloud-native-skunkworks/gitops-kubernetes-bootstrap/HEAD/images/2.png -------------------------------------------------------------------------------- /images/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloud-native-skunkworks/gitops-kubernetes-bootstrap/HEAD/images/3.png -------------------------------------------------------------------------------- /images/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloud-native-skunkworks/gitops-kubernetes-bootstrap/HEAD/images/4.png -------------------------------------------------------------------------------- /images/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloud-native-skunkworks/gitops-kubernetes-bootstrap/HEAD/images/5.png -------------------------------------------------------------------------------- /images/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloud-native-skunkworks/gitops-kubernetes-bootstrap/HEAD/images/6.png -------------------------------------------------------------------------------- /images/yt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloud-native-skunkworks/gitops-kubernetes-bootstrap/HEAD/images/yt.png -------------------------------------------------------------------------------- /bootstrap-resources/templates/clusterissuer.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: cert-manager.io/v1 2 | kind: ClusterIssuer 3 | metadata: 4 | name: letsencrypt-ci 5 | spec: 6 | selfSigned: {} -------------------------------------------------------------------------------- /bootstrap-resources/templates/metallb.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: metallb.io/v1beta1 2 | kind: IPAddressPool 3 | metadata: 4 | name: default-ip-space 5 | namespace: metallb-system 6 | annotations: 7 | argocd.argoproj.io/sync-wave: "1" 8 | spec: 9 | addresses: 10 | - {{ .Values.metallb.addresspool}} -------------------------------------------------------------------------------- /.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /bootstrap-resources/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /bootstrap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Application 3 | metadata: 4 | name: bootstrap 5 | namespace: argocd 6 | spec: 7 | destination: 8 | namespace: argocd 9 | server: https://kubernetes.default.svc 10 | project: default 11 | source: 12 | path: . 13 | repoURL: https://github.com/cloud-native-skunkworks/gitops-kubernetes-bootstrap 14 | targetRevision: HEAD 15 | syncPolicy: 16 | automated: 17 | selfHeal: true 18 | syncOptions: 19 | - CreateNamespace=true 20 | -------------------------------------------------------------------------------- /templates/application_metallb.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Application 3 | metadata: 4 | name: metallb 5 | namespace: argocd 6 | annotations: 7 | argocd.argoproj.io/sync-wave: "-1" 8 | finalizers: 9 | - resources-finalizer.argocd.argoproj.io 10 | spec: 11 | project: default 12 | source: 13 | repoURL: 'https://metallb.github.io/metallb' 14 | chart: metallb 15 | targetRevision: 0.14.5 16 | destination: 17 | server: 'https://kubernetes.default.svc' 18 | namespace: metallb-system 19 | syncPolicy: 20 | automated: {} 21 | syncOptions: 22 | - CreateNamespace=true -------------------------------------------------------------------------------- /templates/application_nginx.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Application 3 | metadata: 4 | name: nginx 5 | namespace: argocd 6 | annotations: 7 | argocd.argoproj.io/sync-wave: "2" 8 | spec: 9 | destination: 10 | namespace: nginx-ingress 11 | server: https://kubernetes.default.svc 12 | project: default 13 | source: 14 | chart: nginx-ingress 15 | helm: 16 | parameters: 17 | - name: controller.kind 18 | value: daemonset 19 | repoURL: https://helm.nginx.com/stable 20 | targetRevision: 0.18.1 21 | syncPolicy: 22 | automated: 23 | prune: true 24 | syncOptions: 25 | - CreateNamespace=true 26 | -------------------------------------------------------------------------------- /values.yaml: -------------------------------------------------------------------------------- 1 | # Global 2 | ## Set the domain to create nginx for argocd and other service ingress 3 | domain: 4 | ## Set local if you wish to start the local path provisioner for "local-path" in your cluster 5 | storage: 6 | local: 7 | enable: true 8 | # Application specific 9 | cats: 10 | storageClass: "local-path" 11 | observability: 12 | storageClass: "local-path" 13 | pdkey: 14 | storageSize: 10Gi 15 | retention: 5d 16 | trivy: 17 | enable: false 18 | logging: 19 | enable: true 20 | metallb: 21 | # This only passes through to the bootstrap resources a single address pool, 22 | # you can use a range if you you want to do something more complex 23 | addresspool: 192.168.88.70/24 24 | -------------------------------------------------------------------------------- /templates/application_cats.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Application 3 | metadata: 4 | name: cats 5 | namespace: argocd 6 | finalizers: 7 | - resources-finalizer.argocd.argoproj.io 8 | spec: 9 | project: default 10 | source: 11 | repoURL: 'https://github.com/AlexsJones/cats' 12 | path: . 13 | targetRevision: HEAD 14 | helm: 15 | valueFiles: 16 | - values.yaml 17 | parameters: 18 | - name: image.tag 19 | value: main 20 | - name: storageclass 21 | value: {{ .Values.cats.storageClass }} 22 | destination: 23 | server: 'https://kubernetes.default.svc' 24 | namespace: cats 25 | syncPolicy: 26 | automated: {} 27 | syncOptions: 28 | - CreateNamespace=true 29 | -------------------------------------------------------------------------------- /templates/bootstrap-resources.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Application 3 | metadata: 4 | name: bootstrap-resources 5 | namespace: argocd 6 | spec: 7 | destination: 8 | namespace: argocd 9 | server: https://kubernetes.default.svc 10 | project: default 11 | source: 12 | path: bootstrap-resources 13 | repoURL: https://github.com/cloud-native-skunkworks/gitops-kubernetes-bootstrap 14 | targetRevision: HEAD 15 | helm: 16 | parameters: 17 | - name: domain 18 | value: {{ .Values.domain }} 19 | - name: metallb.addresspool 20 | value: {{ .Values.metallb.addresspool }} 21 | syncPolicy: 22 | automated: 23 | selfHeal: true 24 | syncOptions: 25 | - CreateNamespace=true 26 | -------------------------------------------------------------------------------- /templates/application_kube-prom-stack-crds.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Application 3 | metadata: 4 | name: kube-prometheus-stack-crds 5 | namespace: argocd 6 | annotations: 7 | argocd.argoproj.io/sync-wave: "2" 8 | finalizers: 9 | - resources-finalizer.argocd.argoproj.io 10 | spec: 11 | destination: 12 | server: 'https://kubernetes.default.svc' 13 | namespace: observability 14 | project: default 15 | source: 16 | repoURL: https://github.com/prometheus-community/helm-charts.git 17 | path: charts/kube-prometheus-stack/crds/ 18 | targetRevision: kube-prometheus-stack-55.5.0 19 | directory: 20 | recurse: true 21 | syncPolicy: 22 | syncOptions: 23 | - CreateNamespace=true 24 | - Replace=true 25 | automated: 26 | prune: true 27 | selfHeal: true 28 | -------------------------------------------------------------------------------- /templates/application_tracing.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.logging.enable }} 2 | apiVersion: argoproj.io/v1alpha1 3 | kind: Application 4 | metadata: 5 | name: tempo 6 | namespace: argocd 7 | annotations: 8 | argocd.argoproj.io/sync-wave: "2" 9 | finalizers: 10 | - resources-finalizer.argocd.argoproj.io 11 | spec: 12 | project: default 13 | source: 14 | repoURL: 'https://grafana.github.io/helm-charts' 15 | targetRevision: 1.5.0 16 | chart: tempo 17 | helm: 18 | releaseName: tempo 19 | parameters: 20 | - name: grafana.sidecar.datasources.enabled 21 | value: "false" 22 | destination: 23 | server: 'https://kubernetes.default.svc' 24 | namespace: observability 25 | syncPolicy: 26 | automated: 27 | selfHeal: true 28 | syncOptions: 29 | - CreateNamespace=true 30 | {{- end }} 31 | -------------------------------------------------------------------------------- /templates/application_logging.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.logging.enable }} 2 | apiVersion: argoproj.io/v1alpha1 3 | kind: Application 4 | metadata: 5 | name: logging 6 | namespace: argocd 7 | annotations: 8 | argocd.argoproj.io/sync-wave: "2" 9 | finalizers: 10 | - resources-finalizer.argocd.argoproj.io 11 | spec: 12 | project: default 13 | source: 14 | repoURL: 'https://grafana.github.io/helm-charts' 15 | targetRevision: 2.9.10 16 | chart: loki-stack 17 | helm: 18 | releaseName: loki 19 | parameters: 20 | - name: grafana.sidecar.datasources.enabled 21 | value: "false" 22 | destination: 23 | server: 'https://kubernetes.default.svc' 24 | namespace: observability 25 | syncPolicy: 26 | automated: 27 | selfHeal: true 28 | syncOptions: 29 | - CreateNamespace=true 30 | {{- end }} 31 | -------------------------------------------------------------------------------- /templates/application_trivy.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.trivy.enable }} 2 | apiVersion: argoproj.io/v1alpha1 3 | kind: Application 4 | metadata: 5 | name: trivy-operator 6 | namespace: argocd 7 | annotations: 8 | argocd.argoproj.io/sync-wave: "3" 9 | spec: 10 | project: default 11 | source: 12 | chart: trivy-operator 13 | repoURL: https://aquasecurity.github.io/helm-charts/ 14 | targetRevision: 0.19.0 15 | helm: 16 | values: | 17 | serviceMonitor: 18 | enabled: true # has to be false if you do not have Prometheus already installed 19 | trivy: 20 | ignoreUnfixed: true 21 | destination: 22 | server: https://kubernetes.default.svc 23 | namespace: trivy-system 24 | syncPolicy: 25 | automated: 26 | prune: true 27 | syncOptions: 28 | - CreateNamespace=true 29 | {{- end }} -------------------------------------------------------------------------------- /templates/application_cert-manager.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Application 3 | metadata: 4 | name: cert-manager 5 | namespace: argocd 6 | annotations: 7 | argocd.argoproj.io/sync-wave: "-2" 8 | finalizers: 9 | - resources-finalizer.argocd.argoproj.io 10 | spec: 11 | project: default 12 | source: 13 | repoURL: 'https://charts.jetstack.io' 14 | targetRevision: v1.14.4 15 | helm: 16 | parameters: 17 | - name: installCRDs 18 | value: 'true' 19 | - name: prometheus.servicemonitor.enabled 20 | value: 'false' 21 | - name: prometheus.servicemonitor.honorLabels 22 | value: 'true' 23 | chart: cert-manager 24 | destination: 25 | server: 'https://kubernetes.default.svc' 26 | namespace: cert-manager 27 | syncPolicy: 28 | automated: {} 29 | syncOptions: 30 | - CreateNamespace=true 31 | -------------------------------------------------------------------------------- /templates/application_local-path-provisioner.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.storage.local.enable }} 2 | apiVersion: argoproj.io/v1alpha1 3 | kind: Application 4 | metadata: 5 | name: localpath 6 | namespace: argocd 7 | annotations: 8 | argocd.argoproj.io/sync-wave: "-1" 9 | finalizers: 10 | - resources-finalizer.argocd.argoproj.io 11 | spec: 12 | project: default 13 | source: 14 | repoURL: 'https://github.com/rancher/local-path-provisioner.git' 15 | path: deploy/chart/local-path-provisioner 16 | targetRevision: HEAD 17 | helm: 18 | parameters: 19 | - name: rbac.create 20 | value: "true" 21 | - name: storageClass.defaultClass 22 | value: "true" 23 | destination: 24 | server: 'https://kubernetes.default.svc' 25 | namespace: local-path-storage 26 | syncPolicy: 27 | automated: {} 28 | syncOptions: 29 | - CreateNamespace=true 30 | {{- end }} 31 | -------------------------------------------------------------------------------- /scripts/generate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export CLUSTER_NAME="do-lon1-demo" 4 | 5 | export APISERVER=$(kubectl config view -o jsonpath="{.clusters[?(@.name==\"$CLUSTER_NAME\")].cluster.server}") 6 | 7 | export TOKEN=$(kubectl get secret sa1-token -o jsonpath='{.data.token}' | base64 --decode) 8 | 9 | 10 | server="https://378e3ca6-b825-44c4-85bc-a982fdc51242.k8s.ondigitalocean.com" 11 | ca=$(kubectl get secret/sa1-token -o jsonpath='{.data.ca\.crt}') 12 | token=$(kubectl get secret/sa1-token -o jsonpath='{.data.token}' | base64 --decode) 13 | namespace=$(kubectl get secret/sa1-token -o jsonpath='{.data.namespace}' | base64 --decode) 14 | 15 | echo " 16 | apiVersion: v1 17 | kind: Config 18 | clusters: 19 | - name: default-cluster 20 | cluster: 21 | certificate-authority-data: ${ca} 22 | server: ${server} 23 | contexts: 24 | - name: default-context 25 | context: 26 | cluster: default-cluster 27 | namespace: default 28 | user: default-user 29 | current-context: default-context 30 | users: 31 | - name: default-user 32 | user: 33 | token: ${token} 34 | " 35 | 36 | -------------------------------------------------------------------------------- /Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: gitops-cluster-bootstrap 3 | description: A Helm chart for Kubernetes 4 | 5 | # A chart can be either an 'application' or a 'library' chart. 6 | # 7 | # Application charts are a collection of templates that can be packaged into versioned archives 8 | # to be deployed. 9 | # 10 | # Library charts provide useful utilities or functions for the chart developer. They're included as 11 | # a dependency of application charts to inject those utilities and functions into the rendering 12 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 13 | type: application 14 | 15 | # This is the chart version. This version number should be incremented each time you make changes 16 | # to the chart and its templates, including the app version. 17 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 18 | version: 0.1.0 19 | 20 | # This is the version number of the application being deployed. This version number should be 21 | # incremented each time you make changes to the application. Versions are not expected to 22 | # follow Semantic Versioning. They should reflect the version the application is using. 23 | # It is recommended to use it with quotes. 24 | appVersion: "1.16.0" 25 | -------------------------------------------------------------------------------- /bootstrap-resources/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: bootstrap-resources 3 | description: A Helm chart for Kubernetes 4 | 5 | # A chart can be either an 'application' or a 'library' chart. 6 | # 7 | # Application charts are a collection of templates that can be packaged into versioned archives 8 | # to be deployed. 9 | # 10 | # Library charts provide useful utilities or functions for the chart developer. They're included as 11 | # a dependency of application charts to inject those utilities and functions into the rendering 12 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 13 | type: application 14 | 15 | # This is the chart version. This version number should be incremented each time you make changes 16 | # to the chart and its templates, including the app version. 17 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 18 | version: 0.1.0 19 | 20 | # This is the version number of the application being deployed. This version number should be 21 | # incremented each time you make changes to the application. Versions are not expected to 22 | # follow Semantic Versioning. They should reflect the version the application is using. 23 | # It is recommended to use it with quotes. 24 | appVersion: "1.16.0" 25 | -------------------------------------------------------------------------------- /scripts/read-only-access.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: read-only 5 | rules: 6 | - apiGroups: [""] 7 | resources: ["secrets"] 8 | verbs: [""] 9 | - apiGroups: 10 | - "" 11 | resources: 12 | - 'pods' 13 | verbs: 14 | - get 15 | - list 16 | - watch 17 | - apiGroups: 18 | - extensions 19 | resources: 20 | - '*' 21 | verbs: 22 | - get 23 | - list 24 | - watch 25 | - apiGroups: 26 | - apps 27 | resources: 28 | - '*' 29 | verbs: 30 | - get 31 | - list 32 | - watch 33 | --- 34 | kind: ClusterRoleBinding 35 | apiVersion: rbac.authorization.k8s.io/v1 36 | metadata: 37 | name: read-only-binding 38 | subjects: 39 | - kind: ServiceAccount 40 | name: read-only 41 | namespace: default 42 | roleRef: 43 | kind: ClusterRole 44 | name: read-only 45 | apiGroup: rbac.authorization.k8s.io 46 | --- 47 | apiVersion: v1 48 | kind: Secret 49 | metadata: 50 | name: sa1-token 51 | namespace: default 52 | annotations: 53 | kubernetes.io/service-account.name: read-only 54 | type: kubernetes.io/service-account-token 55 | --- 56 | 57 | apiVersion: v1 58 | kind: ServiceAccount 59 | metadata: 60 | name: read-only 61 | namespace: default 62 | secrets: 63 | - name: sa1-token 64 | -------------------------------------------------------------------------------- /bootstrap-resources/templates/ingress.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.domain }} 2 | apiVersion: networking.k8s.io/v1 3 | kind: Ingress 4 | metadata: 5 | name: ingress-grafana 6 | namespace: observability 7 | annotations: 8 | kubernetes.io/ingress.class: "nginx" 9 | cert-manager.io/issuer: "letsencrypt-ci" 10 | spec: 11 | tls: 12 | - hosts: 13 | - grafana.{{ .Values.domain }} 14 | secretName: nginx-grafana-tls 15 | rules: 16 | - host: grafana.{{ .Values.domain }} 17 | http: 18 | paths: 19 | - path: / 20 | pathType: Prefix 21 | backend: 22 | service: 23 | name: observability-grafana 24 | port: 25 | number: 80 26 | --- 27 | apiVersion: networking.k8s.io/v1 28 | kind: Ingress 29 | metadata: 30 | name: ingress-argocd 31 | namespace: argocd 32 | annotations: 33 | kubernetes.io/ingress.class: "nginx" 34 | cert-manager.io/issuer: "letsencrypt-ci" 35 | spec: 36 | tls: 37 | - hosts: 38 | - argocd.{{ .Values.domain }} 39 | secretName: nginx-argocd-tls 40 | rules: 41 | - host: argocd.{{ .Values.domain }} 42 | http: 43 | paths: 44 | - path: / 45 | pathType: Prefix 46 | backend: 47 | service: 48 | name: argocd-server 49 | port: 50 | number: 80 51 | {{- end }} -------------------------------------------------------------------------------- /templates/application_kube-state-metrics.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Application 3 | metadata: 4 | name: kube-state-metrics 5 | namespace: argocd 6 | annotations: 7 | argocd.argoproj.io/sync-wave: "1" 8 | finalizers: 9 | - resources-finalizer.argocd.argoproj.io 10 | spec: 11 | project: default 12 | source: 13 | repoURL: 'https://prometheus-community.github.io/helm-charts' 14 | targetRevision: 5.13.0 15 | chart: kube-state-metrics 16 | helm: 17 | values: | 18 | serviceMonitor: 19 | enabled: true 20 | metricLabelsAllowlist: 21 | - nodes=[*] 22 | - pods=[*] 23 | - deployments=[*] 24 | - statefulsets=[*] 25 | - daemonsets=[*] 26 | - replicasets=[*] 27 | - services=[*] 28 | - configmaps=[*] 29 | - secrets=[*] 30 | - persistentvolumeclaims=[*] 31 | - persistentvolumes=[*] 32 | - namespaces=[*] 33 | - resourcequotas=[*] 34 | - limitranges=[*] 35 | - nodes=[*] 36 | - pods=[*] 37 | - deployments=[*] 38 | - statefulsets=[*] 39 | - daemonsets=[*] 40 | - replicasets=[*] 41 | - services=[*] 42 | - configmaps=[*] 43 | - secrets=[*] 44 | - persistentvolumeclaims=[*] 45 | - persistentvolumes=[*] 46 | - namespaces=[*] 47 | - resourcequotas=[*] 48 | - limitranges=[*] 49 | destination: 50 | server: 'https://kubernetes.default.svc' 51 | namespace: observability 52 | syncPolicy: 53 | automated: 54 | prune: true 55 | selfHeal: true 56 | syncOptions: 57 | - CreateNamespace=true -------------------------------------------------------------------------------- /templates/application_observability.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Application 3 | metadata: 4 | name: observability 5 | namespace: argocd 6 | annotations: 7 | argocd.argoproj.io/sync-wave: "1" 8 | finalizers: 9 | - resources-finalizer.argocd.argoproj.io 10 | spec: 11 | project: default 12 | source: 13 | repoURL: 'https://prometheus-community.github.io/helm-charts' 14 | targetRevision: 55.5.0 15 | helm: 16 | skipCrds: true 17 | values: | 18 | {{ if .Values.observability.pdkey }} 19 | alertmanager: 20 | config: 21 | route: 22 | group_by: ['namespace'] 23 | group_wait: 30s 24 | group_interval: 5m 25 | repeat_interval: 12h 26 | receiver: default 27 | routes: 28 | - receiver: default 29 | matchers: 30 | - alertname =~ "InfoInhibitor|Watchdog" 31 | receivers: 32 | - name: default 33 | pagerduty_configs: 34 | - service_key: {{ .Values.observability.pdkey }} 35 | {{ end }} 36 | prometheus: 37 | prometheusSpec: 38 | podMonitorNamespaceSelector: 39 | any: true 40 | podMonitorSelector: {} 41 | podMonitorSelectorNilUsesHelmValues: false 42 | ruleNamespaceSelector: 43 | any: true 44 | ruleSelector: {} 45 | ruleSelectorNilUsesHelmValues: false 46 | serviceMonitorNamespaceSelector: 47 | any: true 48 | serviceMonitorSelector: {} 49 | serviceMonitorSelectorNilUsesHelmValues: false 50 | retention: {{ .Values.observability.retention }} 51 | storageSpec: 52 | volumeClaimTemplate: 53 | spec: 54 | storageClassName: {{ .Values.observability.storageClass }} 55 | accessModes: ["ReadWriteOnce"] 56 | resources: 57 | requests: 58 | storage: {{ .Values.observability.storageSize }} 59 | grafana: 60 | sidecar: 61 | dashboards: 62 | searchNamespace: ALL 63 | service: 64 | type: ClusterIP 65 | additionalDataSources: 66 | - name: loki 67 | type: loki 68 | url: http://loki.observability.svc.cluster.local:3100 69 | - name: tempo 70 | type: tempo 71 | url: http://tempo.observability.svc.cluster.local:3100 72 | 73 | 74 | chart: kube-prometheus-stack 75 | destination: 76 | server: 'https://kubernetes.default.svc' 77 | namespace: observability 78 | syncPolicy: 79 | automated: 80 | prune: true 81 | selfHeal: true 82 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## gitops-cluster-bootstrap 2 | 3 | This is an app-of-apps style start up repository for ArgoCD. 4 | 5 | The goal is to setup a production like set of workloads ( observability, security and example applications ). 6 | 7 | _See the video here_ 8 | 9 | 10 | 11 | 12 | 13 | ## Workloads 14 | 15 | Workloads are deployed through ArgoCD in an app-of-apps style deployment. 16 | Configuration of the application is done via the `bootstrap` root app that has it's own configuration within `values.yaml`. This is propagated into the child apps. 17 | 18 | When looking at the wider business context, we see how the applications in this repository can feed more broadly back into the business. 19 | 20 | ### bootstrap 21 | 22 | This folder contains application templates. You can either add a helm chart or git repository as the source. You can copy an existing application or import some you've written before for argocd. 23 | 24 | 25 | #### bootstrap-resources 26 | 27 | This folder contains the resources that are used by the bootstrap application. Such things might be application specific resources like network policies, ingress settings or service accounts. The idea is that this folder is continuously and automatically synced with the cluster. **It helps to get around the problem of having to make a another gitOps repo just for settings of an app.** 28 | 29 | 30 | 31 | 32 | ### Default applications 33 | 34 | | Application | Link | 35 | |------------------------|---------------------------------------------------------| 36 | | Cats | https://github.com/AlexsJones/cats | 37 | | Cert manager | https://charts.jetstack.io | 38 | | K8sgpt | https://charts.k8sgpt.ai/ | 39 | | Observability CRDS | https://github.com/prometheus-community/helm-charts.git | 40 | | Local path provisioner | https://github.com/rancher/local-path-provisioner.git | 41 | | Logging | https://grafana.github.io/helm-charts | 42 | | Metallb | https://metallb.github.io/metallb | 43 | | Observability | https://prometheus-community.github.io/helm-charts | 44 | | Nginx | https://helm.nginx.com/stable | 45 | | Trivy | https://aquasecurity.github.io/helm-charts/ | 46 | 47 | 48 | ## Prerequisites 49 | 50 | - Spin up a Kubernetes cluster on your favourite cloud provider or hardware 51 | 52 | - Setup argocd 53 | 54 | ``` 55 | kubectl create namespace argocd 56 | kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml 57 | ``` 58 | - Save the Argocd password 59 | ``` 60 | kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d 61 | ``` 62 | 63 | - Add this repository as a bootstrap cluster 64 | ``` 65 | kubectl apply -f bootstrap.yaml 66 | ``` 67 | 68 | 69 | ### Custom values 70 | 71 | Check `values.yaml` and adjust as required 72 | 73 | ## Credits 74 | 75 | Prometheus CRD's when used with ArgoCD apply can get big, so here is a hack to get arond the sync errors 76 | Thanks to [this](https://blog.ediri.io/kube-prometheus-stack-and-argocd-23-how-to-remove-a-workaround) guide. 77 | 78 | ### Software tooling BOM 79 | 80 | - kubectl 81 | - kubectx 82 | - k9s 83 | - jq 84 | - kustomize 85 | - helm 86 | - sshuttle 87 | --------------------------------------------------------------------------------