├── .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 |
--------------------------------------------------------------------------------