├── .gitignore
├── .travis.yml
├── Makefile
├── README.md
├── applications
├── Chart.yaml
├── templates
│ ├── ambassador
│ │ ├── ambassador-mapping.yaml
│ │ ├── ambassador.yaml
│ │ ├── namespace.yaml
│ │ └── project.yaml
│ ├── argocd
│ │ └── argocd.yaml
│ ├── guestbook
│ │ ├── guestbook.yaml
│ │ ├── namespace.yaml
│ │ └── project.yaml
│ ├── kube-system
│ │ ├── kubernetes-dashboard.yaml
│ │ ├── metrics-server.yaml
│ │ ├── project.yaml
│ │ └── spotify-docker-gc.yaml
│ └── observe
│ │ ├── cerebro.yaml
│ │ ├── curator.yaml
│ │ ├── elasticsearch.yaml
│ │ ├── fluent-bit.yaml
│ │ ├── kibana.yaml
│ │ ├── kube-ops-view.yaml
│ │ ├── namespace.yaml
│ │ ├── project.yaml
│ │ └── prometheus-operator.yaml
└── values.yaml
├── charts
├── ambassador-mapping
│ ├── Chart.yaml
│ ├── templates
│ │ ├── ambassador-mapping.yaml
│ │ ├── guestbook-mapping.yaml
│ │ └── httpbin-mapping.yaml
│ └── values.yaml
└── seed
│ ├── Chart.yaml
│ ├── requirements.yaml
│ ├── templates
│ ├── applications.yaml
│ ├── namespace.yaml
│ └── project.yaml
│ └── values.yaml
├── docs
├── Weaveworks_ContinuousDelivery_wp_2018.pdf
├── charts-TODO.txt
├── img
│ ├── architecture.png
│ ├── argocd-ui.png
│ ├── bootstrap.png
│ ├── charts.png
│ └── gitops-k8s.drawio
└── setup.md
└── scripts
├── bootstrap.sh
└── publish_seed.sh
/.gitignore:
--------------------------------------------------------------------------------
1 | *~
2 | .DS_Store
3 |
4 | *.lock
5 | *.tgz
6 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: bash
2 |
3 | before_install:
4 | - curl -L https://git.io/get_helm.sh | bash
5 |
6 | script:
7 | # verify all charts
8 | - find . -maxdepth 3 -type f -name 'Chart.yaml' -exec dirname {} \; | xargs helm lint
9 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | .DEFAULT_GOAL := all
2 |
3 | HELM := $(shell command -v helm 2> /dev/null)
4 |
5 | .PHONY: requirements
6 | requirements:
7 | ifndef HELM
8 | $(error "helm" not found)
9 | endif
10 |
11 | # publish to https://edgelevel.github.io/gitops-k8s
12 | .PHONY: publish-seed
13 | publish-seed: requirements
14 | ./scripts/publish_seed.sh
15 |
16 | .PHONY: bootstrap
17 | bootstrap: requirements
18 | ./scripts/bootstrap.sh
19 |
20 | .PHONY: all
21 | all: requirements
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # gitops-k8s
2 |
3 | [![Build Status][travis-image]][travis-url]
4 |
5 | [travis-image]: https://travis-ci.org/edgelevel/gitops-k8s.svg?branch=master
6 | [travis-url]: https://travis-ci.org/edgelevel/gitops-k8s
7 |
8 | This document aims to provide an opinionated working solution leveraging Kubernetes and proven GitOps techniques to have a resilient, composable and scalable Kubernetes platform.
9 |
10 | Nothing outlined below is new or innovative, but it should be at least a good starting point to have a cluster up and running pretty quickly and give you a chance to remain focused and try out new ideas.
11 |
12 | Feedback and help are always welcome!
13 |
14 | * [Introduction](#introduction)
15 | * [Argo CD](#argo-cd)
16 | * [Applications](#applications)
17 |
18 | ---
19 |
20 | ## Introduction
21 |
22 | ### TL;DR
23 |
24 | * Kubernetes is a declarative system
25 | * Git can be used to describe infrastructure and applications
26 | * Git repository is the source of truth and represents a cluster
27 | * GitOps is a way to do Continuous Delivery and operate Kubernetes via Git pull requests
28 | * GitOps empowers developers to do operations
29 | * CI pipelines should only run builds, tests and publish images
30 | * In a pull-based approach, an operator deploys new images from inside of the cluster
31 | * You can only observe the actual state of the cluster and react when it diverges from the desired state
32 |
33 | ### Imperative vs Declarative
34 |
35 | In an *imperative* system, the user knows the desired state, determines the sequence of commands to transition the system to the desired state and supplies a representation of the commands to the system.
36 |
37 | By contrast, in a *declarative* system, the user knows the desired state, supplies a representation of the desired state to the system, then the system reads the current state and determines the sequence of commands to transition the system to the desired state.
38 |
39 | Declarative systems have the distinct advantage of being able to react to unintended state changes without further supervision. In the event of an unintended state change leading to a state drift, the system may autonomously determine and apply the set of mitigating actions leading to a state match. This process is called a **control loop**, a popular choice for the implementation of controllers.
40 |
41 | ### What is GitOps?
42 |
43 | GitOps is the art and science of using Git pull requests to manage infrastructure provisioning and software deployment.
44 |
45 | The concept of GitOps originated at Weaveworks, whose developers described how they use Git to create a **single source of truth**. Kubernetes is a **declarative** system and by using declarative tools, the entire set of configuration files can be version controlled in Git.
46 |
47 | More generally, GitOps is a way to do Continuous Delivery and operate Kubernetes via Git.
48 |
49 | ### Push vs Pull
50 |
51 | In a *push*-based pipeline, the CI system runs build and tests, followed by a deployment directly to Kubernetes. This is an *anti-pattern*. CI server is not an orchestration tool. You need something that continually attempts to make progress until there are no more diffs because CI fails when it encounters a difference and then you could end up being in a partial and unknown state.
52 |
53 | In a *pull*-based pipeline, a Kubernetes **operator** deploys new images from inside of the cluster. The operator notices when a new image has been pushed to the registry. Convergence of the cluster state is then triggered and the new image is pulled from the registry, the manifest is automatically updated and the new image is deployed to the cluster.
54 |
55 | A CI pipeline should be used to merge and integrate updates with master, while with GitOps you should rely on Kubernetes or the cluster to internally manage deployments based on those master updates.
56 |
57 | You could potentially have multiple cluster pointing to the same GitOps repository, but you won't have a centralized view of them, all the clusters will be independent.
58 |
59 | ### Observability
60 |
61 | Git provides a source of truth for the desired state of the system and *observability* provides a source of truth for the actual state of the running system.
62 |
63 | You cannot say what actual state is in the cluster. You can only observe it. This is why diffs are so important.
64 |
65 | A system is observable if developers can understand its current state from the outside. Observability is a property of systems like Availability and Scalability. Monitoring, Tracing and Logging are techniques for baseline observations.
66 |
67 | Observability is a source of truth for the actual running state of the system right now. You observe the running system in order to understand and control it. Observed state must be compared with the desired state in Git and usually you want to monitor and alert when the system diverge from the desired state.
68 |
69 | **Resources**
70 |
71 | * [Imperative vs Declarative](https://medium.com/@dominik.tornow/imperative-vs-declarative-8abc7dcae82e)
72 | * [GitOps - Operations by Pull Request](https://www.weave.works/blog/gitops-operations-by-pull-request) (Part 1)
73 | * [The GitOps Pipeline](https://www.weave.works/blog/the-gitops-pipeline) (Part 2)
74 | * [GitOps - Observability](https://www.weave.works/blog/gitops-part-3-observability) (Part 3)
75 | * [GitOps - Application Delivery Compliance and Secure CICD](https://www.weave.works/blog/gitops-compliance-and-secure-cicd) (Part 4)
76 | * [Making the Leap from Continuous Integration to Continuous Delivery](docs/Weaveworks_ContinuousDelivery_wp_2018.pdf) (Whitepaper)
77 | * [What is GitOps really?](https://www.weave.works/blog/what-is-gitops-really)
78 | * [Why is a PULL vs a PUSH pipeline important?](https://www.weave.works/blog/why-is-a-pull-vs-a-push-pipeline-important)
79 | * [Kubernetes anti-patterns: Let's do GitOps, not CIOps!](https://www.weave.works/blog/kubernetes-anti-patterns-let-s-do-gitops-not-ciops)
80 | * [GitOps: High velocity CICD for Kubernetes](https://www.weave.works/blog/gitops-high-velocity-cicd-for-kubernetes)
81 | * [GitOps - What you need to know](https://www.weave.works/technologies/gitops)
82 | * [GitOps for Kubernetes - A DevOps Iteration Focused on Declarative Infrastructure](https://youtu.be/wJleh-6DZJ0)
83 | * [Automating continuous delivery with Kubernetes, Google Cloud and Git](https://vimeo.com/255633066)
84 | * [Continuous Delivery the Hard Way](https://www.weave.works/blog/continuous-delivery-the-hard-way)
85 |
86 | ## Argo CD
87 |
88 | Argo CD is a declarative, GitOps continuous delivery tool for Kubernetes. It automates the deployment of the desired application states in the specified target environments. In this project Kubernetes manifests are specified as [helm](https://helm.sh/docs) charts.
89 |
90 | This guide will explain how to setup in few steps the whole infrastructure via GitOps with Argo CD. Note that it's not tightly coupled to any specific vendor and you should be able to easily run it on [DigitalOcean](https://www.digitalocean.com/docs/kubernetes), [EKS](https://aws.amazon.com/eks) or [GKE](https://cloud.google.com/kubernetes-engine) for example.
91 |
92 |
95 |
96 |
97 |
98 |
99 |
100 | Most of the steps have been kept manual on purpose, but they should be automated in a production enviroment.
101 |
102 | ### Prerequisites
103 |
104 | * [Setup](docs/setup.md) required tools
105 | * Create a Kubernetes cluster locally or with your favourite provider
106 | * Download the cluster configs and test connection
107 | ```bash
108 | export KUBECONFIG=~/.kube/-kubeconfig.yaml
109 | kubectl get nodes
110 | ```
111 |
112 | ### Bootstrap
113 |
114 | 1. *TODO Setup secrets (optional)*
115 | 2. Setup Argo CD and all the applications
116 | ```bash
117 | make bootstrap
118 | ```
119 | 3. Access Argo CD
120 | ```bash
121 | # username: admin
122 | # password: (autogenerated) the pod name of the Argo CD API server
123 | kubectl get pods -n argocd -l app.kubernetes.io/name=argocd-server -o name | cut -d'/' -f 2
124 |
125 | # port forward the service
126 | kubectl port-forward service/argocd-server -n argocd 8080:443
127 |
128 | # from the UI
129 | [open|xdg-open] https://localhost:8080
130 | # from the CLI
131 | argocd login localhost:8080 --username admin
132 | ```
133 | * You might need to *Allow invalid certificates for resources loaded from localhost* on Chrome enabling the flag `chrome://flags/#allow-insecure-localhost` to access it
134 | 4. First time only sync all the `OutOfSync` applications
135 | * manually
136 | * *TODO with a cronjob (optional)*
137 | * verify [guestbook](https://github.com/argoproj/argocd-example-apps/tree/master/guestbook) example
138 | ```bash
139 | # port forward the service
140 | kubectl port-forward service/guestbook-ui -n guestbook 8081:80
141 | # open browser
142 | [open|xdg-open] http://localhost:8081
143 | ```
144 |
145 | This is how it should looks like on the UI
146 |
147 | 
148 |
149 | **Resources**
150 |
151 | * [Introducing Argo CD](https://blog.argoproj.io/introducing-argo-cd-declarative-continuous-delivery-for-kubernetes-da2a73a780cd)
152 | * [Argo CD - Declarative Continuous Delivery for Kubernetes](https://argoproj.github.io/argo-cd)
153 |
154 | ## Applications
155 |
156 | Applications in this repository are defined in the parent [applications](applications/templates) chart and are logically split into folders which represent Kubernetes namespaces.
157 |
158 |
159 |
160 |
161 |
162 | **`ambassador`** namespace is dedicated for [Ambassador](https://www.getambassador.io), a lightweight Kubernetes-native microservices API gateway built on the Envoy Proxy which is mainly used for routing and supports canary deployments, traffic shadowing, rate limiting, authentication and more
163 | ```bash
164 | # retrieve EXTERNAL-IP
165 | kubectl get service ambassador -n ambassador
166 | [open|xdg-open] http:///ambassador
167 | [open|xdg-open] http:///httpbin/
168 | [open|xdg-open] http:///guestbook
169 |
170 | # debug ambassador
171 | kubectl port-forward service/ambassador-admins 8877 -n ambassador
172 | [open|xdg-open] http://localhost:8877/ambassador/v0/diag
173 | ```
174 |
175 | *Ambassador is [disabled](applications/values.yaml) by default because the recommended way is to use host-based routing which requires a domain*
176 |
177 | For a working example on DigitalOcean using [`external-dns`](https://github.com/helm/charts/tree/master/stable/external-dns) you can have a look at [niqdev/do-k8s](https://github.com/niqdev/do-k8s)
178 |
179 | *TODO Service mesh*
180 |
181 | * [Istio](https://istio.io)
182 | * [A Crash Course For Running Istio](https://medium.com/namely-labs/a-crash-course-for-running-istio-1c6125930715)
183 |
184 | **`observe`** namespace is dedicated for observability and in the specific Monitoring, Alerting and Logging
185 |
186 | * [`prometheus-operator`](https://github.com/helm/charts/tree/master/stable/prometheus-operator) provides monitoring and alerting managing Prometheus, Alertmanager and Grafana
187 | ```bash
188 | # prometheus
189 | kubectl port-forward service/prometheus-operator-prometheus 8001:9090 -n observe
190 |
191 | # alertmanager
192 | kubectl port-forward service/prometheus-operator-alertmanager 8002:9093 -n observe
193 |
194 | # grafana
195 | # username: admin
196 | # password: prom-operator
197 | kubectl port-forward service/prometheus-operator-grafana 8003:80 -n observe
198 | ```
199 |
200 | * [`kube-ops-view`](https://github.com/helm/charts/tree/master/stable/kube-ops-view) provides a read-only system dashboard for multiple k8s clusters
201 | ```bash
202 | kubectl port-forward service/kube-ops-view -n observe 8004:80
203 | ```
204 |
205 | *EFK stack for logging*
206 |
207 | * [`elasticsearch`](https://github.com/elastic/helm-charts/tree/master/elasticsearch) is a distributed, RESTful search and analytics engine and it's used for log storage
208 | ```bash
209 | kubectl port-forward service/elasticsearch-master 9200:9200 -n observe
210 | ```
211 |
212 | * [`cerebro`](https://github.com/helm/charts/tree/master/stable/cerebro) is an Elasticsearch web admin tool
213 | ```bash
214 | kubectl port-forward service/cerebro 9000:80 -n observe
215 | ```
216 |
217 | * [`kibana`](https://github.com/elastic/helm-charts/tree/master/kibana) visualize and query the log data stored in an Elasticsearch index
218 | ```bash
219 | kubectl port-forward service/kibana-kibana 9001:5601 -n observe
220 | ```
221 | * [`fluentbit`](https://github.com/helm/charts/tree/master/stable/fluent-bit) is a fast and lightweight Log Processor and Forwarder
222 |
223 | * [`elasticsearch-curator`](https://github.com/helm/charts/tree/master/stable/elasticsearch-curator) or [`curator`](https://github.com/giantswarm/curator) helps to curate, or manage, Elasticsearch indices and snapshots
224 |
225 | **Resources**
226 |
227 | * [Prometheus](https://prometheus.io/docs/introduction/overview)
228 | * Prometheus Operator - [Getting Started Guide](https://coreos.com/operators/prometheus/docs/latest/user-guides/getting-started.html)
229 | * Grafana - [Dashboards](https://grafana.com/dashboards)
230 | * [Fluent Bit](https://docs.fluentbit.io/manual)
231 | * [Logging Best Practices for Kubernetes using Elasticsearch, Fluent Bit and Kibana](https://itnext.io/logging-best-practices-for-kubernetes-using-elasticsearch-fluent-bit-and-kibana-be9b7398dfee)
232 | * [Exporting Kubernetes Logs to Elasticsearch Using Fluent Bit](https://supergiant.io/blog/exporting-kubernetes-logs-to-elasticsearch-using-fluent-bit)
233 | * [Fluentd vs. Fluent Bit: Side by Side Comparison](https://logz.io/blog/fluentd-vs-fluent-bit)
234 | * [Logging & Monitoring of Kubernetes Applications: Requirements & Recommended Toolset](https://platform9.com/blog/logging-monitoring-of-kubernetes-applications-requirements-recommended-toolset)
235 | * [Loki](https://github.com/grafana/loki)
236 |
237 | **`kube-system`** namespace is reserved for Kubernete system applications
238 |
239 | * [`kubernetes-dashboard`](https://github.com/helm/charts/tree/master/stable/kubernetes-dashboard) is a general purpose, web-based UI for Kubernetes clusters. It allows users to manage applications running in the cluster and troubleshoot them, as well as manage the cluster itself
240 | ```bash
241 | kubectl port-forward service/kubernetes-dashboard -n kube-system 8000:443
242 | ```
243 |
244 | * [`metrics-server`](https://github.com/helm/charts/tree/master/stable/metrics-server) is an add-on which extends the metrics api group and enables the Kubernetes resource `HorizontalPodAutoscaler`
245 | ```bash
246 | kubectl top node
247 | kubectl top pod --all-namespaces
248 | ```
249 |
250 | * [`spotify-docker-gc`](https://github.com/helm/charts/tree/master/stable/spotify-docker-gc) performs garbage collection in the Kubernetes cluster and the default configurations have the gc running once a day which:
251 | * removes containers that exited more than a hour ago
252 | * removes images that don't belong to any container
253 | * removes volumes that are not associated to any remaining container
254 |
255 | ---
256 |
257 | ### TODO (not in order)
258 |
259 | * [ ] argocd: example secrets for private charts
260 | * [ ] argocd: override default `admin.password`
261 | * [ ] argocd-bootstrap: open source and explain solution of how to sync automatically first time with cronjob
262 | * [ ] expose argocd over http i.e. `--insecure` flag
263 | * [ ] configure TLS/cert and authentication on ambassador for all services
264 | * [ ] centralize auth on ambassador/istio
265 | * [ ] [Jaeger](https://www.jaegertracing.io) tracing
266 | * [ ] [kube-monkey](https://github.com/asobti/kube-monkey) or [chaoskube](https://github.com/helm/charts/tree/master/stable/chaoskube)
267 | * [ ] explain how to switch cluster via DNS
268 | * [ ] Kafka from public chart + [JMX fix](https://github.com/helm/charts/pull/10799/files)
269 | * [ ] stateless vs stateful: disaster recovery stratecy e.g S3 backup/restore
270 | * [ ] example with multiple providers: DigitalOcean, EKS, GKE
271 | * [ ] add prometheus adapter for custom metrics that can be used by the [HorizontalPodAutoscaler](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale)
272 | * [ ] explain how to test a branch i.e. change target revision from the UI
273 | * [ ] TODO fix `alertmanager: error: unrecognized log format "", try --help`
274 | * [ ] add screenshots to readme for each app
275 | * [ ] explain how to add grafana dashboards with `ConfigMap`
276 | * [ ] add alerting example on Slack/PagerDuty
277 | * [ ] add example of prometheus `ServiceMonitor` + dashboard
278 | * [ ] explain how to init es index on kibana for logging + screenshot
279 | * [ ] add `kubefwd` to docs
280 | * [ ] argocd [issue](https://github.com/argoproj/argo-cd/issues/1786): Add support for secrets in Application parameters
281 | * [ ] argocd [issue](https://github.com/argoproj/argo-cd/issues/1145): Helm repository as first class Argo CD Application source
282 |
--------------------------------------------------------------------------------
/applications/Chart.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | name: applications
3 | version: 0.1.0
4 |
--------------------------------------------------------------------------------
/applications/templates/ambassador/ambassador-mapping.yaml:
--------------------------------------------------------------------------------
1 | {{- if .Values.ambassador.enabled }}
2 | ---
3 | apiVersion: argoproj.io/v1alpha1
4 | kind: Application
5 | metadata:
6 | name: ambassador-mapping
7 | spec:
8 | project: ambassador
9 | source:
10 | repoURL: https://github.com/edgelevel/gitops-k8s.git
11 | path: charts/ambassador-mapping
12 | destination:
13 | server: https://kubernetes.default.svc
14 | namespace: ambassador
15 | {{- end }}
16 |
--------------------------------------------------------------------------------
/applications/templates/ambassador/ambassador.yaml:
--------------------------------------------------------------------------------
1 | {{- if .Values.ambassador.enabled }}
2 | ---
3 | apiVersion: argoproj.io/v1alpha1
4 | kind: Application
5 | metadata:
6 | name: ambassador
7 | spec:
8 | project: ambassador
9 | source:
10 | repoURL: https://github.com/helm/charts.git
11 | path: stable/ambassador
12 | helm:
13 | parameters:
14 | - name: replicaCount
15 | value: "1"
16 | destination:
17 | server: https://kubernetes.default.svc
18 | namespace: ambassador
19 | {{- end }}
20 |
--------------------------------------------------------------------------------
/applications/templates/ambassador/namespace.yaml:
--------------------------------------------------------------------------------
1 | {{- if .Values.ambassador.enabled }}
2 | ---
3 | apiVersion: v1
4 | kind: Namespace
5 | metadata:
6 | name: ambassador
7 | {{- end }}
8 |
--------------------------------------------------------------------------------
/applications/templates/ambassador/project.yaml:
--------------------------------------------------------------------------------
1 | {{- if .Values.ambassador.enabled }}
2 | ---
3 | apiVersion: argoproj.io/v1alpha1
4 | kind: AppProject
5 | metadata:
6 | name: ambassador
7 | spec:
8 | sourceRepos:
9 | - https://github.com/helm/charts.git
10 | - https://github.com/edgelevel/gitops-k8s.git
11 | destinations:
12 | - namespace: ambassador
13 | server: https://kubernetes.default.svc
14 | clusterResourceWhitelist:
15 | - group: rbac.authorization.k8s.io
16 | kind: ClusterRoleBinding
17 | - group: rbac.authorization.k8s.io
18 | kind: ClusterRole
19 | - group: apiextensions.k8s.io
20 | kind: CustomResourceDefinition
21 | {{- end }}
22 |
--------------------------------------------------------------------------------
/applications/templates/argocd/argocd.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: argoproj.io/v1alpha1
3 | kind: Application
4 | metadata:
5 | name: argocd
6 | spec:
7 | project: argocd
8 | source:
9 | repoURL: https://github.com/edgelevel/helm-charts.git
10 | path: argocd
11 | destination:
12 | server: https://kubernetes.default.svc
13 | namespace: argocd
14 |
--------------------------------------------------------------------------------
/applications/templates/guestbook/guestbook.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: argoproj.io/v1alpha1
3 | kind: Application
4 | metadata:
5 | name: guestbook
6 | spec:
7 | project: guestbook
8 | source:
9 | repoURL: https://github.com/argoproj/argocd-example-apps.git
10 | path: guestbook
11 | #targetRevision: HEAD
12 | destination:
13 | server: https://kubernetes.default.svc
14 | namespace: guestbook
15 |
--------------------------------------------------------------------------------
/applications/templates/guestbook/namespace.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: v1
3 | kind: Namespace
4 | metadata:
5 | name: guestbook
6 |
--------------------------------------------------------------------------------
/applications/templates/guestbook/project.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: argoproj.io/v1alpha1
3 | kind: AppProject
4 | metadata:
5 | name: guestbook
6 | spec:
7 | sourceRepos:
8 | - https://github.com/argoproj/argocd-example-apps.git
9 | destinations:
10 | - namespace: guestbook
11 | server: https://kubernetes.default.svc
12 |
--------------------------------------------------------------------------------
/applications/templates/kube-system/kubernetes-dashboard.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: argoproj.io/v1alpha1
3 | kind: Application
4 | metadata:
5 | name: kubernetes-dashboard
6 | spec:
7 | project: kube-system
8 | source:
9 | repoURL: https://github.com/helm/charts.git
10 | path: stable/kubernetes-dashboard
11 | helm:
12 | parameters:
13 | - name: enableSkipLogin
14 | value: "true"
15 | - name: enableInsecureLogin
16 | value: "true"
17 | - name: rbac.clusterAdminRole
18 | value: "true"
19 | destination:
20 | server: https://kubernetes.default.svc
21 | namespace: kube-system
22 |
--------------------------------------------------------------------------------
/applications/templates/kube-system/metrics-server.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: argoproj.io/v1alpha1
3 | kind: Application
4 | metadata:
5 | name: metrics-server
6 | spec:
7 | project: kube-system
8 | source:
9 | repoURL: https://github.com/helm/charts.git
10 | path: stable/metrics-server
11 | helm:
12 | parameters:
13 | - name: serviceAccount.name
14 | value: metrics-server
15 | - name: resources.requests.memory
16 | value: 50Mi
17 | - name: resources.limits.memory
18 | value: 50Mi
19 | - name: args[0]
20 | value: "--kubelet-preferred-address-types=InternalIP"
21 | - name: args[1]
22 | value: "--logtostderr"
23 | - name: args[2]
24 | value: "--kubelet-insecure-tls"
25 | destination:
26 | server: https://kubernetes.default.svc
27 | namespace: kube-system
28 |
--------------------------------------------------------------------------------
/applications/templates/kube-system/project.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: argoproj.io/v1alpha1
3 | kind: AppProject
4 | metadata:
5 | name: kube-system
6 | spec:
7 | clusterResourceWhitelist:
8 | - group: rbac.authorization.k8s.io
9 | kind: ClusterRoleBinding
10 | - group: rbac.authorization.k8s.io
11 | kind: ClusterRole
12 | - group: apiextensions.k8s.io
13 | kind: CustomResourceDefinition
14 | - group: apiregistration.k8s.io
15 | kind: APIService
16 | sourceRepos:
17 | - https://github.com/helm/charts.git
18 | destinations:
19 | - server: https://kubernetes.default.svc
20 | namespace: kube-system
21 |
--------------------------------------------------------------------------------
/applications/templates/kube-system/spotify-docker-gc.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: argoproj.io/v1alpha1
3 | kind: Application
4 | metadata:
5 | name: spotify-docker-gc
6 | spec:
7 | project: kube-system
8 | source:
9 | repoURL: https://github.com/helm/charts.git
10 | path: stable/spotify-docker-gc
11 | destination:
12 | server: https://kubernetes.default.svc
13 | namespace: kube-system
14 |
--------------------------------------------------------------------------------
/applications/templates/observe/cerebro.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: argoproj.io/v1alpha1
3 | kind: Application
4 | metadata:
5 | name: cerebro
6 | spec:
7 | project: observe
8 | source:
9 | repoURL: https://github.com/helm/charts.git
10 | path: stable/cerebro
11 | helm:
12 | parameters:
13 | - name: config.hosts[0].host
14 | value: http://elasticsearch-master.observe:9200
15 | - name: config.hosts[0].name
16 | value: elasticsearch-observe
17 | destination:
18 | server: https://kubernetes.default.svc
19 | namespace: observe
20 |
--------------------------------------------------------------------------------
/applications/templates/observe/curator.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: argoproj.io/v1alpha1
3 | kind: Application
4 | metadata:
5 | name: curator
6 | spec:
7 | project: observe
8 | source:
9 | repoURL: https://github.com/helm/charts.git
10 | path: stable/elasticsearch-curator
11 | destination:
12 | server: https://kubernetes.default.svc
13 | namespace: observe
14 |
--------------------------------------------------------------------------------
/applications/templates/observe/elasticsearch.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: argoproj.io/v1alpha1
3 | kind: Application
4 | metadata:
5 | name: elasticsearch
6 | spec:
7 | project: observe
8 | source:
9 | repoURL: https://github.com/elastic/helm-charts.git
10 | path: elasticsearch
11 | helm:
12 | # see https://github.com/elastic/helm-charts/blob/master/elasticsearch/examples/minikube/values.yaml
13 | parameters:
14 | - name: antiAffinity
15 | value: "soft"
16 | - name: esJavaOpts
17 | value: "-Xmx128m -Xms128m"
18 | - name: resources.requests.cpu
19 | value: "100m"
20 | - name: resources.requests.memory
21 | value: "512M"
22 | - name: resources.limits.memory
23 | value: "512M"
24 | - name: volumeClaimTemplate.resources.requests.storage
25 | value: "1Gi"
26 | - name: volumeClaimTemplate.storageClassName
27 | value: "standard"
28 | destination:
29 | server: https://kubernetes.default.svc
30 | namespace: observe
31 |
--------------------------------------------------------------------------------
/applications/templates/observe/fluent-bit.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: argoproj.io/v1alpha1
3 | kind: Application
4 | metadata:
5 | name: fluent-bit
6 | spec:
7 | project: observe
8 | source:
9 | repoURL: https://github.com/helm/charts.git
10 | path: stable/fluent-bit
11 | helm:
12 | parameters:
13 | - name: rbac.create
14 | value: "false"
15 | - name: serviceAccount.create
16 | value: "false"
17 | - name: backend.type
18 | value: es
19 | - name: backend.es.host
20 | value: elasticsearch-master.observe
21 | - name: backend.es.port
22 | value: "9200"
23 | - name: parsers.enabled
24 | value: "true"
25 | - name: parsers.json[0].name
26 | value: "docker"
27 | - name: parsers.json[0].timeKeep
28 | value: "On"
29 | - name: parsers.json[0].timeKey
30 | value: "time"
31 | - name: parsers.json[0].timeFormat
32 | value: "%Y-%m-%dT%H:%M:%S.%L"
33 | - name: parsers.json[0].extraEntries
34 | value: "\nDecode_Field_As escaped_utf8 log do_next\nDecode_Field_As json log"
35 | destination:
36 | server: https://kubernetes.default.svc
37 | namespace: observe
38 |
--------------------------------------------------------------------------------
/applications/templates/observe/kibana.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: argoproj.io/v1alpha1
3 | kind: Application
4 | metadata:
5 | name: kibana
6 | spec:
7 | project: observe
8 | source:
9 | repoURL: https://github.com/elastic/helm-charts.git
10 | path: kibana
11 | destination:
12 | server: https://kubernetes.default.svc
13 | namespace: observe
14 |
--------------------------------------------------------------------------------
/applications/templates/observe/kube-ops-view.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: argoproj.io/v1alpha1
3 | kind: Application
4 | metadata:
5 | name: kube-ops-view
6 | spec:
7 | project: observe
8 | source:
9 | repoURL: https://github.com/helm/charts.git
10 | path: stable/kube-ops-view
11 | helm:
12 | parameters:
13 | - name: rbac.create
14 | value: "true"
15 | destination:
16 | server: https://kubernetes.default.svc
17 | namespace: observe
18 |
--------------------------------------------------------------------------------
/applications/templates/observe/namespace.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: v1
3 | kind: Namespace
4 | metadata:
5 | name: observe
6 |
--------------------------------------------------------------------------------
/applications/templates/observe/project.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: argoproj.io/v1alpha1
3 | kind: AppProject
4 | metadata:
5 | name: observe
6 | spec:
7 | sourceRepos:
8 | - https://github.com/helm/charts.git
9 | - https://github.com/elastic/helm-charts.git
10 | destinations:
11 | - namespace: observe
12 | server: https://kubernetes.default.svc
13 | - namespace: kube-system
14 | server: https://kubernetes.default.svc
15 | clusterResourceWhitelist:
16 | - group: rbac.authorization.k8s.io
17 | kind: ClusterRoleBinding
18 | - group: rbac.authorization.k8s.io
19 | kind: ClusterRole
20 | - group: apiextensions.k8s.io
21 | kind: CustomResourceDefinition
22 | - group: policy
23 | kind: PodSecurityPolicy
24 | - group: extensions
25 | kind: PodSecurityPolicy
26 |
--------------------------------------------------------------------------------
/applications/templates/observe/prometheus-operator.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: argoproj.io/v1alpha1
3 | kind: Application
4 | metadata:
5 | name: prometheus-operator
6 | spec:
7 | project: observe
8 | source:
9 | repoURL: https://github.com/helm/charts.git
10 | path: stable/prometheus-operator
11 | helm:
12 | parameters:
13 | - name: kubeEtcd.enabled
14 | value: "false"
15 | - name: kubeControllerManager.enabled
16 | value: "false"
17 | - name: kubeScheduler.enabled
18 | value: "false"
19 | destination:
20 | server: https://kubernetes.default.svc
21 | namespace: observe
22 |
--------------------------------------------------------------------------------
/applications/values.yaml:
--------------------------------------------------------------------------------
1 | ambassador:
2 | enabled: false
3 |
--------------------------------------------------------------------------------
/charts/ambassador-mapping/Chart.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | name: ambassador-mapping
3 | version: 0.1.0
4 |
--------------------------------------------------------------------------------
/charts/ambassador-mapping/templates/ambassador-mapping.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: getambassador.io/v1
3 | kind: Mapping
4 | metadata:
5 | name: ambassador-mapping
6 | spec:
7 | prefix: /ambassador
8 | rewrite: /ambassador/v0/diag/
9 | service: ambassador-admins.ambassador:8877
10 |
--------------------------------------------------------------------------------
/charts/ambassador-mapping/templates/guestbook-mapping.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: getambassador.io/v1
3 | kind: Mapping
4 | metadata:
5 | name: guestbook-mapping
6 | spec:
7 | prefix: /guestbook
8 | # SERVICE_LABEL.NAMESPACE:PORT
9 | service: guestbook-ui.guestbook
10 |
--------------------------------------------------------------------------------
/charts/ambassador-mapping/templates/httpbin-mapping.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: getambassador.io/v1
3 | kind: Mapping
4 | metadata:
5 | name: httpbin-mapping
6 | spec:
7 | prefix: /httpbin/
8 | host_rewrite: httpbin.org
9 | service: httpbin.org:80
10 |
--------------------------------------------------------------------------------
/charts/ambassador-mapping/values.yaml:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edgelevel/gitops-k8s/e067e831961b3f3bf85273606b8fc3da6bc03bc2/charts/ambassador-mapping/values.yaml
--------------------------------------------------------------------------------
/charts/seed/Chart.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | name: seed
3 | version: 0.6.0
4 |
--------------------------------------------------------------------------------
/charts/seed/requirements.yaml:
--------------------------------------------------------------------------------
1 | dependencies:
2 | - name: argocd
3 | version: 1.1.1-0
4 | repository: https://edgelevel.github.io/helm-charts
5 | condition: argocd.enabled
6 |
--------------------------------------------------------------------------------
/charts/seed/templates/applications.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: argoproj.io/v1alpha1
3 | kind: Application
4 | metadata:
5 | name: applications
6 | spec:
7 | project: argocd
8 | source:
9 | repoURL: {{ .Values.repository.url }}
10 | targetRevision: {{ .Values.repository.targetRevision }}
11 | path: applications
12 | destination:
13 | server: https://kubernetes.default.svc
14 | namespace: argocd
15 | # https://argoproj.github.io/argo-cd/user-guide/auto_sync
16 | syncPolicy:
17 | automated: {}
18 |
--------------------------------------------------------------------------------
/charts/seed/templates/namespace.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: v1
3 | kind: Namespace
4 | metadata:
5 | name: argocd
6 |
--------------------------------------------------------------------------------
/charts/seed/templates/project.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: argoproj.io/v1alpha1
3 | kind: AppProject
4 | metadata:
5 | name: argocd
6 | spec:
7 | sourceRepos:
8 | - {{ .Values.repository.url }}
9 | - https://github.com/edgelevel/helm-charts.git
10 | {{- range .Values.argocd.sourceRepos }}
11 | - {{ . }}
12 | {{- end }}
13 | destinations:
14 | - namespace: argocd
15 | server: https://kubernetes.default.svc
16 | clusterResourceWhitelist:
17 | - group: '*'
18 | kind: '*'
19 |
--------------------------------------------------------------------------------
/charts/seed/values.yaml:
--------------------------------------------------------------------------------
1 | argocd:
2 | enabled: true
3 | sourceRepos:
4 | # - https://github.com/niqdev/do-k8s.git
5 |
6 | repository:
7 | url: https://github.com/edgelevel/gitops-k8s.git
8 | # e.g. branch, SHA, tag
9 | targetRevision: HEAD
10 |
--------------------------------------------------------------------------------
/docs/Weaveworks_ContinuousDelivery_wp_2018.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edgelevel/gitops-k8s/e067e831961b3f3bf85273606b8fc3da6bc03bc2/docs/Weaveworks_ContinuousDelivery_wp_2018.pdf
--------------------------------------------------------------------------------
/docs/charts-TODO.txt:
--------------------------------------------------------------------------------
1 | https://stackoverflow.com/questions/23145621/how-to-publish-pages-on-github
2 |
3 | # init gh-pages
4 | git checkout --orphan gh-pages
5 | git rm -rf .
6 | echo "edgelevel-gitops" > index.html
7 | git add index.html
8 | git commit -a -m "add index.html"
9 | git push origin -u gh-pages
10 |
11 | # reset gh-pages
12 | git push origin :gh-pages
13 | git branch -D gh-pages
14 |
15 | https://github.com/edgelevel/gitops-k8s/settings
16 |
17 | Section: GitHub Pages
18 | Source: "gh-pages branch"
19 | Tick: "Enforce HTTPS"
20 |
21 | https://edgelevel.github.io/gitops-k8s
22 | https://edgelevel.github.io/gitops-k8s/index.html
23 |
24 | ---
25 |
26 | https://stackoverflow.com/questions/13897717/push-commits-to-another-branch
27 | https://stackoverflow.com/questions/23145621/how-to-publish-pages-on-github
28 | https://help.github.com/en/articles/creating-project-pages-using-the-command-line
29 |
30 | ---
31 |
32 | TODO master branch
33 |
34 | ```
35 | git checkout seed
36 | git pull --rebase
37 | git clone -b gh-pages git@github.com:edgelevel/gitops-k8s.git output
38 |
39 | # temporary for official argocd
40 | cd seed/
41 | helm init --client-only
42 | helm repo add argo https://argoproj.github.io/argo-helm
43 | helm dependency update
44 | cd ..
45 |
46 | cd output/
47 | helm lint ../seed/
48 | # output in this folder
49 | helm package ../seed/
50 | helm repo index .
51 | git add .
52 | git commit -m "release seed v0.1.0"
53 | git push origin gh-pages
54 | cd ..
55 | rm -fr output/
56 | ```
57 |
58 | # charts
59 |
60 | * [Using Helm to manage charts](https://helm.sh/docs/developing_charts/#using-helm-to-manage-charts)
61 | * [The chart repository guide](https://helm.sh/docs/developing_charts/#the-chart-repository-guide)
62 | * [Github Pages example](https://helm.sh/docs/developing_charts/#github-pages-example)
63 | * [How to make and share your own Helm package](https://medium.com/containerum/how-to-make-and-share-your-own-helm-package-50ae40f6c221)
64 | * [helm-github-pages](https://github.com/marcellodesales/helm-github-pages)
65 |
66 |
67 |
68 | Public Helm Charts repository
69 |
70 |
71 | Public Helm Charts repository
72 | Add this repository
73 |
74 | helm repo add edgelevel-gitops https://edgelevel.github.io/gitops-k8s
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/docs/img/architecture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edgelevel/gitops-k8s/e067e831961b3f3bf85273606b8fc3da6bc03bc2/docs/img/architecture.png
--------------------------------------------------------------------------------
/docs/img/argocd-ui.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edgelevel/gitops-k8s/e067e831961b3f3bf85273606b8fc3da6bc03bc2/docs/img/argocd-ui.png
--------------------------------------------------------------------------------
/docs/img/bootstrap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edgelevel/gitops-k8s/e067e831961b3f3bf85273606b8fc3da6bc03bc2/docs/img/bootstrap.png
--------------------------------------------------------------------------------
/docs/img/charts.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edgelevel/gitops-k8s/e067e831961b3f3bf85273606b8fc3da6bc03bc2/docs/img/charts.png
--------------------------------------------------------------------------------
/docs/setup.md:
--------------------------------------------------------------------------------
1 | ## Setup
2 |
3 | * [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl) to run commands against Kubernetes clusters
4 | * [helm](https://helm.sh/docs/using_helm/#installing-helm) for templating purposes only
5 | * [argocd](https://argoproj.github.io/argo-cd/getting_started/#2-download-argo-cd-cli) CLI
6 |
7 | ### Ubuntu
8 |
9 | ```bash
10 | # kubectl
11 | sudo snap install kubectl --classic
12 |
13 | # helm
14 | sudo snap install helm --classic
15 |
16 | # argocd
17 | sudo mkdir -p /opt/argo
18 | ARGO_VERSION=1.0.0 && \
19 | sudo curl -L -o /opt/argo/argocd-linux-amd64 \
20 | https://github.com/argoproj/argo-cd/releases/download/v$ARGO_VERSION/argocd-linux-amd64
21 | sudo chmod +x /opt/argo/argocd-linux-amd64
22 | sudo ln -s /opt/argo/argocd-linux-amd64 /usr/local/bin/argocd
23 | ```
24 |
25 | ### macOS
26 |
27 | ```bash
28 | # kubectl
29 | brew install kubernetes-cli
30 |
31 | # helm
32 | brew install kubernetes-helm
33 |
34 | # argocd
35 | brew tap argoproj/tap
36 | brew install argoproj/tap/argocd
37 | ```
38 |
39 | ## Recommended tools
40 |
41 | * [kubectx](https://ahmet.im/blog/kubectx/index.html) - A tool to switch between Kubernetes contexts
42 | * [kube-ps1](https://github.com/jonmosco/kube-ps1) - Kubernetes prompt
43 |
44 | Add to `.bashrc` or `.bash_profile`
45 | ```bash
46 | # K8S PROMPT
47 | [[ -f /opt/kube-ps1/kube-ps1.sh ]] && source /opt/kube-ps1/kube-ps1.sh
48 | #export KUBE_PS1_SYMBOL_COLOR=green
49 | PS1='$(kube_ps1)'$PS1
50 | # default
51 | kubeoff
52 |
53 | # K8S CONFIGS
54 | function kube-config-local {
55 | export KUBECONFIG=
56 | }
57 | function kube-config- {
58 | export KUBECONFIG=~/.kube/-kubeconfig.yaml
59 | kubeon
60 | }
61 | # default
62 | kube-config-local
63 | ```
64 |
--------------------------------------------------------------------------------
/scripts/bootstrap.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # unofficial bash strict mode
4 | set -euo pipefail
5 | IFS=$'\n\t'
6 |
7 | # run from any directory (no symlink allowed)
8 | CURRENT_PATH=$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd -P)
9 | cd ${CURRENT_PATH}
10 |
11 | ##############################
12 |
13 | ROOT_PATH="${CURRENT_PATH}/.."
14 | SEED_PATH="${ROOT_PATH}/charts/seed/"
15 |
16 | cd ${SEED_PATH}
17 |
18 | # add helm repository
19 | helm repo add edgelevel-public https://edgelevel.github.io/helm-charts
20 |
21 | # download chart locally
22 | helm dependency update
23 |
24 | # apply chart
25 | helm template --values values.yaml . | kubectl apply -n argocd -f -
26 |
--------------------------------------------------------------------------------
/scripts/publish_seed.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # unofficial bash strict mode
4 | set -euo pipefail
5 | IFS=$'\n\t'
6 |
7 | # run from any directory (no symlink allowed)
8 | CURRENT_PATH=$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd -P)
9 | cd ${CURRENT_PATH}
10 |
11 | ##############################
12 |
13 | ROOT_PATH="${CURRENT_PATH}/.."
14 | SEED_PATH="${ROOT_PATH}/charts/seed/"
15 | TMP_REPOSITORY="tmp-gh-pages"
16 |
17 | cd ${SEED_PATH}
18 | helm repo add edgelevel-public https://edgelevel.github.io/helm-charts
19 | helm dependency update
20 | helm template --values values.yaml .
21 | helm lint .
22 |
23 | git clone -b gh-pages git@github.com:edgelevel/gitops-k8s.git ${ROOT_PATH}/${TMP_REPOSITORY}
24 |
25 | cd ${ROOT_PATH}/${TMP_REPOSITORY}
26 | helm package ${SEED_PATH}
27 | helm repo index .
28 | git add .
29 | git commit -m "release seed chart"
30 | git push origin gh-pages
31 | cd ${ROOT_PATH}
32 | rm -fr ${ROOT_PATH}/${TMP_REPOSITORY}
33 |
--------------------------------------------------------------------------------