Commit a447bcdc by Denise Schannon Committed by Craig Jellick

remove harbor

parent 12e82e39
docs/*
.git/*
.gitignore
CONTRIBUTING.md
# Contributing to Helm Chart for Harbor
Please follow [Harbor contributing guide](https://github.com/goharbor/harbor/blob/master/CONTRIBUTING.md) to learn how to make code contribution.
# Contributers
Thanks very much to all contributers who submitted pull requests to Helm Chart for Harbor.
- [Paul Czarkowski @paulczar](https://github.com/paulczar)
- [Luca Innocenti Mirri @lucaim](https://github.com/lucaim)
- [Steven Arnott @ArcticSnowman](https://github.com/ArcticSnowman)
- [Alex M @draeron](https://github.com/draeron)
- [SangJun Yun](https://github.com/YunSangJun)
name: harbor
version: 1.7.5-rancher1
appVersion: 1.7.5
description: An open source trusted cloud native registry that stores, signs, and scans content
keywords:
- docker
- registry
- harbor
home: https://goharbor.io
icon: https://raw.githubusercontent.com/goharbor/harbor/master/docs/img/harbor_logo.png
sources:
- https://github.com/goharbor/harbor
- https://github.com/goharbor/harbor-helm
maintainers:
- name: Rancher
email: support@rancher.com
engine: gotpl
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 [yyyy] [name of copyright owner]
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.
# Helm Chart for Harbor
**Notes:** The master branch is in heavy development, please use the codes on other branch instead. A high available solution for Harbor based on chart can be find [here](docs/High%20Availability.md). And refer to the [guide](docs/Upgrade.md) to upgrade the existing deployment.
## Introduction
This [Helm](https://github.com/kubernetes/helm) chart installs [Harbor](https://github.com/goharbor/harbor) in a Kubernetes cluster. Welcome to [contribute](CONTRIBUTING.md) to Helm Chart for Harbor.
## Prerequisites
- Kubernetes cluster 1.10+
- Helm 2.8.0+
## Installation
### Download the chart
Download Harbor helm chart code.
```bash
git clone https://github.com/goharbor/harbor-helm
```
Checkout the branch.
```bash
cd harbor-helm
git checkout branch_name
```
### Configure the chart
The following items can be configured in `values.yaml` or set via `--set` flag during installation.
#### Configure the way how to expose Harbor service:
- **Ingress**: The ingress controller must be installed in the Kubernetes cluster.
**Notes:** if the TLS is disabled, the port must be included in the command when pulling/pushing images. Refer to issue [#5291](https://github.com/goharbor/harbor/issues/5291) for the detail.
- **ClusterIP**: Exposes the service on a cluster-internal IP. Choosing this value makes the service only reachable from within the cluster.
- **NodePort**: Exposes the service on each Node’s IP at a static port (the NodePort). You’ll be able to contact the NodePort service, from outside the cluster, by requesting `NodeIP:NodePort`.
- **LoadBalancer**: Exposes the service externally using a cloud provider’s load balancer.
#### Configure the external URL
The external URL for Harbor core service is used to:
1. populate the docker/helm commands showed on portal
2. populate the token service URL returned to docker/notary client
Format: `protocol://domain[:port]`. Usually:
- if expose the service via `Ingress`, the `domain` should be the value of `expose.ingress.hosts.core`
- if expose the service via `ClusterIP`, the `domain` should be the value of `expose.clusterIP.name`
- if expose the service via `NodePort`, the `domain` should be the IP address of one Kubernetes node
- if expose the service via `LoadBalancer`, set the `domain` as your own domain name and add a CNAME record to map the domain name to the one you got from the cloud provider
If Harbor is deployed behind the proxy, set it as the URL of proxy.
#### Configure the way how to persistent data:
- **Disable**: The data does not survive the termination of a pod.
- **Persistent Volume Claim(default)**: A default `StorageClass` is needed in the Kubernetes cluster to dynamic provision the volumes. Specify another StorageClass in the `storageClass` or set `existingClaim` if you have already existing persistent volumes to use.
- **External Storage(only for images and charts)**: For images and charts, the external storages are supported: `azure`, `gcs`, `s3` `swift` and `oss`.
#### Configure the secrets
- **Secret keys**: Secret keys are used for secure communication between components. Fill `core.secret`, `jobservice.secret` and `registry.secret` to configure.
- **Certificates**:
- *notary*: Used for authentication during communications. Fill `notary.secretName` to configure. Notary server certificate must be issued with notary service name as subject alternative name.
- *core*: Used for token encryption/decryption. Fill `core.secretName` to configure.
Secrets and certificates must be setup to avoid changes on every Helm upgrade (see: [#107](https://github.com/goharbor/harbor-helm/issues/107)).
#### Configure the other items listed in [configuration](#configuration) section.
### Install the chart
Install the Harbor helm chart with a release name `my-release`:
```bash
helm install --name my-release .
```
## Uninstallation
To uninstall/delete the `my-release` deployment:
```bash
helm delete --purge my-release
```
## Configuration
The following table lists the configurable parameters of the Harbor chart and the default values.
| Parameter | Description | Default |
| --------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------- |
| **Expose** |
| `expose.type` | The way how to expose the service: `ingress`, `clusterIP`, `nodePort` or `loadBalancer` | `ingress` |
| `expose.tls.type` | Choose TLS certificate type : `secretName`, `custom CA`, `rancher` or `self-signed x509 certificate` | `secretName`
| `expose.tls.secretName` | Fill the name of secret if you want to use your own TLS certificate and private key. The secret must contain keys named `tls.crt` and `tls.key` that contain the certificate and private key to use for TLS. The certificate and private key will be generated automatically if it is not set | |
| `expose.tls.notarySecretName` | By default, the Notary service will use the same cert and key as described above. Fill the name of secret if you want to use a separated one. Only needed when the `expose.type` is `ingress`. | |
| `expose.tls.commonName` | The common name used to generate the certificate, it's necessary when the `expose.type` is `clusterIP` or `nodePort` and `expose.tls.secretName` is null | |
| `expose.ingress.host` | The host of Harbor core service in ingress rule | `core.harbor.domain` |
| `expose.ingress.annotations` | The annotations used in ingress | |
| `expose.clusterIP.name` | The name of ClusterIP service | `harbor` |
| `expose.clusterIP.ports.httpPort` | The service port Harbor listens on when serving with HTTP | `80` |
| `expose.clusterIP.ports.httpsPort` | The service port Harbor listens on when serving with HTTPS | `443` |
| `expose.clusterIP.ports.notaryPort` | The service port Notary listens on. Only needed when `notary.enabled` is set to `true` | `4443` |
| `expose.nodePort.name` | The name of NodePort service | `harbor` |
| `expose.nodePort.ports.http.port` | The service port Harbor listens on when serving with HTTP | `80` |
| `expose.nodePort.ports.http.nodePort` | The node port Harbor listens on when serving with HTTP | `30002` |
| `expose.nodePort.ports.https.port` | The service port Harbor listens on when serving with HTTPS | `443` |
| `expose.nodePort.ports.https.nodePort` | The node port Harbor listens on when serving with HTTPS | `30003` |
| `expose.nodePort.ports.notary.port` | The service port Notary listens on. Only needed when `notary.enabled` is set to `true` | `4443` |
| `expose.nodePort.ports.notary.nodePort` | The node port Notary listens on. Only needed when `notary.enabled` is set to `true` | `30004` |
| `expose.loadBalancer.name` | The name of service |`harbor`|
| `expose.loadBalancer.ports.httpPort` | The service port Harbor listens on when serving with HTTP |`80`|
| `expose.loadBalancer.ports.httpsPort` | The service port Harbor listens on when serving with HTTP |`30002`|
| `expose.loadBalancer.ports.notaryPort` | The service port Notary listens on. Only needed when `notary.enabled` is set to `true`|
| **Persistence** |
| `persistence.enabled` | Enable the data persistence or not | `true` |
| `persistence.resourcePolicy` | Setting it to `keep` to avoid removing PVCs during a helm delete operation. Leaving it empty will delete PVCs after the chart deleted | `keep` |
| `persistence.persistentVolumeClaim.registry.existingClaim` | Use the existing PVC which must be created manually before bound, and specify the `subPath` if the PVC is shared with other components | |
| `persistence.persistentVolumeClaim.registry.storageClass` | Specify the `storageClass` used to provision the volume. Or the default StorageClass will be used(the default). Set it to `-` to disable dynamic provisioning | |
| `persistence.persistentVolumeClaim.registry.subPath` | The sub path used in the volume | |
| `persistence.persistentVolumeClaim.registry.accessMode` | The access mode of the volume | `ReadWriteOnce` |
| `persistence.persistentVolumeClaim.registry.size` | The size of the volume | `5Gi` |
| `persistence.persistentVolumeClaim.chartmuseum.existingClaim` | Use the existing PVC which must be created manually before bound, and specify the `subPath` if the PVC is shared with other components | |
| `persistence.persistentVolumeClaim.chartmuseum.storageClass` | Specify the `storageClass` used to provision the volume. Or the default StorageClass will be used(the default). Set it to `-` to disable dynamic provisioning | |
| `persistence.persistentVolumeClaim.chartmuseum.subPath` | The sub path used in the volume | |
| `persistence.persistentVolumeClaim.chartmuseum.accessMode` | The access mode of the volume | `ReadWriteOnce` |
| `persistence.persistentVolumeClaim.chartmuseum.size` | The size of the volume | `5Gi` |
| `persistence.persistentVolumeClaim.jobservice.existingClaim` | Use the existing PVC which must be created manually before bound, and specify the `subPath` if the PVC is shared with other components | |
| `persistence.persistentVolumeClaim.jobservice.storageClass` | Specify the `storageClass` used to provision the volume. Or the default StorageClass will be used(the default). Set it to `-` to disable dynamic provisioning | |
| `persistence.persistentVolumeClaim.jobservice.subPath` | The sub path used in the volume | |
| `persistence.persistentVolumeClaim.jobservice.accessMode` | The access mode of the volume | `ReadWriteOnce` |
| `persistence.persistentVolumeClaim.jobservice.size` | The size of the volume | `1Gi` |
| `persistence.persistentVolumeClaim.database.existingClaim` | Use the existing PVC which must be created manually before bound, and specify the `subPath` if the PVC is shared with other components. If external database is used, the setting will be ignored | |
| `persistence.persistentVolumeClaim.database.storageClass` | Specify the `storageClass` used to provision the volume. Or the default StorageClass will be used(the default). Set it to `-` to disable dynamic provisioning. If external database is used, the setting will be ignored | |
| `persistence.persistentVolumeClaim.database.subPath` | The sub path used in the volume. If external database is used, the setting will be ignored | |
| `persistence.persistentVolumeClaim.database.accessMode` | The access mode of the volume. If external database is used, the setting will be ignored | `ReadWriteOnce` |
| `persistence.persistentVolumeClaim.database.size` | The size of the volume. If external database is used, the setting will be ignored | `1Gi` |
| `persistence.persistentVolumeClaim.redis.existingClaim` | Use the existing PVC which must be created manually before bound, and specify the `subPath` if the PVC is shared with other components. If external Redis is used, the setting will be ignored | |
| `persistence.persistentVolumeClaim.redis.storageClass` | Specify the `storageClass` used to provision the volume. Or the default StorageClass will be used(the default). Set it to `-` to disable dynamic provisioning. If external Redis is used, the setting will be ignored | |
| `persistence.persistentVolumeClaim.redis.subPath` | The sub path used in the volume. If external Redis is used, the setting will be ignored | |
| `persistence.persistentVolumeClaim.redis.accessMode` | The access mode of the volume. If external Redis is used, the setting will be ignored | `ReadWriteOnce` |
| `persistence.persistentVolumeClaim.redis.size` | The size of the volume. If external Redis is used, the setting will be ignored | `1Gi` |
| `imageChartStorage.disableredirect` | The configuration for managing redirects from content backends. For backends which not supported it (such as using minio for `s3` storage type), please set it to `true` to disable redirects. Refer to the [guide](https://github.com/docker/distribution/blob/master/docs/configuration.md#redirect) for more information about the detail | `false` |
| `imageChartStorage.type` | The type of storage for images and charts: `filesystem`, `azure`, `gcs`, `s3`, `swift` or `oss`. The type must be `filesystem` if you want to use persistent volumes for registry and chartmuseum. Refer to the [guide](https://github.com/docker/distribution/blob/master/docs/configuration.md#storage) for more information about the detail | `filesystem` |
| **General** |
| `externalURL` | The external URL for Harbor core service | `https://core.harbor.domain` |
| `imagePullPolicy` | The image pull policy | `IfNotPresent` |
| `logLevel` | The log level | `debug` |
| `harborAdminPassword` | The initial password of Harbor admin. Change it from portal after launching Harbor | `Harbor12345` |
| `secretkey` | The key used for encryption. Must be a string of 16 chars | `not-a-secure-key` |
| **Nginx** (if expose the service via `ingress`, the Nginx will not be used) |
| `nginx.image.repository` | Image repository | `goharbor/nginx-photon` |
| `nginx.image.tag` | Image tag | `dev` |
| `nginx.replicas` | The replica count | `1` |
| `nginx.resources` | The [resources] to allocate for container | undefined |
| `nginx.nodeSelector` | Node labels for pod assignment | `{}` |
| `nginx.tolerations` | Tolerations for pod assignment | `[]` |
| `nginx.affinity` | Node/Pod affinities | `{}` |
| `nginx.podAnnotations` | Annotations to add to the nginx pod | `{}` |
| **Portal** |
| `portal.image.repository` | Repository for portal image | `goharbor/harbor-portal` |
| `portal.image.tag` | Tag for portal image | `dev` |
| `portal.replicas` | The replica count | `1` |
| `portal.resources` | The [resources] to allocate for container | undefined |
| `portal.nodeSelector` | Node labels for pod assignment | `{}` |
| `portal.tolerations` | Tolerations for pod assignment | `[]` |
| `portal.affinity` | Node/Pod affinities | `{}` |
| `portal.podAnnotations` | Annotations to add to the portal pod | `{}` |
| **Adminserver** |
| `adminserver.image.repository` | Repository for adminserver image | `goharbor/harbor-adminserver` |
| `adminserver.image.tag` | Tag for adminserver image | `dev` |
| `adminserver.replicas` | The replica count | `1` |
| `adminserver.resources` | [resources](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/) to allocate for container | undefined |
| `adminserver.nodeSelector` | Node labels for pod assignment | `{}` |
| `adminserver.tolerations` | Tolerations for pod assignment | `[]` |
| `adminserver.affinity` | Node/Pod affinities | `{}` |
| `adminserver.podAnnotations` | Annotations to add to the adminserver pod | `{}` |
| **Core** |
| `core.image.repository` | Repository for Harbor core image | `goharbor/harbor-core` |
| `core.image.tag` | Tag for Harbor core image | `dev` |
| `core.replicas` | The replica count | `1` |
| `core.resources` | The [resources] to allocate for container | undefined |
| `core.nodeSelector` | Node labels for pod assignment | `{}` |
| `core.tolerations` | Tolerations for pod assignment | `[]` |
| `core.affinity` | Node/Pod affinities | `{}` |
| `core.podAnnotations` | Annotations to add to the core pod | `{}` |
| `core.secret` | Secret is used when core server communicates with other components. If a secret key is not specified, Helm will generate one. Must be a string of 16 chars. | |
| `core.secret` | Fill the name of a kubernetes secret if you want to use your own TLS certificate and private key for token encryption/decryption. The secret must contain keys named `tls.tokenServiceRootCertBundle` and `tls.tokenServicePrivateKey` that contain the certificate and private key. They will be automatically generated if not set. | |
| **Jobservice** |
| `jobservice.image.repository` | Repository for jobservice image | `goharbor/harbor-jobservice` |
| `jobservice.image.tag` | Tag for jobservice image | `dev` |
| `jobservice.replicas` | The replica count | `1` |
| `jobservice.maxJobWorkers` | The max job workers | `10` |
| `jobservice.jobLogger` | The logger for jobs: `file`, `database` or `stdout` | `database` |
| `jobservice.resources` | The [resources] to allocate for container | undefined |
| `jobservice.nodeSelector` | Node labels for pod assignment | `{}` |
| `jobservice.tolerations` | Tolerations for pod assignment | `[]` |
| `jobservice.affinity` | Node/Pod affinities | `{}` |
| `jobservice.podAnnotations` | Annotations to add to the jobservice pod | `{}` |
| `jobservice.secret` | Secret is used when job service communicates with other components. If a secret key is not specified, Helm will generate one. Must be a string of 16 chars. | |
| **Registry** |
| `registry.registry.image.repository` | Repository for registry image | `goharbor/registry-photon` |
| `registry.registry.image.tag` | Tag for registry image |
| `registry.registry.resources` | The [resources] to allocate for container | undefined | | `dev` |
| `registry.controller.image.repository` | Repository for registry controller image | `goharbor/harbor-registryctl` |
| `registry.controller.image.tag` | Tag for registry controller image |
| `registry.controller.resources` | The [resources] to allocate for container | undefined | | `dev` |
| `registry.replicas` | The replica count | `1` |
| `registry.nodeSelector` | Node labels for pod assignment | `{}` |
| `registry.tolerations` | Tolerations for pod assignment | `[]` |
| `registry.affinity` | Node/Pod affinities | `{}` |
| `registry.podAnnotations` | Annotations to add to the registry pod | `{}` |
| `registry.secret` | Secret is used to secure the upload state from client and registry storage backend. See: https://github.com/docker/distribution/blob/master/docs/configuration.md#http. If a secret key is not specified, Helm will generate one. Must be a string of 16 chars. | |
| **Chartmuseum** |
| `chartmuseum.enabled` | Enable chartmusuem to store chart | `true` |
| `chartmuseum.image.repository` | Repository for chartmuseum image | `goharbor/chartmuseum-photon` |
| `chartmuseum.image.tag` | Tag for chartmuseum image | `dev` |
| `chartmuseum.replicas` | The replica count | `1` |
| `chartmuseum.resources` | The [resources] to allocate for container | undefined |
| `chartmuseum.nodeSelector` | Node labels for pod assignment | `{}` |
| `chartmuseum.tolerations` | Tolerations for pod assignment | `[]` |
| `chartmuseum.affinity` | Node/Pod affinities | `{}` |
| `chartmuseum.podAnnotations` | Annotations to add to the chart museum pod | `{}` |
| **Clair** |
| `clair.enabled` | Enable Clair | `true` |
| `clair.image.repository` | Repository for clair image | `goharbor/clair-photon` |
| `clair.image.tag` | Tag for clair image | `dev` |
| `clair.replicas` | The replica count | `1` |
| `clair.httpProxy` | The HTTP proxy used to update vulnerabilities database from internet | |
| `clair.httpsProxy` | The HTTPS proxy used to update vulnerabilities database from internet | |
| `clair.updatersInterval` | The interval of clair updaters, the unit is hour, set to 0 to disable the updaters | `12` |
| `clair.resources` | The [resources] to allocate for container | undefined |
| `clair.nodeSelector` | Node labels for pod assignment | `{}` |
| `clair.tolerations` | Tolerations for pod assignment | `[]` |
| `clair.affinity` | Node/Pod affinities | `{}` |
| `clair.podAnnotations` | Annotations to add to the clair pod | `{}` |
| **Notary** |
| `notary.enabled` | Enable Notary? | `true` |
| `notary.server.image.repository` | Repository for notary server image | `goharbor/notary-server-photon` |
| `notary.server.image.tag` | Tag for notary server image | `dev` |
| `notary.server.replicas` | The replica count |
| `notary.server.resources` | The [resources] to allocate for container | undefined | | `1` |
| `notary.signer.image.repository` | Repository for notary signer image | `goharbor/notary-signer-photon` |
| `notary.signer.image.tag` | Tag for notary signer image | `dev` |
| `notary.signer.replicas` | The replica count |
| `notary.signer.resources` | The [resources] to allocate for container | undefined | | `1` |
| `notary.nodeSelector` | Node labels for pod assignment | `{}` |
| `notary.tolerations` | Tolerations for pod assignment | `[]` |
| `notary.affinity` | Node/Pod affinities | `{}` |
| `notary.podAnnotations` | Annotations to add to the notary pod | `{}` |
| `notary.secretName` | Fill the name of a kubernetes secret if you want to use your own TLS certificate authority, certificate and private key for notary communications. The secret must contain keys named `tls.ca`, `tls.crt` and `tls.key` that contain the CA, certificate and private key. They will be generated if not set. | |
| **Database** |
| `database.type` | If external database is used, set it to `external` | `internal` |
| `database.internal.image.repository` | Repository for database image | `goharbor/harbor-db` |
| `database.internal.image.tag` | Tag for database image | `dev` |
| `database.internal.password` | The password for database | `changeit` |
| `database.internal.resources` | The [resources] to allocate for container | undefined |
| `database.internal.nodeSelector` | Node labels for pod assignment | `{}` |
| `database.internal.tolerations` | Tolerations for pod assignment | `[]` |
| `database.internal.affinity` | Node/Pod affinities | `{}` |
| `database.external.host` | The hostname of external database | `192.168.0.1` |
| `database.external.port` | The port of external database | `5432` |
| `database.external.username` | The username of external database | `user` |
| `database.external.password` | The password of external database | `password` |
| `database.external.coreDatabase` | The database used by core service | `registry` |
| `database.external.clairDatabase` | The database used by clair | `clair` |
| `database.external.notaryServerDatabase` | The database used by Notary server | `notary_server` |
| `database.external.notarySignerDatabase` | The database used by Notary signer | `notary_signer` |
| `database.external.sslmode` | Connection method of external database (require | prefer | disable) | `disable` |
| `database.podAnnotations` | Annotations to add to the database pod | `{}` |
| **Redis** |
| `redis.type` | If external redis is used, set it to `external` | `internal` |
| `redis.internal.image.repository` | Repository for redis image | `goharbor/redis-photon` |
| `redis.internal.image.tag` | Tag for redis image | `dev` |
| `redis.internal.resources` | The [resources] to allocate for container | undefined |
| `redis.internal.nodeSelector` | Node labels for pod assignment | `{}` |
| `redis.internal.tolerations` | Tolerations for pod assignment | `[]` |
| `redis.internal.affinity` | Node/Pod affinities | `{}` |
| `redis.external.host` | The hostname of external Redis | `192.168.0.2` |
| `redis.external.port` | The port of external Redis | `6379` |
| `redis.external.coreDatabaseIndex` | The database index for core | `0` |
| `redis.external.jobserviceDatabaseIndex` | The database index for jobservice | `1` |
| `redis.external.registryDatabaseIndex` | The database index for registry | `2` |
| `redis.external.chartmuseumDatabaseIndex` | The database index for chartmuseum | `3` |
| `redis.external.password` | The password of external Redis | |
| `redis.podAnnotations` | Annotations to add to the redis pod | `{}` |
[resources]: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/
Please wait for several minutes for Harbor deployment to complete.
{{- if .Values.globalRegistryMode -}}
Then you should be able to visit the Harbor portal at {{ .Values.externalURL }}.
{{- else -}}
Then you should be able to visit the Harbor portal at {{ .Values.externalURL }}/registry.
{{- end -}}
For more details, please visit https://github.com/goharbor/harbor.
\ No newline at end of file
{{/* vim: set filetype=mustache: */}}
{{/*
Expand the name of the chart.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
*/}}
{{- define "harbor.name" -}}
{{- default "harbor" .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
*/}}
{{- define "harbor.fullname" -}}
{{- $name := default "harbor" .Values.nameOverride -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/* Helm required labels */}}
{{- define "harbor.labels" -}}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
chart: {{ .Chart.Name }}
app: "{{ template "harbor.name" . }}"
{{- end -}}
{{/* matchLabels */}}
{{- define "harbor.matchLabels" -}}
release: {{ .Release.Name }}
app: "{{ template "harbor.name" . }}"
{{- end -}}
{{- define "harbor.autoGenCert" -}}
{{- if .Values.globalRegistryMode -}}
{{- printf "false" -}}
{{- else if and .Values.expose.tls.enabled (not .Values.expose.tls.secretName) -}}
{{- printf "true" -}}
{{- else -}}
{{- printf "false" -}}
{{- end -}}
{{- end -}}
{{- define "harbor.autoGenCertForIngress" -}}
{{- if and (eq (include "harbor.autoGenCert" .) "true") (eq .Values.expose.type "ingress") -}}
{{- printf "true" -}}
{{- else -}}
{{- printf "false" -}}
{{- end -}}
{{- end -}}
{{- define "harbor.autoGenCertForNginx" -}}
{{- if and (eq (include "harbor.autoGenCert" .) "true") (ne .Values.expose.type "ingress") -}}
{{- printf "true" -}}
{{- else -}}
{{- printf "false" -}}
{{- end -}}
{{- end -}}
{{- define "harbor.database.host" -}}
{{- if eq .Values.database.type "internal" -}}
{{- template "harbor.database" . }}
{{- else -}}
{{- .Values.database.external.host -}}
{{- end -}}
{{- end -}}
{{- define "harbor.database.port" -}}
{{- if eq .Values.database.type "internal" -}}
{{- printf "%s" "5432" -}}
{{- else -}}
{{- .Values.database.external.port -}}
{{- end -}}
{{- end -}}
{{- define "harbor.database.username" -}}
{{- if eq .Values.database.type "internal" -}}
{{- printf "%s" "postgres" -}}
{{- else -}}
{{- .Values.database.external.username -}}
{{- end -}}
{{- end -}}
{{- define "harbor.database.rawPassword" -}}
{{- if eq .Values.database.type "internal" -}}
{{- .Values.database.internal.password -}}
{{- else -}}
{{- .Values.database.external.password -}}
{{- end -}}
{{- end -}}
{{- define "harbor.database.encryptedPassword" -}}
{{- include "harbor.database.rawPassword" . | b64enc | quote -}}
{{- end -}}
{{- define "harbor.database.coreDatabase" -}}
{{- if eq .Values.database.type "internal" -}}
{{- printf "%s" "registry" -}}
{{- else -}}
{{- .Values.database.external.coreDatabase -}}
{{- end -}}
{{- end -}}
{{- define "harbor.database.clairDatabase" -}}
{{- if eq .Values.database.type "internal" -}}
{{- printf "%s" "postgres" -}}
{{- else -}}
{{- .Values.database.external.clairDatabase -}}
{{- end -}}
{{- end -}}
{{- define "harbor.database.notaryServerDatabase" -}}
{{- if eq .Values.database.type "internal" -}}
{{- printf "%s" "notaryserver" -}}
{{- else -}}
{{- .Values.database.external.notaryServerDatabase -}}
{{- end -}}
{{- end -}}
{{- define "harbor.database.notarySignerDatabase" -}}
{{- if eq .Values.database.type "internal" -}}
{{- printf "%s" "notarysigner" -}}
{{- else -}}
{{- .Values.database.external.notarySignerDatabase -}}
{{- end -}}
{{- end -}}
{{- define "harbor.database.sslmode" -}}
{{- if eq .Values.database.type "internal" -}}
{{- printf "%s" "disable" -}}
{{- else -}}
{{- .Values.database.external.sslmode -}}
{{- end -}}
{{- end -}}
{{- define "harbor.database.clair" -}}
postgres://{{ template "harbor.database.username" . }}:{{ template "harbor.database.rawPassword" . }}@{{ template "harbor.database.host" . }}:{{ template "harbor.database.port" . }}/{{ template "harbor.database.clairDatabase" . }}?sslmode={{ template "harbor.database.sslmode" . }}
{{- end -}}
{{- define "harbor.database.notaryServer" -}}
postgres://{{ template "harbor.database.username" . }}:{{ template "harbor.database.rawPassword" . }}@{{ template "harbor.database.host" . }}:{{ template "harbor.database.port" . }}/{{ template "harbor.database.notaryServerDatabase" . }}?sslmode={{ template "harbor.database.sslmode" . }}
{{- end -}}
{{- define "harbor.database.notarySigner" -}}
postgres://{{ template "harbor.database.username" . }}:{{ template "harbor.database.rawPassword" . }}@{{ template "harbor.database.host" . }}:{{ template "harbor.database.port" . }}/{{ template "harbor.database.notarySignerDatabase" . }}?sslmode={{ template "harbor.database.sslmode" . }}
{{- end -}}
{{- define "harbor.redis.host" -}}
{{- if eq .Values.redis.type "internal" -}}
{{- template "harbor.redis" . -}}
{{- else -}}
{{- .Values.redis.external.host -}}
{{- end -}}
{{- end -}}
{{- define "harbor.redis.port" -}}
{{- if eq .Values.redis.type "internal" -}}
{{- printf "%s" "6379" -}}
{{- else -}}
{{- .Values.redis.external.port -}}
{{- end -}}
{{- end -}}
{{- define "harbor.redis.coreDatabaseIndex" -}}
{{- if eq .Values.redis.type "internal" -}}
{{- printf "%s" "0" }}
{{- else -}}
{{- .Values.redis.external.coreDatabaseIndex -}}
{{- end -}}
{{- end -}}
{{- define "harbor.redis.jobserviceDatabaseIndex" -}}
{{- if eq .Values.redis.type "internal" -}}
{{- printf "%s" "1" }}
{{- else -}}
{{- .Values.redis.external.jobserviceDatabaseIndex -}}
{{- end -}}
{{- end -}}
{{- define "harbor.redis.registryDatabaseIndex" -}}
{{- if eq .Values.redis.type "internal" -}}
{{- printf "%s" "2" }}
{{- else -}}
{{- .Values.redis.external.registryDatabaseIndex -}}
{{- end -}}
{{- end -}}
{{- define "harbor.redis.chartmuseumDatabaseIndex" -}}
{{- if eq .Values.redis.type "internal" -}}
{{- printf "%s" "3" }}
{{- else -}}
{{- .Values.redis.external.chartmuseumDatabaseIndex -}}
{{- end -}}
{{- end -}}
{{- define "harbor.redis.rawPassword" -}}
{{- if and (eq .Values.redis.type "external") .Values.redis.external.password -}}
{{- .Values.redis.external.password -}}
{{- end -}}
{{- end -}}
{{/*the username redis is used for a placeholder as no username needed in redis*/}}
{{- define "harbor.redisForJobservice" -}}
{{- if (include "harbor.redis.rawPassword" . ) -}}
{{- printf "redis://redis:%s@%s:%s/%s" (include "harbor.redis.rawPassword" . ) (include "harbor.redis.host" . ) (include "harbor.redis.port" . ) (include "harbor.redis.jobserviceDatabaseIndex" . ) }}
{{- else }}
{{- template "harbor.redis.host" . }}:{{ template "harbor.redis.port" . }}/{{ template "harbor.redis.jobserviceDatabaseIndex" . }}
{{- end -}}
{{- end -}}
{{/*the username redis is used for a placeholder as no username needed in redis*/}}
{{- define "harbor.redisForGC" -}}
{{- if (include "harbor.redis.rawPassword" . ) -}}
{{- printf "redis://redis:%s@%s:%s/%s" (include "harbor.redis.rawPassword" . ) (include "harbor.redis.host" . ) (include "harbor.redis.port" . ) (include "harbor.redis.registryDatabaseIndex" . ) }}
{{- else }}
{{- printf "redis://%s:%s/%s" (include "harbor.redis.host" . ) (include "harbor.redis.port" . ) (include "harbor.redis.registryDatabaseIndex" . ) -}}
{{- end -}}
{{- end -}}
{{/*
host:port,pool_size,password
100 is the default value of pool size
*/}}
{{- define "harbor.redisForCore" -}}
{{- template "harbor.redis.host" . }}:{{ template "harbor.redis.port" . }},100,{{ template "harbor.redis.rawPassword" . }}
{{- end -}}
{{- define "harbor.portal" -}}
{{- printf "%s-portal" (include "harbor.fullname" .) -}}
{{- end -}}
{{- define "harbor.core" -}}
{{- printf "%s-core" (include "harbor.fullname" .) -}}
{{- end -}}
{{- define "harbor.redis" -}}
{{- printf "%s-redis" (include "harbor.fullname" .) -}}
{{- end -}}
{{- define "harbor.adminserver" -}}
{{- printf "%s-adminserver" (include "harbor.fullname" .) -}}
{{- end -}}
{{- define "harbor.jobservice" -}}
{{- printf "%s-jobservice" (include "harbor.fullname" .) -}}
{{- end -}}
{{- define "harbor.registry" -}}
{{- printf "%s-registry" (include "harbor.fullname" .) -}}
{{- end -}}
{{- define "harbor.chartmuseum" -}}
{{- printf "%s-chartmuseum" (include "harbor.fullname" .) -}}
{{- end -}}
{{- define "harbor.database" -}}
{{- printf "%s-database" (include "harbor.fullname" .) -}}
{{- end -}}
{{- define "harbor.clair" -}}
{{- printf "%s-clair" (include "harbor.fullname" .) -}}
{{- end -}}
{{- define "harbor.notary-server" -}}
{{- printf "%s-notary-server" (include "harbor.fullname" .) -}}
{{- end -}}
{{- define "harbor.notary-signer" -}}
{{- printf "%s-notary-signer" (include "harbor.fullname" .) -}}
{{- end -}}
{{- define "harbor.proxy" -}}
{{- printf "%s-proxy" (include "harbor.fullname" .) -}}
{{- end -}}
{{- define "harbor.nginx" -}}
{{- printf "%s-nginx" (include "harbor.fullname" .) -}}
{{- end -}}
{{- define "harbor.ingress.core" -}}
{{- printf "%s-ingress-core" (include "harbor.fullname" .) -}}
{{- end -}}
{{- define "harbor.ingress.notary" -}}
{{- printf "%s-ingress-notary" (include "harbor.fullname" .) -}}
{{- end -}}
{{- define "harbor.externalURL" -}}
{{- if eq .Values.expose.type "ingress" }}
{{- printf "https://%s" .Values.expose.ingress.host -}}
{{- else if eq .Values.expose.type "clusterIP" }}
{{- printf "https://%s" .Values.expose.clusterIP.name -}}
{{- else }}
{{- .Values.externalURL -}}
{{- end }}
{{- end -}}
{{/*
The commmon name used to generate the certificate, it's necessary
when the type is "clusterIP" or "nodePort" and "secretName" is null
*/}}
{{- define "harbor.tlsCommonName" -}}
{{- $trimURL := (include "harbor.externalURL" .) | trimPrefix "https://" | trimPrefix "http://" -}}
{{ regexReplaceAll ":.*$" $trimURL "${1}" }}
{{- end -}}
{{- define "system_default_registry" -}}
{{- if .Values.global.systemDefaultRegistry -}}
{{- printf "%s/" .Values.global.systemDefaultRegistry -}}
{{- else -}}
{{- "" -}}
{{- end -}}
{{- end -}}
apiVersion: v1
kind: ConfigMap
metadata:
name: "{{ template "harbor.adminserver" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
component: adminserver
data:
DATABASE_TYPE: "postgresql"
POSTGRESQL_HOST: "{{ template "harbor.database.host" . }}"
POSTGRESQL_PORT: "{{ template "harbor.database.port" . }}"
POSTGRESQL_USERNAME: "{{ template "harbor.database.username" . }}"
POSTGRESQL_DATABASE: "{{ template "harbor.database.coreDatabase" . }}"
POSTGRESQL_SSLMODE: "{{ template "harbor.database.sslmode" . }}"
EXT_ENDPOINT: "{{ template "harbor.externalURL" . }}"
CORE_URL: "http://{{ template "harbor.core" . }}"
JOBSERVICE_URL: "http://{{ template "harbor.fullname" . }}-jobservice"
REGISTRY_URL: "http://{{ template "harbor.registry" . }}:5000"
TOKEN_SERVICE_URL: "http://{{ template "harbor.core" . }}/service/token"
WITH_NOTARY: "{{ .Values.notary.enabled }}"
NOTARY_URL: "http://{{ template "harbor.notary-server" . }}:4443"
LOG_LEVEL: "{{ .Values.logLevel }}"
IMAGE_STORE_PATH: "/" # This is a temporary hack.
CFG_EXPIRATION: "5"
ADMIRAL_URL: "NA"
RESET: "false"
WITH_CLAIR: "{{ .Values.clair.enabled }}"
CLAIR_DB_HOST: "{{ template "harbor.database.host" . }}"
CLAIR_DB_PORT: "{{ template "harbor.database.port" . }}"
CLAIR_DB_USERNAME: "{{ template "harbor.database.username" . }}"
CLAIR_DB: "{{ template "harbor.database.clairDatabase" . }}"
CLAIR_URL: "http://{{ template "harbor.fullname" . }}-clair:6060"
CLAIR_DB_SSLMODE: "{{ template "harbor.database.sslmode" . }}"
REGISTRY_STORAGE_PROVIDER_NAME: "{{ .Values.imageChartStorage.type }}"
WITH_CHARTMUSEUM: "{{ .Values.chartmuseum.enabled }}"
CHART_REPOSITORY_URL: "http://{{ template "harbor.chartmuseum" . }}"
# The following properties are for Harbor configurations
AUTH_MODE: "db_auth"
SELF_REGISTRATION: "on"
PROJECT_CREATION_RESTRICTION: "everyone"
TOKEN_EXPIRATION: "30"
EMAIL_HOST: "smtp.mydomain.com"
EMAIL_FROM: "admin <sample_admin@mydomain.com>"
EMAIL_PORT: "25"
\ No newline at end of file
apiVersion: apps/v1
kind: Deployment
metadata:
name: "{{ template "harbor.adminserver" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
component: adminserver
spec:
replicas: {{ .Values.adminserver.replicas }}
selector:
matchLabels:
{{ include "harbor.matchLabels" . | indent 6 }}
component: adminserver
template:
metadata:
labels:
{{ include "harbor.labels" . | indent 8 }}
component: adminserver
annotations:
checksum/configmap: {{ include (print $.Template.BasePath "/adminserver/adminserver-cm.yaml") . | sha256sum }}
checksum/secret: {{ include (print $.Template.BasePath "/adminserver/adminserver-secrets.yaml") . | sha256sum }}
checksum/secret-core: {{ include (print $.Template.BasePath "/core/core-secret.yaml") . | sha256sum }}
checksum/secret-jobservice: {{ include (print $.Template.BasePath "/jobservice/jobservice-secrets.yaml") . | sha256sum }}
{{- if .Values.adminserver.podAnnotations }}
{{ toYaml .Values.adminserver.podAnnotations | indent 8 }}
{{- end }}
spec:
containers:
- name: adminserver
image: {{ template "system_default_registry" . }}{{ .Values.adminserver.image.repository }}:{{ .Values.adminserver.image.tag }}
imagePullPolicy: "{{ .Values.imagePullPolicy }}"
livenessProbe:
httpGet:
path: /api/ping
port: 8080
initialDelaySeconds: 1
periodSeconds: 10
readinessProbe:
httpGet:
path: /api/ping
port: 8080
initialDelaySeconds: 1
periodSeconds: 10
resources:
{{ toYaml .Values.adminserver.resources | indent 10 }}
envFrom:
- configMapRef:
name: "{{ template "harbor.adminserver" . }}"
- secretRef:
name: "{{ template "harbor.adminserver" . }}"
env:
- name: PORT
value: "8080"
- name: JSON_CFG_STORE_PATH
value: /etc/adminserver/config/config.json
- name: KEY_PATH
value: /etc/adminserver/key
- name: CORE_SECRET
valueFrom:
secretKeyRef:
name: "{{ template "harbor.core" . }}"
key: secret
- name: JOBSERVICE_SECRET
valueFrom:
secretKeyRef:
name: "{{ template "harbor.jobservice" . }}"
key: secret
ports:
- containerPort: 8080
volumeMounts:
- name: adminserver-key
mountPath: /etc/adminserver/key
subPath: key
volumes:
- name: adminserver-key
secret:
secretName: "{{ template "harbor.adminserver" . }}"
items:
- key: secretKey
path: key
{{- with .Values.adminserver.nodeSelector }}
nodeSelector:
beta.kubernetes.io/os: linux
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.adminserver.affinity }}
affinity:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.adminserver.tolerations }}
tolerations:
{{ toYaml . | indent 8 }}
{{- end }}
apiVersion: v1
kind: Secret
metadata:
name: "{{ template "harbor.adminserver" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
component: adminserver
type: Opaque
data:
secretKey: {{ .Values.secretKey | b64enc | quote }}
HARBOR_ADMIN_PASSWORD: {{ .Values.harborAdminPassword | b64enc | quote }}
POSTGRESQL_PASSWORD: {{ template "harbor.database.encryptedPassword" . }}
{{ if .Values.clair.enabled }}
CLAIR_DB_PASSWORD: {{ template "harbor.database.encryptedPassword" . }}
{{ end }}
apiVersion: v1
kind: Service
metadata:
name: {{ template "harbor.adminserver" . }}
labels:
{{ include "harbor.labels" . | indent 4 }}
spec:
ports:
- port: 80
targetPort: 8080
selector:
{{ include "harbor.matchLabels" . | indent 4 }}
component: adminserver
{{- if .Values.chartmuseum.enabled }}
apiVersion: v1
kind: ConfigMap
metadata:
name: "{{ template "harbor.chartmuseum" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
data:
PORT: "9999"
CACHE: "redis"
CACHE_REDIS_ADDR: "{{ template "harbor.redis.host" . }}:{{ template "harbor.redis.port" . }}"
CACHE_REDIS_DB: "{{ template "harbor.redis.chartmuseumDatabaseIndex" . }}"
BASIC_AUTH_USER: "chart_controller"
DEPTH: "1"
{{- if eq .Values.logLevel "debug" }}
DEBUG: "true"
{{- else }}
DEBUG: "false"
{{- end }}
LOG_JSON: "true"
DISABLE_METRICS: "false"
DISABLE_API: "false"
DISABLE_STATEFILES: "false"
ALLOW_OVERWRITE: "true"
#CHART_URL: {{ template "harbor.externalURL" . }}/chartrepo
AUTH_ANONYMOUS_GET: "false"
TLS_CERT:
TLS_KEY:
CONTEXT_PATH:
INDEX_LIMIT: "0"
MAX_STORAGE_OBJECTS: "0"
MAX_UPLOAD_SIZE: "20971520"
CHART_POST_FORM_FIELD_NAME: "chart"
PROV_POST_FORM_FIELD_NAME: "prov"
{{- $storage := .Values.imageChartStorage }}
{{- $storageType := $storage.type }}
{{- if eq $storageType "filesystem" }}
STORAGE: "local"
STORAGE_LOCAL_ROOTDIR: "/chart_storage"
{{- else if eq $storageType "azure" }}
STORAGE: "microsoft"
STORAGE_MICROSOFT_CONTAINER: {{ $storage.azure.container }}
AZURE_STORAGE_ACCOUNT: {{ $storage.azure.accountname }}
STORAGE_MICROSOFT_PREFIX: "/azure/harbor/charts"
{{- else if eq $storageType "gcs" }}
STORAGE: "google"
STORAGE_GOOGLE_BUCKET: {{ $storage.gcs.bucket }}
GOOGLE_APPLICATION_CREDENTIALS: /etc/chartmuseum/gcs-key.json
{{- if $storage.gcs.rootdirectory }}
STORAGE_GOOGLE_PREFIX: {{ $storage.gcs.rootdirectory }}
{{- end }}
{{- else if eq $storageType "s3" }}
STORAGE: "amazon"
STORAGE_AMAZON_BUCKET: {{ $storage.s3.bucket }}
{{- if $storage.s3.rootdirectory }}
STORAGE_AMAZON_PREFIX: {{ $storage.s3.rootdirectory }}
{{- end }}
STORAGE_AMAZON_REGION: {{ $storage.s3.region }}
{{- if $storage.s3.regionendpoint }}
STORAGE_AMAZON_ENDPOINT: {{ $storage.s3.regionendpoint }}
{{- end }}
{{- if $storage.s3.accesskey }}
AWS_ACCESS_KEY_ID: {{ $storage.s3.accesskey }}
{{- end }}
{{- else if eq $storageType "swift" }}
STORAGE: "openstack"
STORAGE_OPENSTACK_CONTAINER: {{ $storage.swift.container }}
{{- if $storage.swift.secretkey }}
STORAGE_OPENSTACK_PREFIX: {{ $storage.swift.prefix }}
{{- end }}
{{- if $storage.swift.secretkey }}
STORAGE_OPENSTACK_REGION: {{ $storage.swift.region }}
{{- end }}
OS_AUTH_URL: {{ $storage.swift.authurl }}
OS_USERNAME: {{ $storage.swift.username }}
{{- if $storage.swift.secretkey }}
OS_PROJECT_ID: {{ $storage.swift.tenantid }}
{{- end }}
{{- if $storage.swift.secretkey }}
OS_PROJECT_NAME: {{ $storage.swift.tenant }}
{{- end }}
{{- if $storage.swift.secretkey }}
OS_DOMAIN_ID: {{ $storage.swift.domainid }}
{{- end }}
{{- if $storage.swift.secretkey }}
OS_DOMAIN_NAME: {{ $storage.swift.domain }}
{{- end }}
{{- else if eq $storageType "oss" }}
STORAGE: "alibaba"
STORAGE_ALIBABA_BUCKET: {{ $storage.oss.bucket }}
{{- if $storage.oss.secretkey }}
STORAGE_ALIBABA_PREFIX: {{ $storage.oss.rootdirectory }}
{{- end }}
{{- if $storage.oss.secretkey }}
STORAGE_ALIBABA_ENDPOINT: {{ $storage.oss.endpoint }}
{{- end }}
ALIBABA_CLOUD_ACCESS_KEY_ID: {{ $storage.oss.accesskeyid }}
{{- end }}
{{- end }}
\ No newline at end of file
{{- if .Values.chartmuseum.enabled }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: "{{ template "harbor.chartmuseum" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
component: chartmuseum
spec:
replicas: {{ .Values.chartmuseum.replicas }}
selector:
matchLabels:
{{ include "harbor.matchLabels" . | indent 6 }}
component: chartmuseum
template:
metadata:
labels:
{{ include "harbor.labels" . | indent 8 }}
component: chartmuseum
annotations:
checksum/configmap: {{ include (print $.Template.BasePath "/chartmuseum/chartmuseum-cm.yaml") . | sha256sum }}
checksum/secret: {{ include (print $.Template.BasePath "/chartmuseum/chartmuseum-secret.yaml") . | sha256sum }}
checksum/secret-core: {{ include (print $.Template.BasePath "/core/core-secret.yaml") . | sha256sum }}
{{- if .Values.chartmuseum.podAnnotations }}
{{ toYaml .Values.chartmuseum.podAnnotations | indent 8 }}
{{- end }}
spec:
containers:
- name: chartmuseum
image: {{ template "system_default_registry" . }}{{ .Values.chartmuseum.image.repository }}:{{ .Values.chartmuseum.image.tag }}
imagePullPolicy: {{ .Values.imagePullPolicy }}
livenessProbe:
httpGet:
path: /health
port: 9999
initialDelaySeconds: 1
periodSeconds: 10
readinessProbe:
httpGet:
path: /health
port: 9999
initialDelaySeconds: 1
periodSeconds: 10
{{- if .Values.chartmuseum.resources }}
resources:
{{ toYaml .Values.chartmuseum.resources | indent 10 }}
{{- end }}
envFrom:
- configMapRef:
name: "{{ template "harbor.chartmuseum" . }}"
- secretRef:
name: "{{ template "harbor.chartmuseum" . }}"
env:
- name: BASIC_AUTH_PASS
valueFrom:
secretKeyRef:
name: {{ template "harbor.core" . }}
key: secret
ports:
- containerPort: 9999
volumeMounts:
- name: chartmuseum-data
mountPath: /chart_storage
subPath: {{ .Values.persistence.persistentVolumeClaim.chartmuseum.subPath }}
{{- if and .Values.persistence.enabled (eq .Values.imageChartStorage.type "gcs") }}
- name: gcs-key
mountPath: /etc/chartmuseum/gcs-key.json
subPath: gcs-key.json
{{- end }}
volumes:
- name: chartmuseum-data
{{- if and .Values.persistence.enabled (eq .Values.imageChartStorage.type "filesystem") }}
persistentVolumeClaim:
claimName: {{ .Values.persistence.persistentVolumeClaim.chartmuseum.existingClaim | default (include "harbor.chartmuseum" .) }}
{{- else }}
emptyDir: {}
{{- end }}
{{- if and .Values.persistence.enabled (eq .Values.imageChartStorage.type "gcs") }}
- name: gcs-key
secret:
secretName: {{ template "harbor.registry" . }}
items:
- key: GCS_KEY_DATA
path: gcs-key.json
{{- end }}
{{- with .Values.chartmuseum.nodeSelector }}
nodeSelector:
beta.kubernetes.io/os: linux
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.chartmuseum.affinity }}
affinity:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.chartmuseum.tolerations }}
tolerations:
{{ toYaml . | indent 8 }}
{{- end }}
{{- end }}
{{- $persistence := .Values.persistence -}}
{{- if and .Values.chartmuseum.enabled $persistence.enabled }}
{{- $chartmuseum := $persistence.persistentVolumeClaim.chartmuseum -}}
{{- if and (not $chartmuseum.existingClaim) (eq $persistence.imageChartStorage.type "filesystem") }}
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: {{ template "harbor.chartmuseum" . }}
{{- if eq $persistence.resourcePolicy "keep" }}
annotations:
helm.sh/resource-policy: keep
{{- end }}
labels:
{{ include "harbor.labels" . | indent 4 }}
component: chartmuseum
spec:
accessModes:
- {{ $chartmuseum.accessMode }}
resources:
requests:
storage: {{ $chartmuseum.size }}
{{- if $chartmuseum.storageClass }}
{{- if eq "-" $chartmuseum.storageClass }}
storageClassName: ""
{{- else }}
storageClassName: {{ $chartmuseum.storageClass }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
{{- if .Values.chartmuseum.enabled }}
apiVersion: v1
kind: Secret
metadata:
name: "{{ template "harbor.chartmuseum" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
type: Opaque
data:
CACHE_REDIS_PASSWORD: {{ include "harbor.redis.rawPassword" . | b64enc | quote }}
{{- $storage := .Values.imageChartStorage }}
{{- $storageType := $storage.type }}
{{- if eq $storageType "azure" }}
AZURE_STORAGE_ACCESS_KEY: {{ $storage.azure.accountkey | b64enc | quote }}
{{- else if eq $storageType "gcs" }}
# TODO support the keyfile of gcs
{{- else if eq $storageType "s3" }}
{{- if $storage.s3.secretkey }}
AWS_SECRET_ACCESS_KEY: {{ $storage.s3.secretkey | b64enc | quote }}
{{- end }}
{{- else if eq $storageType "swift" }}
OS_PASSWORD: {{ $storage.swift.password | b64enc | quote }}
{{- else if eq $storageType "oss" }}
ALIBABA_CLOUD_ACCESS_KEY_SECRET: {{ $storage.oss.accesskeysecret | b64enc | quote }}
{{- end }}
{{- end }}
\ No newline at end of file
{{- if .Values.chartmuseum.enabled }}
apiVersion: v1
kind: Service
metadata:
name: "{{ template "harbor.chartmuseum" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
spec:
ports:
- port: 80
targetPort: 9999
selector:
{{ include "harbor.matchLabels" . | indent 4 }}
component: chartmuseum
{{- end }}
\ No newline at end of file
{{ if .Values.clair.enabled }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ template "harbor.clair" . }}
labels:
{{ include "harbor.labels" . | indent 4 }}
component: clair
data:
config.yaml: |
clair:
database:
type: pgsql
options:
source: "{{ template "harbor.database.clair" . }}"
# Number of elements kept in the cache
# Values unlikely to change (e.g. namespaces) are cached in order to save prevent needless roundtrips to the database.
cachesize: 16384
api:
# API server port
port: 6060
healthport: 6061
# Deadline before an API request will respond with a 503
timeout: 300s
updater:
interval: {{ .Values.clair.updatersInterval }}h
notifier:
attempts: 3
renotifyinterval: 2h
http:
endpoint: "http://{{ template "harbor.core" . }}/service/notifications/clair"
{{ end }}
{{ if .Values.clair.enabled }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ template "harbor.clair" . }}
labels:
{{ include "harbor.labels" . | indent 4 }}
component: clair
spec:
replicas: {{ .Values.clair.replicas }}
selector:
matchLabels:
{{ include "harbor.matchLabels" . | indent 6 }}
component: clair
template:
metadata:
labels:
{{ include "harbor.labels" . | indent 8 }}
component: clair
annotations:
checksum/configmap: {{ include (print $.Template.BasePath "/clair/clair-cm.yaml") . | sha256sum }}
{{- if .Values.clair.podAnnotations }}
{{ toYaml .Values.clair.podAnnotations | indent 8 }}
{{- end }}
spec:
containers:
- name: clair
image: {{ template "system_default_registry" . }}{{ .Values.clair.image.repository }}:{{ .Values.clair.image.tag }}
imagePullPolicy: {{ .Values.imagePullPolicy }}
livenessProbe:
httpGet:
path: /health
port: 6061
initialDelaySeconds: 50
periodSeconds: 20
readinessProbe:
httpGet:
path: /health
port: 6061
initialDelaySeconds: 30
periodSeconds: 10
args: ["-log-level", "{{ .Values.logLevel }}"]
env:
{{- if .Values.clair.httpProxy }}
- name: HTTP_PROXY
value: {{ .Values.clair.httpProxy }}
{{- end }}
{{- if .Values.clair.httpsProxy }}
- name: HTTPS_PROXY
value: {{ .Values.clair.httpsProxy }}
{{- end }}
- name: NO_PROXY
value: "{{ template "harbor.registry" . }},{{ template "harbor.core" . }}"
{{- if .Values.clair.resources }}
resources:
{{ toYaml .Values.clair.resources | indent 10 }}
{{- end }}
ports:
- containerPort: 6060
volumeMounts:
- name: clair-config
mountPath: /etc/clair/config.yaml
subPath: config.yaml
volumes:
- name: clair-config
configMap:
name: "{{ template "harbor.clair" . }}"
items:
- key: config.yaml
path: config.yaml
{{- with .Values.clair.nodeSelector }}
nodeSelector:
beta.kubernetes.io/os: linux
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.clair.affinity }}
affinity:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.clair.tolerations }}
tolerations:
{{ toYaml . | indent 8 }}
{{- end }}
{{ end }}
{{ if .Values.clair.enabled }}
apiVersion: v1
kind: Service
metadata:
name: "{{ template "harbor.clair" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
spec:
ports:
- name: clair
port: 6060
- name: health
port: 6061
selector:
{{ include "harbor.matchLabels" . | indent 4 }}
component: clair
{{ end }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ template "harbor.core" . }}
labels:
{{ include "harbor.labels" . | indent 4 }}
data:
app.conf: |+
appname = Harbor
runmode = prod
enablegzip = true
[prod]
httpport = 8080
_REDIS_URL: "{{ template "harbor.redisForCore" . }}"
_REDIS_URL_REG: "{{ template "harbor.redisForGC" . }}"
LOG_LEVEL: "{{ .Values.logLevel }}"
CONFIG_PATH: "/etc/core/app.conf"
SYNC_REGISTRY: "false"
ADMINSERVER_URL: "http://{{ template "harbor.adminserver" . }}"
CHART_CACHE_DRIVER: "redis"
CORE_URL: "http://{{ template "harbor.core" . }}"
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ template "harbor.core" . }}
labels:
{{ include "harbor.labels" . | indent 4 }}
component: core
spec:
replicas: {{ .Values.core.replicas }}
selector:
matchLabels:
{{ include "harbor.matchLabels" . | indent 6 }}
component: core
template:
metadata:
labels:
{{ include "harbor.matchLabels" . | indent 8 }}
component: core
annotations:
checksum/configmap: {{ include (print $.Template.BasePath "/core/core-cm.yaml") . | sha256sum }}
checksum/secret: {{ include (print $.Template.BasePath "/core/core-secret.yaml") . | sha256sum }}
checksum/secret-jobservice: {{ include (print $.Template.BasePath "/jobservice/jobservice-secrets.yaml") . | sha256sum }}
{{- if .Values.core.podAnnotations }}
{{ toYaml .Values.core.podAnnotations | indent 8 }}
{{- end }}
spec:
containers:
- name: core
image: {{ template "system_default_registry" . }}{{ .Values.core.image.repository }}:{{ .Values.core.image.tag }}
imagePullPolicy: {{ .Values.imagePullPolicy }}
livenessProbe:
httpGet:
path: /api/ping
port: 8080
initialDelaySeconds: 20
periodSeconds: 10
readinessProbe:
httpGet:
path: /api/ping
port: 8080
initialDelaySeconds: 20
periodSeconds: 10
envFrom:
- configMapRef:
name: "{{ template "harbor.core" . }}"
- secretRef:
name: "{{ template "harbor.core" . }}"
env:
- name: CORE_SECRET
valueFrom:
secretKeyRef:
name: {{ template "harbor.core" . }}
key: secret
- name: JOBSERVICE_SECRET
valueFrom:
secretKeyRef:
name: "{{ template "harbor.jobservice" . }}"
key: secret
ports:
- containerPort: 8080
volumeMounts:
- name: config
mountPath: /etc/core/app.conf
subPath: app.conf
- name: secret-key
mountPath: /etc/core/key
subPath: key
- name: token-service-private-key
mountPath: /etc/core/private_key.pem
subPath: tokenServicePrivateKey
{{- if eq (include "harbor.autoGenCert" .) "true" }}
- name: ca-download
mountPath: /etc/core/ca/ca.crt
subPath: ca.crt
{{- end }}
- name: psc
mountPath: /etc/core/token
{{- if .Values.core.resources }}
resources:
{{ toYaml .Values.core.resources | indent 10 }}
{{- end }}
volumes:
- name: config
configMap:
name: {{ template "harbor.core" . }}
- name: secret-key
secret:
secretName: {{ template "harbor.core" . }}
items:
- key: secretKey
path: key
- name: token-service-private-key
secret:
{{- if .Values.core.secretName }}
secretName: {{ .Values.core.secretName }}
{{- else }}
secretName: {{ template "harbor.core" . }}
{{- end }}
- name: ca-download
secret:
{{- if .Values.globalRegistryMode }}
secretName: "tls-rancher"
items:
- key: tls.crt
path: ca.crt
{{- else if eq (include "harbor.autoGenCert" .) "true" }}
secretName: {{ template "harbor.ingress.core" . }}
items:
- key: ca.crt
path: ca.crt
{{- else }}
secretName: {{ template "harbor.nginx" . }}
items:
- key: ca.crt
path: ca.crt
{{- end }}
- name: psc
emptyDir: {}
{{- with .Values.core.nodeSelector }}
nodeSelector:
beta.kubernetes.io/os: linux
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.core.affinity }}
affinity:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.core.tolerations }}
tolerations:
{{ toYaml . | indent 8 }}
{{- end }}
{{- $cert := genSelfSignedCert "harbor" nil nil 365 }}
apiVersion: v1
kind: Secret
metadata:
name: {{ template "harbor.core" . }}
labels:
{{ include "harbor.labels" . | indent 4 }}
type: Opaque
data:
secretKey: {{ .Values.secretKey | b64enc | quote }}
secret: {{ .Values.core.secret | default (randAlphaNum 16) | b64enc | quote }}
{{- if not .Values.core.secretName }}
tokenServiceRootCertBundle: {{ $cert.Cert | b64enc | quote }}
tokenServicePrivateKey: {{ $cert.Key | b64enc | quote }}
{{- end }}
HARBOR_ADMIN_PASSWORD: {{ .Values.harborAdminPassword | b64enc | quote }}
POSTGRESQL_PASSWORD: {{ template "harbor.database.encryptedPassword" . }}
{{ if .Values.clair.enabled }}
CLAIR_DB_PASSWORD: {{ template "harbor.database.encryptedPassword" . }}
{{ end }}
apiVersion: v1
kind: Service
metadata:
name: {{ template "harbor.core" . }}
labels:
{{ include "harbor.labels" . | indent 4 }}
spec:
{{- if (eq .Values.expose.ingress.controller "gce") }}
type: NodePort
{{- end }}
ports:
- port: 80
targetPort: 8080
selector:
{{ include "harbor.matchLabels" . | indent 4 }}
component: core
{{- if eq .Values.database.type "internal" -}}
apiVersion: v1
kind: Secret
metadata:
name: "{{ template "harbor.database" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
type: Opaque
data:
POSTGRES_PASSWORD: {{ template "harbor.database.encryptedPassword" . }}
{{- end -}}
{{- if eq .Values.database.type "internal" -}}
{{- $database := .Values.persistence.persistentVolumeClaim.database -}}
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: "{{ template "harbor.database" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
component: database
spec:
replicas: 1
serviceName: "{{ template "harbor.database" . }}"
selector:
matchLabels:
{{ include "harbor.matchLabels" . | indent 6 }}
component: database
template:
metadata:
labels:
{{ include "harbor.labels" . | indent 8 }}
component: database
annotations:
checksum/secret: {{ include (print $.Template.BasePath "/database/database-secret.yaml") . | sha256sum }}
{{- if .Values.database.podAnnotations }}
{{ toYaml .Values.database.podAnnotations | indent 8 }}
{{- end }}
spec:
initContainers:
- name: "remove-lost-found"
image: {{ template "system_default_registry" . }}{{ .Values.database.internal.image.repository }}:{{ .Values.database.internal.image.tag }}
imagePullPolicy: {{ .Values.imagePullPolicy }}
command: ["rm", "-Rf", "/var/lib/postgresql/data/lost+found"]
volumeMounts:
- name: database-data
mountPath: /var/lib/postgresql/data
containers:
- name: database
image: {{ template "system_default_registry" . }}{{ .Values.database.internal.image.repository }}:{{ .Values.database.internal.image.tag }}
imagePullPolicy: {{ .Values.imagePullPolicy }}
livenessProbe:
exec:
command:
- /docker-healthcheck.sh
initialDelaySeconds: 1
periodSeconds: 10
readinessProbe:
exec:
command:
- /docker-healthcheck.sh
initialDelaySeconds: 1
periodSeconds: 10
{{- if .Values.database.internal.resources }}
resources:
{{ toYaml .Values.database.internal.resources | indent 10 }}
{{- end }}
envFrom:
- secretRef:
name: "{{ template "harbor.database" . }}"
volumeMounts:
- name: database-data
mountPath: /var/lib/postgresql/data
subPath: {{ $database.subPath }}
{{- if not .Values.persistence.enabled }}
volumes:
- name: "database-data"
emptyDir: {}
{{- else if $database.existingClaim }}
volumes:
- name: "database-data"
persistentVolumeClaim:
claimName: {{ $database.existingClaim }}
{{- end -}}
{{- with .Values.database.internal.nodeSelector }}
nodeSelector:
beta.kubernetes.io/os: linux
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.database.internal.affinity }}
affinity:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.database.internal.tolerations }}
tolerations:
{{ toYaml . | indent 8 }}
{{- end }}
{{- if and .Values.persistence.enabled (not $database.existingClaim) }}
volumeClaimTemplates:
- metadata:
name: "database-data"
labels:
{{ include "harbor.labels" . | indent 8 }}
spec:
accessModes: [{{ $database.accessMode | quote }}]
{{- if $database.storageClass }}
{{- if (eq "-" $database.storageClass) }}
storageClassName: ""
{{- else }}
storageClassName: "{{ $database.storageClass }}"
{{- end }}
{{- end }}
resources:
requests:
storage: {{ $database.size | quote }}
{{- end -}}
{{- end -}}
{{- if eq .Values.database.type "internal" -}}
apiVersion: v1
kind: Service
metadata:
name: "{{ template "harbor.database" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
spec:
ports:
- port: 5432
selector:
{{ include "harbor.matchLabels" . | indent 4 }}
component: database
{{- end -}}
\ No newline at end of file
{{- if eq .Values.expose.type "ingress" }}
{{- $ingress := .Values.expose.ingress -}}
{{- $tls := .Values.expose.tls -}}
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: "{{ template "harbor.ingress.core" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
annotations:
{{ toYaml $ingress.annotations | indent 4 }}
spec:
tls:
- hosts:
- {{ $ingress.host }}
{{- if .Values.globalRegistryMode }}
secretName: "tls-rancher-ingress"
{{- else if $tls.secretName }}
secretName: {{ $tls.secretName }}
{{- else }}
secretName: "{{ template "harbor.ingress.core" . }}"
{{- end }}
{{- if .Values.globalRegistryMode }}
rules:
- http:
paths:
- path: /v2/
backend:
serviceName: {{ template "harbor.core" . }}
servicePort: 80
- path: /api/projects
backend:
serviceName: {{ template "harbor.core" . }}
servicePort: 80
- path: /registry/
backend:
serviceName: {{ template "harbor.proxy" . }}
servicePort: 80
{{- if $ingress.host }}
host: {{ $ingress.host }}
{{- end }}
{{- else if eq .Values.expose.ingress.controller "gce" }}
rules:
- http:
paths:
- path: /*
backend:
serviceName: {{ template "harbor.portal" . }}
servicePort: 80
- path: /api/*
backend:
serviceName: {{ template "harbor.core" . }}
servicePort: 80
- path: /service/*
backend:
serviceName: {{ template "harbor.core" . }}
servicePort: 80
- path: /v2/*
backend:
serviceName: {{ template "harbor.core" . }}
servicePort: 80
- path: /chartrepo/*
backend:
serviceName: {{ template "harbor.core" . }}
servicePort: 80
- path: /c/*
backend:
serviceName: {{ template "harbor.core" . }}
servicePort: 80
{{- if $ingress.host }}
host: {{ $ingress.host }}
{{- end }}
{{- else }}
rules:
- http:
paths:
- path: /
backend:
serviceName: {{ template "harbor.portal" . }}
servicePort: 80
- path: /api/
backend:
serviceName: {{ template "harbor.core" . }}
servicePort: 80
- path: /service/
backend:
serviceName: {{ template "harbor.core" . }}
servicePort: 80
- path: /v2/
backend:
serviceName: {{ template "harbor.core" . }}
servicePort: 80
- path: /chartrepo/
backend:
serviceName: {{ template "harbor.core" . }}
servicePort: 80
- path: /c/
backend:
serviceName: {{ template "harbor.core" . }}
servicePort: 80
{{- if $ingress.host }}
host: {{ $ingress.host }}
{{- end }}
{{- end }}
{{- end }}
{{- if not .Values.globalRegistryMode }}
{{- if .Values.notary.enabled }}
{{- if eq .Values.expose.type "ingress" }}
{{- $ingress := .Values.expose.ingress -}}
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: "{{ template "harbor.ingress.notary" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
annotations:
{{ toYaml $ingress.annotations | indent 4 }}
{{ printf "%s: /" $ingress.rewriteAnnotation }}
spec:
{{- if .Values.expose.tls.enabled }}
tls:
- secretName: {{ .Values.expose.tls.secretName }}
{{- if $ingress.host }}
hosts:
- {{ $ingress.host }}
{{- end }}
{{- end }}
rules:
- http:
paths:
- path: /notary/
backend:
serviceName: {{ template "harbor.notary-server" . }}
servicePort: 4443
{{- if $ingress.host }}
host: {{ $ingress.host }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
\ No newline at end of file
{{- if eq (include "harbor.autoGenCertForIngress" .) "true" -}}
{{- $cn := (required "The \"expose.ingress.host\" is required!" (include "harbor.tlsCommonName" .)) }}
{{- $ca := genCA "harbor-ca" 3650 }}
{{- $cert := genSignedCert .Values.expose.ingress.host nil (list .Values.expose.ingress.host) 3650 $ca }}
apiVersion: v1
kind: Secret
metadata:
name: "{{ template "harbor.ingress.core" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
type: kubernetes.io/tls
data:
{{- if regexMatch `^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$` $cn }}
{{- $cert := genSignedCert $cn (list $cn) nil 365 $ca }}
tls.crt: {{ $cert.Cert | b64enc | quote }}
tls.key: {{ $cert.Key | b64enc | quote }}
ca.crt: {{ $ca.Cert | b64enc | quote }}
{{- else }}
{{- $cert := genSignedCert $cn nil (list $cn) 365 $ca }}
tls.crt: {{ $cert.Cert | b64enc | quote }}
tls.key: {{ $cert.Key | b64enc | quote }}
ca.crt: {{ $ca.Cert | b64enc | quote }}
{{- end }}
{{- end }}
apiVersion: v1
kind: ConfigMap
metadata:
name: "{{ template "harbor.jobservice" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
data:
config.yml: |+
protocol: "http"
port: 8080
worker_pool:
workers: {{ .Values.jobservice.maxJobWorkers }}
backend: "redis"
redis_pool:
redis_url: "{{ template "harbor.redisForJobservice" . }}"
namespace: "harbor_job_service_namespace"
job_loggers:
{{- if eq .Values.jobservice.jobLogger "file" }}
- name: "FILE"
level: {{ .Values.logLevel | upper }}
settings: # Customized settings of logger
base_dir: "/var/log/jobs"
sweeper:
duration: 14 #days
settings: # Customized settings of sweeper
work_dir: "/var/log/jobs"
{{- else if eq .Values.jobservice.jobLogger "database" }}
- name: "DB"
level: {{ .Values.logLevel | upper }}
sweeper:
duration: 14 #days
{{- else }}
- name: "STD_OUTPUT"
level: {{ .Values.logLevel | upper }}
{{- end }}
#Loggers for the job service
loggers:
- name: "STD_OUTPUT"
level: {{ .Values.logLevel | upper }}
admin_server: "http://{{ template "harbor.adminserver" . }}"
apiVersion: apps/v1
kind: Deployment
metadata:
name: "{{ template "harbor.jobservice" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
component: jobservice
spec:
replicas: {{ .Values.jobservice.replicas }}
selector:
matchLabels:
{{ include "harbor.matchLabels" . | indent 6 }}
component: jobservice
template:
metadata:
labels:
{{ include "harbor.labels" . | indent 8 }}
component: jobservice
annotations:
checksum/configmap: {{ include (print $.Template.BasePath "/jobservice/jobservice-cm.yaml") . | sha256sum }}
checksum/secret: {{ include (print $.Template.BasePath "/jobservice/jobservice-secrets.yaml") . | sha256sum }}
checksum/secret-core: {{ include (print $.Template.BasePath "/core/core-secret.yaml") . | sha256sum }}
{{- if .Values.jobservice.podAnnotations }}
{{ toYaml .Values.jobservice.podAnnotations | indent 8 }}
{{- end }}
spec:
containers:
- name: jobservice
image: {{ template "system_default_registry" . }}{{ .Values.jobservice.image.repository }}:{{ .Values.jobservice.image.tag }}
imagePullPolicy: {{ .Values.imagePullPolicy }}
livenessProbe:
httpGet:
path: /api/v1/stats
port: 8080
initialDelaySeconds: 20
periodSeconds: 10
readinessProbe:
httpGet:
path: /api/v1/stats
port: 8080
initialDelaySeconds: 20
periodSeconds: 10
{{- if .Values.jobservice.resources }}
resources:
{{ toYaml .Values.jobservice.resources | indent 10 }}
{{- end }}
env:
- name: CORE_SECRET
valueFrom:
secretKeyRef:
name: {{ template "harbor.core" . }}
key: secret
- name: JOBSERVICE_SECRET
valueFrom:
secretKeyRef:
name: "{{ template "harbor.jobservice" . }}"
key: secret
- name: ADMINSERVER_URL
value: "http://{{ template "harbor.adminserver" . }}"
- name: REGISTRY_CONTROLLER_URL
value: "http://{{ template "harbor.registry" . }}:8080"
- name: LOG_LEVEL
value: debug
ports:
- containerPort: 8080
volumeMounts:
- name: jobservice-config
mountPath: /etc/jobservice/config.yml
subPath: config.yml
- name: job-logs
mountPath: /var/log/jobs
subPath: {{ .Values.persistence.persistentVolumeClaim.jobservice.subPath }}
volumes:
- name: jobservice-config
configMap:
name: "{{ template "harbor.jobservice" . }}"
- name: job-logs
{{- if and .Values.persistence.enabled (eq .Values.jobservice.jobLogger "file") }}
persistentVolumeClaim:
claimName: {{ .Values.persistence.persistentVolumeClaim.jobservice.existingClaim | default (include "harbor.jobservice" .) }}
{{- else }}
emptyDir: {}
{{- end }}
{{- with .Values.jobservice.nodeSelector }}
nodeSelector:
beta.kubernetes.io/os: linux
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.jobservice.affinity }}
affinity:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.jobservice.tolerations }}
tolerations:
{{ toYaml . | indent 8 }}
{{- end }}
{{- $jobservice := .Values.persistence.persistentVolumeClaim.jobservice -}}
{{- if and .Values.persistence.enabled (not $jobservice.existingClaim) }}
{{- if eq .Values.jobservice.jobLogger "file" }}
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: {{ template "harbor.jobservice" . }}
{{- if eq .Values.persistence.resourcePolicy "keep" }}
annotations:
helm.sh/resource-policy: keep
{{- end }}
labels:
{{ include "harbor.labels" . | indent 4 }}
component: jobservice
spec:
accessModes:
- {{ $jobservice.accessMode }}
resources:
requests:
storage: {{ $jobservice.size }}
{{- if $jobservice.storageClass }}
{{- if eq "-" $jobservice.storageClass }}
storageClassName: ""
{{- else }}
storageClassName: {{ $jobservice.storageClass }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
\ No newline at end of file
apiVersion: v1
kind: Secret
metadata:
name: "{{ template "harbor.jobservice" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
type: Opaque
data:
secret: {{ .Values.jobservice.secret | default (randAlphaNum 16) | b64enc | quote }}
apiVersion: v1
kind: Service
metadata:
name: "{{ template "harbor.jobservice" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
spec:
ports:
- port: 80
targetPort: 8080
selector:
{{ include "harbor.matchLabels" . | indent 4 }}
component: jobservice
{{- if and (ne .Values.expose.type "ingress") }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ template "harbor.nginx" . }}
labels:
{{ include "harbor.labels" . | indent 4 }}
data:
nginx.conf: |+
worker_processes auto;
events {
worker_connections 1024;
use epoll;
multi_accept on;
}
http {
tcp_nodelay on;
# this is necessary for us to be able to disable request buffering in all cases
proxy_http_version 1.1;
upstream core {
server {{ template "harbor.core" . }};
}
upstream portal {
server {{ template "harbor.portal" . }};
}
{{- if .Values.notary.enabled }}
upstream notary-server {
server {{ template "harbor.notary-server" . }}:4443;
}
{{- end }}
log_format timed_combined 'remote_addr - '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'$request_time $upstream_response_time $pipe';
access_log /dev/stdout timed_combined;
server {
listen 443 ssl;
# server_name harbordomain.com;
server_tokens off;
# SSL
ssl_certificate /etc/nginx/cert/tls.crt;
ssl_certificate_key /etc/nginx/cert/tls.key;
# Recommendations from https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html
ssl_protocols TLSv1.1 TLSv1.2;
ssl_ciphers '!aNULL:kECDH+AESGCM:ECDH+AESGCM:RSA+AESGCM:kECDH+AES:ECDH+AES:RSA+AES:';
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
# disable any limits to avoid HTTP 413 for large image uploads
client_max_body_size 0;
# required to avoid HTTP 411: see Issue #1486 (https://github.com/docker/docker/issues/1486)
chunked_transfer_encoding on;
location / {
proxy_pass http://portal/;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# When setting up Harbor behind other proxy, such as an Nginx instance, remove the below line if the proxy already has similar settings.
proxy_set_header X-Forwarded-Proto $scheme;
# Add Secure flag when serving HTTPS
proxy_cookie_path / "/; secure";
proxy_buffering off;
proxy_request_buffering off;
}
location /api/ {
proxy_pass http://core/api/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# When setting up Harbor behind other proxy, such as an Nginx instance, remove the below line if the proxy already has similar settings.
proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffering off;
proxy_request_buffering off;
}
location /chartrepo/ {
proxy_pass http://core/chartrepo/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# When setting up Harbor behind other proxy, such as an Nginx instance, remove the below line if the proxy already has similar settings.
proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffering off;
proxy_request_buffering off;
}
location /c/ {
proxy_pass http://core/c/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# When setting up Harbor behind other proxy, such as an Nginx instance, remove the below line if the proxy already has similar settings.
proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffering off;
proxy_request_buffering off;
}
location /v1/ {
return 404;
}
location /v2/ {
proxy_pass http://core/v2/;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# When setting up Harbor behind other proxy, such as an Nginx instance, remove the below line if the proxy already has similar settings.
proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffering off;
proxy_request_buffering off;
}
location /service/ {
proxy_pass http://core/service/;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# When setting up Harbor behind other proxy, such as an Nginx instance, remove the below line if the proxy already has similar settings.
proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffering off;
proxy_request_buffering off;
}
location /service/notifications {
return 404;
}
{{- if .Values.notary.enabled }}
location /notary/ {
proxy_pass http://notary-server;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# When setting up Harbor behind other proxy, such as an Nginx instance, remove the below line if the proxy already has similar settings.
proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffering off;
proxy_request_buffering off;
rewrite /notary/(.*) /$1 break;
}
{{- end }}
}
server {
listen 80;
#server_name harbordomain.com;
return 301 https://$host$request_uri;
}
}
{{- end }}
{{- if ne .Values.expose.type "ingress" }}
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: {{ template "harbor.nginx" . }}
labels:
{{ include "harbor.labels" . | indent 4 }}
component: nginx
spec:
replicas: 1
selector:
matchLabels:
{{ include "harbor.matchLabels" . | indent 6 }}
component: nginx
template:
metadata:
labels:
{{ include "harbor.labels" . | indent 8 }}
component: nginx
annotations:
checksum/configmap: {{ include (print $.Template.BasePath "/nginx/configmap-https.yaml") . | sha256sum }}
{{- if eq (include "harbor.autoGenCertForNginx" .) "true" }}
checksum/secret: {{ include (print $.Template.BasePath "/nginx/secret.yaml") . | sha256sum }}
{{- end }}
{{- if .Values.nginx.podAnnotations }}
{{ toYaml .Values.nginx.podAnnotations | indent 8 }}
{{- end }}
spec:
containers:
- name: nginx
image: {{ template "system_default_registry" . }}{{ .Values.nginx.image.repository }}:{{ .Values.nginx.image.tag }}
imagePullPolicy: "{{ .Values.imagePullPolicy }}"
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 1
periodSeconds: 10
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 1
periodSeconds: 10
{{- if .Values.nginx.resources }}
resources:
{{ toYaml .Values.nginx.resources | indent 10 }}
{{- end }}
ports:
- containerPort: 80
- containerPort: 443
volumeMounts:
- name: config
mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf
- name: certificate
mountPath: /etc/nginx/cert
volumes:
- name: config
configMap:
name: {{ template "harbor.nginx" . }}
- name: certificate
secret:
{{- if .Values.expose.tls.secretName }}
secretName: {{ .Values.expose.tls.secretName }}
{{- else }}
secretName: {{ template "harbor.nginx" . }}
{{- end }}
{{- with .Values.nginx.nodeSelector }}
nodeSelector:
beta.kubernetes.io/os: linux
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.nginx.affinity }}
affinity:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.nginx.tolerations }}
tolerations:
{{ toYaml . | indent 8 }}
{{- end }}
{{- end }}
\ No newline at end of file
{{- if eq (include "harbor.autoGenCertForNginx" .) "true" }}
{{- $ca := genCA "harbor-ca" 3650 }}
{{- $cn := (include "harbor.tlsCommonName" .) }}
apiVersion: v1
kind: Secret
metadata:
name: {{ template "harbor.nginx" . }}
labels:
{{ include "harbor.labels" . | indent 4 }}
type: Opaque
data:
{{- if regexMatch `^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$` $cn }}
{{- $cert := genSignedCert $cn (list $cn) nil 3650 $ca }}
tls.crt: {{ $cert.Cert | b64enc | quote }}
tls.key: {{ $cert.Key | b64enc | quote }}
ca.crt: {{ $ca.Cert | b64enc | quote }}
{{- else }}
{{- $cert := genSignedCert $cn nil (list $cn) 3650 $ca }}
tls.crt: {{ $cert.Cert | b64enc | quote }}
tls.key: {{ $cert.Key | b64enc | quote }}
ca.crt: {{ $ca.Cert | b64enc | quote }}
{{- end }}
{{- end }}
{{- if ne .Values.expose.type "ingress" }}
apiVersion: v1
kind: Service
metadata:
{{- if eq .Values.expose.type "clusterIP" }}
{{- $clusterIP := .Values.expose.clusterIP }}
name: {{ $clusterIP.name }}
labels:
{{ include "harbor.labels" . | indent 4 }}
spec:
type: ClusterIP
ports:
- name: https
port: {{ $clusterIP.ports.https }}
targetPort: 443
{{- else if eq .Values.expose.type "nodePort" }}
{{- $nodePort := .Values.expose.nodePort }}
name: {{ $nodePort.name }}
labels:
{{ include "harbor.labels" . | indent 4 }}
spec:
type: NodePort
ports:
- name: https
port: {{ $nodePort.ports.https.port }}
targetPort: 443
{{- if $nodePort.ports.https.nodePort }}
nodePort: {{ $nodePort.ports.https.nodePort }}
{{- end }}
{{- else if eq .Values.expose.type "loadBalancer" }}
{{- $loadBalancer := .Values.expose.loadBalancer }}
name: {{ $loadBalancer.name }}
labels:
{{ include "harbor.labels" . | indent 4 }}
spec:
type: LoadBalancer
ports:
- name: https
port: {{ $loadBalancer.ports.https }}
targetPort: 443
{{- end }}
selector:
{{ include "harbor.matchLabels" . | indent 4 }}
component: nginx
{{- end }}
{{ if .Values.notary.enabled }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ template "harbor.notary-server" . }}
labels:
{{ include "harbor.labels" . | indent 4 }}
component: notary
data:
{{ $ca := genCA "harbor-notary-ca" 365 }}
{{ $cert := genSignedCert (include "harbor.notary-signer" .) nil nil 365 $ca }}
{{- if not .Values.notary.secretName }}
notary-signer-ca.crt: |
{{ $ca.Cert | indent 4 }}
notary-signer.crt: |
{{ $cert.Cert | indent 4 }}
notary-signer.key: |
{{ $cert.Key | indent 4 }}
{{- end }}
server-config.postgres.json: |
{
"server": {
"http_addr": ":4443"
},
"trust_service": {
"type": "remote",
"hostname": "{{ template "harbor.notary-signer" . }}",
"port": "7899",
{{- if not .Values.notary.secretName }}
"tls_ca_file": "./notary-signer-ca.crt",
{{- else }}
"tls_ca_file": "/etc/ssl/notary/cert/notary-signer-ca.crt",
{{- end }}
"key_algorithm": "ecdsa"
},
"logging": {
"level": "{{ .Values.logLevel }}"
},
"storage": {
"backend": "postgres",
"db_url": "{{ template "harbor.database.notaryServer" . }}"
},
"auth": {
"type": "token",
"options": {
{{- if .Values.globalRegistryMode }}
"realm": "{{ template "harbor.externalURL" . }}/registry/service/token",
{{- else }}
"realm": "{{ template "harbor.externalURL" . }}/service/token",
{{- end }}
"service": "harbor-notary",
"issuer": "harbor-token-issuer",
"rootcertbundle": "/root.crt"
}
}
}
signer-config.postgres.json: |
{
"server": {
"grpc_addr": ":7899",
{{- if not .Values.notary.secretName }}
"tls_cert_file": "./notary-signer.crt",
"tls_key_file": "./notary-signer.key"
{{- else }}
"tls_cert_file": "/etc/ssl/notary/cert/notary-signer.crt",
"tls_key_file": "/etc/ssl/notary/cert/notary-signer.key"
{{- end }}
},
"logging": {
"level": "{{ .Values.logLevel }}"
},
"storage": {
"backend": "postgres",
"db_url": "{{ template "harbor.database.notarySigner" . }}",
"default_alias": "defaultalias"
}
}
{{ end }}
{{ if .Values.notary.enabled }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ template "harbor.notary-server" . }}
labels:
{{ include "harbor.labels" . | indent 4 }}
component: notary-server
spec:
replicas: {{ .Values.notary.server.replicas }}
selector:
matchLabels:
{{ include "harbor.matchLabels" . | indent 6 }}
component: notary-server
template:
metadata:
labels:
{{ include "harbor.labels" . | indent 8 }}
component: notary-server
annotations:
checksum/configmap: {{ include (print $.Template.BasePath "/notary/notary-cm.yaml") . | sha256sum }}
checksum/secret-core: {{ include (print $.Template.BasePath "/core/core-secret.yaml") . | sha256sum }}
{{- if .Values.notary.podAnnotations }}
{{ toYaml .Values.notary.podAnnotations | indent 8 }}
{{- end }}
spec:
containers:
- name: notary-server
image: {{ template "system_default_registry" . }}{{ .Values.notary.server.image.repository }}:{{ .Values.notary.server.image.tag }}
imagePullPolicy: {{ .Values.imagePullPolicy }}
{{- if .Values.notary.server.resources }}
resources:
{{ toYaml .Values.notary.server.resources | indent 10 }}
{{- end }}
env:
- name: MIGRATIONS_PATH
value: migrations/server/postgresql
- name: DB_URL
value: {{ template "harbor.database.notaryServer" . }}
volumeMounts:
- name: notary-config
mountPath: /etc/notary
- name: root-certificate
mountPath: /root.crt
subPath: tokenServiceRootCertBundle
{{- if .Values.notary.secretName }}
- name: notary-ca
mountPath: /etc/ssl/notary/cert/notary-signer-ca.crt
subPath: ca
{{- end }}
volumes:
- name: notary-config
configMap:
name: "{{ template "harbor.notary-server" . }}"
- name: root-certificate
secret:
{{- if .Values.core.secretName }}
secretName: {{ .Values.core.secretName }}
{{- else }}
secretName: {{ template "harbor.core" . }}
{{- end }}
{{- if .Values.notary.secretName }}
- name: notary-ca
secret:
secretName: {{ .Values.notary.secretName }}
{{- end }}
{{- with .Values.notary.nodeSelector }}
nodeSelector:
beta.kubernetes.io/os: linux
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.notary.affinity }}
affinity:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.notary.tolerations }}
tolerations:
{{ toYaml . | indent 8 }}
{{- end }}
{{ end }}
{{ if .Values.notary.enabled }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ template "harbor.notary-signer" . }}
labels:
{{ include "harbor.labels" . | indent 4 }}
component: notary-signer
spec:
replicas: {{ .Values.notary.signer.replicas }}
selector:
matchLabels:
{{ include "harbor.matchLabels" . | indent 6 }}
component: notary-signer
template:
metadata:
labels:
{{ include "harbor.labels" . | indent 8 }}
component: notary-signer
annotations:
checksum/configmap: {{ include (print $.Template.BasePath "/notary/notary-cm.yaml") . | sha256sum }}
spec:
containers:
- name: notary-signer
image: {{ template "system_default_registry" . }}{{ .Values.notary.signer.image.repository }}:{{ .Values.notary.signer.image.tag }}
imagePullPolicy: {{ .Values.imagePullPolicy }}
{{- if .Values.notary.signer.resources }}
resources:
{{ toYaml .Values.notary.signer.resources | indent 10 }}
{{- end }}
env:
- name: MIGRATIONS_PATH
value: migrations/signer/postgresql
- name: DB_URL
value: {{ template "harbor.database.notarySigner" . }}
- name: NOTARY_SIGNER_DEFAULTALIAS
value: defaultalias
volumeMounts:
- name: notary-config
mountPath: /etc/notary
{{- if .Values.notary.secretName }}
- name: notary-cert
mountPath: /etc/ssl/notary/cert/notary-signer-ca.crt
subPath: ca
- name: notary-cert
mountPath: /etc/ssl/notary/cert/notary-signer.crt
subPath: crt
- name: notary-cert
mountPath: /etc/ssl/notary/cert/notary-signer.key
subPath: key
{{- end }}
volumes:
- name: notary-config
configMap:
name: "{{ template "harbor.notary-server" . }}"
{{- if .Values.notary.secretName }}
- name: notary-cert
secret:
secretName: {{ .Values.notary.secretName }}
{{- end }}
{{- with .Values.notary.nodeSelector }}
nodeSelector:
beta.kubernetes.io/os: linux
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.notary.affinity }}
affinity:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.notary.tolerations }}
tolerations:
{{ toYaml . | indent 8 }}
{{- end }}
{{ end }}
{{ if .Values.notary.enabled }}
apiVersion: v1
kind: Service
metadata:
name: {{ template "harbor.notary-server" . }}
labels:
{{ include "harbor.labels" . | indent 4 }}
spec:
{{- if (eq .Values.expose.ingress.controller "gce") }}
type: NodePort
{{- end }}
ports:
- port: 4443
selector:
{{ include "harbor.matchLabels" . | indent 4 }}
component: notary-server
---
apiVersion: v1
kind: Service
metadata:
name: {{ template "harbor.notary-signer" . }}
labels:
{{ include "harbor.labels" . | indent 4 }}
spec:
ports:
- port: 7899
selector:
{{ include "harbor.matchLabels" . | indent 4 }}
component: notary-signer
{{ end }}
\ No newline at end of file
apiVersion: apps/v1
kind: Deployment
metadata:
name: "{{ template "harbor.portal" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
component: portal
spec:
replicas: {{ .Values.portal.replicas }}
selector:
matchLabels:
{{ include "harbor.matchLabels" . | indent 6 }}
component: portal
template:
metadata:
labels:
{{ include "harbor.matchLabels" . | indent 8 }}
component: portal
annotations:
{{- if .Values.portal.podAnnotations }}
{{ toYaml .Values.portal.podAnnotations | indent 8 }}
{{- end }}
spec:
containers:
- name: portal
image: {{ template "system_default_registry" . }}{{ .Values.portal.image.repository }}:{{ .Values.portal.image.tag }}
imagePullPolicy: {{ .Values.imagePullPolicy }}
{{- if .Values.portal.resources }}
resources:
{{ toYaml .Values.portal.resources | indent 10 }}
{{- end }}
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 1
periodSeconds: 10
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 1
periodSeconds: 10
ports:
- containerPort: 80
{{- with .Values.portal.nodeSelector }}
nodeSelector:
beta.kubernetes.io/os: linux
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.portal.affinity }}
affinity:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.portal.tolerations }}
tolerations:
{{ toYaml . | indent 8 }}
{{- end }}
apiVersion: v1
kind: Service
metadata:
name: "{{ template "harbor.portal" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
spec:
{{- if (eq .Values.expose.ingress.controller "gce") }}
type: NodePort
{{- end }}
ports:
- port: 80
targetPort: 80
selector:
{{ include "harbor.matchLabels" . | indent 4 }}
component: portal
{{ if .Values.globalRegistryMode }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ template "harbor.proxy" . }}
labels:
{{ include "harbor.labels" . | indent 4 }}
component: proxy
data:
default.conf: |
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
location = /registry {
return 302 /registry/;
}
location /registry/service/ {
proxy_pass http://{{ template "harbor.core" . }}/service/;
}
location /registry/api/ {
proxy_pass http://{{ template "harbor.core" . }}/api/;
}
{{ if .Values.chartmuseum.enabled }}
location /registry/chartrepo/ {
proxy_pass http://{{ template "harbor.core" . }}/chartrepo/;
}
{{ end }}
location /registry/c/ {
proxy_pass http://{{ template "harbor.core" . }}/c/;
}
{{ if .Values.notary.enabled }}
location /registry/notary/ {
proxy_pass http://{{ template "harbor.notary-server" . }}:4443/;
}
{{ end }}
location /registry/ {
proxy_pass http://{{ template "harbor.portal" . }}/;
include filters.conf;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
filters.conf: |
sub_filter_types application/javascript;
sub_filter 'src="main' 'src="/registry/main';
sub_filter 'src="runtime' 'src="/registry/runtime';
sub_filter 'src="scripts' 'src="/registry/scripts';
sub_filter '"/c/login"' '"/registry/c/login"';
sub_filter '"/c/log_out"' '"/registry/c/log_out"';
sub_filter '"/c/userExists"' '"/registry/c/userExists"';
sub_filter '"/c/reset"' '"/registry/c/reset"';
sub_filter '"/c/sendEmail' '"/registry/c/sendEmail';
sub_filter '"/c/oidc_login"' '"/registry/c/oidc_login"';
sub_filter '"/api/' '"/registry/api/';
sub_filter '"/service/' '"/registry/service/';
sub_filter '"/chartrepo/' '"/registry/chartrepo/';
sub_filter '<base href="/">' '<base href="/registry">';
sub_filter 'href="favicon.ico' 'href="/registry/favicon.ico';
sub_filter 'href="styles' 'href="/registry/styles';
sub_filter '"images/harbor-logo.svg"' '"/registry/images/harbor-logo.svg"';
sub_filter '"/images/helm-gray.svg"' '"/registry/images/helm-gray.svg"';
sub_filter '"images/harbor-black-logo.png' '"/registry/images/harbor-black-logo.png';
#sub_filter '"static/images' '"registry/static/images';
sub_filter '"../../../images' '"/registry/images';
sub_filter '"/swagger.json"' '"/registry/swagger.json"';
sub_filter '"i18n/lang/"' '"/registry/i18n/lang/"';
sub_filter '"/language' '"/registry/language';
sub_filter 'http.get("setting.json"' 'http.get("/registry/setting.json"';
sub_filter_once off;
proxy_set_header Accept-Encoding "";
{{ end }}
{{ if .Values.globalRegistryMode }}
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: {{ template "harbor.proxy" . }}
labels:
{{ include "harbor.labels" . | indent 4 }}
component: proxy
spec:
replicas: 1
selector:
matchLabels:
{{ include "harbor.matchLabels" . | indent 6 }}
component: proxy
template:
metadata:
labels:
{{ include "harbor.labels" . | indent 8 }}
component: proxy
spec:
containers:
- name: nginx
image: {{ template "system_default_registry" . }}{{ .Values.proxy.image.repository }}:{{ .Values.proxy.image.tag }}
imagePullPolicy: {{ .Values.proxy.image.pullPolicy }}
resources:
{{ toYaml .Values.proxy.resources | indent 10 }}
ports:
- containerPort: 80
volumeMounts:
- name: nginx-config
mountPath: /etc/nginx/conf.d
readOnly: true
- mountPath: /etc/nginx/filters.conf
name: filter-config
subPath: filters.conf
readOnly: true
volumes:
- name: nginx-config
configMap:
name: "{{ template "harbor.proxy" . }}"
items:
- key: default.conf
path: default.conf
- name: filter-config
configMap:
name: "{{ template "harbor.proxy" . }}"
items:
- key: filters.conf
path: filters.conf
{{- with .Values.proxy.nodeSelector }}
nodeSelector:
beta.kubernetes.io/os: linux
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.proxy.affinity }}
affinity:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.proxy.tolerations }}
tolerations:
{{ toYaml . | indent 8 }}
{{- end }}
{{ end }}
\ No newline at end of file
{{ if .Values.globalRegistryMode }}
apiVersion: v1
kind: Service
metadata:
name: "{{ template "harbor.proxy" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
spec:
ports:
- port: 80
selector:
{{ include "harbor.matchLabels" . | indent 4 }}
component: proxy
{{ end }}
\ No newline at end of file
{{- if eq .Values.redis.type "internal" -}}
apiVersion: v1
kind: Service
metadata:
name: {{ template "harbor.redis" . }}
labels:
{{ include "harbor.labels" . | indent 4 }}
spec:
ports:
- port: 6379
selector:
{{ include "harbor.matchLabels" . | indent 4 }}
component: redis
{{- end -}}
\ No newline at end of file
{{- if eq .Values.redis.type "internal" -}}
{{- $redis := .Values.persistence.persistentVolumeClaim.redis -}}
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: {{ template "harbor.redis" . }}
labels:
{{ include "harbor.labels" . | indent 4 }}
component: redis
spec:
replicas: 1
serviceName: {{ template "harbor.redis" . }}
selector:
matchLabels:
{{ include "harbor.matchLabels" . | indent 6 }}
component: redis
template:
metadata:
labels:
{{ include "harbor.labels" . | indent 8 }}
component: redis
{{- if .Values.redis.podAnnotations }}
annotations:
{{ toYaml .Values.redis.podAnnotations | indent 8 }}
{{- end }}
spec:
containers:
- name: redis
image: {{ template "system_default_registry" . }}{{ .Values.redis.internal.image.repository }}:{{ .Values.redis.internal.image.tag }}
imagePullPolicy: {{ .Values.imagePullPolicy }}
livenessProbe:
tcpSocket:
port: 6379
initialDelaySeconds: 1
periodSeconds: 10
readinessProbe:
tcpSocket:
port: 6379
initialDelaySeconds: 1
periodSeconds: 10
{{- if .Values.redis.internal.resources }}
resources:
{{ toYaml .Values.redis.internal.resources | indent 10 }}
{{- end }}
volumeMounts:
- name: data
mountPath: /var/lib/redis
subPath: {{ $redis.subPath }}
{{- if not .Values.persistence.enabled }}
volumes:
- name: data
emptyDir: {}
{{- else if $redis.existingClaim }}
volumes:
- name: data
persistentVolumeClaim:
claimName: {{ $redis.existingClaim }}
{{- end -}}
{{- with .Values.redis.internal.nodeSelector }}
nodeSelector:
beta.kubernetes.io/os: linux
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.redis.internal.affinity }}
affinity:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.redis.internal.tolerations }}
tolerations:
{{ toYaml . | indent 8 }}
{{- end }}
{{- if and .Values.persistence.enabled (not $redis.existingClaim) }}
volumeClaimTemplates:
- metadata:
name: data
labels:
{{ include "harbor.labels" . | indent 8 }}
spec:
accessModes: [{{ $redis.accessMode | quote }}]
{{- if $redis.storageClass }}
{{- if (eq "-" $redis.storageClass) }}
storageClassName: ""
{{- else }}
storageClassName: "{{ $redis.storageClass }}"
{{- end }}
{{- end }}
resources:
requests:
storage: {{ $redis.size | quote }}
{{- end -}}
{{- end -}}
apiVersion: v1
kind: ConfigMap
metadata:
name: "{{ template "harbor.registry" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
data:
config.yml: |+
version: 0.1
log:
level: {{ .Values.logLevel }}
fields:
service: registry
storage:
{{- $storage := .Values.imageChartStorage }}
{{- $type := $storage.type }}
{{- if eq $type "filesystem" }}
filesystem:
rootdirectory: {{ $storage.filesystem.rootdirectory }}
{{- if $storage.filesystem.maxthreads }}
maxthreads: {{ $storage.filesystem.maxthreads }}
{{- end }}
{{- else if eq $type "azure" }}
azure:
accountname: {{ $storage.azure.accountname }}
container: {{ $storage.azure.container }}
{{- if $storage.azure.realm }}
realm: {{ $storage.azure.realm }}
{{- end }}
{{- else if eq $type "gcs" }}
gcs:
bucket: {{ $storage.gcs.bucket }}
keyfile: /etc/registry/gcs-key.json
{{- if $storage.gcs.rootdirectory }}
rootdirectory: {{ $storage.gcs.rootdirectory }}
{{- end }}
{{- if $storage.gcs.chunksize }}
chunksize: {{ $storage.gcs.chunksize }}
{{- end }}
{{- else if eq $type "s3" }}
s3:
region: {{ $storage.s3.region }}
bucket: {{ $storage.s3.bucket }}
{{- if $storage.s3.regionendpoint }}
regionendpoint: {{ $storage.s3.regionendpoint }}
{{- end }}
{{- if $storage.s3.encrypt }}
encrypt: {{ $storage.s3.encrypt }}
{{- end }}
{{- if $storage.s3.insecure }}
secure: false
{{- end }}
{{- if $storage.s3.v4auth }}
v4auth: {{ $storage.s3.v4auth }}
{{- end }}
{{- if $storage.s3.chunksize }}
chunksize: {{ $storage.s3.chunksize }}
{{- end }}
{{- if $storage.s3.rootdirectory }}
rootdirectory: {{ $storage.s3.rootdirectory }}
{{- end }}
{{- if $storage.s3.storageclass }}
storageclass: {{ $storage.s3.storageclass }}
{{- end }}
{{- else if eq $type "swift" }}
swift:
authurl: {{ $storage.swift.authurl }}
username: {{ $storage.swift.username }}
container: {{ $storage.swift.container }}
{{- if $storage.swift.region }}
region: {{ $storage.swift.region }}
{{- end }}
{{- if $storage.swift.tenant }}
tenant: {{ $storage.swift.tenant }}
{{- end }}
{{- if $storage.swift.tenantid }}
tenantid: {{ $storage.swift.tenantid }}
{{- end }}
{{- if $storage.swift.domain }}
domain: {{ $storage.swift.domain }}
{{- end }}
{{- if $storage.swift.domainid }}
domainid: {{ $storage.swift.domainid }}
{{- end }}
{{- if $storage.swift.trustid }}
trustid: {{ $storage.swift.trustid }}
{{- end }}
{{- if $storage.swift.insecureskipverify }}
insecureskipverify: {{ $storage.swift.insecureskipverify }}
{{- end }}
{{- if $storage.swift.chunksize }}
chunksize: {{ $storage.swift.chunksize }}
{{- end }}
{{- if $storage.swift.prefix }}
prefix: {{ $storage.swift.prefix }}
{{- end }}
{{- if $storage.swift.authversion }}
authversion: {{ $storage.swift.authversion }}
{{- end }}
{{- if $storage.swift.endpointtype }}
endpointtype: {{ $storage.swift.endpointtype }}
{{- end }}
{{- if $storage.swift.tempurlcontainerkey }}
tempurlcontainerkey: {{ $storage.swift.tempurlcontainerkey }}
{{- end }}
{{- if $storage.swift.tempurlmethods }}
tempurlmethods: {{ $storage.swift.tempurlmethods }}
{{- end }}
{{- else if eq $type "oss" }}
oss:
accesskeyid: {{ $storage.oss.accesskeyid }}
region: {{ $storage.oss.region }}
bucket: {{ $storage.oss.bucket }}
{{- if $storage.oss.endpoint }}
endpoint: {{ $storage.oss.endpoint }}
{{- end }}
{{- if $storage.oss.internal }}
internal: {{ $storage.oss.internal }}
{{- end }}
{{- if $storage.oss.encrypt }}
encrypt: {{ $storage.oss.encrypt }}
{{- end }}
{{- if $storage.oss.insecure }}
secure: false
{{- end }}
{{- if $storage.oss.chunksize }}
chunksize: {{ $storage.oss.chunksize }}
{{- end }}
{{- if $storage.oss.rootdirectory }}
rootdirectory: {{ $storage.oss.rootdirectory }}
{{- end }}
{{- end }}
cache:
layerinfo: redis
maintenance:
uploadpurging:
enabled: false
delete:
enabled: true
redirect:
disable: {{ $storage.disableredirect }}
redis:
addr: "{{ template "harbor.redis.host" . }}:{{ template "harbor.redis.port" . }}"
password: {{ template "harbor.redis.rawPassword" . }}
db: {{ template "harbor.redis.registryDatabaseIndex" . }}
http:
addr: :5000
# set via environment variable
# secret: placeholder
debug:
addr: localhost:5001
auth:
token:
issuer: harbor-token-issuer
{{- if .Values.globalRegistryMode }}
realm: "{{ template "harbor.externalURL" . }}/registry/service/token"
{{- else }}
realm: "{{ template "harbor.externalURL" . }}/service/token"
{{- end }}
rootcertbundle: /etc/registry/root.crt
service: harbor-registry
validation:
disabled: true
notifications:
endpoints:
- name: harbor
disabled: false
url: http://{{ template "harbor.core" . }}/service/notifications
timeout: 3000ms
threshold: 5
backoff: 1s
ctl-config.yml: |+
---
protocol: "http"
port: 8080
log_level: {{ .Values.logLevel }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: "{{ template "harbor.registry" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
component: registry
spec:
replicas: {{ .Values.registry.replicas }}
selector:
matchLabels:
{{ include "harbor.matchLabels" . | indent 6 }}
component: registry
strategy:
rollingUpdate:
maxUnavailable: 1
template:
metadata:
labels:
{{ include "harbor.labels" . | indent 8 }}
component: registry
annotations:
checksum/configmap: {{ include (print $.Template.BasePath "/registry/registry-cm.yaml") . | sha256sum }}
checksum/secret: {{ include (print $.Template.BasePath "/registry/registry-secret.yaml") . | sha256sum }}
checksum/secret-jobservice: {{ include (print $.Template.BasePath "/jobservice/jobservice-secrets.yaml") . | sha256sum }}
checksum/secret-core: {{ include (print $.Template.BasePath "/core/core-secret.yaml") . | sha256sum }}
{{- if .Values.registry.podAnnotations }}
{{ toYaml .Values.registry.podAnnotations | indent 8 }}
{{- end }}
spec:
containers:
- name: registry
image: {{ template "system_default_registry" . }}{{ .Values.registry.registry.image.repository }}:{{ .Values.registry.registry.image.tag }}
imagePullPolicy: {{ .Values.imagePullPolicy }}
livenessProbe:
httpGet:
path: /
port: 5000
initialDelaySeconds: 1
periodSeconds: 10
readinessProbe:
httpGet:
path: /
port: 5000
initialDelaySeconds: 1
periodSeconds: 10
{{- if .Values.registry.registry.resources }}
resources:
{{ toYaml .Values.registry.registry.resources | indent 10 }}
{{- end }}
args: ["serve", "/etc/registry/config.yml"]
envFrom:
- secretRef:
name: "{{ template "harbor.registry" . }}"
ports:
- containerPort: 5000
- containerPort: 5001
volumeMounts:
- name: registry-data
mountPath: {{ .Values.imageChartStorage.filesystem.rootdirectory }}
subPath: {{ .Values.persistence.persistentVolumeClaim.registry.subPath }}
- name: registry-root-certificate
mountPath: /etc/registry/root.crt
subPath: tokenServiceRootCertBundle
- name: registry-config
mountPath: /etc/registry/config.yml
subPath: config.yml
{{- if and .Values.persistence.enabled (eq .Values.imageChartStorage.type "gcs") }}
- name: gcs-key
mountPath: /etc/registry/gcs-key.json
subPath: gcs-key.json
{{- end }}
- name: registryctl
image: {{ template "system_default_registry" . }}{{ .Values.registry.controller.image.repository }}:{{ .Values.registry.controller.image.tag }}
imagePullPolicy: {{ .Values.imagePullPolicy }}
livenessProbe:
httpGet:
path: /api/health
port: 8080
initialDelaySeconds: 1
periodSeconds: 10
readinessProbe:
httpGet:
path: /api/health
port: 8080
initialDelaySeconds: 1
periodSeconds: 10
{{- if .Values.registry.controller.resources }}
resources:
{{ toYaml .Values.registry.controller.resources | indent 10 }}
{{- end }}
args: ["serve", "/etc/registry/config.yml"]
envFrom:
- secretRef:
name: "{{ template "harbor.registry" . }}"
env:
- name: CORE_SECRET
valueFrom:
secretKeyRef:
name: {{ template "harbor.core" . }}
key: secret
- name: JOBSERVICE_SECRET
valueFrom:
secretKeyRef:
name: {{ template "harbor.jobservice" . }}
key: secret
ports:
- containerPort: 8080
volumeMounts:
- name: registry-data
mountPath: {{ .Values.imageChartStorage.filesystem.rootdirectory }}
subPath: {{ .Values.persistence.persistentVolumeClaim.registry.subPath }}
- name: registry-config
mountPath: /etc/registry/config.yml
subPath: config.yml
- name: registry-config
mountPath: /etc/registryctl/config.yml
subPath: ctl-config.yml
volumes:
- name: registry-root-certificate
secret:
{{- if .Values.core.secretName }}
secretName: {{ .Values.core.secretName }}
{{- else }}
secretName: {{ template "harbor.core" . }}
{{- end }}
- name: registry-config
configMap:
name: "{{ template "harbor.registry" . }}"
- name: registry-data
{{- if and .Values.persistence.enabled (eq .Values.imageChartStorage.type "filesystem") }}
persistentVolumeClaim:
claimName: {{ .Values.persistence.persistentVolumeClaim.registry.existingClaim | default (include "harbor.registry" .) }}
{{- else }}
emptyDir: {}
{{- end }}
{{- if and .Values.persistence.enabled (eq .Values.imageChartStorage.type "gcs") }}
- name: gcs-key
secret:
secretName: {{ template "harbor.registry" . }}
items:
- key: GCS_KEY_DATA
path: gcs-key.json
{{- end }}
{{- with .Values.registry.nodeSelector }}
nodeSelector:
beta.kubernetes.io/os: linux
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.registry.affinity }}
affinity:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.registry.tolerations }}
tolerations:
{{ toYaml . | indent 8 }}
{{- end }}
{{- if .Values.persistence.enabled }}
{{- $registry := .Values.persistence.persistentVolumeClaim.registry -}}
{{- if and (not $registry.existingClaim) (eq .Values.imageChartStorage.type "filesystem") }}
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: {{ template "harbor.registry" . }}
{{- if eq .Values.persistence.resourcePolicy "keep" }}
annotations:
helm.sh/resource-policy: keep
{{- end }}
labels:
{{ include "harbor.labels" . | indent 4 }}
component: registry
spec:
accessModes:
- {{ $registry.accessMode }}
resources:
requests:
storage: {{ $registry.size }}
{{- if $registry.storageClass }}
{{- if eq "-" $registry.storageClass }}
storageClassName: ""
{{- else }}
storageClassName: {{ $registry.storageClass }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
\ No newline at end of file
apiVersion: v1
kind: Secret
metadata:
name: "{{ template "harbor.registry" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
type: Opaque
data:
REGISTRY_HTTP_SECRET: {{ .Values.registry.secret | default (randAlphaNum 16) | b64enc | quote }}
{{- $storage := .Values.imageChartStorage }}
{{- $type := $storage.type }}
{{- if eq $type "azure" }}
REGISTRY_STORAGE_AZURE_ACCOUNTKEY: {{ $storage.azure.accountkey | b64enc | quote }}
{{- else if eq $type "gcs" }}
GCS_KEY_DATA: {{ $storage.gcs.encodedkey | quote }}
{{- else if eq $type "s3" }}
{{- if $storage.s3.accesskey }}
REGISTRY_STORAGE_S3_ACCESSKEY: {{ $storage.s3.accesskey | b64enc | quote }}
{{- end }}
{{- if $storage.s3.secretkey }}
REGISTRY_STORAGE_S3_SECRETKEY: {{ $storage.s3.secretkey | b64enc | quote }}
{{- end }}
{{- else if eq $type "swift" }}
REGISTRY_STORAGE_SWIFT_PASSWORD: {{ $storage.swift.password | b64enc | quote }}
{{- if $storage.swift.secretkey }}
REGISTRY_STORAGE_SWIFT_SECRETKEY: {{ $storage.swift.secretkey | b64enc | quote }}
{{- end }}
{{- if $storage.swift.accesskey }}
REGISTRY_STORAGE_SWIFT_ACCESSKEY: {{ $storage.swift.accesskey | b64enc | quote }}
{{- end }}
{{- else if eq $type "oss" }}
REGISTRY_STORAGE_OSS_ACCESSKEYSECRET: {{ $storage.oss.accesskeysecret | b64enc | quote }}
{{- end }}
apiVersion: v1
kind: Service
metadata:
name: "{{ template "harbor.registry" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
spec:
ports:
- name: registry
port: 5000
- name: controller
port: 8080
selector:
{{ include "harbor.matchLabels" . | indent 4 }}
component: registry
\ No newline at end of file
suite: Test Enable/Disable Addons
templates:
- clair-cm.yaml
- clair-dpl.yaml
- clair-svc.yaml
- notary-cm.yaml
- notary-server.yaml
- notary-signer.yaml
- notary-svc.yaml
- core-secret.yaml
tests:
- it: should enable clair and notary by default
asserts:
- template: clair/clair-cm.yaml
hasDocuments:
count: 1
- template: clair/clair-dpl.yaml
hasDocuments:
count: 1
- template: clair/clair-svc.yaml
hasDocuments:
count: 1
- template: notary/notary-cm.yaml
hasDocuments:
count: 1
- template: notary/notary-server.yaml
hasDocuments:
count: 1
- template: notary/notary-signer.yaml
hasDocuments:
count: 1
- template: notary/notary-svc.yaml
hasDocuments:
count: 2
- it: should disable clair
set:
clair:
enabled: false
asserts:
- template: clair/clair-cm.yaml
hasDocuments:
count: 0
- template: clair/clair-dpl.yaml
hasDocuments:
count: 0
- template: clair/clair-svc.yaml
hasDocuments:
count: 0
- it: should disable notary
set:
notary:
enabled: false
asserts:
- template: notary/notary-cm.yaml
hasDocuments:
count: 0
- template: notary/notary-server.yaml
hasDocuments:
count: 0
- template: notary/notary-signer.yaml
hasDocuments:
count: 0
- template: notary/notary-svc.yaml
hasDocuments:
count: 0
suite: Test Global Options
templates:
- registry-cm.yaml
- registry-dpl.yaml
- registry-secret.yaml
- jobservice-secrets.yaml
- core-secret.yaml
tests:
- it: has no system default registry set
set:
registry:
registry:
image:
repository: test/registry-photon
tag: mytag
asserts:
- template: registry/registry-dpl.yaml
equal:
path: spec.template.spec.containers[0].image
value: test/registry-photon:mytag
- it: should use system default registry
set:
global:
systemDefaultRegistry: reg.myorg.com
registry:
registry:
image:
repository: test/registry-photon
tag: mytag
asserts:
- template: registry/registry-dpl.yaml
equal:
path: spec.template.spec.containers[0].image
value: reg.myorg.com/test/registry-photon:mytag
suite: Test Ingress
templates:
- ingress.yaml
tests:
- it: should set ingress host
set:
expose:
ingress:
host: test.myorg.com
asserts:
- template: ingress/ingress.yaml
equal:
path: spec.tls[0].hosts[0]
value: test.myorg.com
- template: ingress/ingress.yaml
equal:
path: spec.rules[0].host
value: test.myorg.com
- it: should use tls-rancher-ingress secret
set:
expose:
ingress:
host: test.myorg.com
globalRegistryMode: true
asserts:
- template: ingress/ingress.yaml
equal:
path: spec.tls[0].secretName
value: tls-rancher-ingress
suite: Test Registry Configmap
templates:
- registry-cm.yaml
- registry-dpl.yaml
- registry-secret.yaml
- jobservice-secrets.yaml
- core-secret.yaml
tests:
- it: should use filesystem storage backend by default
asserts:
- template: registry/registry-cm.yaml
matchRegex:
path: data.config\.yml
pattern: "filesystem:"
- it: should use s3 storage backend
set:
imageChartStorage:
type: s3
s3:
region: us-west-2
bucket: mybucket
accesskey: myaccesskey
secretkey: mysecretkey
asserts:
- template: registry/registry-cm.yaml
matchRegex:
path: data.config\.yml
pattern: "(?s)s3:.*region: us-west-2.*bucket: mybucket"
- template: registry/registry-secret.yaml
equal:
path: data.REGISTRY_STORAGE_S3_ACCESSKEY
value: bXlhY2Nlc3NrZXk=
- template: registry/registry-secret.yaml
equal:
path: data.REGISTRY_STORAGE_S3_SECRETKEY
value: bXlzZWNyZXRrZXk=
expose:
# Set the way how to expose the service. Set the type as "ingress",
# "clusterIP", "nodePort" or "loadBalancer" and fill the information
# in the corresponding section
type: ingress
tls:
# Enable the tls or not. Note: if the type is "ingress" and the tls
# is disabled, the port must be included in the command when pull/push
# images. Refer to https://github.com/goharbor/harbor/issues/5291
# for the detail.
enabled: true
# Fill the name of secret if you want to use your own TLS certificate
# and private key. The secret must contain keys named tls.crt and
# tls.key that contain the certificate and private key to use for TLS
# The certificate and private key will be generated automatically if
# it is not set
secretName: ""
ingress:
host: harbor.local
# set to the type of ingress controller if it has specific requirements.
# leave as `default` for most ingress controllers.
# set to `gce` if using the GCE ingress controller
controller: default
annotations:
ingress.kubernetes.io/ssl-redirect: "true"
ingress.kubernetes.io/proxy-body-size: "0"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/proxy-body-size: "0"
# The annotation name for "rewrite-target", only needed when Notary
# service is enabled
rewriteAnnotation: nginx.ingress.kubernetes.io/rewrite-target
clusterIP:
# The name of ClusterIP service
name: harbor
ports:
# The service port Harbor listens on when serving with HTTPS
https: 443
nodePort:
# The name of NodePort service
name: harbor
ports:
https:
# The service port Harbor listens on when serving with HTTPS
port: 443
# The node port Harbor listens on when serving with HTTPS
nodePort: 30003
loadBalancer:
# The name of LoadBalancer service
name: harbor
ports:
# The service port Harbor listens on when serving with HTTPS
https: 443
# The external URL for Harbor service. It is used to
# 1) populate the docker/helm commands showed on portal
# 2) populate the token service URL returned to docker/notary client
#
# Format: protocol://domain[:port]. Usually:
# 1) if "expose.type" is "ingress", the "domain" should be
# the value of "expose.ingress.host"
# 2) if "expose.type" is "clusterIP", the "domain" should be
# the value of "expose.clusterIP.name"
# 3) if "expose.type" is "nodePort", the "domain" should be
# the IP address of k8s node
#
# If Harbor is deployed behind the proxy, set it as the URL of proxy
externalURL: https://harbor.local
# Use the Harbor instance as the global registry in Rancher
globalRegistryMode: true
# The persistence is enabled by default and a default StorageClass
# is needed in the k8s cluster to provision volumes dynamicly.
# Specify another StorageClass in the "storageClass" or set "existingClaim"
# if you have already existing persistent volumes to use
#
# For storing images and charts, you can also use "azure", "gcs", "s3",
# "swift" or "oss". Set it in the "imageChartStorage" section
persistence:
enabled: true
# Setting it to "keep" to avoid removing PVCs during a helm delete
# operation. Leaving it empty will delete PVCs after the chart deleted
resourcePolicy: "keep"
persistentVolumeClaim:
registry:
# Use the existing PVC which must be created manually before bound,
# and specify the "subPath" if the PVC is shared with other components
existingClaim: ""
# Specify the "storageClass" used to provision the volume. Or the default
# StorageClass will be used(the default).
# Set it to "-" to disable dynamic provisioning
storageClass: ""
subPath: ""
accessMode: ReadWriteOnce
size: 5Gi
chartmuseum:
existingClaim: ""
storageClass: ""
subPath: ""
accessMode: ReadWriteOnce
size: 5Gi
# update default jobservice jobLogger to DB so pvc is not really required
jobservice:
existingClaim: ""
storageClass: ""
subPath: ""
accessMode: ReadWriteOnce
size: 1Gi
# If external database is used, the following settings for database will
# be ignored
database:
existingClaim: ""
storageClass: ""
subPath: ""
accessMode: ReadWriteOnce
size: 1Gi
# If external Redis is used, the following settings for Redis will
# be ignored
redis:
existingClaim: ""
storageClass: ""
subPath: ""
accessMode: ReadWriteOnce
size: 1Gi
# Define which storage backend is used for registry and chartmuseum to store
# images and charts. Refer to
# https://github.com/docker/distribution/blob/master/docs/configuration.md#storage
# for the detail.
imageChartStorage:
# Specify whether to disable `redirect` for images and chart storage, for
# backends which not supported it (such as using minio for `s3` storage type), please disable
# it. To disable redirects, simply set `disableredirect` to `true` instead.
# Refer to
# https://github.com/docker/distribution/blob/master/docs/configuration.md#redirect
# for the detail.
disableredirect: false
# Specify the type of storage: "filesystem", "azure", "gcs", "s3", "swift",
# "oss" and fill the information needed in the corresponding section. The type
# must be "filesystem" if you want to use persistent volumes for registry
# and chartmuseum
type: filesystem
filesystem:
rootdirectory: /storage
#maxthreads: 100
azure:
accountname: accountname
accountkey: base64encodedaccountkey
container: containername
#realm: core.windows.net
gcs:
bucket: bucketname
# The base64 encoded json file which contains the key
encodedkey: base64-encoded-json-key-file
#rootdirectory: /gcs/object/name/prefix
#chunksize: "5242880"
s3:
region: us-west-1
bucket: bucketname
#accesskey: awsaccesskey
#secretkey: awssecretkey
#regionendpoint: http://myobjects.local
#encrypt: false
#keyid: mykeyid
#insecure: false
#v4auth: true
#chunksize: "5242880"
#rootdirectory: /s3/object/name/prefix
#storageclass: STANDARD
swift:
authurl: https://storage.myprovider.com/v3/auth
username: username
password: password
container: containername
#region: fr
#tenant: tenantname
#tenantid: tenantid
#domain: domainname
#domainid: domainid
#trustid: trustid
#insecureskipverify: false
#chunksize: 5M
#prefix:
#secretkey: secretkey
#accesskey: accesskey
#authversion: 3
#endpointtype: public
#tempurlcontainerkey: false
#tempurlmethods:
oss:
accesskeyid: accesskeyid
accesskeysecret: accesskeysecret
region: regionname
bucket: bucketname
#endpoint: endpoint
#internal: false
#encrypt: false
#insecure: false
#chunksize: 10M
#rootdirectory: rootdirectory
imagePullPolicy: IfNotPresent
logLevel: debug
# The initial password of Harbor admin. Change it from portal after launching Harbor
harborAdminPassword: "Harbor12345"
# The secret key used for encryption. Must be a string of 16 chars.
secretKey: "not-a-secure-key"
# nginx proxy adapter for global registry, it is used when globalRegistryMode is true.
proxy:
image:
repository: rancher/nginx
tag: 1.14.2
pullPolicy: IfNotPresent
resources:
requests:
cpu: 50m
memory: 64Mi
# limits:
# cpu: 50m
# memory: 64Mi
nodeSelector: {}
tolerations: []
affinity: {}
# If expose the service via "ingress", the Nginx will not be used
nginx:
image:
repository: rancher/goharbor-nginx-photon
tag: v1.7.5
replicas: 1
resources:
requests:
cpu: 50m
memory: 64Mi
# limits:
# cpu: 100m
# memory: 64Mi
nodeSelector: {}
tolerations: []
affinity: {}
## Additional deployment annotations
podAnnotations: {}
portal:
image:
repository: rancher/goharbor-harbor-portal
tag: v1.7.5
replicas: 1
resources:
requests:
cpu: 50m
memory: 64Mi
# limits:
# cpu: 100m
# memory: 128Mi
nodeSelector: {}
tolerations: []
affinity: {}
## Additional deployment annotations
podAnnotations: {}
adminserver:
image:
repository: rancher/goharbor-harbor-adminserver
tag: v1.7.5
replicas: 1
resources:
requests:
cpu: 10m
memory: 20Mi
# limits:
# cpu: 100m
# memory: 128Mi
nodeSelector: {}
tolerations: []
affinity: {}
## Additional deployment annotations
podAnnotations: {}
core:
image:
repository: rancher/goharbor-harbor-core
tag: v1.7.5
replicas: 1
resources:
requests:
cpu: 50m
memory: 64Mi
# limits:
# cpu: 100m
# memory: 256Mi
nodeSelector: {}
tolerations: []
affinity: {}
## Additional deployment annotations
podAnnotations: {}
# Secret is used when core server communicates with other components.
# If a secret key is not specified, Helm will generate one.
# Must be a string of 16 chars.
secret: ""
# Fill the name of a kubernetes secret if you want to use your own
# TLS certificate and private key for token encryption/decryption.
# The secret must contain keys named tls.tokenServiceRootCertBundle and
# tls.tokenServicePrivateKey that contain the certificate and private key.
# They will be automatically generated if not set
secretName: ""
jobservice:
image:
repository: rancher/goharbor-harbor-jobservice
tag: v1.7.5
replicas: 1
maxJobWorkers: 10
# The logger for jobs: "file", "database" or "stdout"
jobLogger: database
resources:
requests:
cpu: 50m
memory: 64Mi
# limits:
# cpu: 100m
# memory: 256Mi
nodeSelector: {}
tolerations: []
affinity: {}
## Additional deployment annotations
podAnnotations: {}
# Secret is used when job service communicates with other components.
# If a secret key is not specified, Helm will generate one.
# Must be a string of 16 chars.
secret: ""
registry:
registry:
image:
repository: rancher/goharbor-registry-photon
tag: v2.6.2-v1.7.5
resources:
requests:
cpu: 20m
memory: 64Mi
# limits:
# cpu: 100m
# memory: 256Mi
controller:
image:
repository: rancher/goharbor-harbor-registryctl
tag: v1.7.5
resources:
requests:
cpu: 20m
memory: 64Mi
# limits:
# cpu: 100m
# memory: 128Mi
replicas: 1
nodeSelector: {}
tolerations: []
affinity: {}
## Additional deployment annotations
podAnnotations: {}
# Secret is used to secure the upload state from client
# and registry storage backend.
# See: https://github.com/docker/distribution/blob/master/docs/configuration.md#http
# If a secret key is not specified, Helm will generate one.
# Must be a string of 16 chars.
secret: ""
chartmuseum:
enabled: false
image:
repository: rancher/goharbor-chartmuseum-photon
tag: v0.8.1-v1.7.5
replicas: 1
resources:
requests:
cpu: 20m
memory: 64Mi
# limits:
# cpu: 100m
# memory: 256Mi
nodeSelector: {}
tolerations: []
affinity: {}
## Additional deployment annotations
podAnnotations: {}
clair:
enabled: true
image:
repository: rancher/goharbor-clair-photon
tag: v2.0.8-v1.7.5
replicas: 1
# The http(s) proxy used to update vulnerabilities database from internet
httpProxy:
httpsProxy:
# The interval of clair updaters, the unit is hour, set to 0 to
# disable the updaters
updatersInterval: 12
resources:
requests:
cpu: 100m
memory: 256Mi
# limits:
# cpu: 200m
# memory: 1500Mi
nodeSelector: {}
tolerations: []
affinity: {}
## Additional deployment annotations
podAnnotations: {}
notary:
enabled: true
server:
image:
repository: rancher/goharbor-notary-server-photon
tag: v0.6.1-v1.7.5
replicas: 1
resources:
requests:
cpu: 20m
memory: 64Mi
# limits:
# cpu: 100m
# memory: 128Mi
signer:
image:
repository: rancher/goharbor-notary-signer-photon
tag: v0.6.1-v1.7.5
replicas: 1
resources:
requests:
cpu: 20m
memory: 64Mi
# limits:
# cpu: 100m
# memory: 128Mi
nodeSelector: {}
tolerations: []
affinity: {}
## Additional deployment annotations
podAnnotations: {}
# Fill the name of a kubernetes secret if you want to use your own
# TLS certificate authority, certificate and private key for notary
# communications.
# The secret must contain keys named tls.ca, tls.crt and tls.key that
# contain the CA, certificate and private key.
# They will be generated if not set.
secretName: ""
database:
# if external database is used, set "type" to "external"
# and fill the connection informations in "external" section
type: internal
internal:
image:
repository: rancher/goharbor-harbor-db
tag: v1.7.5
# The initial superuser password for internal database
password: "changeit"
resources:
requests:
cpu: 100m
memory: 128Mi
nodeSelector: {}
tolerations: []
affinity: {}
external:
host: "192.168.0.1"
port: "5432"
username: "user"
password: "password"
coreDatabase: "registry"
clairDatabase: "clair"
notaryServerDatabase: "notary_server"
notarySignerDatabase: "notary_signer"
sslmode: "disable"
## Additional deployment annotations
podAnnotations: {}
redis:
# if external Redis is used, set "type" to "external"
# and fill the connection informations in "external" section
type: internal
internal:
image:
repository: rancher/goharbor-redis-photon
tag: v1.7.5
resources:
requests:
cpu: 100m
memory: 128Mi
nodeSelector: {}
tolerations: []
affinity: {}
external:
host: "192.168.0.2"
port: "6379"
# The "coreDatabaseIndex" must be "0" as the library Harbor
# used doesn't support configuring it
coreDatabaseIndex: "0"
jobserviceDatabaseIndex: "1"
registryDatabaseIndex: "2"
chartmuseumDatabaseIndex: "3"
password: ""
## Additional deployment annotations
podAnnotations: {}
global:
systemDefaultRegistry: ""
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment