gerrit: charts and app configuration
Change-Id: If4f05f749719d6ba0e2ced8da563699bc6fbc4c0
diff --git a/charts/gerrit-replica/.helmignore b/charts/gerrit-replica/.helmignore
new file mode 100644
index 0000000..4f4562f
--- /dev/null
+++ b/charts/gerrit-replica/.helmignore
@@ -0,0 +1,24 @@
+# Patterns to ignore when building packages.
+# This supports shell glob matching, relative path matching, and
+# negation (prefixed with !). Only one pattern per line.
+.DS_Store
+# Common VCS dirs
+.git/
+.gitignore
+.bzr/
+.bzrignore
+.hg/
+.hgignore
+.svn/
+# Common backup files
+*.swp
+*.bak
+*.tmp
+*~
+# Various IDEs
+.project
+.idea/
+*.tmproj
+
+docs/
+supplements/
diff --git a/charts/gerrit-replica/Chart.yaml b/charts/gerrit-replica/Chart.yaml
new file mode 100644
index 0000000..0fc9a45
--- /dev/null
+++ b/charts/gerrit-replica/Chart.yaml
@@ -0,0 +1,24 @@
+apiVersion: v2
+appVersion: 3.9.1
+description: |-
+ The Gerrit replica serves as a read-only Gerrit instance to serve repositories
+ that it receives from a Gerrit instance via replication. It can be used to
+ reduce the load on Gerrit instances.
+name: gerrit-replica
+version: 0.2.0
+maintainers:
+- name: Thomas Draebing
+ email: thomas.draebing@sap.com
+- name: Matthias Sohn
+ email: matthias.sohn@sap.com
+- name: Sasa Zivkov
+ email: sasa.zivkov@sap.com
+- name: Christian Halstrick
+ email: christian.halstrick@sap.com
+home: https://gerrit.googlesource.com/k8s-gerrit/+/master/helm-charts/gerrit-replica
+icon: http://commondatastorage.googleapis.com/gerrit-static/diffy-w200.png
+sources:
+- https://gerrit.googlesource.com/k8s-gerrit/+/master
+keywords:
+- gerrit
+- git
diff --git a/charts/gerrit-replica/LICENSE b/charts/gerrit-replica/LICENSE
new file mode 100644
index 0000000..028fc9f
--- /dev/null
+++ b/charts/gerrit-replica/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/charts/gerrit-replica/README.md b/charts/gerrit-replica/README.md
new file mode 100644
index 0000000..8b68b43
--- /dev/null
+++ b/charts/gerrit-replica/README.md
@@ -0,0 +1,547 @@
+# Gerrit replica on Kubernetes
+
+Gerrit is a web-based code review tool, which acts as a Git server. On large setups
+Gerrit servers can see a sizable amount of traffic from git operations performed by
+developers and build servers. The major part of requests are read-only requests
+(e.g. by `git fetch` operations). To take some load of the Gerrit server,
+Gerrit replicas can be deployed to serve read-only requests.
+
+This helm chart provides a Gerrit replica setup that can be deployed on Kubernetes.
+The Gerrit replica is capable of receiving replicated git repositories from a
+Gerrit. The Gerrit replica can then serve authenticated read-only requests.
+
+***note
+Gerrit versions before 3.0 are no longer supported, since the support of ReviewDB
+was removed.
+***
+
+## Prerequisites
+
+- Helm (>= version 3.0)
+
+ (Check out [this guide](https://docs.helm.sh/using_helm/#quickstart-guide)
+ how to install and use helm.)
+
+- Access to a provisioner for persistent volumes with `Read Write Many (RWM)`-
+ capability.
+
+ A list of applicaple volume types can be found
+ [here](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#access-modes).
+ This project was developed using the
+ [NFS-server-provisioner helm chart](https://github.com/helm/charts/tree/master/stable/nfs-server-provisioner),
+ a NFS-provisioner deployed in the Kubernetes cluster itself. Refer to
+ [this guide](/helm-charts/gerrit-replica/docs/nfs-provisioner.md) of how to
+ deploy it in context of this project.
+
+- A domain name that is configured to point to the IP address of the node running
+ the Ingress controller on the kubernetes cluster (as described
+ [here](http://alesnosek.com/blog/2017/02/14/accessing-kubernetes-pods-from-outside-of-the-cluster/)).
+
+- (Optional: Required, if SSL is configured)
+ A [Java keystore](https://gerrit-review.googlesource.com/Documentation/config-gerrit.html#httpd.sslKeyStore)
+ to be used by Gerrit.
+
+## Installing the Chart
+
+***note
+**ATTENTION:** The value for `ingress.host` is required for rendering
+the chart's templates. The nature of the value does not allow defaults.
+Thus a custom `values.yaml`-file setting this value is required!
+***
+
+To install the chart with the release name `gerrit-replica`, execute:
+
+```sh
+cd $(git rev-parse --show-toplevel)/helm-charts
+helm install \
+ gerrit-replica \ # release name
+ ./gerrit-replica \ # path to chart
+ -f <path-to-custom-values>.yaml
+```
+
+The command deploys the Gerrit replica on the current Kubernetes cluster. The
+[configuration section](#Configuration) lists the parameters that can be
+configured during installation.
+
+The Gerrit replica requires the replicated `All-Projects.git`- and `All-Users.git`-
+repositories to be present in the `/var/gerrit/git`-directory. The `gerrit-init`-
+InitContainer will wait for this being the case. A way to do this is to access
+the Gerrit replica pod and to clone the repositories from the primary Gerrit (Make
+sure that you have the correct access rights do so.):
+
+```sh
+kubectl exec -it <gerrit-replica-pod> -c gerrit-init ash
+gerrit@<gerrit-replica-pod>:/var/tools$ cd /var/gerrit/git
+gerrit@<gerrit-replica-pod>:/var/gerrit/git$ git clone "http://gerrit.com/All-Projects" --mirror
+Cloning into bare repository 'All-Projects.git'...
+gerrit@<gerrit-replica-pod>:/var/gerrit/git$ git clone "http://gerrit.com/All-Users" --mirror
+Cloning into bare repository 'All-Users.git'...
+```
+
+## Configuration
+
+The following sections list the configurable values in `values.yaml`. To configure
+a Gerrit replica setup, make a copy of the `values.yaml`-file and change the
+parameters as needed. The configuration can be applied by installing the chart as
+described [above](#Installing-the-chart).
+
+In addition, single options can be set without creating a custom `values.yaml`:
+
+```sh
+cd $(git rev-parse --show-toplevel)/helm-charts
+helm install \
+ gerrit-replica \ # release name
+ ./gerrit-replica \ # path to chart
+ --set=gitRepositoryStorage.size=100Gi,gitBackend.replicas=2
+```
+
+### Container images
+
+| Parameter | Description | Default |
+|-----------|-------------|---------|
+| `images.busybox.registry` | The registry to pull the busybox container images from | `docker.io` |
+| `images.busybox.tag` | The busybox image tag to use | `latest` |
+| `images.registry.name` | The image registry to pull the container images from | `` |
+| `images.registry.ImagePullSecret.name` | Name of the ImagePullSecret | `image-pull-secret` (if empty no image pull secret will be deployed) |
+| `images.registry.ImagePullSecret.create` | Whether to create an ImagePullSecret | `false` |
+| `images.registry.ImagePullSecret.username` | The image registry username | `nil` |
+| `images.registry.ImagePullSecret.password` | The image registry password | `nil` |
+| `images.version` | The image version (image tag) to use | `latest` |
+| `images.imagePullPolicy` | Image pull policy | `Always` |
+| `images.additionalImagePullSecrets` | Additional image pull policies that pods should use | `[]` |
+
+### Labels
+
+| Parameter | Description | Default |
+|-----------|-------------|---------|
+| `additionalLabels` | Additional labels for resources managed by this Helm chart | `{}` |
+
+### Storage classes
+
+For information of how a `StorageClass` is configured in Kubernetes, read the
+[official Documentation](https://kubernetes.io/docs/concepts/storage/storage-classes/#introduction).
+
+| Parameter | Description | Default |
+|-----------|-------------|---------|
+| `storageClasses.default.name` | The name of the default StorageClass (RWO) | `default` |
+| `storageClasses.default.create` | Whether to create the StorageClass | `false` |
+| `storageClasses.default.provisioner` | Provisioner of the StorageClass | `kubernetes.io/aws-ebs` |
+| `storageClasses.default.reclaimPolicy` | Whether to `Retain` or `Delete` volumes, when they become unbound | `Delete` |
+| `storageClasses.default.parameters` | Parameters for the provisioner | `parameters.type: gp2`, `parameters.fsType: ext4` |
+| `storageClasses.default.mountOptions` | The mount options of the default StorageClass | `[]` |
+| `storageClasses.default.allowVolumeExpansion` | Whether to allow volume expansion. | `false` |
+| `storageClasses.shared.name` | The name of the shared StorageClass (RWM) | `shared-storage` |
+| `storageClasses.shared.create` | Whether to create the StorageClass | `false` |
+| `storageClasses.shared.provisioner` | Provisioner of the StorageClass | `nfs` |
+| `storageClasses.shared.reclaimPolicy` | Whether to `Retain` or `Delete` volumes, when they become unbound | `Delete` |
+| `storageClasses.shared.parameters` | Parameters for the provisioner | `parameters.mountOptions: vers=4.1` |
+| `storageClasses.shared.mountOptions` | The mount options of the shared StorageClass | `[]` |
+| `storageClasses.shared.allowVolumeExpansion` | Whether to allow volume expansion. | `false` |
+
+### CA certificate
+
+Some application may require TLS verification. If the default CA built into the
+containers is not enough a custom CA certificate can be given to the deployment.
+Note, that Gerrit will require its CA in a JKS keytore, which is described below.
+
+| Parameter | Description | Default |
+|-----------|-------------|---------|
+| `caCert` | CA certificate for TLS verification (if not set, the default will be used) | `None` |
+
+### Workaround for NFS
+
+Kubernetes will not always be able to adapt the ownership of the files within NFS
+volumes. Thus, a workaround exists that will add init-containers to
+adapt file ownership. Note, that only the ownership of the root directory of the
+volume will be changed. All data contained within will be expected to already be
+owned by the user used by Gerrit. Also the ID-domain will be configured to ensure
+correct ID-mapping.
+
+| Parameter | Description | Default |
+|-----------|-------------|---------|
+| `nfsWorkaround.enabled` | Whether the volume used is an NFS-volume | `false` |
+| `nfsWorkaround.chownOnStartup` | Whether to chown the volume on pod startup | `false` |
+| `nfsWorkaround.idDomain` | The ID-domain that should be used to map user-/group-IDs for the NFS mount | `localdomain.com` |
+
+### Network policies
+
+| Parameter | Description | Default |
+|-----------|-------------|---------|
+| `networkPolicies.enabled` | Whether to enable preconfigured NetworkPolicies | `false` |
+| `networkPolicies.dnsPorts` | List of ports used by DNS-service (e.g. KubeDNS) | `[53, 8053]` |
+
+The NetworkPolicies provided here are quite strict and do not account for all
+possible scenarios. Thus, custom NetworkPolicies have to be added, e.g. for
+connecting to a database. On the other hand some defaults may be not restrictive
+enough. By default, the ingress traffic of the git-backend pod is not restricted.
+Thus, every source (with the right credentials) could push to the git-backend.
+To add an additional layer of security, the ingress rule could be defined more
+finegrained. The chart provides the possibility to define custom rules for ingress-
+traffic of the git-backend pod under `gitBackend.networkPolicy.ingress`.
+Depending on the scenario, there are different ways to restrict the incoming
+connections.
+
+If the replicator (e.g. Gerrit) is running in a pod on the same cluster,
+a podSelector (and namespaceSelector, if the pod is running in a different
+namespace) can be used to whitelist the traffic:
+
+```yaml
+gitBackend:
+ networkPolicy:
+ ingress:
+ - from:
+ - podSelector:
+ matchLabels:
+ app: gerrit
+```
+
+If the replicator is outside the cluster, the IP of the replicator can also be
+whitelisted, e.g.:
+
+```yaml
+gitBackend:
+ networkPolicy:
+ ingress:
+ - from:
+ - ipBlock:
+ cidr: xxx.xxx.0.0/16
+```
+
+The same principle also applies to other use cases, e.g. connecting to a database.
+For more information about the NetworkPolicy resource refer to the
+[Kubernetes documentation](https://kubernetes.io/docs/concepts/services-networking/network-policies/).
+
+### Storage for Git repositories
+
+| Parameter | Description | Default |
+|-----------|-------------|---------|
+| `gitRepositoryStorage.externalPVC.use` | Whether to use a PVC deployed outside the chart | `false` |
+| `gitRepositoryStorage.externalPVC.name` | Name of the external PVC | `git-repositories-pvc` |
+| `gitRepositoryStorage.size` | Size of the volume storing the Git repositories | `5Gi` |
+
+If the git repositories should be persisted even if the chart is deleted and in
+a way that the volume containing them can be mounted by the reinstalled chart,
+the PVC claiming the volume has to be created independently of the chart. To use
+the external PVC, set `gitRepositoryStorage.externalPVC.enabled` to `true` and
+give the name of the PVC under `gitRepositoryStorage.externalPVC.name`.
+
+### Storage for Logs
+
+In addition to collecting logs with a log collection tool like Promtail, the logs
+can also be stored in a persistent volume. This volume has to be a read-write-many
+volume to be able to be used by multiple pods.
+
+| Parameter | Description | Default |
+|-----------|-------------|---------|
+| `logStorage.enabled` | Whether to enable persistence of logs | `false` |
+| `logStorage.externalPVC.use` | Whether to use a PVC deployed outside the chart | `false` |
+| `logStorage.externalPVC.name` | Name of the external PVC | `gerrit-logs-pvc` |
+| `logStorage.size` | Size of the volume | `5Gi` |
+| `logStorage.cleanup.enabled` | Whether to regularly delete old logs | `false` |
+| `logStorage.cleanup.schedule` | Cron schedule defining when to run the cleanup job | `0 0 * * *` |
+| `logStorage.cleanup.retentionDays` | Number of days to retain the logs | `14` |
+| `logStorage.cleanup.resources` | Resources the container is allowed to use | `requests.cpu: 100m` |
+| `logStorage.cleanup.additionalPodLabels` | Additional labels for pods | `{}` |
+| | | `requests.memory: 256Mi` |
+| | | `limits.cpu: 100m` |
+| | | `limits.memory: 256Mi` |
+
+Each pod will create a separate folder for its logs, allowing to trace logs to
+the respective pods.
+
+### Istio
+
+Istio can be used as an alternative to Kubernetes Ingresses to manage the traffic
+into the cluster and also inside the cluster. This requires istio to be installed
+beforehand. Some guidance on how to set up istio can be found [here](/Documentation/istio.md).
+The helm chart expects `istio-injection` to be enabled in the namespace, in which
+it will be installed.
+
+In the case istio is used, all configuration for ingresses in the chart will be
+ignored.
+
+| Parameter | Description | Default |
+|-----------|-------------|---------|
+| `istio.enabled` | Whether istio should be used (requires istio to be installed) | `false` |
+| `istio.host` | Hostname (CNAME must point to istio ingress gateway loadbalancer service) | `nil` |
+| `istio.tls.enabled` | Whether to enable TLS | `false` |
+| `istio.tls.secret.create` | Whether to create TLS certificate secret | `true` |
+| `istio.tls.secret.name` | Name of external secret containing TLS certificates | `nil` |
+| `istio.tls.cert` | TLS certificate | `-----BEGIN CERTIFICATE-----` |
+| `istio.tls.key` | TLS key | `-----BEGIN RSA PRIVATE KEY-----` |
+| `istio.ssh.enabled` | Whether to enable SSH | `false` |
+
+### Ingress
+
+As an alternative to istio the Nginx Ingress controller can be used to manage
+ingress traffic.
+
+| Parameter | Description | Default |
+|-----------|-------------|---------|
+| `ingress.enabled` | Whether to deploy an Ingress | `false` |
+| `ingress.host` | Host name to use for the Ingress (required for Ingress) | `nil` |
+| `ingress.maxBodySize` | Maximum request body size allowed (Set to 0 for an unlimited request body size) | `50m` |
+| `ingress.additionalAnnotations` | Additional annotations for the Ingress | `nil` |
+| `ingress.tls.enabled` | Whether to enable TLS termination in the Ingress | `false` |
+| `ingress.tls.secret.create` | Whether to create a TLS-secret | `true` |
+| `ingress.tls.secret.name` | Name of an external secret that will be used as a TLS-secret | `nil` |
+| `ingress.tls.cert` | Public SSL server certificate | `-----BEGIN CERTIFICATE-----` |
+| `ingress.tls.key` | Private SSL server certificate | `-----BEGIN RSA PRIVATE KEY-----` |
+
+***note
+For graceful shutdown to work with an ingress, the ingress controller has to be
+configured to gracefully close the connections as well.
+***
+
+### Promtail Sidecar
+
+To collect Gerrit logs, a Promtail sidecar can be deployed into the Gerrit replica
+pods. This can for example be used together with the [gerrit-monitoring](https://gerrit-review.googlesource.com/admin/repos/gerrit-monitoring)
+project.
+
+| Parameter | Description | Default |
+|-----------|-------------|---------|
+| `promtailSidecar.enabled` | Whether to install the Promatil sidecar container | `false` |
+| `promtailSidecar.image` | The promtail container image to use | `grafana/promtail` |
+| `promtailSidecar.version` | The promtail container image version | `1.3.0` |
+| `promtailSidecar.resources` | Configure the amount of resources the container requests/is allowed | `requests.cpu: 100m` |
+| | | `requests.memory: 128Mi` |
+| | | `limits.cpu: 200m` |
+| | | `limits.memory: 128Mi` |
+| `promtailSidecar.tls.skipverify` | Whether to skip TLS verification | `true` |
+| `promtailSidecar.tls.caCert` | CA certificate for TLS verification | `-----BEGIN CERTIFICATE-----` |
+| `promtailSidecar.loki.url` | URL to reach Loki | `loki.example.com` |
+| `promtailSidecar.loki.user` | Loki user | `admin` |
+| `promtailSidecar.loki.password` | Loki password | `secret` |
+
+
+### Apache-Git-HTTP-Backend (Git-Backend)
+
+| Parameter | Description | Default |
+|-----------|-------------|---------|
+| `gitBackend.image` | Image name of the Apache-git-http-backend container image | `k8sgerrit/apache-git-http-backend` |
+| `gitBackend.additionalPodLabels` | Additional labels for Pods | `{}` |
+| `gitBackend.tolerations` | Taints and tolerations work together to ensure that pods are not scheduled onto inappropriate nodes. For more information, please refer to the following documents. [Taints and Tolerations](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration) | [] |
+| `gitBackend.topologySpreadConstraints` | Control how Pods are spread across your cluster among failure-domains. For more information, please refer to the following documents. [Pod Topology Spread Constraints](https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints) | {} |
+| `gitBackend.nodeSelector` | Assigns a Pod to the specified Nodes. For more information, please refer to the following documents. [Assign Pods to Nodes](https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes/). [Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/) | {} |
+| `gitBackend.affinity` | Assigns a Pod to the specified Nodes | podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].weight: 100 |
+| | | podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.topologyKey: "topology.kubernetes.io/zone" |
+| | | podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.labelSelector.matchExpressions[0].key: app |
+| | | podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.labelSelector.matchExpressions[0].operator: In |
+| | | podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.labelSelector.matchExpressions[0].values[0]: git-backend |
+| `gitBackend.replicas` | Number of pod replicas to deploy | `1` |
+| `gitBackend.maxSurge` | Max. percentage or number of pods allowed to be scheduled above the desired number | `25%` |
+| `gitBackend.maxUnavailable` | Max. percentage or number of pods allowed to be unavailable at a time | `100%` |
+| `gitBackend.networkPolicy.ingress` | Custom ingress-network policy for git-backend pods | `[{}]` (allow all) |
+| `gitBackend.networkPolicy.egress` | Custom egress-network policy for git-backend pods | `nil` |
+| `gitBackend.resources` | Configure the amount of resources the pod requests/is allowed | `requests.cpu: 100m` |
+| | | `requests.memory: 256Mi` |
+| | | `limits.cpu: 100m` |
+| | | `limits.memory: 256Mi` |
+| `gitBackend.livenessProbe` | Configuration of the liveness probe timings | `{initialDelaySeconds: 10, periodSeconds: 5}` |
+| `gitBackend.readinessProbe` | Configuration of the readiness probe timings | `{initialDelaySeconds: 5, periodSeconds: 1}` |
+| `gitBackend.credentials.htpasswd` | `.htpasswd`-file containing username/password-credentials for accessing git | `git:$apr1$O/LbLKC7$Q60GWE7OcqSEMSfe/K8xU.` (user: git, password: secret) |
+| `gitBackend.service.additionalAnnotations` | Additional annotations for the Service | `{}` |
+| `gitBackend.service.loadBalancerSourceRanges` | The list of allowed IPs for the Service | `[]` |
+| `gitBackend.service.type` | Which kind of Service to deploy | `LoadBalancer` |
+| `gitBackend.service.externalTrafficPolicy` | Specify how traffic from external is handled | `Cluster` |
+| `gitBackend.service.http.enabled` | Whether to serve HTTP-requests (needed for Ingress) | `true` |
+| `gitBackend.service.http.port` | Port over which to expose HTTP | `80` |
+| `gitBackend.service.https.enabled` | Whether to serve HTTPS-requests | `false` |
+| `gitBackend.service.https.port` | Port over which to expose HTTPS | `443` |
+
+***note
+At least one endpoint (HTTP and/or HTTPS) has to be enabled in the service!
+***
+
+Project creation, project deletion and HEAD update can also replicated. To enable
+this feature configure the replication plugin to use an adminUrl using the format
+`gerrit+https://<apache-git-http-backend host>`.
+
+### Git garbage collection
+
+| Parameter | Description | Default |
+|-----------|-------------|---------|
+| `gitGC.image` | Image name of the Git-GC container image | `k8sgerrit/git-gc` |
+| `gitGC.schedule` | Cron-formatted schedule with which to run Git garbage collection | `0 6,18 * * *` |
+| `gitGC.resources` | Configure the amount of resources the pod requests/is allowed | `requests.cpu: 100m` |
+| | | `requests.memory: 256Mi` |
+| | | `limits.cpu: 100m` |
+| | | `limits.memory: 256Mi` |
+| `gitGC.tolerations` | Taints and tolerations work together to ensure that pods are not scheduled onto inappropriate nodes. For more information, please refer to the following documents. [Taints and Tolerations](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration) | [] |
+| `gitGC.nodeSelector` | Assigns a Pod to the specified Nodes. For more information, please refer to the following documents. [Assign Pods to Nodes](https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes/). [Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/) | {} |
+| `gitGC.affinity` | Assigns a Pod to the specified Nodes. For more information, please refer to the following documents. [Assign Pods to Nodes using Node Affinity](https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes-using-node-affinity/). [Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/) | {} |
+| `gitGC.additionalPodLabels` | Additional labels for Pods | `{}` |
+
+### Gerrit replica
+
+***note
+The way the Jetty servlet used by Gerrit works, the Gerrit replica component of the
+gerrit-replica chart actually requires the URL to be known, when the chart is installed.
+The suggested way to do that is to use the provided Ingress resource. This requires
+that a URL is available and that the DNS is configured to point the URL to the
+IP of the node the Ingress controller is running on!
+***
+
+***note
+Setting the canonical web URL in the gerrit.config to the host used for the Ingress
+is mandatory, if access to the Gerrit replica is required!
+***
+
+| Parameter | Description | Default |
+|-----------|-------------|---------|
+| `gerritReplica.images.gerritInit` | Image name of the Gerrit init container image | `k8sgerrit/gerrit-init` |
+| `gerritReplica.images.gerritReplica` | Image name of the Gerrit replica container image | `k8sgerrit/gerrit` |
+| `gerritReplica.tolerations` | Taints and tolerations work together to ensure that pods are not scheduled onto inappropriate nodes. For more information, please refer to the following documents. [Taints and Tolerations](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration) | [] |
+| `gerritReplica.topologySpreadConstraints` | Control how Pods are spread across your cluster among failure-domains. For more information, please refer to the following documents. [Pod Topology Spread Constraints](https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints) | {} |
+| `gerritReplica.nodeSelector` | Assigns a Pod to the specified Nodes. For more information, please refer to the following documents. [Assign Pods to Nodes](https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes/). [Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/) | {} |
+| `gerritReplica.affinity` | Assigns a Pod to the specified Nodes. By default, gerrit-replica is evenly distributed on `topology.kubernetes.io/zone`. For more information, please refer to the following documents. [Assign Pods to Nodes using Node Affinity](https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes-using-node-affinity/). [Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/) | podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].weight: 100 |
+| | | podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.topologyKey: "topology.kubernetes.io/zone" |
+| | | podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.labelSelector.matchExpressions[0].key: app |
+| | | podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.labelSelector.matchExpressions[0].operator: In |
+| | | podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.labelSelector.matchExpressions[0].values[0]: gerrit-replica |
+| `gerritReplica.replicas` | Number of pod replicas to deploy | `1` |
+| `gerritReplica.additionalAnnotations` | Additional annotations for the Pods | {} |
+| `gerritReplica.additionalPodLabels` | Additional labels for the Pods | `{}` |
+| `gerritReplica.maxSurge` | Max. percentage or number of pods allowed to be scheduled above the desired number | `25%` |
+| `gerritReplica.maxUnavailable` | Max. percentage or number of pods allowed to be unavailable at a time | `100%` |
+| `gerritReplica.livenessProbe` | Configuration of the liveness probe timings | `{initialDelaySeconds: 60, periodSeconds: 5}` |
+| `gerritReplica.probeScheme` | Scheme for probes, for example HTTPS | `nil` |
+| `gerritReplica.readinessProbe` | Configuration of the readiness probe timings | `{initialDelaySeconds: 10, periodSeconds: 10}` |
+| `gerritReplica.startupProbe` | Configuration of the startup probe timings | `{initialDelaySeconds: 10, periodSeconds: 5}` |
+| `gerritReplica.gracefulStopTimeout` | Time in seconds Kubernetes will wait until killing the pod during termination (has to be longer then Gerrit's httpd.gracefulStopTimeout to allow graceful shutdown of Gerrit) | `90` |
+| `gerritReplica.resources` | Configure the amount of resources the pod requests/is allowed | `requests.cpu: 1` |
+| | | `requests.memory: 5Gi` |
+| | | `limits.cpu: 1` |
+| | | `limits.memory: 6Gi` |
+| `gerritReplica.networkPolicy.ingress` | Custom ingress-network policy for gerrit-replica pods | `nil` |
+| `gerritReplica.networkPolicy.egress` | Custom egress-network policy for gerrit-replica pods | `nil` |
+| `gerritReplica.service.additionalAnnotations` | Additional annotations for the Service | `{}` |
+| `gerritReplica.service.loadBalancerSourceRanges` | The list of allowed IPs for the Service | `[]` |
+| `gerritReplica.service.type` | Which kind of Service to deploy | `NodePort` |
+| `gerritReplica.service.externalTrafficPolicy` | Specify how traffic from external is handled | `Cluster` |
+| `gerritReplica.service.http.port` | Port over which to expose HTTP | `80` |
+| `gerritReplica.service.ssh.enabled` | Whether to enable SSH for the Gerrit replica | `false` |
+| `gerritReplica.service.ssh.port` | Port for SSH | `29418` |
+| `gerritReplica.keystore` | base64-encoded Java keystore (`cat keystore.jks \| base64`) to be used by Gerrit, when using SSL | `nil` |
+| `gerritReplica.pluginManagement.plugins` | List of Gerrit plugins to install | `[]` |
+| `gerritReplica.pluginManagement.plugins[0].name` | Name of plugin | `nil` |
+| `gerritReplica.pluginManagement.plugins[0].url` | Download url of plugin. If given the plugin will be downloaded, otherwise it will be installed from the gerrit.war-file. | `nil` |
+| `gerritReplica.pluginManagement.plugins[0].sha1` | SHA1 sum of plugin jar used to ensure file integrity and version (optional) | `nil` |
+| `gerritReplica.pluginManagement.plugins[0].installAsLibrary` | Whether the plugin should be symlinked to the lib-dir in the Gerrit site. | `nil` |
+| `gerritReplica.pluginManagement.libs` | List of Gerrit library modules to install | `[]` |
+| `gerritReplica.pluginManagement.libs[0].name` | Name of the lib module | `nil` |
+| `gerritReplica.pluginManagement.libs[0].url` | Download url of lib module. | `nil` |
+| `gerritReplica.pluginManagement.libs[0].sha1` | SHA1 sum of plugin jar used to ensure file integrity and version | `nil` |
+| `gerritReplica.pluginManagement.cache.enabled` | Whether to cache downloaded plugins | `false` |
+| `gerritReplica.pluginManagement.cache.size` | Size of the volume used to store cached plugins | `1Gi` |
+| `gerritReplica.priorityClassName` | Name of the PriorityClass to apply to replica pods | `nil` |
+| `gerritReplica.etc.config` | Map of config files (e.g. `gerrit.config`) that will be mounted to `$GERRIT_SITE/etc`by a ConfigMap | `{gerrit.config: ..., replication.config: ...}`[see here](#Gerrit-config-files) |
+| `gerritReplica.etc.secret` | Map of config files (e.g. `secure.config`) that will be mounted to `$GERRIT_SITE/etc`by a Secret | `{secure.config: ...}` [see here](#Gerrit-config-files) |
+| `gerritReplica.additionalConfigMaps` | Allows to mount additional ConfigMaps into a subdirectory of `$SITE/data` | `[]` |
+| `gerritReplica.additionalConfigMaps[*].name` | Name of the ConfigMap | `nil` |
+| `gerritReplica.additionalConfigMaps[*].subDir` | Subdirectory under `$SITE/data` into which the files should be symlinked | `nil` |
+| `gerritReplica.additionalConfigMaps[*].data` | Data of the ConfigMap. If not set, ConfigMap has to be created manually | `nil` |
+
+### Gerrit config files
+
+The gerrit-replica chart provides a ConfigMap containing the configuration files
+used by Gerrit, e.g. `gerrit.config` and a Secret containing sensitive configuration
+like the `secure.config` to configure the Gerrit installation in the Gerrit
+component. The content of the config files can be set in the `values.yaml` under
+the keys `gerritReplica.etc.config` and `gerritReplica.etc.secret` respectively.
+The key has to be the filename (eg. `gerrit.config`) and the file's contents
+the value. This way an arbitrary number of configuration files can be loaded into
+the `$GERRIT_SITE/etc`-directory, e.g. for plugins.
+All configuration options for Gerrit are described in detail in the
+[official documentation of Gerrit](https://gerrit-review.googlesource.com/Documentation/config-gerrit.html).
+Some options however have to be set in a specified way for Gerrit to work as
+intended with the chart:
+
+- `gerrit.basePath`
+
+ Path to the directory containing the repositories. The chart mounts this
+ directory from a persistent volume to `/var/gerrit/git` in the container. For
+ Gerrit to find the correct directory, this has to be set to `git`.
+
+- `gerrit.serverId`
+
+ In Gerrit-version higher than 2.14 Gerrit needs a server ID, which is used by
+ NoteDB. Gerrit would usually generate a random ID on startup, but since the
+ gerrit.config file is read only, when mounted as a ConfigMap this fails.
+ Thus the server ID has to be set manually!
+
+- `gerrit.canonicalWebUrl`
+
+ The canonical web URL has to be set to the Ingress host.
+
+- `httpd.listenURL`
+
+ This has to be set to `proxy-http://*:8080/` or `proxy-https://*:8080`,
+ depending of TLS is enabled in the Ingress or not, otherwise the Jetty
+ servlet will run into an endless redirect loop.
+
+- `httpd.gracefulStopTimeout` / `sshd.gracefulStopTimeout`
+
+ To enable graceful shutdown of the embedded jetty server and SSHD, a timeout
+ has to be set with this option. This will be the maximum time, Gerrit will wait
+ for HTTP requests to finish before shutdown.
+
+- `container.user`
+
+ The technical user in the Gerrit replica container is called `gerrit`. Thus, this
+ value is required to be `gerrit`.
+
+- `container.replica`
+
+ Since this chart is meant to install a Gerrit replica, this naturally has to be
+ `true`.
+
+- `container.javaHome`
+
+ This has to be set to `/usr/lib/jvm/java-11-openjdk-amd64`, since this is
+ the path of the Java installation in the container.
+
+- `container.javaOptions`
+
+ The maximum heap size has to be set. And its value has to be lower than the
+ memory resource limit set for the container (e.g. `-Xmx4g`). In your calculation
+ allow memory for other components running in the container.
+
+To enable liveness- and readiness probes, the healthcheck plugin will be installed
+by default. Note, that by configuring to use a packaged or downloaded version of
+the healthcheck plugin, the configured version will take precedence over the default
+version. The plugin is by default configured to disable the `querychanges` and
+`auth` healthchecks, since the Gerrit replica does not index changes and a new
+Gerrit server will not yet necessarily have an user to validate authentication.
+
+The default configuration can be overwritten by adding the `healthcheck.config`
+file as a key-value pair to `gerritReplica.etc.config` as for every other configuration.
+
+SSH keys should be configured via the helm-chart using the `gerritReplica.etc.secret`
+map. Gerrit will create its own keys, if none are present in the site, but if
+multiple Gerrit pods are running, each Gerrit instance would have its own keys.
+Users accessing Gerrit via a load balancer would get issues due to changing
+host keys.
+
+## Upgrading the Chart
+
+To upgrade an existing installation of the gerrit-replica chart, e.g. to install
+a newer chart version or to use an updated custom `values.yaml`-file, execute
+the following command:
+
+```sh
+cd $(git rev-parse --show-toplevel)/helm-charts
+helm upgrade \
+ <release-name> \
+ ./gerrit-replica \ # path to chart
+ -f <path-to-custom-values>.yaml \
+```
+
+## Uninstalling the Chart
+
+To delete the chart from the cluster, use:
+
+```sh
+helm delete <release-name>
+```
diff --git a/charts/gerrit-replica/docs/nfs-provisioner.md b/charts/gerrit-replica/docs/nfs-provisioner.md
new file mode 100644
index 0000000..e2d0806
--- /dev/null
+++ b/charts/gerrit-replica/docs/nfs-provisioner.md
@@ -0,0 +1,64 @@
+# Installing a NFS-provisioner
+
+The Gerrit replica requires access to a persistent volume capable of running in
+`Read Write Many (RWM)`-mode to store the git repositories, since the repositories
+have to be accessed by mutiple pods. One possibility to provide such volumes
+is to install a provisioner for NFS-volumes into the same Kubernetes-cluster.
+This document will guide through the process.
+
+The [Kubernetes external-storage project](https://github.com/kubernetes-incubator/external-storage)
+provides an out-of-tree dynamic [provisioner](https://github.com/kubernetes-incubator/external-storage/tree/master/nfs)
+for NFS volumes. A chart exists for easy deployment of the project onto a
+Kubernetes cluster. The chart's sources can be found [here](https://github.com/helm/charts/tree/master/stable/nfs-server-provisioner).
+
+## Prerequisites
+
+This guide will use Helm to install the NFS-provisioner. Thus, Helm has to be
+installed.
+
+## Installing the nfs-server-provisioner chart
+
+A custom `values.yaml`-file containing a configuration tested with the
+gerrit-replica chart can be found in the `supplements/nfs`-directory in the
+gerrit-replica chart's root directory. In addition a file stating the tested
+version of the nfs-server-provisioner chart is present in the same directory.
+
+If needed, adapt the `values.yaml`-file for the nfs-server-provisioner chart
+further and then run:
+
+```sh
+cd $(git rev-parse --show-toplevel)/helm-charts/gerrit-replica/supplements/nfs
+helm install nfs \
+ stable/nfs-server-provisioner \
+ -f values.yaml \
+ --version $(cat VERSION)
+```
+
+For a description of the configuration options, refer to the
+[chart's documentation](https://github.com/helm/charts/blob/master/stable/nfs-server-provisioner/README.md).
+
+Here are some tips for configuring the nfs-server-provisioner chart to work with
+the gerrit-replica chart:
+
+- Deploying more than 1 `replica` led to some reliability issues in tests and
+ should be further tested for now, if required.
+- The name of the StorageClass created for NFS-volumes has to be the same as the
+ one defined in the gerrit-replica chart for `storageClasses.shared.name`
+- The StorageClas for NFS-volumes needs to have the parameter `mountOptions: vers=4.1`,
+ due to compatibility [issues](https://github.com/kubernetes-incubator/external-storage/issues/223)
+ with Ganesha.
+
+## Deleting the nfs-server-provisioner chart
+
+***note
+**Attention:** Never delete the nfs-server-provisioner chart, if there is still a
+PersistentVolumeClaim and Pods using a NFS-volume provisioned by the NFS server
+provisioner. This will lead to crashed pods, that will not be terminated correctly.
+***
+
+If no Pod or PVC is using a NFS-volume provisioned by the NFS server provisioner
+anymore, delete it like any other chart:
+
+```sh
+helm delete nfs
+```
diff --git a/charts/gerrit-replica/supplements/nfs/VERSION b/charts/gerrit-replica/supplements/nfs/VERSION
new file mode 100644
index 0000000..7dff5b8
--- /dev/null
+++ b/charts/gerrit-replica/supplements/nfs/VERSION
@@ -0,0 +1 @@
+0.2.1
\ No newline at end of file
diff --git a/charts/gerrit-replica/supplements/nfs/values.yaml b/charts/gerrit-replica/supplements/nfs/values.yaml
new file mode 100644
index 0000000..aa3d9ce
--- /dev/null
+++ b/charts/gerrit-replica/supplements/nfs/values.yaml
@@ -0,0 +1,42 @@
+# Deploying more than 1 `replica` led to some reliability issues in tests and
+# should be further tested for now, if required.
+replicaCount: 1
+
+image:
+ repository: quay.io/kubernetes_incubator/nfs-provisioner
+ tag: v1.0.9
+ pullPolicy: IfNotPresent
+
+service:
+ type: ClusterIP
+ nfsPort: 2049
+ mountdPort: 20048
+ rpcbindPort: 51413
+
+persistence:
+ enabled: true
+ storageClass: default
+ accessMode: ReadWriteOnce
+ size: 7.5Gi
+
+storageClass:
+ create: true
+ defaultClass: false
+ # The name of the StorageClass has to be the same as the one defined in the
+ # gerrit-replica chart for `storageClasses.shared.name`
+ name: shared-storage
+ parameters:
+ # Required!
+ mountOptions: vers=4.1
+ reclaimPolicy: Delete
+
+rbac:
+ create: true
+
+resources:
+ requests:
+ cpu: 100m
+ memory: 256Mi
+ limits:
+ cpu: 100m
+ memory: 256Mi
diff --git a/charts/gerrit-replica/templates/NOTES.txt b/charts/gerrit-replica/templates/NOTES.txt
new file mode 100644
index 0000000..30e263f
--- /dev/null
+++ b/charts/gerrit-replica/templates/NOTES.txt
@@ -0,0 +1,35 @@
+A Gerrit replica has been deployed.
+=================================
+
+The Apache-Git-HTTP-Backend is now ready to receive replication requests from the
+primary Gerrit. Please configure the replication plugin of the primary Gerrit to
+push the repositories to:
+
+{{ if .Values.istio.enabled -}}
+ http {{- if .Values.istio.tls.enabled -}} s {{- end -}} :// {{- .Values.istio.host -}} /${name}.git
+{{ else if .Values.ingress.enabled -}}
+ http {{- if .Values.ingress.tls.enabled -}} s {{- end -}} :// {{- .Values.ingress.host -}} /${name}.git
+{{- else }}
+ http://<EXTERNAL-IP>: {{- .Values.gitBackend.service.http.port -}} /${name}.git
+ The external IP of the service can be found by running:
+ kubectl get svc git-backend-service
+{{- end }}
+
+Project creation, project deletion and HEAD update can also be replicated. To enable
+this feature configure the replication plugin to use an adminUrl using the format
+`gerrit+http {{- if .Values.ingress.tls.enabled -}} s {{- end -}} :// {{- .Values.ingress.host -}}`.
+
+A detailed guide of how to configure Gerrit's replication plugin can be found here:
+
+https://gerrit.googlesource.com/plugins/replication/+doc/master/src/main/resources/Documentation/config.md
+
+The Gerrit replica is starting up.
+
+The initialization process may take some time. Afterwards the git repositories
+will be available under:
+
+{{ if .Values.istio.enabled -}}
+ http {{- if .Values.istio.tls.enabled -}} s {{- end -}} :// {{- .Values.istio.host -}} /<repository-name>.git
+{{- else }}
+ http {{- if .Values.ingress.tls.enabled -}} s {{- end -}} :// {{- .Values.ingress.host -}} /<repository-name>.git
+{{- end }}
diff --git a/charts/gerrit-replica/templates/_helpers.tpl b/charts/gerrit-replica/templates/_helpers.tpl
new file mode 100644
index 0000000..500d58c
--- /dev/null
+++ b/charts/gerrit-replica/templates/_helpers.tpl
@@ -0,0 +1,20 @@
+{{/*
+Create chart name and version as used by the chart label.
+*/}}
+{{- define "gerrit-replica.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+{{/*
+Create secret to access docker registry
+*/}}
+{{- define "imagePullSecret" }}
+{{- printf "{\"auths\": {\"%s\": {\"auth\": \"%s\"}}}" .Values.images.registry.name (printf "%s:%s" .Values.images.registry.ImagePullSecret.username .Values.images.registry.ImagePullSecret.password | b64enc) | b64enc }}
+{{- end }}
+
+{{/*
+Add '/' to registry if needed.
+*/}}
+{{- define "registry" -}}
+{{ if .Values.images.registry.name }}{{- printf "%s/" .Values.images.registry.name -}}{{end}}
+{{- end -}}
diff --git a/charts/gerrit-replica/templates/gerrit-replica.configmap.yaml b/charts/gerrit-replica/templates/gerrit-replica.configmap.yaml
new file mode 100644
index 0000000..1aa9496
--- /dev/null
+++ b/charts/gerrit-replica/templates/gerrit-replica.configmap.yaml
@@ -0,0 +1,78 @@
+{{- $root := . -}}
+
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: {{ .Release.Name }}-gerrit-replica-configmap
+ labels:
+ app.kubernetes.io/component: gerrit-replica
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit-replica.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+data:
+ {{- range $key, $value := .Values.gerritReplica.etc.config }}
+ {{ $key }}:
+{{ toYaml $value | indent 4 }}
+ {{- end }}
+ {{- if not (hasKey .Values.gerritReplica.etc.config "healthcheck.config") }}
+ healthcheck.config: |-
+ [healthcheck "auth"]
+ # On new instances there may be no users to use for healthchecks
+ enabled = false
+ [healthcheck "querychanges"]
+ # On new instances there won't be any changes to query
+ enabled = false
+ {{- end }}
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: {{ .Release.Name }}-gerrit-init-configmap
+ labels:
+ app.kubernetes.io/component: gerrit-replica
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit-replica.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+data:
+ gerrit-init.yaml: |-
+ {{ if .Values.caCert -}}
+ caCertPath: /var/config/ca.crt
+ {{- end }}
+ pluginCacheEnabled: {{ .Values.gerritReplica.pluginManagement.cache.enabled }}
+ pluginCacheDir: /var/mnt/plugins
+ {{- if .Values.gerritReplica.pluginManagement.plugins }}
+ plugins:
+{{ toYaml .Values.gerritReplica.pluginManagement.plugins | indent 6}}
+ {{- end }}
+ {{- if .Values.gerritReplica.pluginManagement.libs }}
+ libs:
+{{ toYaml .Values.gerritReplica.pluginManagement.libs | indent 6}}
+ {{- end }}
+{{- range .Values.gerritReplica.additionalConfigMaps -}}
+{{- if .data }}
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: {{ $root.Release.Name }}-{{ .name }}
+ labels:
+ app.kubernetes.io/component: gerrit-replica
+ app.kubernetes.io/instance: {{ $root.Release.Name }}
+ chart: {{ template "gerrit-replica.chart" $root }}
+ heritage: {{ $root.Release.Service }}
+ release: {{ $root.Release.Name }}
+ {{- if $root.Values.additionalLabels }}
+{{ toYaml $root.Values.additionalLabels | indent 4 }}
+ {{- end }}
+data:
+{{ toYaml .data | indent 2 }}
+{{- end }}
+{{- end }}
diff --git a/charts/gerrit-replica/templates/gerrit-replica.secrets.yaml b/charts/gerrit-replica/templates/gerrit-replica.secrets.yaml
new file mode 100644
index 0000000..ece9b9a
--- /dev/null
+++ b/charts/gerrit-replica/templates/gerrit-replica.secrets.yaml
@@ -0,0 +1,21 @@
+apiVersion: v1
+kind: Secret
+metadata:
+ name: {{ .Release.Name }}-gerrit-replica-secure-config
+ labels:
+ app.kubernetes.io/component: gerrit-replica
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit-replica.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+data:
+ {{ if .Values.gerritReplica.keystore -}}
+ keystore: {{ .Values.gerritReplica.keystore }}
+ {{- end }}
+ {{- range $key, $value := .Values.gerritReplica.etc.secret }}
+ {{ $key }}: {{ $value | b64enc }}
+ {{- end }}
+type: Opaque
diff --git a/charts/gerrit-replica/templates/gerrit-replica.service.yaml b/charts/gerrit-replica/templates/gerrit-replica.service.yaml
new file mode 100644
index 0000000..01030b4
--- /dev/null
+++ b/charts/gerrit-replica/templates/gerrit-replica.service.yaml
@@ -0,0 +1,40 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: {{ .Release.Name }}-gerrit-replica-service
+ labels:
+ app.kubernetes.io/component: gerrit-replica
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit-replica.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+ {{- if .Values.gerritReplica.service.additionalAnnotations }}
+ annotations:
+{{ toYaml .Values.gerritReplica.service.additionalAnnotations | indent 4 }}
+ {{- end }}
+spec:
+ {{ with .Values.gerritReplica.service }}
+ {{- if .loadBalancerSourceRanges -}}
+ loadBalancerSourceRanges:
+{{- range .loadBalancerSourceRanges }}
+ - {{ . | quote }}
+{{- end }}
+ {{- end }}
+ ports:
+ - name: http
+ port: {{ .http.port }}
+ targetPort: 8080
+ {{ if .ssh.enabled -}}
+ - name: ssh
+ port: {{ .ssh.port }}
+ targetPort: 29418
+ {{- end }}
+ type: {{ .type }}
+ externalTrafficPolicy: {{ .externalTrafficPolicy }}
+ {{- end }}
+ selector:
+ app.kubernetes.io/component: gerrit-replica
+ app.kubernetes.io/instance: {{ .Release.Name }}
diff --git a/charts/gerrit-replica/templates/gerrit-replica.stateful-set.yaml b/charts/gerrit-replica/templates/gerrit-replica.stateful-set.yaml
new file mode 100644
index 0000000..8493c7a
--- /dev/null
+++ b/charts/gerrit-replica/templates/gerrit-replica.stateful-set.yaml
@@ -0,0 +1,346 @@
+{{- $root := . -}}
+
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+ name: {{ .Release.Name }}-gerrit-replica-statefulset
+ labels:
+ app.kubernetes.io/component: gerrit-replica
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit-replica.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+spec:
+ serviceName: {{ .Release.Name }}-gerrit-replica-service
+ replicas: {{ .Values.gerritReplica.replicas }}
+ updateStrategy:
+ rollingUpdate:
+ partition: {{ .Values.gerritReplica.updatePartition }}
+ selector:
+ matchLabels:
+ app.kubernetes.io/component: gerrit-replica
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ template:
+ metadata:
+ labels:
+ app.kubernetes.io/component: gerrit-replica
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit-replica.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 8 }}
+ {{- end }}
+ {{- if .Values.gerritReplica.additionalPodLabels }}
+{{ toYaml .Values.gerritReplica.additionalPodLabels | indent 8 }}
+ {{- end }}
+ annotations:
+ chartRevision: "{{ .Release.Revision }}"
+ {{- if .Values.gerritReplica.additionalAnnotations }}
+{{ toYaml .Values.gerritReplica.additionalAnnotations | indent 8 }}
+ {{- end }}
+ spec:
+ {{- with .Values.gerritReplica.tolerations }}
+ tolerations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.gerritReplica.topologySpreadConstraints }}
+ topologySpreadConstraints:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.gerritReplica.nodeSelector }}
+ nodeSelector:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.gerritReplica.affinity }}
+ affinity:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.gerritReplica.priorityClassName }}
+ priorityClassName: {{ . }}
+ {{- end }}
+ terminationGracePeriodSeconds: {{ .Values.gerritReplica.gracefulStopTimeout }}
+ securityContext:
+ fsGroup: 100
+ {{ if .Values.images.registry.ImagePullSecret.name -}}
+ imagePullSecrets:
+ - name: {{ .Values.images.registry.ImagePullSecret.name }}
+ {{- range .Values.images.additionalImagePullSecrets }}
+ - name: {{ . }}
+ {{- end }}
+ {{- end }}
+ initContainers:
+ {{- if and .Values.nfsWorkaround.enabled .Values.nfsWorkaround.chownOnStartup }}
+ - name: nfs-init
+ image: {{ .Values.images.busybox.registry -}}/busybox:{{- .Values.images.busybox.tag }}
+ command:
+ - sh
+ - -c
+ args:
+ - |
+ chown 1000:100 /var/mnt/logs
+ chown 1000:100 /var/mnt/git
+ env:
+ - name: POD_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.name
+ volumeMounts:
+ - name: logs
+ subPathExpr: "gerrit-replica/$(POD_NAME)"
+ mountPath: "/var/mnt/logs"
+ - name: git-repositories
+ mountPath: "/var/mnt/git"
+ {{- if .Values.nfsWorkaround.idDomain }}
+ - name: nfs-config
+ mountPath: "/etc/idmapd.conf"
+ subPath: idmapd.conf
+ {{- end }}
+ {{- end }}
+ - name: gerrit-init
+ image: {{ template "registry" . }}{{ .Values.gerritReplica.images.gerritInit }}:{{ .Values.images.version }}
+ imagePullPolicy: {{ .Values.images.imagePullPolicy }}
+ env:
+ - name: POD_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.name
+ volumeMounts:
+ - name: gerrit-site
+ mountPath: "/var/gerrit"
+ - name: git-repositories
+ mountPath: "/var/mnt/git"
+ - name: logs
+ subPathExpr: "gerrit-replica/$(POD_NAME)"
+ mountPath: "/var/mnt/logs"
+ - name: gerrit-init-config
+ mountPath: "/var/config/gerrit-init.yaml"
+ subPath: gerrit-init.yaml
+ {{- if and .Values.nfsWorkaround.enabled .Values.nfsWorkaround.idDomain }}
+ - name: nfs-config
+ mountPath: "/etc/idmapd.conf"
+ subPath: idmapd.conf
+ {{- end }}
+ {{- if and .Values.gerritReplica.pluginManagement.cache.enabled }}
+ - name: gerrit-plugin-cache
+ mountPath: "/var/mnt/plugins"
+ {{- end }}
+ - name: gerrit-config
+ mountPath: "/var/mnt/etc/config"
+ - name: gerrit-replica-secure-config
+ mountPath: "/var/mnt/etc/secret"
+ {{ if .Values.caCert -}}
+ - name: tls-ca
+ subPath: ca.crt
+ mountPath: "/var/config/ca.crt"
+ {{- end }}
+ {{- range .Values.gerritReplica.additionalConfigMaps }}
+ - name: {{ .name }}
+ mountPath: "/var/mnt/data/{{ .subDir }}"
+ {{- end }}
+ containers:
+ - name: gerrit-replica
+ image: {{ template "registry" . }}{{ .Values.gerritReplica.images.gerritReplica }}:{{ .Values.images.version }}
+ imagePullPolicy: {{ .Values.images.imagePullPolicy }}
+ env:
+ - name: POD_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.name
+ lifecycle:
+ preStop:
+ exec:
+ command:
+ - "/bin/ash"
+ - "-c"
+ - "kill -2 $(pidof java) && tail --pid=$(pidof java) -f /dev/null"
+ ports:
+ - name: http
+ containerPort: 8080
+ {{ if .Values.gerritReplica.service.ssh -}}
+ - name: ssh
+ containerPort: 29418
+ {{- end }}
+ volumeMounts:
+ - name: gerrit-site
+ mountPath: "/var/gerrit"
+ - name: git-repositories
+ mountPath: "/var/mnt/git"
+ - name: logs
+ subPathExpr: "gerrit-replica/$(POD_NAME)"
+ mountPath: "/var/mnt/logs"
+ {{- if and .Values.nfsWorkaround.enabled .Values.nfsWorkaround.idDomain }}
+ - name: nfs-config
+ mountPath: "/etc/idmapd.conf"
+ subPath: idmapd.conf
+ {{- end }}
+ - name: gerrit-config
+ mountPath: "/var/mnt/etc/config"
+ - name: gerrit-replica-secure-config
+ mountPath: "/var/mnt/etc/secret"
+ {{- range .Values.gerritReplica.additionalConfigMaps }}
+ - name: {{ .name }}
+ mountPath: "/var/mnt/data/{{ .subDir }}"
+ {{- end }}
+ livenessProbe:
+ httpGet:
+ path: /config/server/healthcheck~status
+ port: http
+{{- if .Values.gerritReplica.probeScheme }}
+ scheme: {{ .Values.gerritReplica.probeScheme }}
+{{- end }}
+{{ toYaml .Values.gerritReplica.livenessProbe | indent 10 }}
+ readinessProbe:
+ httpGet:
+ path: /config/server/healthcheck~status
+ port: http
+{{- if .Values.gerritReplica.probeScheme }}
+ scheme: {{ .Values.gerritReplica.probeScheme }}
+{{- end }}
+{{ toYaml .Values.gerritReplica.readinessProbe | indent 10 }}
+ startupProbe:
+ httpGet:
+ path: /config/server/healthcheck~status
+ port: http
+{{- if .Values.gerritReplica.probeScheme }}
+ scheme: {{ .Values.gerritReplica.probeScheme }}
+{{- end }}
+{{ toYaml .Values.gerritReplica.startupProbe | indent 10 }}
+ resources:
+{{ toYaml .Values.gerritReplica.resources | indent 10 }}
+ {{ if .Values.istio.enabled -}}
+ - name: istio-proxy
+ image: auto
+ lifecycle:
+ preStop:
+ exec:
+ command:
+ - "/bin/sh"
+ - "-c"
+ - "while [ $(netstat -plunt | grep tcp | grep -v envoy | wc -l | xargs) -ne 0 ]; do sleep 1; done"
+ {{- end }}
+ {{ if .Values.promtailSidecar.enabled -}}
+ - name: promtail
+ image: {{ .Values.promtailSidecar.image }}:v{{ .Values.promtailSidecar.version }}
+ imagePullPolicy: {{ .Values.images.imagePullPolicy }}
+ command:
+ - sh
+ - -ec
+ args:
+ - |-
+ /usr/bin/promtail \
+ -config.file=/etc/promtail/promtail.yaml \
+ -client.url={{ .Values.promtailSidecar.loki.url }}/loki/api/v1/push \
+ -client.external-labels=instance=$HOSTNAME
+ env:
+ - name: POD_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.name
+ resources:
+{{ toYaml .Values.promtailSidecar.resources | indent 10 }}
+ volumeMounts:
+ - name: promtail-config
+ mountPath: /etc/promtail/promtail.yaml
+ subPath: promtail.yaml
+ - name: promtail-secret
+ mountPath: /etc/promtail/promtail.secret
+ subPath: promtail.secret
+ {{- if not .Values.promtailSidecar.tls.skipVerify }}
+ - name: tls-ca
+ mountPath: /etc/promtail/promtail.ca.crt
+ subPath: ca.crt
+ {{- end }}
+ - name: logs
+ subPathExpr: "gerrit-replica/$(POD_NAME)"
+ mountPath: "/var/gerrit/logs"
+ {{- if and .Values.nfsWorkaround.enabled .Values.nfsWorkaround.idDomain }}
+ - name: nfs-config
+ mountPath: "/etc/idmapd.conf"
+ subPath: idmapd.conf
+ {{- end }}
+ {{- end }}
+ volumes:
+ {{ if not .Values.gerritReplica.persistence.enabled -}}
+ - name: gerrit-site
+ emptyDir: {}
+ {{- end }}
+ {{- if and .Values.gerritReplica.pluginManagement.cache.enabled }}
+ - name: gerrit-plugin-cache
+ persistentVolumeClaim:
+ claimName: {{ .Release.Name }}-plugin-cache-pvc
+ {{- end }}
+ - name: git-repositories
+ persistentVolumeClaim:
+ {{- if .Values.gitRepositoryStorage.externalPVC.use }}
+ claimName: {{ .Values.gitRepositoryStorage.externalPVC.name }}
+ {{- else }}
+ claimName: {{ .Release.Name }}-git-repositories-pvc
+ {{- end }}
+ - name: logs
+ {{ if .Values.logStorage.enabled -}}
+ persistentVolumeClaim:
+ {{- if .Values.logStorage.externalPVC.use }}
+ claimName: {{ .Values.logStorage.externalPVC.name }}
+ {{- else }}
+ claimName: {{ .Release.Name }}-log-pvc
+ {{- end }}
+ {{ else -}}
+ emptyDir: {}
+ {{- end }}
+ - name: gerrit-init-config
+ configMap:
+ name: {{ .Release.Name }}-gerrit-init-configmap
+ - name: gerrit-config
+ configMap:
+ name: {{ .Release.Name }}-gerrit-replica-configmap
+ - name: gerrit-replica-secure-config
+ secret:
+ secretName: {{ .Release.Name }}-gerrit-replica-secure-config
+ {{ if .Values.caCert -}}
+ - name: tls-ca
+ secret:
+ secretName: {{ .Release.Name }}-tls-ca
+ {{- end }}
+ {{- range .Values.gerritReplica.additionalConfigMaps }}
+ - name: {{ .name }}
+ configMap:
+ name: {{ if .data }}{{ $root.Release.Name }}-{{ .name }}{{ else }}{{ .name }}{{ end }}
+ {{- end }}
+ {{- if and .Values.nfsWorkaround.enabled .Values.nfsWorkaround.idDomain }}
+ - name: nfs-config
+ configMap:
+ name: {{ .Release.Name }}-nfs-configmap
+ {{- end }}
+ {{ if .Values.promtailSidecar.enabled -}}
+ - name: promtail-config
+ configMap:
+ name: {{ .Release.Name }}-promtail-gerrit-configmap
+ - name: promtail-secret
+ secret:
+ secretName: {{ .Release.Name }}-promtail-secret
+ {{- end }}
+ {{ if .Values.gerritReplica.persistence.enabled -}}
+ volumeClaimTemplates:
+ - metadata:
+ name: gerrit-site
+ labels:
+ app.kubernetes.io/component: gerrit-replica
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit-replica.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 8 }}
+ {{- end }}
+ spec:
+ accessModes:
+ - ReadWriteOnce
+ resources:
+ requests:
+ storage: {{ .Values.gerritReplica.persistence.size }}
+ storageClassName: {{ .Values.storageClasses.default.name }}
+ {{- end }}
diff --git a/charts/gerrit-replica/templates/gerrit-replica.storage.yaml b/charts/gerrit-replica/templates/gerrit-replica.storage.yaml
new file mode 100644
index 0000000..c710737
--- /dev/null
+++ b/charts/gerrit-replica/templates/gerrit-replica.storage.yaml
@@ -0,0 +1,22 @@
+{{- if and .Values.gerritReplica.pluginManagement.cache.enabled }}
+kind: PersistentVolumeClaim
+apiVersion: v1
+metadata:
+ name: {{ .Release.Name }}-plugin-cache-pvc
+ labels:
+ app.kubernetes.io/component: gerrit-replica
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit-replica.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+spec:
+ accessModes:
+ - ReadWriteMany
+ resources:
+ requests:
+ storage: {{ .Values.gerritReplica.pluginManagement.cache.size }}
+ storageClassName: {{ .Values.storageClasses.shared.name }}
+{{- end }}
diff --git a/charts/gerrit-replica/templates/git-backend.deployment.yaml b/charts/gerrit-replica/templates/git-backend.deployment.yaml
new file mode 100644
index 0000000..037bcb9
--- /dev/null
+++ b/charts/gerrit-replica/templates/git-backend.deployment.yaml
@@ -0,0 +1,168 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: {{ .Release.Name }}-git-backend-deployment
+ labels:
+ app.kubernetes.io/component: git-backend
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit-replica.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+spec:
+ replicas: {{ .Values.gitBackend.replicas }}
+ strategy:
+ rollingUpdate:
+ maxSurge: {{ .Values.gitBackend.maxSurge }}
+ maxUnavailable: {{ .Values.gitBackend.maxUnavailable }}
+ selector:
+ matchLabels:
+ app.kubernetes.io/component: git-backend
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ template:
+ metadata:
+ labels:
+ app.kubernetes.io/component: git-backend
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit-replica.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 8 }}
+ {{- end }}
+ {{- if .Values.gitBackend.additionalPodLabels }}
+{{ toYaml .Values.gitBackend.additionalPodLabels | indent 8 }}
+ {{- end }}
+ annotations:
+ chartRevision: "{{ .Release.Revision }}"
+ spec:
+ {{- with .Values.gitBackend.tolerations }}
+ tolerations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.gitBackend.topologySpreadConstraints }}
+ topologySpreadConstraints:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.gitBackend.nodeSelector }}
+ nodeSelector:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.gitBackend.affinity }}
+ affinity:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ securityContext:
+ fsGroup: 100
+ {{ if .Values.images.registry.ImagePullSecret.name -}}
+ imagePullSecrets:
+ - name: {{ .Values.images.registry.ImagePullSecret.name }}
+ {{- range .Values.images.additionalImagePullSecrets }}
+ - name: {{ . }}
+ {{- end }}
+ {{- end }}
+ initContainers:
+ {{- if and .Values.nfsWorkaround.enabled .Values.nfsWorkaround.chownOnStartup }}
+ - name: nfs-init
+ image: {{ .Values.images.busybox.registry -}}/busybox:{{- .Values.images.busybox.tag }}
+ command:
+ - sh
+ - -c
+ args:
+ - |
+ chown 1000:100 /var/mnt/logs
+ chown 1000:100 /var/mnt/git
+ env:
+ - name: POD_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.name
+ volumeMounts:
+ - name: logs
+ subPathExpr: "gerrit-replica/$(POD_NAME)"
+ mountPath: "/var/mnt/logs"
+ - name: git-repositories
+ mountPath: "/var/mnt/git"
+ {{- if .Values.nfsWorkaround.idDomain }}
+ - name: nfs-config
+ mountPath: "/etc/idmapd.conf"
+ subPath: idmapd.conf
+ {{- end }}
+ {{- end }}
+ containers:
+ - name: apache-git-http-backend
+ imagePullPolicy: {{ .Values.images.imagePullPolicy }}
+ image: {{ template "registry" . }}{{ .Values.gitBackend.image }}:{{ .Values.images.version }}
+ env:
+ - name: POD_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.name
+ ports:
+ - name: http-port
+ containerPort: 80
+ resources:
+{{ toYaml .Values.gitBackend.resources | indent 10 }}
+ livenessProbe:
+ tcpSocket:
+ port: http-port
+{{ toYaml .Values.gitBackend.livenessProbe | indent 10 }}
+ readinessProbe:
+ tcpSocket:
+ port: http-port
+{{ toYaml .Values.gitBackend.readinessProbe | indent 10 }}
+ volumeMounts:
+ - name: git-repositories
+ mountPath: "/var/gerrit/git"
+ - name: logs
+ subPathExpr: "apache-git-http-backend/$(POD_NAME)"
+ mountPath: "/var/log/apache2"
+ {{- if and .Values.nfsWorkaround.enabled .Values.nfsWorkaround.idDomain }}
+ - name: nfs-config
+ mountPath: "/etc/idmapd.conf"
+ subPath: idmapd.conf
+ {{- end }}
+ - name: git-backend-secret
+ readOnly: true
+ subPath: .htpasswd
+ mountPath: "/var/apache/credentials/.htpasswd"
+ {{ if .Values.istio.enabled -}}
+ - name: istio-proxy
+ image: auto
+ lifecycle:
+ preStop:
+ exec:
+ command:
+ - "/bin/sh"
+ - "-c"
+ - "while [ $(netstat -plunt | grep tcp | grep -v envoy | wc -l | xargs) -ne 0 ]; do sleep 1; done"
+ {{- end }}
+ volumes:
+ - name: git-repositories
+ persistentVolumeClaim:
+ {{- if .Values.gitRepositoryStorage.externalPVC.use }}
+ claimName: {{ .Values.gitRepositoryStorage.externalPVC.name }}
+ {{- else }}
+ claimName: {{ .Release.Name }}-git-repositories-pvc
+ {{- end }}
+ - name: git-backend-secret
+ secret:
+ secretName: {{ .Release.Name }}-git-backend-secret
+ - name: logs
+ {{ if .Values.logStorage.enabled -}}
+ persistentVolumeClaim:
+ {{- if .Values.logStorage.externalPVC.use }}
+ claimName: {{ .Values.logStorage.externalPVC.name }}
+ {{- else }}
+ claimName: {{ .Release.Name }}-log-pvc
+ {{- end }}
+ {{ else -}}
+ emptyDir: {}
+ {{- end }}
+ {{- if and .Values.nfsWorkaround.enabled .Values.nfsWorkaround.idDomain }}
+ - name: nfs-config
+ configMap:
+ name: {{ .Release.Name }}-nfs-configmap
+ {{- end }}
diff --git a/charts/gerrit-replica/templates/git-backend.secrets.yaml b/charts/gerrit-replica/templates/git-backend.secrets.yaml
new file mode 100644
index 0000000..94b1705
--- /dev/null
+++ b/charts/gerrit-replica/templates/git-backend.secrets.yaml
@@ -0,0 +1,16 @@
+apiVersion: v1
+kind: Secret
+metadata:
+ name: {{ .Release.Name }}-git-backend-secret
+ labels:
+ app.kubernetes.io/component: git-backend
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit-replica.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+data:
+ .htpasswd: {{ required "A .htpasswd-file is required for the git backend." .Values.gitBackend.credentials.htpasswd | b64enc }}
+type: Opaque
diff --git a/charts/gerrit-replica/templates/git-backend.service.yaml b/charts/gerrit-replica/templates/git-backend.service.yaml
new file mode 100644
index 0000000..7bd47ef
--- /dev/null
+++ b/charts/gerrit-replica/templates/git-backend.service.yaml
@@ -0,0 +1,35 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: {{ .Release.Name }}-git-backend-service
+ labels:
+ app.kubernetes.io/component: git-backend
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit-replica.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+ {{- if .Values.gitBackend.service.additionalAnnotations }}
+ annotations:
+{{ toYaml .Values.gitBackend.service.additionalAnnotations | indent 4 }}
+ {{- end }}
+spec:
+ {{ with .Values.gitBackend.service }}
+ {{- if .loadBalancerSourceRanges -}}
+ loadBalancerSourceRanges:
+{{- range .loadBalancerSourceRanges }}
+ - {{ . | quote }}
+{{- end }}
+ {{- end }}
+ ports:
+ - name: http
+ port: {{ .http.port }}
+ targetPort: 80
+ type: {{ .type }}
+ externalTrafficPolicy: {{ .externalTrafficPolicy }}
+ {{- end }}
+ selector:
+ app.kubernetes.io/component: git-backend
+ app.kubernetes.io/instance: {{ .Release.Name }}
diff --git a/charts/gerrit-replica/templates/git-gc.cronjob.yaml b/charts/gerrit-replica/templates/git-gc.cronjob.yaml
new file mode 100644
index 0000000..028ffe9
--- /dev/null
+++ b/charts/gerrit-replica/templates/git-gc.cronjob.yaml
@@ -0,0 +1,134 @@
+apiVersion: batch/v1
+kind: CronJob
+metadata:
+ name: {{ .Release.Name }}-git-gc
+ labels:
+ app.kubernetes.io/component: git-gc
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit-replica.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+spec:
+ schedule: {{ .Values.gitGC.schedule | quote }}
+ concurrencyPolicy: "Forbid"
+ jobTemplate:
+ spec:
+ template:
+ metadata:
+ annotations:
+ cluster-autoscaler.kubernetes.io/safe-to-evict: "false"
+ {{ if .Values.istio.enabled }}
+ sidecar.istio.io/inject: "false"
+ {{- end }}
+ labels:
+ app.kubernetes.io/component: git-gc
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit-replica.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 12 }}
+ {{- end }}
+ {{- if .Values.gitGC.additionalPodLabels }}
+{{ toYaml .Values.gitGC.additionalPodLabels | indent 12 }}
+ {{- end }}
+ spec:
+ {{- with .Values.gitGC.tolerations }}
+ tolerations:
+ {{- toYaml . | nindent 10 }}
+ {{- end }}
+ {{- with .Values.gitGC.nodeSelector }}
+ nodeSelector:
+ {{- toYaml . | nindent 12 }}
+ {{- end }}
+ {{- with .Values.gitGC.affinity }}
+ affinity:
+ {{- toYaml . | nindent 12 }}
+ {{- end }}
+ restartPolicy: OnFailure
+ securityContext:
+ fsGroup: 100
+ {{ if .Values.images.registry.ImagePullSecret.name -}}
+ imagePullSecrets:
+ - name: {{ .Values.images.registry.ImagePullSecret.name }}
+ {{- range .Values.images.additionalImagePullSecrets }}
+ - name: {{ . }}
+ {{- end }}
+ {{- end }}
+ initContainers:
+ {{- if and .Values.nfsWorkaround.enabled .Values.nfsWorkaround.chownOnStartup }}
+ - name: nfs-init
+ image: {{ .Values.images.busybox.registry -}}/busybox:{{- .Values.images.busybox.tag }}
+ command:
+ - sh
+ - -c
+ args:
+ - |
+ chown 1000:100 /var/mnt/logs
+ chown 1000:100 /var/mnt/git
+ env:
+ - name: POD_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.name
+ volumeMounts:
+ - name: logs
+ subPathExpr: "git-gc/$(POD_NAME)"
+ mountPath: "/var/mnt/logs"
+ - name: git-repositories
+ mountPath: "/var/mnt/git"
+ {{- if .Values.nfsWorkaround.idDomain }}
+ - name: nfs-config
+ mountPath: "/etc/idmapd.conf"
+ subPath: idmapd.conf
+ {{- end }}
+ {{- end }}
+ containers:
+ - name: git-gc
+ imagePullPolicy: {{ .Values.images.imagePullPolicy }}
+ image: {{ template "registry" . }}{{ .Values.gitGC.image }}:{{ .Values.images.version }}
+ resources:
+{{ toYaml .Values.gitGC.resources | indent 14 }}
+ env:
+ - name: POD_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.name
+ volumeMounts:
+ - name: git-repositories
+ mountPath: "/var/gerrit/git"
+ - name: logs
+ subPathExpr: "git-gc/$(POD_NAME)"
+ mountPath: "/var/log/git"
+ {{- if and .Values.nfsWorkaround.enabled .Values.nfsWorkaround.idDomain }}
+ - name: nfs-config
+ mountPath: "/etc/idmapd.conf"
+ subPath: idmapd.conf
+ {{- end }}
+ volumes:
+ - name: git-repositories
+ persistentVolumeClaim:
+ {{- if .Values.gitRepositoryStorage.externalPVC.use }}
+ claimName: {{ .Values.gitRepositoryStorage.externalPVC.name }}
+ {{- else }}
+ claimName: {{ .Release.Name }}-git-repositories-pvc
+ {{- end }}
+ - name: logs
+ {{ if .Values.logStorage.enabled -}}
+ persistentVolumeClaim:
+ {{- if .Values.logStorage.externalPVC.use }}
+ claimName: {{ .Values.logStorage.externalPVC.name }}
+ {{- else }}
+ claimName: {{ .Release.Name }}-log-pvc
+ {{- end }}
+ {{ else -}}
+ emptyDir: {}
+ {{- end }}
+ {{- if and .Values.nfsWorkaround.enabled .Values.nfsWorkaround.idDomain }}
+ - name: nfs-config
+ configMap:
+ name: {{ .Release.Name }}-nfs-configmap
+ {{- end }}
diff --git a/charts/gerrit-replica/templates/global.secrets.yaml b/charts/gerrit-replica/templates/global.secrets.yaml
new file mode 100644
index 0000000..7dfe4a1
--- /dev/null
+++ b/charts/gerrit-replica/templates/global.secrets.yaml
@@ -0,0 +1,18 @@
+{{ if .Values.caCert -}}
+apiVersion: v1
+kind: Secret
+metadata:
+ name: {{ .Release.Name }}-tls-ca
+ labels:
+ app.kubernetes.io/component: gerrit-replica
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit-replica.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+data:
+ ca.crt: {{ .Values.caCert | b64enc }}
+type: Opaque
+{{- end }}
diff --git a/charts/gerrit-replica/templates/image-pull.secret.yaml b/charts/gerrit-replica/templates/image-pull.secret.yaml
new file mode 100644
index 0000000..3f97cd0
--- /dev/null
+++ b/charts/gerrit-replica/templates/image-pull.secret.yaml
@@ -0,0 +1,13 @@
+{{ if and .Values.images.registry.ImagePullSecret.name .Values.images.registry.ImagePullSecret.create -}}
+apiVersion: v1
+kind: Secret
+metadata:
+ name: {{ .Values.images.registry.ImagePullSecret.name }}
+ labels:
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+type: kubernetes.io/dockerconfigjson
+data:
+ .dockerconfigjson: {{ template "imagePullSecret" . }}
+{{- end }}
\ No newline at end of file
diff --git a/charts/gerrit-replica/templates/ingress.yaml b/charts/gerrit-replica/templates/ingress.yaml
new file mode 100644
index 0000000..e78dfcc
--- /dev/null
+++ b/charts/gerrit-replica/templates/ingress.yaml
@@ -0,0 +1,86 @@
+{{ if and .Values.ingress.enabled (not .Values.istio.enabled) -}}
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+ name: {{ .Release.Name }}-ingress
+ labels:
+ app.kubernetes.io/component: gerrit-replica
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit-replica.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+ annotations:
+ kubernetes.io/ingress.class: nginx
+ nginx.ingress.kubernetes.io/proxy-body-size: {{ .Values.ingress.maxBodySize | default "50m" }}
+ nginx.ingress.kubernetes.io/use-regex: "true"
+ nginx.ingress.kubernetes.io/configuration-snippet: |-
+ if ($args ~ service=git-receive-pack){
+ set $proxy_upstream_name "{{ .Release.Namespace }}-{{ .Release.Name }}-git-backend-service-http";
+ set $proxy_host $proxy_upstream_name;
+ set $service_name "{{ .Release.Name }}-git-backend-service";
+ }
+ {{- if .Values.ingress.additionalAnnotations }}
+{{ toYaml .Values.ingress.additionalAnnotations | indent 4 }}
+ {{- end }}
+spec:
+ {{ if .Values.ingress.tls.enabled -}}
+ tls:
+ - hosts:
+ - {{ .Values.ingress.host }}
+ {{ if .Values.ingress.tls.secret.create -}}
+ secretName: {{ .Release.Name }}-tls-secret
+ {{- else }}
+ secretName: {{ .Values.ingress.tls.secret.name }}
+ {{- end }}
+ {{- end }}
+ rules:
+ - host: {{required "A host URL is required for the ingress. Please set 'ingress.host'" .Values.ingress.host }}
+ http:
+ paths:
+ - pathType: Prefix
+ path: /a/projects
+ backend:
+ service:
+ name: {{ .Release.Name }}-git-backend-service
+ port:
+ number: {{ .Values.gitBackend.service.http.port }}
+ - pathType: Prefix
+ path: "/.*/git-receive-pack"
+ backend:
+ service:
+ name: {{ .Release.Name }}-git-backend-service
+ port:
+ number: {{ .Values.gitBackend.service.http.port }}
+ - pathType: Prefix
+ path: /
+ backend:
+ service:
+ name: {{ .Release.Name }}-gerrit-replica-service
+ port:
+ number: {{ .Values.gerritReplica.service.http.port }}
+{{- end }}
+---
+{{ if and (and .Values.ingress.tls.enabled .Values.ingress.tls.secret.create) (not .Values.istio.enabled) -}}
+apiVersion: v1
+kind: Secret
+metadata:
+ name: {{ .Release.Name }}-tls-secret
+ labels:
+ app.kubernetes.io/component: gerrit-replica
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit-replica.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+type: kubernetes.io/tls
+data:
+ {{ with .Values.ingress.tls -}}
+ tls.crt: {{ .cert | b64enc }}
+ tls.key: {{ .key | b64enc }}
+ {{- end }}
+{{- end }}
diff --git a/charts/gerrit-replica/templates/istio.ingressgateway.yaml b/charts/gerrit-replica/templates/istio.ingressgateway.yaml
new file mode 100644
index 0000000..5938536
--- /dev/null
+++ b/charts/gerrit-replica/templates/istio.ingressgateway.yaml
@@ -0,0 +1,144 @@
+{{ if .Values.istio.enabled -}}
+{{ if and .Values.istio.tls.enabled .Values.istio.tls.secret.create }}
+apiVersion: v1
+kind: Secret
+metadata:
+ name: {{ .Release.Name }}-istio-tls-secret
+ namespace: istio-system
+ labels:
+ app.kubernetes.io/component: gerrit-replica
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit-replica.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+type: kubernetes.io/tls
+data:
+ {{ with .Values.istio.tls -}}
+ tls.crt: {{ .cert | b64enc }}
+ tls.key: {{ .key | b64enc }}
+ {{- end }}
+{{- end }}
+---
+apiVersion: networking.istio.io/v1alpha3
+kind: Gateway
+metadata:
+ name: {{ .Release.Name }}-istio-gateway
+ labels:
+ app.kubernetes.io/component: gerrit-replica
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit-replica.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+spec:
+ selector:
+ istio: ingressgateway
+ servers:
+ - port:
+ number: 80
+ name: http
+ protocol: HTTP
+ hosts:
+ - {{ .Values.istio.host }}
+ {{ if .Values.istio.tls.enabled }}
+ tls:
+ httpsRedirect: true
+ - port:
+ number: 443
+ name: https
+ protocol: HTTPS
+ hosts:
+ - {{ .Values.istio.host }}
+ tls:
+ mode: SIMPLE
+ {{ if .Values.istio.tls.secret.create }}
+ credentialName: {{ .Release.Name }}-istio-tls-secret
+ {{- else }}
+ credentialName: {{ .Values.istio.tls.secret.name }}
+ {{- end }}
+ {{- end }}
+ {{ if .Values.istio.ssh.enabled }}
+ - port:
+ number: 29418
+ name: ssh
+ protocol: TCP
+ hosts:
+ - {{ .Values.istio.host }}
+ {{- end }}
+---
+apiVersion: networking.istio.io/v1alpha3
+kind: VirtualService
+metadata:
+ name: {{ .Release.Name }}-istio-virtual-service
+ labels:
+ app.kubernetes.io/component: gerrit-replica
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit-replica.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+spec:
+ hosts:
+ - {{ .Values.istio.host }}
+ gateways:
+ - {{ .Release.Name }}-istio-gateway
+ http:
+ - name: apache-git-http-backend
+ match:
+ - uri:
+ prefix: "/a/projects/"
+ - uri:
+ regex: "/.*/git-receive-pack"
+ - uri:
+ regex: "/.*/info/refs"
+ queryParams:
+ service:
+ exact: git-receive-pack
+ route:
+ - destination:
+ host: {{ .Release.Name }}-git-backend-service.{{ .Release.Namespace }}.svc.cluster.local
+ port:
+ number: 80
+ - name: gerrit-replica
+ route:
+ - destination:
+ host: {{ .Release.Name }}-gerrit-replica-service.{{ .Release.Namespace }}.svc.cluster.local
+ port:
+ number: 80
+ {{ if .Values.istio.ssh.enabled }}
+ tcp:
+ - match:
+ - port: {{ .Values.gerritReplica.service.ssh.port }}
+ route:
+ - destination:
+ host: {{ .Release.Name }}-gerrit-replica-service.{{ .Release.Namespace }}.svc.cluster.local
+ port:
+ number: {{ .Values.gerritReplica.service.ssh.port }}
+ {{- end }}
+---
+apiVersion: networking.istio.io/v1alpha3
+kind: DestinationRule
+metadata:
+ name: {{ .Release.Name }}-gerrit-destination-rule
+ labels:
+ app.kubernetes.io/component: gerrit-replica
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit-replica.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+spec:
+ host: {{ .Release.Name }}-gerrit-replica-service.{{ .Release.Namespace }}.svc.cluster.local
+ trafficPolicy:
+ loadBalancer:
+ simple: LEAST_CONN
+{{- end }}
diff --git a/charts/gerrit-replica/templates/log-cleaner.cronjob.yaml b/charts/gerrit-replica/templates/log-cleaner.cronjob.yaml
new file mode 100644
index 0000000..cbeb88f
--- /dev/null
+++ b/charts/gerrit-replica/templates/log-cleaner.cronjob.yaml
@@ -0,0 +1,69 @@
+{{- if and .Values.logStorage.enabled .Values.logStorage.cleanup.enabled }}
+apiVersion: batch/v1
+kind: CronJob
+metadata:
+ name: {{ .Release.Name }}-log-cleaner
+ labels:
+ app.kubernetes.io/component: log-cleaner
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit-replica.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+spec:
+ schedule: {{ .Values.logStorage.cleanup.schedule | quote }}
+ concurrencyPolicy: "Forbid"
+ jobTemplate:
+ spec:
+ template:
+ metadata:
+ labels:
+ app.kubernetes.io/component: log-cleaner
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit-replica.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 12 }}
+ {{- end }}
+ {{- if .Values.logStorage.cleanup.additionalPodLabels }}
+{{ toYaml .Values.logStorage.cleanup.additionalPodLabels | indent 12 }}
+ {{- end }}
+ {{ if .Values.istio.enabled -}}
+ annotations:
+ sidecar.istio.io/inject: "false"
+ {{- end }}
+ spec:
+ restartPolicy: OnFailure
+ containers:
+ - name: log-cleaner
+ imagePullPolicy: {{ .Values.images.imagePullPolicy }}
+ image: {{ .Values.images.busybox.registry -}}/busybox:{{- .Values.images.busybox.tag }}
+ command:
+ - sh
+ - -c
+ args:
+ - |
+ find /var/logs/ \
+ -mindepth 1 \
+ -type f \
+ -mtime +{{ .Values.logStorage.cleanup.retentionDays }} \
+ -print \
+ -delete
+ find /var/logs/ -type d -empty -delete
+ resources:
+{{ toYaml .Values.logStorage.cleanup.resources | indent 14 }}
+ volumeMounts:
+ - name: logs
+ mountPath: "/var/logs"
+ volumes:
+ - name: logs
+ persistentVolumeClaim:
+ {{- if .Values.logStorage.externalPVC.use }}
+ claimName: {{ .Values.logStorage.externalPVC.name }}
+ {{- else }}
+ claimName: {{ .Release.Name }}-log-pvc
+ {{- end }}
+{{- end }}
diff --git a/charts/gerrit-replica/templates/netpol.yaml b/charts/gerrit-replica/templates/netpol.yaml
new file mode 100644
index 0000000..72a2bbd
--- /dev/null
+++ b/charts/gerrit-replica/templates/netpol.yaml
@@ -0,0 +1,248 @@
+{{ if .Values.networkPolicies.enabled -}}
+kind: NetworkPolicy
+apiVersion: networking.k8s.io/v1
+metadata:
+ name: {{ .Release.Name }}-default-deny-all
+ labels:
+ chart: {{ template "gerrit-replica.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+spec:
+ podSelector:
+ matchLabels:
+ chart: {{ template "gerrit-replica.chart" . }}
+ release: {{ .Release.Name }}
+ policyTypes:
+ - Ingress
+ - Egress
+ ingress: []
+ egress: []
+---
+{{ if .Values.networkPolicies.dnsPorts -}}
+apiVersion: networking.k8s.io/v1
+kind: NetworkPolicy
+metadata:
+ name: {{ .Release.Name }}-allow-dns-access
+ labels:
+ chart: {{ template "gerrit-replica.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+spec:
+ podSelector:
+ matchLabels:
+ chart: {{ template "gerrit-replica.chart" . }}
+ release: {{ .Release.Name }}
+ policyTypes:
+ - Egress
+ egress:
+ - ports:
+ {{ range .Values.networkPolicies.dnsPorts -}}
+ - port: {{ . }}
+ protocol: UDP
+ - port: {{ . }}
+ protocol: TCP
+ {{ end }}
+{{- end }}
+---
+kind: NetworkPolicy
+apiVersion: networking.k8s.io/v1
+metadata:
+ name: gerrit-replica-allow-external
+ labels:
+ app.kubernetes.io/component: gerrit-replica
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit-replica.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+spec:
+ podSelector:
+ matchLabels:
+ chart: {{ template "gerrit-replica.chart" . }}
+ release: {{ .Release.Name }}
+ app.kubernetes.io/component: gerrit-replica
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ ingress:
+ - ports:
+ - port: 8080
+ from: []
+---
+{{ if or .Values.gitBackend.networkPolicy.ingress -}}
+kind: NetworkPolicy
+apiVersion: networking.k8s.io/v1
+metadata:
+ name: git-backend-custom-ingress-policies
+ labels:
+ app.kubernetes.io/component: git-backend
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit-replica.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+spec:
+ policyTypes:
+ - Ingress
+ podSelector:
+ matchLabels:
+ chart: {{ template "gerrit-replica.chart" . }}
+ release: {{ .Release.Name }}
+ app.kubernetes.io/component: git-backend
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ ingress:
+{{ toYaml .Values.gitBackend.networkPolicy.ingress | indent 2 }}
+{{- end }}
+---
+{{ if or .Values.gitBackend.networkPolicy.egress -}}
+kind: NetworkPolicy
+apiVersion: networking.k8s.io/v1
+metadata:
+ name: git-backend-custom-egress-policies
+ labels:
+ app.kubernetes.io/component: git-backend
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit-replica.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+spec:
+ policyTypes:
+ - Egress
+ podSelector:
+ matchLabels:
+ chart: {{ template "gerrit-replica.chart" . }}
+ release: {{ .Release.Name }}
+ app.kubernetes.io/component: git-backend
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ egress:
+{{ toYaml .Values.gitBackend.networkPolicy.egress | indent 2 }}
+{{- end }}
+---
+{{ if or .Values.gerritReplica.networkPolicy.ingress -}}
+kind: NetworkPolicy
+apiVersion: networking.k8s.io/v1
+metadata:
+ name: gerrit-replica-custom-ingress-policies
+ labels:
+ app.kubernetes.io/component: gerrit-replica
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit-replica.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+spec:
+ policyTypes:
+ - Ingress
+ podSelector:
+ matchLabels:
+ chart: {{ template "gerrit-replica.chart" . }}
+ release: {{ .Release.Name }}
+ app.kubernetes.io/component: gerrit-replica
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ ingress:
+{{ toYaml .Values.gerritReplica.networkPolicy.ingress | indent 2 }}
+{{- end }}
+---
+{{ if or .Values.gerritReplica.networkPolicy.egress -}}
+kind: NetworkPolicy
+apiVersion: networking.k8s.io/v1
+metadata:
+ name: gerrit-replica-custom-egress-policies
+ labels:
+ app.kubernetes.io/component: gerrit-replica
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit-replica.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+spec:
+ policyTypes:
+ - Egress
+ podSelector:
+ matchLabels:
+ chart: {{ template "gerrit-replica.chart" . }}
+ release: {{ .Release.Name }}
+ app.kubernetes.io/component: gerrit-replica
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ egress:
+{{ toYaml .Values.gerritReplica.networkPolicy.egress | indent 2 }}
+{{- end }}
+---
+{{ if or .Values.istio.enabled -}}
+kind: NetworkPolicy
+apiVersion: networking.k8s.io/v1
+metadata:
+ name: istio-proxy
+ labels:
+ chart: {{ template "gerrit-replica.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+spec:
+ policyTypes:
+ - Egress
+ - Ingress
+ podSelector:
+ matchLabels:
+ chart: {{ template "gerrit-replica.chart" . }}
+ release: {{ .Release.Name }}
+ egress:
+ - ports:
+ - protocol: TCP
+ port: 15012
+ ingress:
+ - ports:
+ - protocol: TCP
+ port: 15012
+---
+apiVersion: networking.k8s.io/v1
+kind: NetworkPolicy
+metadata:
+ name: {{ .Release.Name }}-istio-ingress
+ labels:
+ chart: {{ template "gerrit-replica.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+spec:
+ podSelector:
+ matchLabels:
+ chart: {{ template "gerrit-replica.chart" . }}
+ release: {{ .Release.Name }}
+ ingress:
+ - ports:
+ - protocol: TCP
+ port: 80
+ {{ if .Values.istio.ssh.enabled }}
+ - protocol: TCP
+ port: {{ .Values.gerritReplica.service.ssh.port }}
+ {{- end }}
+ from:
+ - namespaceSelector:
+ matchLabels:
+ name: istio-system
+ - podSelector:
+ matchLabels:
+ istio: ingressgateway
+
+{{- end }}
+{{- end }}
diff --git a/charts/gerrit-replica/templates/nfs.configmap.yaml b/charts/gerrit-replica/templates/nfs.configmap.yaml
new file mode 100644
index 0000000..32b167b
--- /dev/null
+++ b/charts/gerrit-replica/templates/nfs.configmap.yaml
@@ -0,0 +1,28 @@
+{{- if and .Values.nfsWorkaround.enabled .Values.nfsWorkaround.idDomain -}}
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: {{ .Release.Name }}-nfs-configmap
+ labels:
+ app.kubernetes.io/component: gerrit-replica
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit-replica.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+data:
+ idmapd.conf: |-
+ [General]
+
+ Verbosity = 0
+ Pipefs-Directory = /run/rpc_pipefs
+ # set your own domain here, if it differs from FQDN minus hostname
+ Domain = {{ .Values.nfsWorkaround.idDomain }}
+
+ [Mapping]
+
+ Nobody-User = nobody
+ Nobody-Group = nogroup
+{{- end }}
diff --git a/charts/gerrit-replica/templates/promtail.configmap.yaml b/charts/gerrit-replica/templates/promtail.configmap.yaml
new file mode 100644
index 0000000..8dac380
--- /dev/null
+++ b/charts/gerrit-replica/templates/promtail.configmap.yaml
@@ -0,0 +1,94 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: {{ .Release.Name }}-promtail-gerrit-configmap
+ labels:
+ app.kubernetes.io/component: gerrit-replica
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit-replica.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+data:
+ promtail.yaml: |-
+ positions:
+ filename: /var/gerrit/logs/promtail-positions.yaml
+
+ client:
+ tls_config:
+ insecure_skip_verify: {{ .Values.promtailSidecar.tls.skipVerify }}
+ {{- if not .Values.promtailSidecar.tls.skipVerify }}
+ ca_file: /etc/promtail/promtail.ca.crt
+ {{- end }}
+ basic_auth:
+ username: {{ .Values.promtailSidecar.loki.user }}
+ password_file: /etc/promtail/promtail.secret
+ scrape_configs:
+ - job_name: gerrit_error
+ static_configs:
+ - targets:
+ - localhost
+ labels:
+ job: gerrit_error
+ __path__: /var/gerrit/logs/error_log.json
+ entry_parser: raw
+ pipeline_stages:
+ - json:
+ expressions:
+ timestamp: '"@timestamp"'
+ message:
+ - template:
+ source: timestamp
+ template: {{`'{{ Replace .Value "," "." 1 }}'`}}
+ - template:
+ source: timestamp
+ template: {{`'{{ Replace .Value "Z" " +0000" 1 }}'`}}
+ - template:
+ source: timestamp
+ template: {{`'{{ Replace .Value "T" " " 1 }}'`}}
+ - timestamp:
+ source: timestamp
+ format: "2006-01-02 15:04:05.999 -0700"
+ - regex:
+ source: message
+ expression: "Gerrit Code Review (?P<gerrit_version>.*) ready"
+ - labels:
+ gerrit_version:
+ - job_name: gerrit_httpd
+ static_configs:
+ - targets:
+ - localhost
+ labels:
+ job: gerrit_httpd
+ __path__: /var/gerrit/logs/httpd_log.json
+ entry_parser: raw
+ pipeline_stages:
+ - json:
+ expressions:
+ timestamp: null
+ - template:
+ source: timestamp
+ template: {{`'{{ Replace .Value "," "." 1 }}'`}}
+ - timestamp:
+ format: 02/Jan/2006:15:04:05.999 -0700
+ source: timestamp
+ - job_name: gerrit_sshd
+ static_configs:
+ - targets:
+ - localhost
+ labels:
+ job: gerrit_sshd
+ __path__: /var/gerrit/logs/sshd_log.json
+ entry_parser: raw
+ pipeline_stages:
+ - json:
+ expressions:
+ timestamp:
+ - template:
+ source: timestamp
+ template: {{`'{{ Replace .Value "," "." 1 }}'`}}
+ - timestamp:
+ source: timestamp
+ format: 2006-01-02 15:04:05.999 -0700
diff --git a/charts/gerrit-replica/templates/promtail.secret.yaml b/charts/gerrit-replica/templates/promtail.secret.yaml
new file mode 100644
index 0000000..012fb5b
--- /dev/null
+++ b/charts/gerrit-replica/templates/promtail.secret.yaml
@@ -0,0 +1,18 @@
+{{ if .Values.promtailSidecar.enabled -}}
+apiVersion: v1
+kind: Secret
+metadata:
+ name: {{ .Release.Name }}-promtail-secret
+ labels:
+ app.kubernetes.io/component: gerrit-replica
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit-replica.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+type: Opaque
+data:
+ promtail.secret: {{ .Values.promtailSidecar.loki.password | b64enc }}
+{{- end }}
diff --git a/charts/gerrit-replica/templates/storage.pvc.yaml b/charts/gerrit-replica/templates/storage.pvc.yaml
new file mode 100644
index 0000000..5f8974e
--- /dev/null
+++ b/charts/gerrit-replica/templates/storage.pvc.yaml
@@ -0,0 +1,27 @@
+{{- if not .Values.gitRepositoryStorage.externalPVC.use }}
+kind: PersistentVolumeClaim
+apiVersion: v1
+metadata:
+ name: {{ .Release.Name }}-git-repositories-pvc
+spec:
+ accessModes:
+ - ReadWriteMany
+ resources:
+ requests:
+ storage: {{ .Values.gitRepositoryStorage.size }}
+ storageClassName: {{ .Values.storageClasses.shared.name }}
+{{- end }}
+{{- if and .Values.logStorage.enabled (not .Values.logStorage.externalPVC.use) }}
+---
+kind: PersistentVolumeClaim
+apiVersion: v1
+metadata:
+ name: {{ .Release.Name }}-log-pvc
+spec:
+ accessModes:
+ - ReadWriteMany
+ resources:
+ requests:
+ storage: {{ .Values.logStorage.size }}
+ storageClassName: {{ .Values.storageClasses.shared.name }}
+{{- end }}
diff --git a/charts/gerrit-replica/templates/storageclasses.yaml b/charts/gerrit-replica/templates/storageclasses.yaml
new file mode 100644
index 0000000..fb91856
--- /dev/null
+++ b/charts/gerrit-replica/templates/storageclasses.yaml
@@ -0,0 +1,57 @@
+{{ if .Values.storageClasses.default.create -}}
+kind: StorageClass
+apiVersion: storage.k8s.io/v1
+metadata:
+ name: {{ .Values.storageClasses.default.name }}
+ labels:
+ chart: {{ template "gerrit-replica.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+provisioner: {{ .Values.storageClasses.default.provisioner }}
+reclaimPolicy: {{ .Values.storageClasses.default.reclaimPolicy }}
+{{ if .Values.storageClasses.default.parameters -}}
+parameters:
+{{- range $key, $value := .Values.storageClasses.default.parameters }}
+ {{ $key }}: {{ $value }}
+{{- end }}
+{{ if .Values.storageClasses.default.mountOptions -}}
+mountOptions:
+{{- range .Values.storageClasses.default.mountOptions }}
+ - {{ . }}
+{{- end }}
+{{- end }}
+allowVolumeExpansion: {{ .Values.storageClasses.default.allowVolumeExpansion }}
+{{- end }}
+{{- end }}
+---
+{{ if .Values.storageClasses.shared.create -}}
+kind: StorageClass
+apiVersion: storage.k8s.io/v1
+metadata:
+ name: {{ .Values.storageClasses.shared.name }}
+ labels:
+ chart: {{ template "gerrit-replica.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+provisioner: {{ .Values.storageClasses.shared.provisioner }}
+reclaimPolicy: {{ .Values.storageClasses.shared.reclaimPolicy }}
+{{ if .Values.storageClasses.shared.parameters -}}
+parameters:
+{{- range $key, $value := .Values.storageClasses.shared.parameters }}
+ {{ $key }}: {{ $value }}
+{{- end }}
+{{ if .Values.storageClasses.shared.mountOptions -}}
+mountOptions:
+{{- range .Values.storageClasses.shared.mountOptions }}
+ - {{ . }}
+{{- end }}
+{{- end }}
+allowVolumeExpansion: {{ .Values.storageClasses.shared.allowVolumeExpansion }}
+{{- end }}
+{{- end }}
diff --git a/charts/gerrit-replica/values.yaml b/charts/gerrit-replica/values.yaml
new file mode 100644
index 0000000..f2ba93c
--- /dev/null
+++ b/charts/gerrit-replica/values.yaml
@@ -0,0 +1,433 @@
+images:
+ busybox:
+ registry: docker.io
+ tag: latest
+ # Registry used for container images created by this project
+ registry:
+ # The registry name must NOT contain a trailing slash
+ name:
+ ImagePullSecret:
+ # Leave blank, if no ImagePullSecret is needed.
+ name: image-pull-secret
+ # If set to false, the gerrit-replica chart expects either a ImagePullSecret
+ # with the name configured above to be present on the cluster or that no
+ # credentials are needed.
+ create: false
+ username:
+ password:
+ version: latest
+ imagePullPolicy: Always
+ # Additional ImagePullSecrets that already exist and should be used by the
+ # pods of this chart. E.g. to pull busybox from dockerhub.
+ additionalImagePullSecrets: []
+
+# Additional labels that should be applied to all resources
+additionalLabels: {}
+
+storageClasses:
+ # Storage class used for storing logs and other pod-specific persisted data
+ default:
+ # If create is set to false, an existing StorageClass with the given
+ # name is expected to exist in the cluster. Setting create to true will
+ # create a storage class with the parameters given below.
+ name: default
+ create: false
+ provisioner: kubernetes.io/aws-ebs
+ reclaimPolicy: Delete
+ # Use the parameters key to set all parameters needed for the provisioner
+ parameters:
+ type: gp2
+ fsType: ext4
+ mountOptions: []
+ allowVolumeExpansion: false
+ # Storage class used for storing git repositories. Has to provide RWM access.
+ shared:
+ # If create is set to false, an existing StorageClass with RWM access
+ # mode and the given name has to be provided.
+ name: shared-storage
+ create: false
+ provisioner: nfs
+ reclaimPolicy: Delete
+ # Use the parameters key to set all parameters needed for the provisioner
+ parameters:
+ mountOptions: vers=4.1
+ mountOptions: []
+ allowVolumeExpansion: false
+
+nfsWorkaround:
+ enabled: false
+ chownOnStartup: false
+ idDomain: localdomain.com
+
+
+networkPolicies:
+ enabled: false
+ dnsPorts:
+ - 53
+ - 8053
+
+
+gitRepositoryStorage:
+ externalPVC:
+ use: false
+ name: git-repositories-pvc
+ size: 5Gi
+
+
+logStorage:
+ enabled: false
+ externalPVC:
+ use: false
+ name: gerrit-logs-pvc
+ size: 5Gi
+ cleanup:
+ enabled: false
+ additionalPodLabels: {}
+ schedule: "0 0 * * *"
+ retentionDays: 14
+ resources:
+ requests:
+ cpu: 100m
+ memory: 256Mi
+ limits:
+ cpu: 100m
+ memory: 256Mi
+
+
+istio:
+ enabled: false
+ host:
+ tls:
+ enabled: false
+ secret:
+ # If using an external secret, make sure to name the keys `tls.crt`
+ # and `tls.key`, respectively.
+ create: true
+ # `name` will only be used, if `create` is set to false to bind an
+ # existing secret. Otherwise the name will be automatically generated to
+ # avoid conflicts between multiple chart installations.
+ name:
+ # `cert`and `key` will only be used, if the secret will be created by
+ # this chart.
+ cert: |-
+ -----BEGIN CERTIFICATE-----
+
+ -----END CERTIFICATE-----
+ key: |-
+ -----BEGIN RSA PRIVATE KEY-----
+
+ -----END RSA PRIVATE KEY-----
+ ssh:
+ enabled: false
+
+caCert:
+
+ingress:
+ enabled: false
+ host:
+ # The maximum body size to allow for requests. Use "0" to allow unlimited
+ # reuqest body sizes.
+ maxBodySize: 50m
+ additionalAnnotations:
+ kubernetes.io/ingress.class: nginx
+ # nginx.ingress.kubernetes.io/server-alias: example.com
+ # nginx.ingress.kubernetes.io/whitelist-source-range: xxx.xxx.xxx.xxx
+ tls:
+ enabled: false
+ secret:
+ # If using an external secret, make sure to name the keys `tls.crt`
+ # and `tls.key`, respectively.
+ create: true
+ # `name` will only be used, if `create` is set to false to bind an
+ # existing secret. Otherwise the name will be automatically generated to
+ # avoid conflicts between multiple chart installations.
+ name:
+ # `cert`and `key` will only be used, if the secret will be created by
+ # this chart.
+ cert: |-
+ -----BEGIN CERTIFICATE-----
+
+ -----END CERTIFICATE-----
+ key: |-
+ -----BEGIN RSA PRIVATE KEY-----
+
+ -----END RSA PRIVATE KEY-----
+
+promtailSidecar:
+ enabled: false
+ image: grafana/promtail
+ version: 1.3.0
+ resources:
+ requests:
+ cpu: 100m
+ memory: 128Mi
+ limits:
+ cpu: 200m
+ memory: 128Mi
+ tls:
+ skipVerify: true
+ loki:
+ url: loki.example.com
+ user: admin
+ password: secret
+
+
+gitBackend:
+ image: k8sgerrit/apache-git-http-backend
+
+ additionalPodLabels: {}
+ tolerations: []
+ topologySpreadConstraints: {}
+ nodeSelector: {}
+ affinity:
+ podAntiAffinity:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ - weight: 100
+ podAffinityTerm:
+ labelSelector:
+ matchExpressions:
+ - key: app
+ operator: In
+ values:
+ - git-backend
+ topologyKey: "topology.kubernetes.io/zone"
+
+ replicas: 1
+ maxSurge: 25%
+ # For just one replica, 100 % unavailability has to be allowed for updates to
+ # work.
+ maxUnavailable: 100%
+
+ # The general NetworkPolicy rules implemented by this chart may be too restrictive
+ # for some setups. Here custom rules may be added to whitelist some additional
+ # connections.
+ networkPolicy:
+ # This allows ingress traffic from all sources. If possible, this should be
+ # limited to the respective primary Gerrit that replicates to this replica.
+ ingress:
+ - {}
+ egress: []
+
+ resources:
+ requests:
+ cpu: 100m
+ memory: 256Mi
+ limits:
+ cpu: 100m
+ memory: 256Mi
+
+ livenessProbe:
+ initialDelaySeconds: 10
+ periodSeconds: 5
+
+ readinessProbe:
+ initialDelaySeconds: 5
+ periodSeconds: 1
+
+ service:
+ additionalAnnotations: {}
+ loadBalancerSourceRanges: []
+ type: NodePort
+ externalTrafficPolicy: Cluster
+ http:
+ port: 80
+
+ credentials:
+ # example: user: 'git'; password: 'secret'
+ # run `man htpasswd` to learn about how to create .htpasswd-files
+ htpasswd: git:$apr1$O/LbLKC7$Q60GWE7OcqSEMSfe/K8xU.
+ # TODO: Create htpasswd-file on container startup instead and set user
+ # and password in values.yaml.
+ #user:
+ #password:
+
+
+gitGC:
+ image: k8sgerrit/git-gc
+
+ tolerations: []
+ nodeSelector: {}
+ affinity: {}
+ additionalPodLabels: {}
+
+ schedule: 0 6,18 * * *
+
+ resources:
+ requests:
+ cpu: 100m
+ memory: 256Mi
+ limits:
+ cpu: 100m
+ memory: 256Mi
+
+gerritReplica:
+ images:
+ gerritInit: k8sgerrit/gerrit-init
+ gerritReplica: k8sgerrit/gerrit
+
+ tolerations: []
+ topologySpreadConstraints: {}
+ nodeSelector: {}
+ affinity:
+ podAntiAffinity:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ - weight: 100
+ podAffinityTerm:
+ labelSelector:
+ matchExpressions:
+ - key: app
+ operator: In
+ values:
+ - gerrit-replica
+ topologyKey: "topology.kubernetes.io/zone"
+
+ replicas: 1
+ updatePartition: 0
+ additionalAnnotations: {}
+ additionalPodLabels: {}
+
+ # If no value for probeScheme, the probe will use the default HTTP
+ probeScheme: HTTP
+
+ livenessProbe:
+ initialDelaySeconds: 60
+ periodSeconds: 5
+
+ readinessProbe:
+ initialDelaySeconds: 10
+ periodSeconds: 10
+
+ startupProbe:
+ initialDelaySeconds: 10
+ periodSeconds: 30
+
+ gracefulStopTimeout: 90
+
+ # The memory limit has to be higher than the configures heap-size for Java!
+ resources:
+ requests:
+ cpu: 1
+ memory: 5Gi
+ limits:
+ cpu: 1
+ memory: 6Gi
+
+ persistence:
+ enabled: true
+ size: 5Gi
+
+ # The general NetworkPolicy rules implemented by this chart may be too restrictive
+ # for some setups, e.g. when trying to connect to an external database. Here
+ # custom rules may be added to whitelist some additional connections.
+ networkPolicy:
+ ingress: []
+ egress: []
+
+ service:
+ additionalAnnotations: {}
+ loadBalancerSourceRanges: []
+ type: NodePort
+ externalTrafficPolicy: Cluster
+ http:
+ port: 80
+ ssh:
+ enabled: false
+ port: 29418
+
+ # `gerritReplica.keystore` expects a base64-encoded Java-keystore
+ # Since Java keystores are binary files, adding the unencoded content and
+ # automatic encoding using helm does not work here.
+ keystore:
+
+ pluginManagement:
+ plugins: []
+ # A plugin packaged in the gerrit.war-file
+ # - name: download-commands
+
+ # A plugin packaged in the gerrit.war-file that will also be installed as a
+ # lib
+ # - name: replication
+ # installAsLibrary: true
+
+ # A plugin that will be downloaded on startup
+ # - name: delete-project
+ # url: https://example.com/gerrit-plugins/delete-project.jar
+ # sha1:
+ # installAsLibrary: false
+
+ # Only downloaded plugins will be cached. This will be ignored, if no plugins
+ # are downloaded.
+ libs: []
+ cache:
+ enabled: false
+ size: 1Gi
+
+ priorityClassName:
+
+ etc:
+ # Some values are expected to have a specific value for the deployment installed
+ # by this chart to work. These are marked with `# FIXED`.
+ # Do not change them!
+ config:
+ gerrit.config: |-
+ [gerrit]
+ basePath = git # FIXED
+ serverId = gerrit-replica-1
+ # The canonical web URL has to be set to the Ingress host, if an Ingress
+ # is used. If a LoadBalancer-service is used, this should be set to the
+ # LoadBalancer's external IP. This can only be done manually after installing
+ # the chart, when you know the external IP the LoadBalancer got from the
+ # cluster.
+ canonicalWebUrl = http://example.com/
+ disableReverseDnsLookup = true
+ [index]
+ type = LUCENE
+ [index "scheduledIndexer"]
+ runOnStartup = false
+ [auth]
+ type = DEVELOPMENT_BECOME_ANY_ACCOUNT
+ [httpd]
+ # If using an ingress use proxy-http or proxy-https
+ listenUrl = proxy-http://*:8080/
+ requestLog = true
+ gracefulStopTimeout = 1m
+ [sshd]
+ listenAddress = *:29418
+ gracefulStopTimeout = 1m
+ [transfer]
+ timeout = 120 s
+ [user]
+ name = Gerrit Code Review
+ email = gerrit@example.com
+ anonymousCoward = Unnamed User
+ [cache]
+ directory = cache
+ [container]
+ user = gerrit # FIXED
+ replica = true # FIXED
+ javaHome = /usr/lib/jvm/java-17-openjdk # FIXED
+ javaOptions = -Djavax.net.ssl.trustStore=/var/gerrit/etc/keystore # FIXED
+ javaOptions = -Xms200m
+ # Has to be lower than 'gerritReplica.resources.limits.memory'. Also
+ # consider memories used by other applications in the container.
+ javaOptions = -Xmx4g
+
+ secret:
+ secure.config: |-
+ # Password for the keystore added as value for 'gerritReplica.keystore'
+ # Only needed, if SSL is enabled.
+ #[httpd]
+ # sslKeyPassword = gerrit
+
+ # ssh_host_ecdsa_key: |-
+ # -----BEGIN EC PRIVATE KEY-----
+
+ # -----END EC PRIVATE KEY-----
+
+ # ssh_host_ecdsa_key.pub: ecdsa-sha2-nistp256...
+
+ additionalConfigMaps:
+ # - name:
+ # subDir:
+ # data:
+ # file.txt: test
diff --git a/charts/gerrit/.helmignore b/charts/gerrit/.helmignore
new file mode 100644
index 0000000..4f4562f
--- /dev/null
+++ b/charts/gerrit/.helmignore
@@ -0,0 +1,24 @@
+# Patterns to ignore when building packages.
+# This supports shell glob matching, relative path matching, and
+# negation (prefixed with !). Only one pattern per line.
+.DS_Store
+# Common VCS dirs
+.git/
+.gitignore
+.bzr/
+.bzrignore
+.hg/
+.hgignore
+.svn/
+# Common backup files
+*.swp
+*.bak
+*.tmp
+*~
+# Various IDEs
+.project
+.idea/
+*.tmproj
+
+docs/
+supplements/
diff --git a/charts/gerrit/Chart.yaml b/charts/gerrit/Chart.yaml
new file mode 100644
index 0000000..cafaa43
--- /dev/null
+++ b/charts/gerrit/Chart.yaml
@@ -0,0 +1,27 @@
+apiVersion: v2
+appVersion: 3.9.1
+description: |-
+ Gerrit is a free, web-based team code collaboration tool. Software developers
+ in a team can review each other's modifications on their source code using
+ a Web browser and approve or reject those changes. It integrates closely with
+ Git, a distributed version control system. [1]
+
+ [1](https://en.wikipedia.org/wiki/Gerrit_(software)
+name: gerrit
+version: 0.2.0
+maintainers:
+- name: Thomas Draebing
+ email: thomas.draebing@sap.com
+- name: Matthias Sohn
+ email: matthias.sohn@sap.com
+- name: Sasa Zivkov
+ email: sasa.zivkov@sap.com
+- name: Christian Halstrick
+ email: christian.halstrick@sap.com
+home: https://gerrit.googlesource.com/k8s-gerrit/+/master/helm-charts/gerrit-replica
+icon: http://commondatastorage.googleapis.com/gerrit-static/diffy-w200.png
+sources:
+- https://gerrit.googlesource.com/k8s-gerrit/+/master/
+keywords:
+- gerrit
+- git
diff --git a/charts/gerrit/LICENSE b/charts/gerrit/LICENSE
new file mode 100644
index 0000000..028fc9f
--- /dev/null
+++ b/charts/gerrit/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/charts/gerrit/README.md b/charts/gerrit/README.md
new file mode 100644
index 0000000..8300e0a
--- /dev/null
+++ b/charts/gerrit/README.md
@@ -0,0 +1,460 @@
+# Gerrit on Kubernetes
+
+Gerrit is a web-based code review tool, which acts as a Git server. This helm
+chart provides a Gerrit setup that can be deployed on Kubernetes.
+In addition, the chart provides a CronJob to perform Git garbage collection.
+
+***note
+Gerrit versions before 3.0 are no longer supported, since the support of ReviewDB
+was removed.
+***
+
+## Prerequisites
+
+- Helm (>= version 3.0)
+
+ (Check out [this guide](https://docs.helm.sh/using_helm/#quickstart-guide)
+ how to install and use helm.)
+
+- Access to a provisioner for persistent volumes with `Read Write Many (RWM)`-
+ capability.
+
+ A list of applicaple volume types can be found
+ [here](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#access-modes).
+ This project was developed using the
+ [NFS-server-provisioner helm chart](https://github.com/helm/charts/tree/master/stable/nfs-server-provisioner),
+ a NFS-provisioner deployed in the Kubernetes cluster itself. Refer to
+ [this guide](/helm-charts/gerrit/docs/nfs-provisioner.md) of how to
+ deploy it in context of this project.
+
+- A domain name that is configured to point to the IP address of the node running
+ the Ingress controller on the kubernetes cluster (as described
+ [here](http://alesnosek.com/blog/2017/02/14/accessing-kubernetes-pods-from-outside-of-the-cluster/)).
+
+- (Optional: Required, if SSL is configured)
+ A [Java keystore](https://gerrit-review.googlesource.com/Documentation/config-gerrit.html#httpd.sslKeyStore)
+ to be used by Gerrit.
+
+## Installing the Chart
+
+***note
+**ATTENTION:** The value for `ingress.host` is required for rendering
+the chart's templates. The nature of the value does not allow defaults.
+Thus a custom `values.yaml`-file setting this value is required!
+***
+
+To install the chart with the release name `gerrit`, execute:
+
+```sh
+cd $(git rev-parse --show-toplevel)/helm-charts
+helm install \
+ gerrit \ # release name
+ ./gerrit \ # path to chart
+ -f <path-to-custom-values>.yaml
+```
+
+The command deploys the Gerrit instance on the current Kubernetes cluster.
+The [configuration section](#Configuration) lists the parameters that can be
+configured during installation.
+
+## Configuration
+
+The following sections list the configurable values in `values.yaml`. To configure
+a Gerrit setup, make a copy of the `values.yaml`-file and change the parameters
+as needed. The configuration can be applied by installing the chart as described
+[above](#Installing-the-chart).
+
+In addition, single options can be set without creating a custom `values.yaml`:
+
+```sh
+cd $(git rev-parse --show-toplevel)/helm-charts
+helm install \
+ gerrit \ # release name
+ ./gerrit \ # path to chart
+ --set=gitRepositoryStorage.size=100Gi
+```
+
+### Container images
+
+| Parameter | Description | Default |
+|-----------|-------------|---------|
+| `images.busybox.registry` | The registry to pull the busybox container images from | `docker.io` |
+| `images.busybox.tag` | The busybox image tag to use | `latest` |
+| `images.registry.name` | The image registry to pull the container images from | `` |
+| `images.registry.ImagePullSecret.name` | Name of the ImagePullSecret | `image-pull-secret` (if empty no image pull secret will be deployed) |
+| `images.registry.ImagePullSecret.create` | Whether to create an ImagePullSecret | `false` |
+| `images.registry.ImagePullSecret.username` | The image registry username | `nil` |
+| `images.registry.ImagePullSecret.password` | The image registry password | `nil` |
+| `images.version` | The image version (image tag) to use | `latest` |
+| `images.imagePullPolicy` | Image pull policy | `Always` |
+| `images.additionalImagePullSecrets` | Additional image pull policies that pods should use | `[]` |
+
+### Labels
+
+| Parameter | Description | Default |
+|-----------|-------------|---------|
+| `additionalLabels` | Additional labels for resources managed by this Helm chart | `{}` |
+
+### Storage classes
+
+For information of how a `StorageClass` is configured in Kubernetes, read the
+[official Documentation](https://kubernetes.io/docs/concepts/storage/storage-classes/#introduction).
+
+| Parameter | Description | Default |
+|-----------|-------------|---------|
+| `storageClasses.default.name` | The name of the default StorageClass (RWO) | `default` |
+| `storageClasses.default.create` | Whether to create the StorageClass | `false` |
+| `storageClasses.default.provisioner` | Provisioner of the StorageClass | `kubernetes.io/aws-ebs` |
+| `storageClasses.default.reclaimPolicy` | Whether to `Retain` or `Delete` volumes, when they become unbound | `Delete` |
+| `storageClasses.default.parameters` | Parameters for the provisioner | `parameters.type: gp2`, `parameters.fsType: ext4` |
+| `storageClasses.default.mountOptions` | The mount options of the default StorageClass | `[]` |
+| `storageClasses.default.allowVolumeExpansion` | Whether to allow volume expansion. | `false` |
+| `storageClasses.shared.name` | The name of the shared StorageClass (RWM) | `shared-storage` |
+| `storageClasses.shared.create` | Whether to create the StorageClass | `false` |
+| `storageClasses.shared.provisioner` | Provisioner of the StorageClass | `nfs` |
+| `storageClasses.shared.reclaimPolicy` | Whether to `Retain` or `Delete` volumes, when they become unbound | `Delete` |
+| `storageClasses.shared.parameters` | Parameters for the provisioner | `parameters.mountOptions: vers=4.1` |
+| `storageClasses.shared.mountOptions` | The mount options of the shared StorageClass | `[]` |
+| `storageClasses.shared.allowVolumeExpansion` | Whether to allow volume expansion. | `false` |
+
+### Network policies
+
+| Parameter | Description | Default |
+|-----------|-------------|---------|
+| `networkPolicies.enabled` | Whether to enable preconfigured NetworkPolicies | `false` |
+| `networkPolicies.dnsPorts` | List of ports used by DNS-service (e.g. KubeDNS) | `[53, 8053]` |
+
+The NetworkPolicies provided here are quite strict and do not account for all
+possible scenarios. Thus, custom NetworkPolicies have to be added, e.g. for
+allowing Gerrit to replicate to a Gerrit replica. By default, the egress traffic
+of the gerrit pod is blocked, except for connections to the DNS-server.
+Thus, replication which requires Gerrit to perform git pushes to the replica will
+not work. The chart provides the possibility to define custom rules for egress-
+traffic of the gerrit pod under `gerrit.networkPolicy.egress`.
+Depending on the scenario, there are different ways to allow the required
+connections. The easiest way is to allow all egress-traffic for the gerrit
+pods:
+
+```yaml
+gerrit:
+ networkPolicy:
+ egress:
+ - {}
+```
+
+If the remote that is replicated to is running in a pod on the same cluster and
+the service-DNS is used as the remote's URL (e.g. http://gerrit-replica-git-backend-service:80/git/${name}.git),
+a podSelector (and namespaceSelector, if the pod is running in a different
+namespace) can be used to whitelist the traffic:
+
+```yaml
+gerrit:
+ networkPolicy:
+ egress:
+ - to:
+ - podSelector:
+ matchLabels:
+ app: git-backend
+```
+
+If the remote is outside the cluster, the IP of the remote or its load balancer
+can also be whitelisted, e.g.:
+
+```yaml
+gerrit:
+ networkPolicy:
+ egress:
+ - to:
+ - ipBlock:
+ cidr: xxx.xxx.0.0/16
+```
+
+The same principle also applies to other use cases, e.g. connecting to a database.
+For more information about the NetworkPolicy resource refer to the
+[Kubernetes documentation](https://kubernetes.io/docs/concepts/services-networking/network-policies/).
+
+### Workaround for NFS
+
+Kubernetes will not always be able to adapt the ownership of the files within NFS
+volumes. Thus, a workaround exists that will add init-containers to
+adapt file ownership. Note, that only the ownership of the root directory of the
+volume will be changed. All data contained within will be expected to already be
+owned by the user used by Gerrit. Also the ID-domain will be configured to ensure
+correct ID-mapping.
+
+| Parameter | Description | Default |
+|-----------|-------------|---------|
+| `nfsWorkaround.enabled` | Whether the volume used is an NFS-volume | `false` |
+| `nfsWorkaround.chownOnStartup` | Whether to chown the volume on pod startup | `false` |
+| `nfsWorkaround.idDomain` | The ID-domain that should be used to map user-/group-IDs for the NFS mount | `localdomain.com` |
+
+### Storage for Git repositories
+
+| Parameter | Description | Default |
+|-----------|-------------|---------|
+| `gitRepositoryStorage.externalPVC.use` | Whether to use a PVC deployed outside the chart | `false` |
+| `gitRepositoryStorage.externalPVC.name` | Name of the external PVC | `git-repositories-pvc` |
+| `gitRepositoryStorage.size` | Size of the volume storing the Git repositories | `5Gi` |
+
+If the git repositories should be persisted even if the chart is deleted and in
+a way that the volume containing them can be mounted by the reinstalled chart,
+the PVC claiming the volume has to be created independently of the chart. To use
+the external PVC, set `gitRepositoryStorage.externalPVC.enabled` to `true` and
+give the name of the PVC under `gitRepositoryStorage.externalPVC.name`.
+
+### Storage for Logs
+
+The logs can be stored in a dedicated persistent volume. This volume has to be a
+read-write-many volume to be able to be used by multiple pods.
+
+| Parameter | Description | Default |
+|-----------|-------------|---------|
+| `logStorage.enabled` | Whether to enable persistence of logs | `false` |
+| `logStorage.externalPVC.use` | Whether to use a PVC deployed outside the chart | `false` |
+| `logStorage.externalPVC.name` | Name of the external PVC | `gerrit-logs-pvc` |
+| `logStorage.size` | Size of the volume | `5Gi` |
+| `logStorage.cleanup.enabled` | Whether to regularly delete old logs | `false` |
+| `logStorage.cleanup.schedule` | Cron schedule defining when to run the cleanup job | `0 0 * * *` |
+| `logStorage.cleanup.retentionDays` | Number of days to retain the logs | `14` |
+| `logStorage.cleanup.resources` | Resources the container is allowed to use | `requests.cpu: 100m` |
+| `logStorage.cleanup.additionalPodLabels` | Additional labels for pods | `{}` |
+| | | `requests.memory: 256Mi` |
+| | | `limits.cpu: 100m` |
+| | | `limits.memory: 256Mi` |
+
+Each pod will create a separate folder for its logs, allowing to trace logs to
+the respective pods.
+
+### CA certificate
+
+Some application may require TLS verification. If the default CA built into the
+containers is not enough a custom CA certificate can be given to the deployment.
+Note, that Gerrit will require its CA in a JKS keytore, which is described below.
+
+| Parameter | Description | Default |
+|-----------|-------------|---------|
+| `caCert` | CA certificate for TLS verification (if not set, the default will be used) | `None` |
+
+### Ingress
+
+| Parameter | Description | Default |
+|-----------|-------------|---------|
+| `ingress.enabled` | Whether to enable the Ingress | `false` |
+| `ingress.host` | REQUIRED: Host name to use for the Ingress (required for Ingress) | `nil` |
+| `ingress.additionalAnnotations` | Additional annotations for the Ingress | `nil` |
+| `ingress.tls.enabled` | Whether to enable TLS termination in the Ingress | `false` |
+| `ingress.tls.secret.create` | Whether to create a TLS-secret | `true` |
+| `ingress.tls.secret.name` | Name of an external secret that will be used as a TLS-secret | `nil` |
+| `ingress.tls.cert` | Public SSL server certificate | `-----BEGIN CERTIFICATE-----` |
+| `ingress.tls.key` | Private SSL server certificate | `-----BEGIN RSA PRIVATE KEY-----` |
+
+***note
+For graceful shutdown to work with an ingress, the ingress controller has to be
+configured to gracefully close the connections as well.
+***
+
+### Git garbage collection
+
+| Parameter | Description | Default |
+|-----------|-------------|---------|
+| `gitGC.image` | Image name of the Git-GC container image | `k8sgerrit/git-gc` |
+| `gitGC.schedule` | Cron-formatted schedule with which to run Git garbage collection | `0 6,18 * * *` |
+| `gitGC.resources` | Configure the amount of resources the pod requests/is allowed | `requests.cpu: 100m` |
+| | | `requests.memory: 256Mi` |
+| | | `limits.cpu: 100m` |
+| | | `limits.memory: 256Mi` |
+| `gitGC.logging.persistence.enabled` | Whether to persist logs | `true` |
+| `gitGC.logging.persistence.size` | Storage size for persisted logs | `1Gi` |
+| `gitGC.tolerations` | Taints and tolerations work together to ensure that pods are not scheduled onto inappropriate nodes. For more information, please refer to the following documents. [Taints and Tolerations](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration) | [] |
+| `gitGC.nodeSelector` | Assigns a Pod to the specified Nodes. For more information, please refer to the following documents. [Assign Pods to Nodes](https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes/). [Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/) | {} |
+| `gitGC.affinity` | Assigns a Pod to the specified Nodes. For more information, please refer to the following documents. [Assign Pods to Nodes using Node Affinity](https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes-using-node-affinity/). [Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/) | {} |
+| `gitGC.additionalPodLabels` | Additional labels for Pods | `{}` |
+
+### Gerrit
+
+***note
+The way the Jetty servlet used by Gerrit works, the Gerrit component of the
+gerrit chart actually requires the URL to be known, when the chart is installed.
+The suggested way to do that is to use the provided Ingress resource. This requires
+that a URL is available and that the DNS is configured to point the URL to the
+IP of the node the Ingress controller is running on!
+***
+
+***note
+Setting the canonical web URL in the gerrit.config to the host used for the Ingress
+is mandatory, if access to Gerrit is required!
+***
+
+***note
+While the chart allows to configure multiple replica for the Gerrit StatefulSet,
+scaling of Gerrit is currently not supported, since no mechanism to guarantee a
+consistent state is currently in place. This is planned to be implemented in the
+future.
+***
+
+| Parameter | Description | Default |
+|-----------|-------------|---------|
+| `gerrit.images.gerritInit` | Image name of the Gerrit init container image | `k8sgerrit/gerrit-init` |
+| `gerrit.images.gerrit` | Image name of the Gerrit container image | `k8sgerrit/gerrit` |
+| `gerrit.tolerations` | Taints and tolerations work together to ensure that pods are not scheduled onto inappropriate nodes. For more information, please refer to the following documents. [Taints and Tolerations](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration) | [] |
+| `gerrit.topologySpreadConstraints` | Control how Pods are spread across your cluster among failure-domains. For more information, please refer to the following documents. [Pod Topology Spread Constraints](https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints) | {} |
+| `gerrit.nodeSelector` | Assigns a Pod to the specified Nodes. For more information, please refer to the following documents. [Assign Pods to Nodes](https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes/). [Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/) | {} |
+| `gerrit.affinity` | Assigns a Pod to the specified Nodes. For more information, please refer to the following documents. [Assign Pods to Nodes using Node Affinity](https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes-using-node-affinity/). [Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/) | {} |
+| `gerrit.additionalAnnotations` | Additional annotations for the Pods | {} |
+| `gerrit.additionalPodLabels` | Additional labels for Pods | `{}` |
+| `gerrit.replicas` | Number of replica pods to deploy | `1` |
+| `gerrit.updatePartition` | Ordinal at which to start updating pods. Pods with a lower ordinal will not be updated. | `0` |
+| `gerrit.resources` | Configure the amount of resources the pod requests/is allowed | `requests.cpu: 1` |
+| | | `requests.memory: 5Gi` |
+| | | `limits.cpu: 1` |
+| | | `limits.memory: 6Gi` |
+| `gerrit.persistence.enabled` | Whether to persist the Gerrit site | `true` |
+| `gerrit.persistence.size` | Storage size for persisted Gerrit site | `10Gi` |
+| `gerrit.probeScheme` | Scheme for probes, for example HTTPS | `nil` |
+| `gerrit.livenessProbe` | Configuration of the liveness probe timings | `{initialDelaySeconds: 30, periodSeconds: 5}` |
+| `gerrit.readinessProbe` | Configuration of the readiness probe timings | `{initialDelaySeconds: 5, periodSeconds: 1}` |
+| `gerrit.startupProbe` | Configuration of the startup probe timings | `{initialDelaySeconds: 10, periodSeconds: 5}` |
+| `gerrit.gracefulStopTimeout` | Time in seconds Kubernetes will wait until killing the pod during termination (has to be longer then Gerrit's httpd.gracefulStopTimeout to allow graceful shutdown of Gerrit) | `90` |
+| `gerrit.networkPolicy.ingress` | Custom ingress-network policy for gerrit pods | `nil` |
+| `gerrit.networkPolicy.egress` | Custom egress-network policy for gerrit pods | `nil` |
+| `gerrit.service.additionalAnnotations` | Additional annotations for the Service | `{}` |
+| `gerrit.service.loadBalancerSourceRanges` | The list of allowed IPs for the Service | `[]` |
+| `gerrit.service.type` | Which kind of Service to deploy | `NodePort` |
+| `gerrit.service.externalTrafficPolicy` | Specify how traffic from external is handled | `Cluster` |
+| `gerrit.service.http.port` | Port over which to expose HTTP | `80` |
+| `gerrit.service.ssh.enabled` | Whether to enable SSH | `false` |
+| `gerrit.service.ssh.port` | Port over which to expose SSH | `29418` |
+| `gerrit.keystore` | base64-encoded Java keystore (`cat keystore.jks \| base64`) to be used by Gerrit, when using SSL | `nil` |
+| `gerrit.index.type` | Index type used by Gerrit (either `lucene` or `elasticsearch`) | `lucene` |
+| `gerrit.pluginManagement.plugins` | List of Gerrit plugins to install | `[]` |
+| `gerrit.pluginManagement.plugins[0].name` | Name of plugin | `nil` |
+| `gerrit.pluginManagement.plugins[0].url` | Download url of plugin. If given the plugin will be downloaded, otherwise it will be installed from the gerrit.war-file. | `nil` |
+| `gerrit.pluginManagement.plugins[0].sha1` | SHA1 sum of plugin jar used to ensure file integrity and version (optional) | `nil` |
+| `gerrit.pluginManagement.plugins[0].installAsLibrary` | Whether the plugin should be symlinked to the lib-dir in the Gerrit site. | `nil` |
+| `gerrit.pluginManagement.libs` | List of Gerrit library modules to install | `[]` |
+| `gerrit.pluginManagement.libs[0].name` | Name of the lib module | `nil` |
+| `gerrit.pluginManagement.libs[0].url` | Download url of lib module. | `nil` |
+| `gerrit.pluginManagement.libs[0].sha1` | SHA1 sum of plugin jar used to ensure file integrity and version | `nil` |
+| `gerrit.pluginManagement.cache.enabled` | Whether to cache downloaded plugins | `false` |
+| `gerrit.pluginManagement.cache.size` | Size of the volume used to store cached plugins | `1Gi` |
+| `gerrit.priorityClassName` | Name of the PriorityClass to apply to the master pod | `nil` |
+| `gerrit.etc.config` | Map of config files (e.g. `gerrit.config`) that will be mounted to `$GERRIT_SITE/etc`by a ConfigMap | `{gerrit.config: ..., replication.config: ...}`[see here](#Gerrit-config-files) |
+| `gerrit.etc.secret` | Map of config files (e.g. `secure.config`) that will be mounted to `$GERRIT_SITE/etc`by a Secret | `{secure.config: ...}` [see here](#Gerrit-config-files) |
+| `gerrit.additionalConfigMaps` | Allows to mount additional ConfigMaps into a subdirectory of `$SITE/data` | `[]` |
+| `gerrit.additionalConfigMaps[*].name` | Name of the ConfigMap | `nil` |
+| `gerrit.additionalConfigMaps[*].subDir` | Subdirectory under `$SITE/data` into which the files should be symlinked | `nil` |
+| `gerrit.additionalConfigMaps[*].data` | Data of the ConfigMap. If not set, ConfigMap has to be created manually | `nil` |
+
+### Gerrit config files
+
+The gerrit chart provides a ConfigMap containing the configuration files
+used by Gerrit, e.g. `gerrit.config` and a Secret containing sensitive configuration
+like the `secure.config` to configure the Gerrit installation in the Gerrit
+component. The content of the config files can be set in the `values.yaml` under
+the keys `gerrit.etc.config` and `gerrit.etc.secret` respectively.
+The key has to be the filename (eg. `gerrit.config`) and the file's contents
+the value. This way an arbitrary number of configuration files can be loaded into
+the `$GERRIT_SITE/etc`-directory, e.g. for plugins.
+All configuration options for Gerrit are described in detail in the
+[official documentation of Gerrit](https://gerrit-review.googlesource.com/Documentation/config-gerrit.html).
+Some options however have to be set in a specified way for Gerrit to work as
+intended with the chart:
+
+- `gerrit.basePath`
+
+ Path to the directory containing the repositories. The chart mounts this
+ directory from a persistent volume to `/var/gerrit/git` in the container. For
+ Gerrit to find the correct directory, this has to be set to `git`.
+
+- `gerrit.serverId`
+
+ In Gerrit-version higher than 2.14 Gerrit needs a server ID, which is used by
+ NoteDB. Gerrit would usually generate a random ID on startup, but since the
+ gerrit.config file is read only, when mounted as a ConfigMap this fails.
+ Thus the server ID has to be set manually!
+
+- `gerrit.canonicalWebUrl`
+
+ The canonical web URL has to be set to the Ingress host.
+
+- `httpd.listenURL`
+
+ This has to be set to `proxy-http://*:8080/` or `proxy-https://*:8080`,
+ depending of TLS is enabled in the Ingress or not, otherwise the Jetty
+ servlet will run into an endless redirect loop.
+
+- `httpd.gracefulStopTimeout` / `sshd.gracefulStopTimeout`
+
+ To enable graceful shutdown of the embedded jetty server and SSHD, a timeout
+ has to be set with this option. This will be the maximum time, Gerrit will wait
+ for HTTP requests to finish before shutdown.
+
+- `container.user`
+
+ The technical user in the Gerrit container is called `gerrit`. Thus, this
+ value is required to be `gerrit`.
+
+- `container.javaHome`
+
+ This has to be set to `/usr/lib/jvm/java-11-openjdk-amd64`, since this is
+ the path of the Java installation in the container.
+
+- `container.javaOptions`
+
+ The maximum heap size has to be set. And its value has to be lower than the
+ memory resource limit set for the container (e.g. `-Xmx4g`). In your calculation,
+ allow memory for other components running in the container.
+
+To enable liveness- and readiness probes, the healthcheck plugin will be installed
+by default. Note, that by configuring to use a packaged or downloaded version of
+the healthcheck plugin, the configured version will take precedence over the default
+version. The plugin is by default configured to disable the `querychanges` and
+`auth` healthchecks, since these would not work on a new and empty Gerrit server.
+The default configuration can be overwritten by adding the `healthcheck.config`
+file as a key-value pair to `gerrit.etc.config` as for every other configuration.
+
+SSH keys should be configured via the helm-chart using the `gerrit.etc.secret`
+map. Gerrit will create its own keys, if none are present in the site, but if
+multiple Gerrit pods are running, each Gerrit instance would have its own keys.
+Users accessing Gerrit via a load balancer would get issues due to changing
+host keys.
+
+### Installing Gerrit plugins
+
+There are several different ways to install plugins for Gerrit:
+
+- **RECOMMENDED: Package the plugins to install into the WAR-file containing Gerrit.**
+ This method provides the most stable way to install plugins, but requires to
+ use a custom built gerrit-war file and container images, if plugins are required
+ that are not part of the official `release.war`-file.
+
+- **Download and cache plugins.** The chart supports downloading the plugin files and
+ to cache them in a separate volume, that is shared between Gerrit-pods. SHA1-
+ sums are used to validate plugin-files and versions.
+
+- **Download plugins, but do not cache them.** This should only be used during
+ development to save resources (the shared volume). Each pod will download the
+ plugin-files on its own. Pods will fail to start up, if the download-URL is
+ not valid anymore at some point in time.
+
+## Upgrading the Chart
+
+To upgrade an existing installation of the gerrit chart, e.g. to install
+a newer chart version or to use an updated custom `values.yaml`-file, execute
+the following command:
+
+```sh
+cd $(git rev-parse --show-toplevel)/helm-charts
+helm upgrade \
+ <release-name> \
+ ./gerrit \ # path to chart
+ -f <path-to-custom-values>.yaml
+```
+
+## Uninstalling the Chart
+
+To delete the chart from the cluster, use:
+
+```sh
+helm delete <release-name>
+```
diff --git a/charts/gerrit/docs/nfs-provisioner.md b/charts/gerrit/docs/nfs-provisioner.md
new file mode 100644
index 0000000..9e83d47
--- /dev/null
+++ b/charts/gerrit/docs/nfs-provisioner.md
@@ -0,0 +1,64 @@
+# Installing a NFS-provisioner
+
+Gerrit requires access to a persistent volume capable of running in
+`Read Write Many (RWM)`-mode to store the git repositories, since the repositories
+have to be accessed by mutiple pods. One possibility to provide such volumes
+is to install a provisioner for NFS-volumes into the same Kubernetes-cluster.
+This document will guide through the process.
+
+The [Kubernetes external-storage project](https://github.com/kubernetes-incubator/external-storage)
+provides an out-of-tree dynamic [provisioner](https://github.com/kubernetes-incubator/external-storage/tree/master/nfs)
+for NFS volumes. A chart exists for easy deployment of the project onto a
+Kubernetes cluster. The chart's sources can be found [here](https://github.com/helm/charts/tree/master/stable/nfs-server-provisioner).
+
+## Prerequisites
+
+This guide will use Helm to install the NFS-provisioner. Thus, Helm has to be
+installed.
+
+## Installing the nfs-server-provisioner chart
+
+A custom `values.yaml`-file containing a configuration tested with the
+gerrit charts can be found in the `supplements/nfs`-directory in the
+gerrit chart's root directory. In addition a file stating the tested
+version of the nfs-server-provisioner chart is present in the same directory.
+
+If needed, adapt the `values.yaml`-file for the nfs-server-provisioner chart
+further and then run:
+
+```sh
+cd $(git rev-parse --show-toplevel)/helm-charts/gerrit/supplements/nfs
+helm install nfs \
+ stable/nfs-server-provisioner \
+ -f values.yaml \
+ --version $(cat VERSION)
+```
+
+For a description of the configuration options, refer to the
+[chart's documentation](https://github.com/helm/charts/blob/master/stable/nfs-server-provisioner/README.md).
+
+Here are some tips for configuring the nfs-server-provisioner chart to work with
+the gerrit chart:
+
+- Deploying more than 1 `replica` led to some reliability issues in tests and
+ should be further tested for now, if required.
+- The name of the StorageClass created for NFS-volumes has to be the same as the
+ one defined in the gerrit chart for `storageClasses.shared.name`
+- The StorageClas for NFS-volumes needs to have the parameter `mountOptions: vers=4.1`,
+ due to compatibility [issues](https://github.com/kubernetes-incubator/external-storage/issues/223)
+ with Ganesha.
+
+## Deleting the nfs-server-provisioner chart
+
+***note
+**Attention:** Never delete the nfs-server-provisioner chart, if there is still a
+PersistentVolumeClaim and Pods using a NFS-volume provisioned by the NFS server
+provisioner. This will lead to crashed pods, that will not be terminated correctly.
+***
+
+If no Pod or PVC is using a NFS-volume provisioned by the NFS server provisioner
+anymore, delete it like any other chart:
+
+```sh
+helm delete nfs
+```
diff --git a/charts/gerrit/supplements/nfs/VERSION b/charts/gerrit/supplements/nfs/VERSION
new file mode 100644
index 0000000..7dff5b8
--- /dev/null
+++ b/charts/gerrit/supplements/nfs/VERSION
@@ -0,0 +1 @@
+0.2.1
\ No newline at end of file
diff --git a/charts/gerrit/supplements/nfs/values.yaml b/charts/gerrit/supplements/nfs/values.yaml
new file mode 100644
index 0000000..a413d8a
--- /dev/null
+++ b/charts/gerrit/supplements/nfs/values.yaml
@@ -0,0 +1,42 @@
+# Deploying more than 1 `replica` led to some reliability issues in tests and
+# should be further tested for now, if required.
+replicaCount: 1
+
+image:
+ repository: quay.io/kubernetes_incubator/nfs-provisioner
+ tag: v1.0.9
+ pullPolicy: IfNotPresent
+
+service:
+ type: ClusterIP
+ nfsPort: 2049
+ mountdPort: 20048
+ rpcbindPort: 51413
+
+persistence:
+ enabled: true
+ storageClass: default
+ accessMode: ReadWriteOnce
+ size: 7.5Gi
+
+storageClass:
+ create: true
+ defaultClass: false
+ # The name of the StorageClass has to be the same as the one defined in the
+ # gerrit chart for `storageClasses.shared.name`
+ name: shared-storage
+ parameters:
+ # Required!
+ mountOptions: vers=4.1
+ reclaimPolicy: Delete
+
+rbac:
+ create: true
+
+resources:
+ requests:
+ cpu: 100m
+ memory: 256Mi
+ limits:
+ cpu: 100m
+ memory: 256Mi
diff --git a/charts/gerrit/templates/NOTES.txt b/charts/gerrit/templates/NOTES.txt
new file mode 100644
index 0000000..b71b3b0
--- /dev/null
+++ b/charts/gerrit/templates/NOTES.txt
@@ -0,0 +1,4 @@
+A primary Gerrit instance has been deployed.
+==================================
+
+Gerrit may be accessed under: {{ .Values.ingress.host }}
diff --git a/charts/gerrit/templates/_helpers.tpl b/charts/gerrit/templates/_helpers.tpl
new file mode 100644
index 0000000..bace6fe
--- /dev/null
+++ b/charts/gerrit/templates/_helpers.tpl
@@ -0,0 +1,20 @@
+{{/*
+Create chart name and version as used by the chart label.
+*/}}
+{{- define "gerrit.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+{{/*
+Create secret to access docker registry
+*/}}
+{{- define "imagePullSecret" }}
+{{- printf "{\"auths\": {\"%s\": {\"auth\": \"%s\"}}}" .Values.images.registry.name (printf "%s:%s" .Values.images.registry.ImagePullSecret.username .Values.images.registry.ImagePullSecret.password | b64enc) | b64enc }}
+{{- end }}
+
+{{/*
+Add '/' to registry if needed.
+*/}}
+{{- define "registry" -}}
+{{ if .Values.images.registry.name }}{{- printf "%s/" .Values.images.registry.name -}}{{end}}
+{{- end -}}
diff --git a/charts/gerrit/templates/gerrit.configmap.yaml b/charts/gerrit/templates/gerrit.configmap.yaml
new file mode 100644
index 0000000..83c188c
--- /dev/null
+++ b/charts/gerrit/templates/gerrit.configmap.yaml
@@ -0,0 +1,78 @@
+{{- $root := . -}}
+
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: {{ .Release.Name }}-gerrit-configmap
+ labels:
+ app.kubernetes.io/component: gerrit
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+data:
+ {{- range $key, $value := .Values.gerrit.etc.config }}
+ {{ $key }}:
+{{ toYaml $value | indent 4 }}
+ {{- end }}
+ {{- if not (hasKey .Values.gerrit.etc.config "healthcheck.config") }}
+ healthcheck.config: |-
+ [healthcheck "auth"]
+ # On new instances there may be no users to use for healthchecks
+ enabled = false
+ [healthcheck "querychanges"]
+ # On new instances there won't be any changes to query
+ enabled = false
+ {{- end }}
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: {{ .Release.Name }}-gerrit-init-configmap
+ labels:
+ app.kubernetes.io/component: gerrit
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+data:
+ gerrit-init.yaml: |-
+ {{ if .Values.caCert -}}
+ caCertPath: /var/config/ca.crt
+ {{- end }}
+ pluginCacheEnabled: {{ .Values.gerrit.pluginManagement.cache.enabled }}
+ pluginCacheDir: /var/mnt/plugins
+ {{- if .Values.gerrit.pluginManagement.plugins }}
+ plugins:
+{{ toYaml .Values.gerrit.pluginManagement.plugins | indent 6}}
+ {{- end }}
+ {{- if .Values.gerrit.pluginManagement.libs }}
+ libs:
+{{ toYaml .Values.gerrit.pluginManagement.libs | indent 6}}
+ {{- end }}
+{{- range .Values.gerrit.additionalConfigMaps -}}
+{{- if .data }}
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: {{ $root.Release.Name }}-{{ .name }}
+ labels:
+ app.kubernetes.io/component: gerrit
+ app.kubernetes.io/instance: {{ $root.Release.Name }}
+ chart: {{ template "gerrit.chart" $root }}
+ heritage: {{ $root.Release.Service }}
+ release: {{ $root.Release.Name }}
+ {{- if $root.Values.additionalLabels }}
+{{ toYaml $root.Values.additionalLabels | indent 4 }}
+ {{- end }}
+data:
+{{ toYaml .data | indent 2 }}
+{{- end }}
+{{- end }}
diff --git a/charts/gerrit/templates/gerrit.secrets.yaml b/charts/gerrit/templates/gerrit.secrets.yaml
new file mode 100644
index 0000000..72cfad3
--- /dev/null
+++ b/charts/gerrit/templates/gerrit.secrets.yaml
@@ -0,0 +1,21 @@
+apiVersion: v1
+kind: Secret
+metadata:
+ name: {{ .Release.Name }}-gerrit-secure-config
+ labels:
+ app.kubernetes.io/component: gerrit
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+data:
+ {{ if .Values.gerrit.keystore -}}
+ keystore: {{ .Values.gerrit.keystore }}
+ {{- end }}
+ {{- range $key, $value := .Values.gerrit.etc.secret }}
+ {{ $key }}: {{ $value | b64enc }}
+ {{- end }}
+type: Opaque
diff --git a/charts/gerrit/templates/gerrit.service.yaml b/charts/gerrit/templates/gerrit.service.yaml
new file mode 100644
index 0000000..fe16d45
--- /dev/null
+++ b/charts/gerrit/templates/gerrit.service.yaml
@@ -0,0 +1,41 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: {{ .Release.Name }}-gerrit-service
+ labels:
+ app.kubernetes.io/component: gerrit
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+ {{- if .Values.gerrit.service.additionalAnnotations }}
+ annotations:
+{{ toYaml .Values.gerrit.service.additionalAnnotations | indent 4 }}
+ {{- end }}
+spec:
+ {{ with .Values.gerrit.service }}
+ {{- if .loadBalancerSourceRanges -}}
+ loadBalancerSourceRanges:
+{{- range .loadBalancerSourceRanges }}
+ - {{ . | quote }}
+{{- end }}
+ {{- end }}
+ ports:
+ - name: http
+ port: {{ .http.port }}
+ targetPort: 8080
+ {{- if .ssh.enabled }}
+ - name: ssh
+ port: {{ .ssh.port }}
+ targetPort: 29418
+ {{- end }}
+ type: {{ .type }}
+ externalTrafficPolicy: {{ .externalTrafficPolicy }}
+ {{- end }}
+ selector:
+ app.kubernetes.io/component: gerrit
+ app.kubernetes.io/instance: {{ .Release.Name }}
+
diff --git a/charts/gerrit/templates/gerrit.stateful-set.yaml b/charts/gerrit/templates/gerrit.stateful-set.yaml
new file mode 100644
index 0000000..2669325
--- /dev/null
+++ b/charts/gerrit/templates/gerrit.stateful-set.yaml
@@ -0,0 +1,299 @@
+{{- $root := . -}}
+
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+ name: {{ .Release.Name }}-gerrit-stateful-set
+ labels:
+ app.kubernetes.io/component: gerrit
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+spec:
+ serviceName: {{ .Release.Name }}-gerrit-service
+ replicas: {{ .Values.gerrit.replicas }}
+ updateStrategy:
+ rollingUpdate:
+ partition: {{ .Values.gerrit.updatePartition }}
+ selector:
+ matchLabels:
+ app.kubernetes.io/component: gerrit
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ template:
+ metadata:
+ labels:
+ app.kubernetes.io/component: gerrit
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 8 }}
+ {{- end }}
+ {{- if .Values.gerrit.additionalPodLabels }}
+{{ toYaml .Values.gerrit.additionalPodLabels | indent 8 }}
+ {{- end }}
+ annotations:
+ chartRevision: "{{ .Release.Revision }}"
+ {{- if .Values.gerrit.additionalAnnotations }}
+{{ toYaml .Values.gerrit.additionalAnnotations | indent 8 }}
+ {{- end }}
+ spec:
+ {{- with .Values.gerrit.tolerations }}
+ tolerations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.gerrit.topologySpreadConstraints }}
+ topologySpreadConstraints:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.gerrit.nodeSelector }}
+ nodeSelector:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.gerrit.affinity }}
+ affinity:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.gerrit.priorityClassName }}
+ priorityClassName: {{ . }}
+ {{- end }}
+ terminationGracePeriodSeconds: {{ .Values.gerrit.gracefulStopTimeout }}
+ securityContext:
+ fsGroup: 100
+ {{ if .Values.images.registry.ImagePullSecret.name -}}
+ imagePullSecrets:
+ - name: {{ .Values.images.registry.ImagePullSecret.name }}
+ {{- range .Values.images.additionalImagePullSecrets }}
+ - name: {{ . }}
+ {{- end }}
+ {{- end }}
+ initContainers:
+ {{- if and .Values.nfsWorkaround.enabled .Values.nfsWorkaround.chownOnStartup }}
+ - name: nfs-init
+ image: {{ .Values.images.busybox.registry -}}/busybox:{{- .Values.images.busybox.tag }}
+ command:
+ - sh
+ - -c
+ args:
+ - |
+ chown 1000:100 /var/mnt/logs
+ chown 1000:100 /var/mnt/git
+ env:
+ - name: POD_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.name
+ volumeMounts:
+ - name: logs
+ subPathExpr: "gerrit-replica/$(POD_NAME)"
+ mountPath: "/var/mnt/logs"
+ - name: git-repositories
+ mountPath: "/var/mnt/git"
+ {{- if .Values.nfsWorkaround.idDomain }}
+ - name: nfs-config
+ mountPath: "/etc/idmapd.conf"
+ subPath: idmapd.conf
+ {{- end }}
+ {{- end }}
+ - name: gerrit-init
+ image: {{ template "registry" . }}{{ .Values.gerrit.images.gerritInit }}:{{ .Values.images.version }}
+ imagePullPolicy: {{ .Values.images.imagePullPolicy }}
+ env:
+ - name: POD_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.name
+ volumeMounts:
+ - name: gerrit-site
+ mountPath: "/var/gerrit"
+ - name: git-repositories
+ mountPath: "/var/mnt/git"
+ - name: logs
+ subPathExpr: "gerrit/$(POD_NAME)"
+ mountPath: "/var/mnt/logs"
+ - name: gerrit-init-config
+ mountPath: "/var/config/gerrit-init.yaml"
+ subPath: gerrit-init.yaml
+ {{- if and .Values.nfsWorkaround.enabled .Values.nfsWorkaround.idDomain }}
+ - name: nfs-config
+ mountPath: "/etc/idmapd.conf"
+ subPath: idmapd.conf
+ {{- end }}
+ {{- if and .Values.gerrit.pluginManagement.cache.enabled }}
+ - name: gerrit-plugin-cache
+ mountPath: "/var/mnt/plugins"
+ {{- end }}
+ {{ if eq .Values.gerrit.index.type "elasticsearch" -}}
+ - name: gerrit-index-config
+ mountPath: "/var/mnt/index"
+ {{- end }}
+ - name: gerrit-config
+ mountPath: "/var/mnt/etc/config"
+ - name: gerrit-secure-config
+ mountPath: "/var/mnt/etc/secret"
+ {{ if .Values.caCert -}}
+ - name: tls-ca
+ subPath: ca.crt
+ mountPath: "/var/config/ca.crt"
+ {{- end }}
+ {{- range .Values.gerrit.additionalConfigMaps }}
+ - name: {{ .name }}
+ mountPath: "/var/mnt/data/{{ .subDir }}"
+ {{- end }}
+ containers:
+ - name: gerrit
+ image: {{ template "registry" . }}{{ .Values.gerrit.images.gerrit }}:{{ .Values.images.version }}
+ imagePullPolicy: {{ .Values.images.imagePullPolicy }}
+ env:
+ - name: POD_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.name
+ lifecycle:
+ preStop:
+ exec:
+ command:
+ - "/bin/ash"
+ - "-c"
+ - "kill -2 $(pidof java) && tail --pid=$(pidof java) -f /dev/null"
+ ports:
+ - name: gerrit-port
+ containerPort: 8080
+ {{- if .Values.gerrit.service.ssh.enabled }}
+ - name: gerrit-ssh
+ containerPort: 29418
+ {{- end }}
+ volumeMounts:
+ - name: gerrit-site
+ mountPath: "/var/gerrit"
+ - name: git-repositories
+ mountPath: "/var/mnt/git"
+ - name: logs
+ subPathExpr: "gerrit/$(POD_NAME)"
+ mountPath: "/var/mnt/logs"
+ {{- if and .Values.nfsWorkaround.enabled .Values.nfsWorkaround.idDomain }}
+ - name: nfs-config
+ mountPath: "/etc/idmapd.conf"
+ subPath: idmapd.conf
+ {{- end }}
+ {{ if eq .Values.gerrit.index.type "elasticsearch" -}}
+ - name: gerrit-index-config
+ mountPath: "/var/mnt/index"
+ {{- end }}
+ - name: gerrit-config
+ mountPath: "/var/mnt/etc/config"
+ - name: gerrit-secure-config
+ mountPath: "/var/mnt/etc/secret"
+ {{- range .Values.gerrit.additionalConfigMaps }}
+ - name: {{ .name }}
+ mountPath: "/var/mnt/data/{{ .subDir }}"
+ {{- end }}
+ resources:
+{{ toYaml .Values.gerrit.resources | indent 10 }}
+ livenessProbe:
+ httpGet:
+ path: /config/server/healthcheck~status
+ port: gerrit-port
+{{- if .Values.gerrit.probeScheme }}
+ scheme: {{ .Values.gerrit.probeScheme }}
+{{- end }}
+{{ toYaml .Values.gerrit.livenessProbe | indent 10 }}
+ readinessProbe:
+ httpGet:
+ path: /config/server/healthcheck~status
+ port: gerrit-port
+{{- if .Values.gerrit.probeScheme }}
+ scheme: {{ .Values.gerrit.probeScheme }}
+{{- end }}
+{{ toYaml .Values.gerrit.readinessProbe | indent 10 }}
+ startupProbe:
+ httpGet:
+ path: /config/server/healthcheck~status
+ port: gerrit-port
+{{- if .Values.gerrit.probeScheme }}
+ scheme: {{ .Values.gerrit.probeScheme }}
+{{- end }}
+{{ toYaml .Values.gerrit.startupProbe | indent 10 }}
+ volumes:
+ {{ if not .Values.gerrit.persistence.enabled -}}
+ - name: gerrit-site
+ emptyDir: {}
+ {{- end }}
+ {{- if and .Values.gerrit.pluginManagement.cache.enabled }}
+ - name: gerrit-plugin-cache
+ persistentVolumeClaim:
+ claimName: {{ .Release.Name }}-plugin-cache-pvc
+ {{- end }}
+ - name: git-repositories
+ persistentVolumeClaim:
+ {{- if .Values.gitRepositoryStorage.externalPVC.use }}
+ claimName: {{ .Values.gitRepositoryStorage.externalPVC.name }}
+ {{- else }}
+ claimName: {{ .Release.Name }}-git-repositories-pvc
+ {{- end }}
+ - name: logs
+ {{ if .Values.logStorage.enabled -}}
+ persistentVolumeClaim:
+ {{- if .Values.logStorage.externalPVC.use }}
+ claimName: {{ .Values.logStorage.externalPVC.name }}
+ {{- else }}
+ claimName: {{ .Release.Name }}-log-pvc
+ {{- end }}
+ {{ else -}}
+ emptyDir: {}
+ {{- end }}
+ - name: gerrit-init-config
+ configMap:
+ name: {{ .Release.Name }}-gerrit-init-configmap
+ {{ if eq .Values.gerrit.index.type "elasticsearch" -}}
+ - name: gerrit-index-config
+ persistentVolumeClaim:
+ claimName: {{ .Release.Name }}-gerrit-index-config-pvc
+ {{- end }}
+ - name: gerrit-config
+ configMap:
+ name: {{ .Release.Name }}-gerrit-configmap
+ - name: gerrit-secure-config
+ secret:
+ secretName: {{ .Release.Name }}-gerrit-secure-config
+ {{ if .Values.caCert -}}
+ - name: tls-ca
+ secret:
+ secretName: {{ .Release.Name }}-tls-ca
+ {{- end }}
+ {{- range .Values.gerrit.additionalConfigMaps }}
+ - name: {{ .name }}
+ configMap:
+ name: {{ if .data }}{{ $root.Release.Name }}-{{ .name }}{{ else }}{{ .name }}{{ end }}
+ {{- end }}
+ {{- if and .Values.nfsWorkaround.enabled .Values.nfsWorkaround.idDomain }}
+ - name: nfs-config
+ configMap:
+ name: {{ .Release.Name }}-nfs-configmap
+ {{- end }}
+ {{ if .Values.gerrit.persistence.enabled -}}
+ volumeClaimTemplates:
+ - metadata:
+ name: gerrit-site
+ labels:
+ app.kubernetes.io/component: gerrit
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 8 }}
+ {{- end }}
+ spec:
+ accessModes:
+ - ReadWriteOnce
+ resources:
+ requests:
+ storage: {{ .Values.gerrit.persistence.size }}
+ storageClassName: {{ .Values.storageClasses.default.name }}
+ {{- end }}
diff --git a/charts/gerrit/templates/gerrit.storage.yaml b/charts/gerrit/templates/gerrit.storage.yaml
new file mode 100644
index 0000000..1d85fc6
--- /dev/null
+++ b/charts/gerrit/templates/gerrit.storage.yaml
@@ -0,0 +1,45 @@
+{{- if and .Values.gerrit.pluginManagement.cache.enabled }}
+kind: PersistentVolumeClaim
+apiVersion: v1
+metadata:
+ name: {{ .Release.Name }}-plugin-cache-pvc
+ labels:
+ app.kubernetes.io/component: gerrit
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+spec:
+ accessModes:
+ - ReadWriteMany
+ resources:
+ requests:
+ storage: {{ .Values.gerrit.pluginManagement.cache.size }}
+ storageClassName: {{ .Values.storageClasses.shared.name }}
+{{- end }}
+{{ if eq .Values.gerrit.index.type "elasticsearch" -}}
+---
+kind: PersistentVolumeClaim
+apiVersion: v1
+metadata:
+ name: {{ .Release.Name }}-gerrit-index-config-pvc
+ labels:
+ app.kubernetes.io/component: gerrit
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+spec:
+ accessModes:
+ - ReadWriteMany
+ resources:
+ requests:
+ storage: 10Mi
+ storageClassName: {{ .Values.storageClasses.shared.name }}
+{{- end }}
diff --git a/charts/gerrit/templates/git-gc.cronjob.yaml b/charts/gerrit/templates/git-gc.cronjob.yaml
new file mode 100644
index 0000000..8230e5d
--- /dev/null
+++ b/charts/gerrit/templates/git-gc.cronjob.yaml
@@ -0,0 +1,132 @@
+apiVersion: batch/v1
+kind: CronJob
+metadata:
+ name: {{ .Release.Name }}-git-gc
+ labels:
+ app.kubernetes.io/component: git-gc
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+spec:
+ schedule: {{ .Values.gitGC.schedule | quote }}
+ concurrencyPolicy: "Forbid"
+ jobTemplate:
+ spec:
+ template:
+ metadata:
+ labels:
+ app.kubernetes.io/component: git-gc
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 12 }}
+ {{- end }}
+ {{- if .Values.gitGC.additionalPodLabels }}
+{{ toYaml .Values.gitGC.additionalPodLabels | indent 12 }}
+ {{- end }}
+ annotations:
+ cluster-autoscaler.kubernetes.io/safe-to-evict: "false"
+ spec:
+ {{- with .Values.gitGC.tolerations }}
+ tolerations:
+ {{- toYaml . | nindent 10 }}
+ {{- end }}
+ {{- with .Values.gitGC.nodeSelector }}
+ nodeSelector:
+ {{- toYaml . | nindent 12 }}
+ {{- end }}
+ {{- with .Values.gitGC.affinity }}
+ affinity:
+ {{- toYaml . | nindent 12 }}
+ {{- end }}
+ restartPolicy: OnFailure
+ securityContext:
+ runAsUser: 1000
+ fsGroup: 100
+ {{ if .Values.images.registry.ImagePullSecret.name -}}
+ imagePullSecrets:
+ - name: {{ .Values.images.registry.ImagePullSecret.name }}
+ {{- range .Values.images.additionalImagePullSecrets }}
+ - name: {{ . }}
+ {{- end }}
+ {{- end }}
+ initContainers:
+ {{- if and .Values.nfsWorkaround.enabled .Values.nfsWorkaround.chownOnStartup }}
+ - name: nfs-init
+ image: {{ .Values.images.busybox.registry -}}/busybox:{{- .Values.images.busybox.tag }}
+ command:
+ - sh
+ - -c
+ args:
+ - |
+ chown 1000:100 /var/mnt/logs
+ chown 1000:100 /var/mnt/git
+ env:
+ - name: POD_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.name
+ volumeMounts:
+ - name: logs
+ subPathExpr: "git-gc/$(POD_NAME)"
+ mountPath: "/var/mnt/logs"
+ - name: git-repositories
+ mountPath: "/var/mnt/git"
+ {{- if .Values.nfsWorkaround.idDomain }}
+ - name: nfs-config
+ mountPath: "/etc/idmapd.conf"
+ subPath: idmapd.conf
+ {{- end }}
+ {{- end }}
+ containers:
+ - name: git-gc
+ imagePullPolicy: {{ .Values.images.imagePullPolicy }}
+ image: {{ template "registry" . }}{{ .Values.gitGC.image }}:{{ .Values.images.version }}
+ env:
+ - name: POD_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.name
+ resources:
+{{ toYaml .Values.gitGC.resources | indent 14 }}
+ volumeMounts:
+ - name: git-repositories
+ mountPath: "/var/gerrit/git"
+ - name: logs
+ subPathExpr: "git-gc/$(POD_NAME)"
+ mountPath: "/var/log/git"
+ {{- if and .Values.nfsWorkaround.enabled .Values.nfsWorkaround.idDomain }}
+ - name: nfs-config
+ mountPath: "/etc/idmapd.conf"
+ subPath: idmapd.conf
+ {{- end }}
+ volumes:
+ - name: git-repositories
+ persistentVolumeClaim:
+ {{- if .Values.gitRepositoryStorage.externalPVC.use }}
+ claimName: {{ .Values.gitRepositoryStorage.externalPVC.name }}
+ {{- else }}
+ claimName: {{ .Release.Name }}-git-repositories-pvc
+ {{- end }}
+ - name: logs
+ {{ if .Values.logStorage.enabled -}}
+ persistentVolumeClaim:
+ {{- if .Values.logStorage.externalPVC.use }}
+ claimName: {{ .Values.logStorage.externalPVC.name }}
+ {{- else }}
+ claimName: {{ .Release.Name }}-log-pvc
+ {{- end }}
+ {{ else -}}
+ emptyDir: {}
+ {{- end }}
+ {{- if and .Values.nfsWorkaround.enabled .Values.nfsWorkaround.idDomain }}
+ - name: nfs-config
+ configMap:
+ name: {{ .Release.Name }}-nfs-configmap
+ {{- end }}
diff --git a/charts/gerrit/templates/git-gc.storage.yaml b/charts/gerrit/templates/git-gc.storage.yaml
new file mode 100644
index 0000000..c69a647
--- /dev/null
+++ b/charts/gerrit/templates/git-gc.storage.yaml
@@ -0,0 +1,22 @@
+{{ if .Values.gitGC.logging.persistence.enabled -}}
+kind: PersistentVolumeClaim
+apiVersion: v1
+metadata:
+ name: {{ .Release.Name }}-git-gc-logs-pvc
+ labels:
+ app.kubernetes.io/component: git-gc
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+spec:
+ accessModes:
+ - ReadWriteOnce
+ resources:
+ requests:
+ storage: {{ .Values.gitGC.logging.persistence.size }}
+ storageClassName: {{ .Values.storageClasses.default.name }}
+{{- end }}
diff --git a/charts/gerrit/templates/global.secrets.yaml b/charts/gerrit/templates/global.secrets.yaml
new file mode 100644
index 0000000..b2c3d5d
--- /dev/null
+++ b/charts/gerrit/templates/global.secrets.yaml
@@ -0,0 +1,18 @@
+{{ if .Values.caCert -}}
+apiVersion: v1
+kind: Secret
+metadata:
+ name: {{ .Release.Name }}-tls-ca
+ labels:
+ app.kubernetes.io/component: gerrit
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+data:
+ ca.crt: {{ .Values.caCert | b64enc }}
+type: Opaque
+{{- end }}
diff --git a/charts/gerrit/templates/image-pull.secret.yaml b/charts/gerrit/templates/image-pull.secret.yaml
new file mode 100644
index 0000000..d107472
--- /dev/null
+++ b/charts/gerrit/templates/image-pull.secret.yaml
@@ -0,0 +1,9 @@
+{{ if and .Values.images.registry.ImagePullSecret.name .Values.images.registry.ImagePullSecret.create -}}
+apiVersion: v1
+kind: Secret
+metadata:
+ name: {{ .Values.images.registry.ImagePullSecret.name }}
+type: kubernetes.io/dockerconfigjson
+data:
+ .dockerconfigjson: {{ template "imagePullSecret" . }}
+{{- end }}
\ No newline at end of file
diff --git a/charts/gerrit/templates/ingress.yaml b/charts/gerrit/templates/ingress.yaml
new file mode 100644
index 0000000..eb19655
--- /dev/null
+++ b/charts/gerrit/templates/ingress.yaml
@@ -0,0 +1,64 @@
+{{- if .Values.ingress.enabled }}
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+ name: {{ .Release.Name }}-gerrit-ingress
+ labels:
+ app.kubernetes.io/component: gerrit
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.ingress.additionalLabels }}
+{{ toYaml .Values.ingress.additionalLabels | indent 4 }}
+ {{- end }}
+ annotations:
+ nginx.ingress.kubernetes.io/proxy-body-size: {{ .Values.ingress.maxBodySize | default "50m" }}
+ {{- if .Values.ingress.additionalAnnotations }}
+{{ toYaml .Values.ingress.additionalAnnotations | indent 4 }}
+ {{- end }}
+spec:
+ {{ if .Values.ingress.tls.enabled -}}
+ tls:
+ - hosts:
+ - {{ .Values.ingress.host }}
+ {{ if .Values.ingress.tls.secret.create -}}
+ secretName: {{ .Release.Name }}-gerrit-tls-secret
+ {{- else }}
+ secretName: {{ .Values.ingress.tls.secret.name }}
+ {{- end }}
+ {{- end }}
+ rules:
+ - host: {{required "A host URL is required for the Gerrit Ingress. Please set 'ingress.host'" .Values.ingress.host }}
+ http:
+ paths:
+ - pathType: Prefix
+ path: /
+ backend:
+ service:
+ name: {{ .Release.Name }}-gerrit-service
+ port:
+ number: {{ .Values.gerrit.service.http.port }}
+{{- end }}
+---
+{{ if and .Values.ingress.tls.enabled .Values.ingress.tls.secret.create -}}
+apiVersion: v1
+kind: Secret
+metadata:
+ name: {{ .Release.Name }}-gerrit-tls-secret
+ labels:
+ app.kubernetes.io/component: gerrit
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.ingress.additionalLabels }}
+{{ toYaml .Values.ingress.additionalLabels | indent 4 }}
+ {{- end }}
+type: kubernetes.io/tls
+data:
+ {{ with .Values.ingress.tls -}}
+ tls.crt: {{ .cert | b64enc }}
+ tls.key: {{ .key | b64enc }}
+ {{- end }}
+{{- end }}
diff --git a/charts/gerrit/templates/log-cleaner.cronjob.yaml b/charts/gerrit/templates/log-cleaner.cronjob.yaml
new file mode 100644
index 0000000..c1314f1
--- /dev/null
+++ b/charts/gerrit/templates/log-cleaner.cronjob.yaml
@@ -0,0 +1,65 @@
+{{- if and .Values.logStorage.enabled .Values.logStorage.cleanup.enabled }}
+apiVersion: batch/v1beta1
+kind: CronJob
+metadata:
+ name: {{ .Release.Name }}-log-cleaner
+ labels:
+ app.kubernetes.io/component: log-cleaner
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+spec:
+ schedule: {{ .Values.logStorage.cleanup.schedule | quote }}
+ concurrencyPolicy: "Forbid"
+ jobTemplate:
+ spec:
+ template:
+ metadata:
+ labels:
+ app.kubernetes.io/component: log-cleaner
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 12 }}
+ {{- end }}
+ {{- if .Values.logStorage.cleanup.additionalPodLabels }}
+{{ toYaml .Values.logStorage.cleanup.additionalPodLabels | indent 12 }}
+ {{- end }}
+ spec:
+ restartPolicy: OnFailure
+ containers:
+ - name: log-cleaner
+ imagePullPolicy: {{ .Values.images.imagePullPolicy }}
+ image: {{ .Values.images.busybox.registry -}}/busybox:{{- .Values.images.busybox.tag }}
+ command:
+ - sh
+ - -c
+ args:
+ - |
+ find /var/logs/ \
+ -mindepth 1 \
+ -type f \
+ -mtime +{{ .Values.logStorage.cleanup.retentionDays }} \
+ -print \
+ -delete
+ find /var/logs/ -type d -empty -delete
+ resources:
+{{ toYaml .Values.logStorage.cleanup.resources | indent 14 }}
+ volumeMounts:
+ - name: logs
+ mountPath: "/var/logs"
+ volumes:
+ - name: logs
+ persistentVolumeClaim:
+ {{- if .Values.logStorage.externalPVC.use }}
+ claimName: {{ .Values.logStorage.externalPVC.name }}
+ {{- else }}
+ claimName: {{ .Release.Name }}-log-pvc
+ {{- end }}
+{{- end }}
diff --git a/charts/gerrit/templates/netpol.yaml b/charts/gerrit/templates/netpol.yaml
new file mode 100644
index 0000000..c0cbc4d
--- /dev/null
+++ b/charts/gerrit/templates/netpol.yaml
@@ -0,0 +1,122 @@
+{{ if .Values.networkPolicies.enabled -}}
+kind: NetworkPolicy
+apiVersion: networking.k8s.io/v1
+metadata:
+ name: {{ .Release.Name }}-default-deny-all
+ labels:
+ chart: {{ template "gerrit.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.networkPolicies.additionalLabels }}
+{{ toYaml .Values.networkPolicies.additionalLabels | indent 4 }}
+ {{- end }}
+spec:
+ podSelector:
+ matchLabels:
+ chart: {{ template "gerrit.chart" . }}
+ release: {{ .Release.Name }}
+ policyTypes:
+ - Ingress
+ - Egress
+ ingress: []
+ egress: []
+---
+{{ if .Values.networkPolicies.dnsPorts -}}
+apiVersion: networking.k8s.io/v1
+kind: NetworkPolicy
+metadata:
+ name: {{ .Release.Name }}-allow-dns-access
+ labels:
+ chart: {{ template "gerrit.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.networkPolicies.additionalLabels }}
+{{ toYaml .Values.networkPolicies.additionalLabels | indent 4 }}
+ {{- end }}
+spec:
+ podSelector:
+ matchLabels:
+ chart: {{ template "gerrit.chart" . }}
+ release: {{ .Release.Name }}
+ policyTypes:
+ - Egress
+ egress:
+ - ports:
+ {{ range .Values.networkPolicies.dnsPorts -}}
+ - port: {{ . }}
+ protocol: UDP
+ - port: {{ . }}
+ protocol: TCP
+ {{ end }}
+{{- end }}
+---
+kind: NetworkPolicy
+apiVersion: networking.k8s.io/v1
+metadata:
+ name: gerrit-allow-external
+ labels:
+ app.kubernetes.io/component: gerrit
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+spec:
+ podSelector:
+ matchLabels:
+ chart: {{ template "gerrit.chart" . }}
+ release: {{ .Release.Name }}
+ app.kubernetes.io/component: gerrit
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ ingress:
+ - ports:
+ - port: 8080
+ from: []
+---
+{{ if or .Values.gerrit.networkPolicy.ingress -}}
+kind: NetworkPolicy
+apiVersion: networking.k8s.io/v1
+metadata:
+ name: gerrit-custom-ingress-policies
+ labels:
+ app.kubernetes.io/component: gerrit
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+spec:
+ policyTypes:
+ - Ingress
+ podSelector:
+ matchLabels:
+ chart: {{ template "gerrit.chart" . }}
+ release: {{ .Release.Name }}
+ app.kubernetes.io/component: gerrit
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ ingress:
+{{ toYaml .Values.gerrit.networkPolicy.ingress | indent 2 }}
+{{- end }}
+---
+{{ if or .Values.gerrit.networkPolicy.egress -}}
+kind: NetworkPolicy
+apiVersion: networking.k8s.io/v1
+metadata:
+ name: gerrit-custom-egress-policies
+ labels:
+ app.kubernetes.io/component: gerrit
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+spec:
+ policyTypes:
+ - Egress
+ podSelector:
+ matchLabels:
+ chart: {{ template "gerrit.chart" . }}
+ release: {{ .Release.Name }}
+ app.kubernetes.io/component: gerrit
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ egress:
+{{ toYaml .Values.gerrit.networkPolicy.egress | indent 2 }}
+{{- end }}
+{{- end }}
diff --git a/charts/gerrit/templates/nfs.configmap.yaml b/charts/gerrit/templates/nfs.configmap.yaml
new file mode 100644
index 0000000..dd2c3dd
--- /dev/null
+++ b/charts/gerrit/templates/nfs.configmap.yaml
@@ -0,0 +1,28 @@
+{{- if and .Values.nfsWorkaround.enabled .Values.nfsWorkaround.idDomain -}}
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: {{ .Release.Name }}-nfs-configmap
+ labels:
+ app.kubernetes.io/component: gerrit
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+data:
+ idmapd.conf: |-
+ [General]
+
+ Verbosity = 0
+ Pipefs-Directory = /run/rpc_pipefs
+ # set your own domain here, if it differs from FQDN minus hostname
+ Domain = {{ .Values.nfsWorkaround.idDomain }}
+
+ [Mapping]
+
+ Nobody-User = nobody
+ Nobody-Group = nogroup
+{{- end }}
diff --git a/charts/gerrit/templates/storage.pvc.yaml b/charts/gerrit/templates/storage.pvc.yaml
new file mode 100644
index 0000000..b262402
--- /dev/null
+++ b/charts/gerrit/templates/storage.pvc.yaml
@@ -0,0 +1,45 @@
+{{- if not .Values.gitRepositoryStorage.externalPVC.use }}
+kind: PersistentVolumeClaim
+apiVersion: v1
+metadata:
+ name: {{ .Release.Name }}-git-repositories-pvc
+ labels:
+ app.kubernetes.io/component: gerrit
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+spec:
+ accessModes:
+ - ReadWriteMany
+ resources:
+ requests:
+ storage: {{ .Values.gitRepositoryStorage.size }}
+ storageClassName: {{ .Values.storageClasses.shared.name }}
+{{- end }}
+{{- if and .Values.logStorage.enabled (not .Values.logStorage.externalPVC.use) }}
+---
+kind: PersistentVolumeClaim
+apiVersion: v1
+metadata:
+ name: {{ .Release.Name }}-log-pvc
+ labels:
+ app.kubernetes.io/component: gerrit
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ chart: {{ template "gerrit.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+spec:
+ accessModes:
+ - ReadWriteMany
+ resources:
+ requests:
+ storage: {{ .Values.logStorage.size }}
+ storageClassName: {{ .Values.storageClasses.shared.name }}
+{{- end }}
diff --git a/charts/gerrit/templates/storageclasses.yaml b/charts/gerrit/templates/storageclasses.yaml
new file mode 100644
index 0000000..552cd6a
--- /dev/null
+++ b/charts/gerrit/templates/storageclasses.yaml
@@ -0,0 +1,53 @@
+{{ if .Values.storageClasses.default.create -}}
+kind: StorageClass
+apiVersion: storage.k8s.io/v1
+metadata:
+ name: {{ .Values.storageClasses.default.name }}
+ labels:
+ chart: {{ template "gerrit.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+provisioner: {{ .Values.storageClasses.default.provisioner }}
+reclaimPolicy: {{ .Values.storageClasses.default.reclaimPolicy }}
+{{ if .Values.storageClasses.default.parameters -}}
+parameters:
+{{- range $key, $value := .Values.storageClasses.default.parameters }}
+ {{ $key }}: {{ $value }}
+{{- end }}
+mountOptions:
+{{- range $value := .Values.storageClasses.default.mountOptions }}
+ - {{ $value }}
+{{- end }}
+allowVolumeExpansion: {{ .Values.storageClasses.default.allowVolumeExpansion }}
+{{- end }}
+{{- end }}
+---
+{{ if .Values.storageClasses.shared.create -}}
+kind: StorageClass
+apiVersion: storage.k8s.io/v1
+metadata:
+ name: {{ .Values.storageClasses.shared.name }}
+ labels:
+ chart: {{ template "gerrit.chart" . }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ {{- if .Values.additionalLabels }}
+{{ toYaml .Values.additionalLabels | indent 4 }}
+ {{- end }}
+provisioner: {{ .Values.storageClasses.shared.provisioner }}
+reclaimPolicy: {{ .Values.storageClasses.shared.reclaimPolicy }}
+{{ if .Values.storageClasses.shared.parameters -}}
+parameters:
+{{- range $key, $value := .Values.storageClasses.shared.parameters }}
+ {{ $key }}: {{ $value }}
+{{- end }}
+mountOptions:
+{{- range $value := .Values.storageClasses.shared.mountOptions }}
+ - {{ $value }}
+{{- end }}
+allowVolumeExpansion: {{ .Values.storageClasses.shared.allowVolumeExpansion }}
+{{- end }}
+{{- end }}
diff --git a/charts/gerrit/values.yaml b/charts/gerrit/values.yaml
new file mode 100644
index 0000000..ef27520
--- /dev/null
+++ b/charts/gerrit/values.yaml
@@ -0,0 +1,336 @@
+images:
+ busybox:
+ registry: docker.io
+ tag: latest
+ # Registry used for container images created by this project
+ registry:
+ # The registry name must NOT contain a trailing slash
+ name:
+ ImagePullSecret:
+ # Leave blank, if no ImagePullSecret is needed.
+ name: image-pull-secret
+ # If set to false, the gerrit chart expects either a ImagePullSecret
+ # with the name configured above to be present on the cluster or that no
+ # credentials are needed.
+ create: false
+ username:
+ password:
+ version: latest
+ imagePullPolicy: Always
+ # Additional ImagePullSecrets that already exist and should be used by the
+ # pods of this chart. E.g. to pull busybox from dockerhub.
+ additionalImagePullSecrets: []
+
+# Additional labels that should be applied to all resources
+additionalLabels: {}
+
+storageClasses:
+ # Storage class used for storing logs and other pod-specific persisted data
+ default:
+ # If create is set to false, an existing StorageClass with the given
+ # name is expected to exist in the cluster. Setting create to true will
+ # create a storage class with the parameters given below.
+ name: default
+ create: false
+ provisioner: kubernetes.io/aws-ebs
+ reclaimPolicy: Delete
+ # Use the parameters key to set all parameters needed for the provisioner
+ parameters:
+ type: gp2
+ fsType: ext4
+ mountOptions: []
+ allowVolumeExpansion: false
+ # Storage class used for storing git repositories. Has to provide RWM access.
+ shared:
+ # If create is set to false, an existing StorageClass with RWM access
+ # mode and the given name has to be provided.
+ name: shared-storage
+ create: false
+ provisioner: nfs
+ reclaimPolicy: Delete
+ # Use the parameters key to set all parameters needed for the provisioner
+ parameters:
+ mountOptions: vers=4.1
+ mountOptions: []
+ allowVolumeExpansion: false
+
+
+nfsWorkaround:
+ enabled: false
+ chownOnStartup: false
+ idDomain: localdomain.com
+
+
+networkPolicies:
+ enabled: false
+ dnsPorts:
+ - 53
+ - 8053
+
+
+gitRepositoryStorage:
+ externalPVC:
+ use: false
+ name: git-repositories-pvc
+ size: 5Gi
+
+logStorage:
+ enabled: false
+ externalPVC:
+ use: false
+ name: gerrit-logs-pvc
+ size: 5Gi
+ cleanup:
+ enabled: false
+ additionalPodLabels: {}
+ schedule: "0 0 * * *"
+ retentionDays: 14
+ resources:
+ requests:
+ cpu: 100m
+ memory: 256Mi
+ limits:
+ cpu: 100m
+ memory: 256Mi
+
+caCert:
+
+ingress:
+ enabled: false
+ host:
+ # The maximum body size to allow for requests. Use "0" to allow unlimited
+ # reuqest body sizes.
+ maxBodySize: 50m
+ additionalAnnotations:
+ kubernetes.io/ingress.class: nginx
+ # nginx.ingress.kubernetes.io/server-alias: example.com
+ # nginx.ingress.kubernetes.io/whitelist-source-range: xxx.xxx.xxx.xxx
+ tls:
+ enabled: false
+ secret:
+ create: true
+ # `name` will only be used, if `create` is set to false to bind an
+ # existing secret. Otherwise the name will be automatically generated to
+ # avoid conflicts between multiple chart installations.
+ name:
+ # `cert`and `key` will only be used, if the secret will be created by
+ # this chart.
+ cert: |-
+ -----BEGIN CERTIFICATE-----
+
+ -----END CERTIFICATE-----
+ key: |-
+ -----BEGIN RSA PRIVATE KEY-----
+
+ -----END RSA PRIVATE KEY-----
+
+
+gitGC:
+ image: k8sgerrit/git-gc
+
+ tolerations: []
+ nodeSelector: {}
+ affinity: {}
+ additionalPodLabels: {}
+
+ schedule: 0 6,18 * * *
+
+ resources:
+ requests:
+ cpu: 100m
+ memory: 256Mi
+ limits:
+ cpu: 100m
+ memory: 256Mi
+
+ logging:
+ persistence:
+ enabled: true
+ size: 1Gi
+
+
+gerrit:
+ images:
+ gerritInit: k8sgerrit/gerrit-init
+ gerrit: k8sgerrit/gerrit
+
+ tolerations: []
+ topologySpreadConstraints: {}
+ nodeSelector: {}
+ affinity: {}
+ additionalAnnotations: {}
+ additionalPodLabels: {}
+
+ replicas: 1
+ updatePartition: 0
+
+ # The memory limit has to be higher than the configures heap-size for Java!
+ resources:
+ requests:
+ cpu: 1
+ memory: 5Gi
+ limits:
+ cpu: 1
+ memory: 6Gi
+
+ persistence:
+ enabled: true
+ size: 10Gi
+
+ # If no value for probeScheme, the probe will use the default HTTP
+ probeScheme: HTTP
+
+ livenessProbe:
+ initialDelaySeconds: 30
+ periodSeconds: 5
+
+ readinessProbe:
+ initialDelaySeconds: 5
+ periodSeconds: 1
+
+ startupProbe:
+ initialDelaySeconds: 10
+ periodSeconds: 30
+
+ gracefulStopTimeout: 90
+
+ # The general NetworkPolicy rules implemented by this chart may be too restrictive
+ # for some setups, e.g. when trying to replicate to a Gerrit replica. Here
+ # custom rules may be added to whitelist some additional connections.
+ networkPolicy:
+ ingress: []
+ egress: []
+ # An example for an egress rule to allow replication to a Gerrit replica
+ # installed with the gerrit-replica setup in the same cluster and namespace
+ # by using the service as the replication destination
+ # (e.g. http://gerrit-replica-git-backend-service:80/git/${name}.git):
+ #
+ # - to:
+ # - podSelector:
+ # matchLabels:
+ # app: git-backend
+
+ service:
+ additionalAnnotations: {}
+ loadBalancerSourceRanges: []
+ type: NodePort
+ externalTrafficPolicy: Cluster
+ http:
+ port: 80
+ ssh:
+ enabled: false
+ port: 29418
+
+ # `gerrit.keystore` expects a base64-encoded Java-keystore
+ # Since Java keystores are binary files, adding the unencoded content and
+ # automatic encoding using helm does not work here.
+ keystore:
+
+ index:
+ # Either `lucene` or `elasticsearch`
+ type: lucene
+
+ pluginManagement:
+ plugins: []
+ # A plugin packaged in the gerrit.war-file
+ # - name: download-commands
+
+ # A plugin packaged in the gerrit.war-file that will also be installed as a
+ # lib
+ # - name: replication
+ # installAsLibrary: true
+
+ # A plugin that will be downloaded on startup
+ # - name: delete-project
+ # url: https://example.com/gerrit-plugins/delete-project.jar
+ # sha1:
+ # installAsLibrary: false
+
+ # Only downloaded plugins will be cached. This will be ignored, if no plugins
+ # are downloaded.
+ libs: []
+ cache:
+ enabled: false
+ size: 1Gi
+
+ priorityClassName:
+
+ etc:
+ # Some values are expected to have a specific value for the deployment installed
+ # by this chart to work. These are marked with `# FIXED`.
+ # Do not change them!
+ config:
+ gerrit.config: |-
+ [gerrit]
+ basePath = git # FIXED
+ serverId = gerrit-1
+ # The canonical web URL has to be set to the Ingress host, if an Ingress
+ # is used. If a LoadBalancer-service is used, this should be set to the
+ # LoadBalancer's external IP. This can only be done manually after installing
+ # the chart, when you know the external IP the LoadBalancer got from the
+ # cluster.
+ canonicalWebUrl = http://example.com/
+ disableReverseDnsLookup = true
+ [index]
+ type = LUCENE
+ [auth]
+ type = DEVELOPMENT_BECOME_ANY_ACCOUNT
+ [httpd]
+ # If using an ingress use proxy-http or proxy-https
+ listenUrl = proxy-http://*:8080/
+ requestLog = true
+ gracefulStopTimeout = 1m
+ [sshd]
+ listenAddress = off
+ [transfer]
+ timeout = 120 s
+ [user]
+ name = Gerrit Code Review
+ email = gerrit@example.com
+ anonymousCoward = Unnamed User
+ [cache]
+ directory = cache
+ [container]
+ user = gerrit # FIXED
+ javaHome = /usr/lib/jvm/java-17-openjdk # FIXED
+ javaOptions = -Djavax.net.ssl.trustStore=/var/gerrit/etc/keystore # FIXED
+ javaOptions = -Xms200m
+ # Has to be lower than 'gerrit.resources.limits.memory'. Also
+ # consider memories used by other applications in the container.
+ javaOptions = -Xmx4g
+
+ replication.config: |-
+ [gerrit]
+ autoReload = false
+ replicateOnStartup = true
+ defaultForceUpdate = true
+
+ # [remote "replica"]
+ # url = http://gerrit-replica.example.com/git/${name}.git
+ # replicationDelay = 0
+ # timeout = 30
+
+ secret:
+ secure.config: |-
+ # Password for the keystore added as value for 'gerritReplica.keystore'
+ # Only needed, if SSL is enabled.
+ #[httpd]
+ # sslKeyPassword = gerrit
+
+ # Credentials for replication targets
+ # [remote "replica"]
+ # username = git
+ # password = secret
+
+ # ssh_host_ecdsa_key: |-
+ # -----BEGIN EC PRIVATE KEY-----
+
+ # -----END EC PRIVATE KEY-----
+
+ # ssh_host_ecdsa_key.pub: ecdsa-sha2-nistp256...
+
+ additionalConfigMaps:
+ # - name:
+ # subDir:
+ # data:
+ # file.txt: test