Unverified Commit 3360e562 by Denise Committed by GitHub

Merge pull request #310 from jfrog/master

upgrading artifactory charts, artifactory version, postgresql version, supported k8s version
parents fd3dbe7d a21494e1
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*~
# Various IDEs
.project
.idea/
*.tmproj
OWNERS
\ No newline at end of file
apiVersion: v1
appVersion: 6.13.1
description: Universal Repository Manager supporting all major packaging formats,
build tools and CI servers.
home: https://www.jfrog.com/artifactory/
icon: https://raw.githubusercontent.com/jfrog/artifactory-dcos/master/images/jfrog_med.png
keywords:
- artifactory
- jfrog
- devops
maintainers:
- email: amithk@jfrog.com
name: amithins
- email: daniele@jfrog.com
name: danielezer
- email: eldada@jfrog.com
name: eldada
- email: rimasm@jfrog.com
name: rimusz
name: artifactory-ha
sources:
- https://bintray.com/jfrog/product/JFrog-Artifactory-Pro/view
- https://github.com/jfrog/charts
version: 1.0.0
# JFrog Artifactory Reverse Proxy Settings using Nginx
#### Reverse Proxy
* To use Artifactory as docker registry it's mandatory to use Reverse Proxy.
* Artifactory provides a Reverse Proxy Configuration Generator screen in which you can fill in a set of fields to generate
the required configuration snippet which you can then download and install directly in the corresponding directory of your reverse proxy server.
* To learn about configuring NGINX or Apache for reverse proxy refer to documentation provided on [JFrog wiki](https://www.jfrog.com/confluence/display/RTF/Configuring+a+Reverse+Proxy)
* By default Artifactory helm chart uses Nginx for reverse proxy and load balancing.
**Note**: Nginx image distributed with Artifactory helm chart is custom image managed and maintained by JFrog.
#### Features of Artifactory Nginx
* Provides default configuration with self signed SSL certificate generated on each helm install/upgrade.
* Persist configuration and SSL certificate in `/var/opt/jfrog/nginx` directory
#### Changing the default Artifactory nginx conf
Use a values.yaml file for changing the value of nginx.mainConf or nginx.artifactoryConf
These configuration will be mounted to the nginx container using a configmap.
For example:
1. Create a values file `nginx-values.yaml` with the following values:
```yaml
nginx:
artifactoryConf: |
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_certificate {{ .Values.nginx.persistence.mountPath }}/ssl/tls.crt;
ssl_certificate_key {{ .Values.nginx.persistence.mountPath }}/ssl/tls.key;
ssl_session_cache shared:SSL:1m;
ssl_prefer_server_ciphers on;
## server configuration
server {
listen {{ .Values.nginx.internalPortHttps }} ssl;
listen {{ .Values.nginx.internalPortHttp }} ;
## Change to you DNS name you use to access Artifactory
server_name ~(?<repo>.+)\.{{ include "artifactory-ha.fullname" . }} {{ include "artifactory-ha.fullname" . }};
if ($http_x_forwarded_proto = '') {
set $http_x_forwarded_proto $scheme;
}
## Application specific logs
## access_log /var/log/nginx/artifactory-access.log timing;
## error_log /var/log/nginx/artifactory-error.log;
rewrite ^/$ /artifactory/webapp/ redirect;
rewrite ^/artifactory/?(/webapp)?$ /artifactory/webapp/ redirect;
if ( $repo != "" ) {
rewrite ^/(v1|v2)/(.*) /artifactory/api/docker/$repo/$1/$2 break;
}
rewrite ^/(v1|v2)/([^/]+)(.*)$ /artifactory/api/docker/$2/$1/$3;
rewrite ^/(v1|v2)/ /artifactory/api/docker/$1/;
chunked_transfer_encoding on;
client_max_body_size 0;
location /artifactory/ {
proxy_read_timeout 900;
proxy_pass_header Server;
proxy_cookie_path ~*^/.* /;
if ( $request_uri ~ ^/artifactory/(.*)$ ) {
proxy_pass http://{{ include "artifactory-ha.fullname" . }}:{{ .Values.artifactory.externalPort }}/artifactory/$1;
}
proxy_pass http://{{ include "artifactory-ha.fullname" . }}:{{ .Values.artifactory.externalPort }}/artifactory/;
proxy_set_header X-Artifactory-Override-Base-Url $http_x_forwarded_proto://$host:$server_port/artifactory;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
```
2. Install/upgrade artifactory:
```bash
helm upgrade --install artifactory-ha jfrog/artifactory-ha -f nginx-values.yaml
```
#### Steps to use static configuration for reverse proxy in nginx.
1. Get Artifactory service name using this command `kubectl get svc -n $NAMESPACE`
2. Create `artifactory.conf` file with nginx configuration. More [nginx configuration examples](https://github.com/jfrog/artifactory-docker-examples/tree/master/files/nginx/conf.d)
Following is example `artifactory.conf`
**Note**:
* Create file with name `artifactory.conf` as it's fixed in configMap key.
* Replace `artifactory-artifactory` with service name taken from step 1.
```bash
## add ssl entries when https has been set in config
ssl_certificate /var/opt/jfrog/nginx/ssl/tls.crt;
ssl_certificate_key /var/opt/jfrog/nginx/ssl/tls.key;
ssl_session_cache shared:SSL:1m;
ssl_prefer_server_ciphers on;
## server configuration
server {
listen 443 ssl;
listen 80;
## Change to you DNS name you use to access Artifactory
server_name ~(?<repo>.+)\.artifactory-artifactory artifactory-artifactory;
if ($http_x_forwarded_proto = '') {
set $http_x_forwarded_proto $scheme;
}
## Application specific logs
## access_log /var/log/nginx/artifactory-access.log timing;
## error_log /var/log/nginx/artifactory-error.log;
rewrite ^/$ /artifactory/webapp/ redirect;
rewrite ^/artifactory/?(/webapp)?$ /artifactory/webapp/ redirect;
if ( $repo != "" ) {
rewrite ^/(v1|v2)/(.*) /artifactory/api/docker/$repo/$1/$2 break;
}
rewrite ^/(v1|v2)/([^/]+)(.*)$ /artifactory/api/docker/$2/$1/$3;
rewrite ^/(v1|v2)/ /artifactory/api/docker/$1/;
chunked_transfer_encoding on;
client_max_body_size 0;
location /artifactory/ {
proxy_read_timeout 900;
proxy_pass_header Server;
proxy_cookie_path ~*^/.* /;
if ( $request_uri ~ ^/artifactory/(.*)$ ) {
proxy_pass http://artifactory-artifactory:8081/artifactory/$1 break;
}
proxy_pass http://artifactory-artifactory:8081/artifactory/;
proxy_set_header X-Artifactory-Override-Base-Url $http_x_forwarded_proto://$host:$server_port/artifactory;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
```
3. Create configMap of `artifactory.conf` created with step above.
```bash
kubectl create configmap art-nginx-conf --from-file=artifactory.conf
```
4. Deploy Artifactory using helm chart.
You can achieve this by providing the name of configMap created above to `nginx.customArtifactoryConfigMap` in [values.yaml](values.yaml)
Following is command to set values at runtime:
```bash
helm install --name artifactory-ha nginx.customArtifactoryConfigMap=art-nginx-conf jfrog/artifactory-ha
```
\ No newline at end of file
# JFrog Artifactory Chart Upgrade Notes
This file describes special upgrade notes needed at specific versions
## Upgrade from 0.X to 1.X
**DOWNTIME IS REQUIRED FOR AN UPGRADE!**
* If this is a new deployment or you already use an external database (`postgresql.enabled=false`), these changes **do not affect you!**
* PostgreSQL sub chart was upgraded to version `6.5.x`. This version is not backward compatible with the old version (`0.9.5`)!
* Note the following **PostgreSQL** Helm chart changes
* The chart configuration has changed! See [values.yaml](values.yaml) for the new keys used
* **PostgreSQL** is deployed as a StatefulSet
* See [PostgreSQL helm chart](https://hub.helm.sh/charts/stable/postgresql) for all available configurations
* Upgrade
* Due to breaking changes in the **PostgreSQL** Helm chart, a migration of the database is needed from the old to the new database
* The recommended migration process is the [full system export and import](https://www.jfrog.com/confluence/display/RTF/Importing+and+Exporting)
* **NOTE:** To save time, export only metadata and configuration (check `Exclude Content` in the `System Import & Export`) since the Artifactory filestore is persisted
* Upgrade steps:
1. Block user access to Artifactory (do not shutdown)
a. Scale down the cluster to primary node only (`node.replicaCount=0`) so the exported db and configuration will be kept on one known node (the primary)
b. If your Artifactory HA K8s service is set to member nodes only (`service.pool=members`) you will need to access the primary node directly (use `kubectl port-forward`)
2. Perform `Export System` from the `Admin` -> `Import & Export` -> `System` -> `Export System`
a. Check `Exclude Content` to save export size (as Artifactory filestore will persist across upgrade)
b. Choose to save the export on the persisted Artifactory volume (`/var/opt/jfrog/artifactory/`)
c. Click `Export` (this can take some time)
3. Run the `helm upgrade` with the new version. Old PostgreSQL will be removed and new one deployed
a. You must pass explicit "ready for upgrade flag" with `--set databaseUpgradeReady=yes`. Failing to provide this will block the upgrade!
4. Once ready, open Artifactory UI (you might need to re-enter a valid license). Skip all onboarding wizard steps
a. **NOTE:** Don't worry you can't see the old config and files. It will all restore with the system import in the next step
5. Perform `Import System` from the `Admin` -> `Import & Export` -> `System` -> `Import System`
a. Browse to where the export was saved Artifactory volume (`/var/opt/jfrog/artifactory/<directory-you-set>`)
b. Click `Import` (this can take some time)
6. Restore access to Artifactory
a. Scale the cluster member nodes back to the original size
* Artifactory should now be ready to get back to normal operation
# JFrog Artifactory High Availability Helm Chart
Universal Repository Manager supporting all major packaging formats, build tools and CI servers.
## Chart Details
This chart will do the following:
* Deploy Artifactory highly available cluster. 1 primary node and 2 member nodes.
* Deploy a PostgreSQL database
* Deploy an Nginx server(optional)
## Useful links
Blog: [Herd Trust Into Your Rancher Labs Multi-Cloud Strategy with Artifactory](https://jfrog.com/blog/herd-trust-into-your-rancher-labs-multi-cloud-strategy-with-artifactory/)
## Activate Your Artifactory Instance
Don't have a license? Please send an email to [rancher-jfrog-licenses@jfrog.com](mailto:rancher-jfrog-licenses@jfrog.com) to get it.
apiVersion: v1
appVersion: 11.5.0
description: Chart for PostgreSQL, an object-relational database management system
(ORDBMS) with an emphasis on extensibility and on standards-compliance.
engine: gotpl
home: https://www.postgresql.org/
icon: https://bitnami.com/assets/stacks/postgresql/img/postgresql-stack-110x117.png
keywords:
- postgresql
- postgres
- database
- sql
- replication
- cluster
maintainers:
- email: containers@bitnami.com
name: Bitnami
- email: cedric@desaintmartin.fr
name: desaintmartin
name: postgresql
sources:
- https://github.com/bitnami/bitnami-docker-postgresql
version: 6.5.3
Copy here your postgresql.conf and/or pg_hba.conf files to use it as a config map.
If you don't want to provide the whole configuration file and only specify certain parameters, you can copy here your extended `.conf` files.
These files will be injected as a config maps and add/overwrite the default configuration using the `include_dir` directive that allows settings to be loaded from files other than the default `postgresql.conf`.
More info in the [bitnami-docker-postgresql README](https://github.com/bitnami/bitnami-docker-postgresql#configuration-file).
You can copy here your custom `.sh`, `.sql` or `.sql.gz` file so they are executed during the first boot of the image.
More info in the [bitnami-docker-postgresql](https://github.com/bitnami/bitnami-docker-postgresql#initializing-a-new-instance) repository.
\ No newline at end of file
** Please be patient while the chart is being deployed **
PostgreSQL can be accessed via port {{ template "postgresql.port" . }} on the following DNS name from within your cluster:
{{ template "postgresql.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local - Read/Write connection
{{- if .Values.replication.enabled }}
{{ template "postgresql.fullname" . }}-read.{{ .Release.Namespace }}.svc.cluster.local - Read only connection
{{- end }}
To get the password for "{{ template "postgresql.username" . }}" run:
export POSTGRES_PASSWORD=$(kubectl get secret --namespace {{ .Release.Namespace }} {{ template "postgresql.secretName" . }} -o jsonpath="{.data.postgresql-password}" | base64 --decode)
To connect to your database run the following command:
kubectl run {{ template "postgresql.fullname" . }}-client --rm --tty -i --restart='Never' --namespace {{ .Release.Namespace }} --image {{ template "postgresql.image" . }} --env="PGPASSWORD=$POSTGRES_PASSWORD" {{- if and (.Values.networkPolicy.enabled) (not .Values.networkPolicy.allowExternal) }}
--labels="{{ template "postgresql.fullname" . }}-client=true" {{- end }} --command -- psql --host {{ template "postgresql.fullname" . }} -U {{ .Values.postgresqlUsername }}{{- if .Values.postgresqlDatabase }} -d {{ .Values.postgresqlDatabase }}{{- end }} -p {{ template "postgresql.port" . }}
{{ if and (.Values.networkPolicy.enabled) (not .Values.networkPolicy.allowExternal) }}
Note: Since NetworkPolicy is enabled, only pods with label {{ template "postgresql.fullname" . }}-client=true" will be able to connect to this PostgreSQL cluster.
{{- end }}
To connect to your database from outside the cluster execute the following commands:
{{- if contains "NodePort" .Values.service.type }}
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "postgresql.fullname" . }})
{{ if (include "postgresql.password" . ) }}PGPASSWORD="$POSTGRES_PASSWORD" {{ end }}psql --host $NODE_IP --port $NODE_PORT -U {{ .Values.postgresqlUsername }}{{- if .Values.postgresqlDatabase }} -d {{ .Values.postgresqlDatabase }}{{- end }}
{{- else if contains "LoadBalancer" .Values.service.type }}
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
Watch the status with: 'kubectl get svc --namespace {{ .Release.Namespace }} -w {{ template "postgresql.fullname" . }}'
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "postgresql.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
{{ if (include "postgresql.password" . ) }}PGPASSWORD="$POSTGRES_PASSWORD" {{ end }}psql --host $SERVICE_IP --port {{ template "postgresql.port" . }} -U {{ .Values.postgresqlUsername }}{{- if .Values.postgresqlDatabase }} -d {{ .Values.postgresqlDatabase }}{{- end }}
{{- else if contains "ClusterIP" .Values.service.type }}
kubectl port-forward --namespace {{ .Release.Namespace }} svc/{{ template "postgresql.fullname" . }} {{ template "postgresql.port" . }}:{{ template "postgresql.port" . }} &
{{ if (include "postgresql.password" . ) }}PGPASSWORD="$POSTGRES_PASSWORD" {{ end }}psql --host 127.0.0.1 -U {{ .Values.postgresqlUsername }}{{- if .Values.postgresqlDatabase }} -d {{ .Values.postgresqlDatabase }}{{- end }} -p {{ template "postgresql.port" . }}
{{- end }}
{{- if and (contains "bitnami/" .Values.image.repository) (not (.Values.image.tag | toString | regexFind "-r\\d+$|sha256:")) }}
WARNING: Rolling tag detected ({{ .Values.image.repository }}:{{ .Values.image.tag }}), please note that it is strongly recommended to avoid using rolling tags in a production environment.
+info https://docs.bitnami.com/containers/how-to/understand-rolling-tags-containers/
{{- end }}
{{ if and (or (.Files.Glob "files/postgresql.conf") (.Files.Glob "files/pg_hba.conf") .Values.postgresqlConfiguration .Values.pgHbaConfiguration) (not .Values.configurationConfigMap) }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ template "postgresql.fullname" . }}-configuration
labels:
app: {{ template "postgresql.name" . }}
chart: {{ template "postgresql.chart" . }}
release: {{ .Release.Name | quote }}
heritage: {{ .Release.Service | quote }}
data:
{{- if (.Files.Glob "files/postgresql.conf") }}
{{ (.Files.Glob "files/postgresql.conf").AsConfig | indent 2 }}
{{- else if .Values.postgresqlConfiguration }}
postgresql.conf: |
{{- range $key, $value := default dict .Values.postgresqlConfiguration }}
{{ $key | snakecase }}={{ $value }}
{{- end }}
{{- end }}
{{- if (.Files.Glob "files/pg_hba.conf") }}
{{ (.Files.Glob "files/pg_hba.conf").AsConfig | indent 2 }}
{{- else if .Values.pgHbaConfiguration }}
pg_hba.conf: |
{{ .Values.pgHbaConfiguration | indent 4 }}
{{- end }}
{{ end }}
{{- if and (or (.Files.Glob "files/conf.d/*.conf") .Values.postgresqlExtendedConf) (not .Values.extendedConfConfigMap)}}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ template "postgresql.fullname" . }}-extended-configuration
labels:
app: {{ template "postgresql.name" . }}
chart: {{ template "postgresql.chart" . }}
release: {{ .Release.Name | quote }}
heritage: {{ .Release.Service | quote }}
data:
{{- with .Files.Glob "files/conf.d/*.conf" }}
{{ .AsConfig | indent 2 }}
{{- end }}
{{ with .Values.postgresqlExtendedConf }}
override.conf: |
{{- range $key, $value := . }}
{{ $key | snakecase }}={{ $value }}
{{- end }}
{{- end }}
{{- end }}
{{- if and (or (.Files.Glob "files/docker-entrypoint-initdb.d/*.{sh,sql,sql.gz}") .Values.initdbScripts) (not .Values.initdbScriptsConfigMap) }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ template "postgresql.fullname" . }}-init-scripts
labels:
app: {{ template "postgresql.name" . }}
chart: {{ template "postgresql.chart" . }}
release: {{ .Release.Name | quote }}
heritage: {{ .Release.Service | quote }}
{{- with .Files.Glob "files/docker-entrypoint-initdb.d/*.sql.gz" }}
binaryData:
{{- range $path, $bytes := . }}
{{ base $path }}: {{ $.Files.Get $path | b64enc | quote }}
{{- end }}
{{- end }}
data:
{{- with .Files.Glob "files/docker-entrypoint-initdb.d/*.{sh,sql}" }}
{{ .AsConfig | indent 2 }}
{{- end }}
{{- with .Values.initdbScripts }}
{{ toYaml . | indent 2 }}
{{- end }}
{{- end }}
{{- if .Values.metrics.enabled }}
apiVersion: v1
kind: Service
metadata:
name: {{ template "postgresql.fullname" . }}-metrics
labels:
app: {{ template "postgresql.name" . }}
chart: {{ template "postgresql.chart" . }}
release: {{ .Release.Name | quote }}
heritage: {{ .Release.Service | quote }}
annotations:
{{ toYaml .Values.metrics.service.annotations | indent 4 }}
spec:
type: {{ .Values.metrics.service.type }}
{{- if and (eq .Values.metrics.service.type "LoadBalancer") .Values.metrics.service.loadBalancerIP }}
loadBalancerIP: {{ .Values.metrics.service.loadBalancerIP }}
{{- end }}
ports:
- name: metrics
port: 9187
targetPort: metrics
selector:
app: {{ template "postgresql.name" . }}
release: {{ .Release.Name }}
role: master
{{- end }}
{{- if .Values.networkPolicy.enabled }}
kind: NetworkPolicy
apiVersion: {{ template "postgresql.networkPolicy.apiVersion" . }}
metadata:
name: {{ template "postgresql.fullname" . }}
labels:
app: {{ template "postgresql.name" . }}
chart: {{ template "postgresql.chart" . }}
release: {{ .Release.Name | quote }}
heritage: {{ .Release.Service | quote }}
spec:
podSelector:
matchLabels:
app: {{ template "postgresql.name" . }}
release: {{ .Release.Name | quote }}
ingress:
# Allow inbound connections
- ports:
- port: {{ template "postgresql.port" . }}
{{- if not .Values.networkPolicy.allowExternal }}
from:
- podSelector:
matchLabels:
{{ template "postgresql.fullname" . }}-client: "true"
- podSelector:
matchLabels:
app: {{ template "postgresql.name" . }}
release: {{ .Release.Name | quote }}
role: slave
{{- end }}
# Allow prometheus scrapes
- ports:
- port: 9187
{{- end }}
{{- if (include "postgresql.createSecret" .) }}
apiVersion: v1
kind: Secret
metadata:
name: {{ template "postgresql.fullname" . }}
labels:
app: {{ template "postgresql.name" . }}
chart: {{ template "postgresql.chart" . }}
release: {{ .Release.Name | quote }}
heritage: {{ .Release.Service | quote }}
type: Opaque
data:
postgresql-password: {{ include "postgresql.password" . | b64enc | quote }}
{{- if .Values.replication.enabled }}
postgresql-replication-password: {{ include "postgresql.replication.password" . | b64enc | quote }}
{{- end }}
{{- end -}}
{{- if and (.Values.serviceAccount.enabled) (not .Values.serviceAccount.name) }}
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
app: {{ template "postgresql.name" . }}
chart: {{ template "postgresql.chart" . }}
release: {{ .Release.Name | quote }}
heritage: {{ .Release.Service | quote }}
name: {{ template "postgresql.fullname" . }}
{{- end }}
\ No newline at end of file
{{- if and .Values.metrics.enabled .Values.metrics.serviceMonitor.enabled }}
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: {{ include "postgresql.fullname" . }}
{{- if .Values.metrics.serviceMonitor.namespace }}
namespace: {{ .Values.metrics.serviceMonitor.namespace }}
{{- end }}
labels:
app: {{ template "postgresql.name" . }}
chart: {{ template "postgresql.chart" . }}
release: {{ .Release.Name | quote }}
heritage: {{ .Release.Service | quote }}
{{- if .Values.metrics.serviceMonitor.additionalLabels }}
{{ toYaml .Values.metrics.serviceMonitor.additionalLabels | indent 4 }}
{{- end }}
spec:
endpoints:
- port: metrics
{{- if .Values.metrics.serviceMonitor.interval }}
interval: {{ .Values.metrics.serviceMonitor.interval }}
{{- end }}
{{- if .Values.metrics.serviceMonitor.scrapeTimeout }}
scrapeTimeout: {{ .Values.metrics.serviceMonitor.scrapeTimeout }}
{{- end }}
namespaceSelector:
matchNames:
- {{ .Release.Namespace }}
selector:
matchLabels:
app: {{ template "postgresql.name" . }}
release: {{ .Release.Name }}
{{- end }}
apiVersion: v1
kind: Service
metadata:
name: {{ template "postgresql.fullname" . }}-headless
labels:
app: {{ template "postgresql.name" . }}
chart: {{ template "postgresql.chart" . }}
release: {{ .Release.Name | quote }}
heritage: {{ .Release.Service | quote }}
spec:
type: ClusterIP
clusterIP: None
ports:
- name: postgresql
port: {{ template "postgresql.port" . }}
targetPort: postgresql
selector:
app: {{ template "postgresql.name" . }}
release: {{ .Release.Name | quote }}
{{- if .Values.replication.enabled }}
apiVersion: v1
kind: Service
metadata:
name: {{ template "postgresql.fullname" . }}-read
labels:
app: {{ template "postgresql.name" . }}
chart: {{ template "postgresql.chart" . }}
release: {{ .Release.Name | quote }}
heritage: {{ .Release.Service | quote }}
{{- with .Values.service.annotations }}
annotations:
{{ toYaml . | indent 4 }}
{{- end }}
spec:
type: {{ .Values.service.type }}
{{- if and .Values.service.loadBalancerIP (eq .Values.service.type "LoadBalancer") }}
loadBalancerIP: {{ .Values.service.loadBalancerIP }}
{{- end }}
ports:
- name: postgresql
port: {{ template "postgresql.port" . }}
targetPort: postgresql
{{- if .Values.service.nodePort }}
nodePort: {{ .Values.service.nodePort }}
{{- end }}
selector:
app: {{ template "postgresql.name" . }}
release: {{ .Release.Name | quote }}
role: slave
{{- end }}
apiVersion: v1
kind: Service
metadata:
name: {{ template "postgresql.fullname" . }}
labels:
app: {{ template "postgresql.name" . }}
chart: {{ template "postgresql.chart" . }}
release: {{ .Release.Name | quote }}
heritage: {{ .Release.Service | quote }}
{{- with .Values.service.annotations }}
annotations:
{{ tpl (toYaml .) $ | indent 4 }}
{{- end }}
spec:
type: {{ .Values.service.type }}
{{- if and .Values.service.loadBalancerIP (eq .Values.service.type "LoadBalancer") }}
loadBalancerIP: {{ .Values.service.loadBalancerIP }}
{{- end }}
{{- if and (eq .Values.service.type "LoadBalancer") .Values.service.loadBalancerSourceRanges }}
loadBalancerSourceRanges:
{{ with .Values.service.loadBalancerSourceRanges }}
{{ toYaml . | indent 4 }}
{{- end }}
{{- end }}
{{- if and (eq .Values.service.type "ClusterIP") .Values.service.clusterIP }}
clusterIP: {{ .Values.service.clusterIP }}
{{- end }}
ports:
- name: postgresql
port: {{ template "postgresql.port" . }}
targetPort: postgresql
{{- if .Values.service.nodePort }}
nodePort: {{ .Values.service.nodePort }}
{{- end }}
selector:
app: {{ template "postgresql.name" . }}
release: {{ .Release.Name | quote }}
role: master
{
"$schema": "http://json-schema.org/schema#",
"type": "object",
"properties": {
"postgresqlUsername": {
"type": "string",
"title": "Admin user",
"form": "username"
},
"postgresqlPassword": {
"type": "string",
"title": "Password",
"form": "password"
},
"persistence": {
"type": "object",
"properties": {
"size": {
"type": "string",
"title": "Disk Size",
"form": "diskSize",
"render": "slider",
"sliderMin": 1,
"sliderMax": 100,
"sliderUnit": "Gi"
}
}
},
"resources": {
"type": "object",
"title": "Required Resources",
"description": "Configure resource requests",
"form": "resources",
"properties": {
"requests": {
"type": "object",
"properties": {
"memory": {
"type": "string",
"form": "memoryRequest",
"render": "slider",
"title": "Memory Request",
"sliderMin": 10,
"sliderMax": 2048,
"sliderUnit": "Mi"
},
"cpu": {
"type": "string",
"form": "cpuRequest",
"render": "slider",
"title": "CPU Request",
"sliderMin": 10,
"sliderMax": 2000,
"sliderUnit": "m"
}
}
}
}
},
"replication": {
"type": "object",
"form": "replication",
"title": "Replication Details",
"properties": {
"enabled": {
"type": "boolean",
"title": "Enable Replication",
"form": "enableReplication",
"enables": "replication"
},
"slaveReplicas": {
"type": "integer",
"title": "Slave Replicas",
"form": "slaveReplicas"
}
}
},
"volumePermissions": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean",
"form": "enableVolumePermissions",
"title": "Enable Init Containers",
"description": "Change the owner of the persist volume mountpoint to RunAsUser:fsGroup"
}
}
},
"metrics": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean",
"title": "Configure metrics exporter",
"form": "enableMetrics"
}
}
}
}
}
artifactory:
persistence:
enabled: true
postgresql:
postgresqlPassword: "password"
postgresqlConfiguration:
max_connections: "102"
persistence:
enabled: true
nginx:
enabled: false
service:
## For minikube, set this to NodePort, elsewhere use LoadBalancer
type: NodePort
ingress:
enabled: true
defaultBackend:
enabled: false
hosts:
- artifactory.test.com
annotations:
ingress.kubernetes.io/proxy-body-size: "0"
ingress.kubernetes.io/proxy-read-timeout: "600"
ingress.kubernetes.io/proxy-send-timeout: "600"
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/proxy-body-size: "0"
artifactory:
persistence:
enabled: true
loggers:
- request.log
- access.log
catalinaLoggers:
- localhost.log
postgresql:
postgresqlPassword: "password"
postgresqlConfiguration:
max_connections: "102"
persistence:
enabled: true
nginx:
enabled: true
service:
## For minikube, set this to NodePort, elsewhere use LoadBalancer
type: NodePort
loggers:
- access.log
- error.log
dependencies:
- name: postgresql
repository: https://kubernetes-charts.storage.googleapis.com/
version: 6.5.3
digest: sha256:5074ce11914b886ccd7925916115f4370ffe2343c39968a69e40ab2ccd593de6
generated: 2019-10-27T16:15:40.559563+02:00
dependencies:
- name: postgresql
version: 6.5.3
repository: https://kubernetes-charts.storage.googleapis.com/
condition: postgresql.enabled
Congratulations. You have just deployed JFrog Artifactory HA!
{{- if and (not .Values.artifactory.masterKeySecretName) (eq .Values.artifactory.masterKey "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF") }}
***************************************** WARNING ******************************************
* Your Artifactory master key is still set to the provided example: *
* artifactory.masterKey=FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF *
* *
* You should change this to your own generated key: *
* $ export MASTER_KEY=$(openssl rand -hex 32) *
* $ echo ${MASTER_KEY} *
* *
* Pass the created master key to helm with '--set artifactory.masterKey=${MASTER_KEY}' *
* *
* Alternatively, you can use a pre-existing secret with a key called master-key with *
* '--set artifactory.masterKeySecretName=${SECRET_NAME}' *
********************************************************************************************
{{- end }}
{{- if .Values.postgresql.enabled }}
DATABASE:
To extract the database password, run the following
export DB_PASSWORD=$(kubectl get --namespace {{ .Release.Namespace }} $(kubectl get secret --namespace {{ .Release.Namespace }} -o name | grep postgresql) -o jsonpath="{.data.postgresql-password}" | base64 --decode)
echo ${DB_PASSWORD}
{{- end }}
SETUP:
1. Get the Artifactory IP and URL
{{- if contains "NodePort" .Values.nginx.service.type }}
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "artifactory-ha.nginx.fullname" . }})
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT/
{{- else if contains "LoadBalancer" .Values.nginx.service.type }}
NOTE: It may take a few minutes for the LoadBalancer public IP to be available!
You can watch the status of the service by running 'kubectl get svc -w {{ template "artifactory-ha.nginx.fullname" . }}'
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "artifactory-ha.nginx.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
echo http://$SERVICE_IP/
{{- else if contains "ClusterIP" .Values.nginx.service.type }}
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "component={{ .Values.nginx.name }}" -o jsonpath="{.items[0].metadata.name}")
kubectl port-forward --namespace {{ .Release.Namespace }} $POD_NAME 8080:80
echo http://127.0.0.1:8080
{{- end }}
2. Open Artifactory in your browser
Default credential for Artifactory:
user: admin
password: password
{{- if .Values.artifactory.license.secret }}
3. Manage Artifactory license through the {{ .Values.artifactory.license.secret }} secret ONLY!
Since the artifactory license(s) is managed with a secret ({{ .Values.artifactory.license.secret }}), any change through the Artifactory UI might not be saved!
{{- else }}
3. Add HA licenses to activate Artifactory HA through the Artifactory UI
NOTE: Each Artifactory node requires a valid license. See https://www.jfrog.com/confluence/display/RTF/HA+Installation+and+Setup for more details.
{{- end }}
{{ if or .Values.artifactory.primary.javaOpts.jmx.enabled .Values.artifactory.node.javaOpts.jmx.enabled }}
JMX configuration:
{{- if not (contains "LoadBalancer" .Values.artifactory.service.type) }}
If you want to access JMX from you computer with jconsole, you should set ".Values.artifactory.service.type=LoadBalancer" !!!
{{ end }}
1. Get the Artifactory service IP:
{{- if .Values.artifactory.primary.javaOpts.jmx.enabled }}
export PRIMARY_SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "artifactory-ha.primary.name" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
{{- end }}
{{- if .Values.artifactory.node.javaOpts.jmx.enabled }}
export MEMBER_SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "artifactory-ha.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
{{- end }}
2. Map the service name to the service IP in /etc/hosts:
{{- if .Values.artifactory.primary.javaOpts.jmx.enabled }}
sudo sh -c "echo \"${PRIMARY_SERVICE_IP} {{ template "artifactory-ha.primary.name" . }}\" >> /etc/hosts"
{{- end }}
{{- if .Values.artifactory.node.javaOpts.jmx.enabled }}
sudo sh -c "echo \"${MEMBER_SERVICE_IP} {{ template "artifactory-ha.fullname" . }}\" >> /etc/hosts"
{{- end }}
3. Launch jconsole:
{{- if .Values.artifactory.primary.javaOpts.jmx.enabled }}
jconsole {{ template "artifactory-ha.primary.name" . }}:{{ .Values.artifactory.primary.javaOpts.jmx.port }}
{{- end }}
{{- if .Values.artifactory.node.javaOpts.jmx.enabled }}
jconsole {{ template "artifactory-ha.fullname" . }}:{{ .Values.artifactory.node.javaOpts.jmx.port }}
{{- end }}
{{- end }}
{{/* vim: set filetype=mustache: */}}
{{/*
Expand the name of the chart.
*/}}
{{- define "artifactory-ha.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
The primary node name
*/}}
{{- define "artifactory-ha.primary.name" -}}
{{- $name := .Release.Name | trunc 29 -}}
{{- printf "%s-%s-primary" $name .Chart.Name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
The member node name
*/}}
{{- define "artifactory-ha.node.name" -}}
{{- $name := .Release.Name | trunc 29 -}}
{{- printf "%s-%s-member" $name .Chart.Name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Expand the name nginx service.
*/}}
{{- define "artifactory-ha.nginx.name" -}}
{{- default .Values.nginx.name .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).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "artifactory-ha.fullname" -}}
{{- if .Values.fullnameOverride -}}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- $name := default .Chart.Name .Values.nameOverride -}}
{{- if contains $name .Release.Name -}}
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- end -}}
{{- 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).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "artifactory-ha.nginx.fullname" -}}
{{- if .Values.nginx.fullnameOverride -}}
{{- .Values.nginx.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- $name := default .Chart.Name .Values.nginx.name -}}
{{- if contains $name .Release.Name -}}
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{/*
Create the name of the service account to use
*/}}
{{- define "artifactory-ha.serviceAccountName" -}}
{{- if .Values.serviceAccount.create -}}
{{ default (include "artifactory-ha.fullname" .) .Values.serviceAccount.name }}
{{- else -}}
{{ default "default" .Values.serviceAccount.name }}
{{- end -}}
{{- end -}}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "artifactory-ha.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Generate SSL certificates
*/}}
{{- define "artifactory-ha.gen-certs" -}}
{{- $altNames := list ( printf "%s.%s" (include "artifactory-ha.name" .) .Release.Namespace ) ( printf "%s.%s.svc" (include "artifactory-ha.name" .) .Release.Namespace ) -}}
{{- $ca := genCA "artifactory-ca" 365 -}}
{{- $cert := genSignedCert ( include "artifactory-ha.name" . ) nil $altNames 365 $ca -}}
tls.crt: {{ $cert.Cert | b64enc }}
tls.key: {{ $cert.Key | b64enc }}
{{- end -}}
{{- if not (and .Values.artifactory.accessAdmin.secret .Values.artifactory.accessAdmin.dataKey) }}
{{- if .Values.artifactory.accessAdmin.password }}
kind: Secret
apiVersion: v1
metadata:
name: {{ template "artifactory-ha.fullname" . }}-bootstrap-creds
labels:
app: {{ template "artifactory-ha.name" . }}
chart: {{ template "artifactory-ha.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
data:
bootstrap.creds: {{ (printf "access-admin@%s=%s" .Values.artifactory.accessAdmin.ip .Values.artifactory.accessAdmin.password) | b64enc }}
{{- end }}
{{- end }}
{{- if not .Values.artifactory.persistence.customBinarystoreXmlSecret }}
kind: Secret
apiVersion: v1
metadata:
name: {{ template "artifactory-ha.fullname" . }}-binarystore
labels:
app: {{ template "artifactory-ha.name" . }}
chart: {{ template "artifactory-ha.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
stringData:
binarystore.xml: |-
{{ tpl .Values.artifactory.persistence.binarystoreXml . | indent 4 }}
{{- end }}
kind: ConfigMap
apiVersion: v1
metadata:
name: {{ template "artifactory-ha.fullname" . }}-installer-info
labels:
app: {{ template "artifactory-ha.name" . }}
chart: {{ template "artifactory-ha.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
data:
installer-info.json: |
{
"productId": "Helm_artifactory-ha/{{ .Chart.Version }}",
"features": [
{
"featureId": "ArtifactoryVersion/{{ default .Chart.AppVersion .Values.artifactory.image.version }}"
},
{
"featureId": "{{ if .Values.postgresql.enabled }}postgresql{{ else }}{{ default "derby" .Values.database.type }}{{ end }}/0.0.0"
},
{
"featureId": "Platform/{{ default "kubernetes" .Values.installer.platform }}"
}
]
}
{{- with .Values.artifactory.license.licenseKey }}
apiVersion: v1
kind: Secret
metadata:
name: {{ template "artifactory-ha.fullname" $ }}-license
labels:
app: {{ template "artifactory-ha.name" $ }}
chart: {{ template "artifactory-ha.chart" $ }}
heritage: {{ $.Release.Service }}
release: {{ $.Release.Name }}
type: Opaque
data:
artifactory.lic: {{ . | b64enc | quote }}
{{- end }}
\ No newline at end of file
{{- range .Values.networkpolicy }}
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: {{ template "artifactory-ha.fullname" $ }}-{{ .name }}-networkpolicy
labels:
app: {{ template "artifactory-ha.name" $ }}
chart: {{ template "artifactory-ha.chart" $ }}
release: {{ $.Release.Name }}
heritage: {{ $.Release.Service }}
spec:
{{- if .podSelector }}
podSelector:
{{ .podSelector | toYaml | trimSuffix "\n" | indent 4 -}}
{{ else }}
podSelector: {}
{{- end }}
policyTypes:
{{- if .ingress }}
- Ingress
{{- end }}
{{- if .egress }}
- Egress
{{- end }}
{{- if .ingress }}
ingress:
{{ .ingress | toYaml | trimSuffix "\n" | indent 2 -}}
{{- end }}
{{- if .egress }}
egress:
{{ .egress | toYaml | trimSuffix "\n" | indent 2 -}}
{{- end }}
---
{{- end -}}
\ No newline at end of file
{{- if eq .Values.artifactory.persistence.type "nfs" }}
### Artifactory HA data
apiVersion: v1
kind: PersistentVolume
metadata:
name: {{ template "artifactory-ha.fullname" . }}-data-pv
labels:
app: {{ template "artifactory-ha.name" . }}
chart: {{ template "artifactory-ha.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
id: {{ template "artifactory-ha.name" . }}-data-pv
type: nfs-volume
spec:
capacity:
storage: {{ .Values.artifactory.persistence.nfs.capacity }}
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
nfs:
server: {{ .Values.artifactory.persistence.nfs.ip }}
path: "{{ .Values.artifactory.persistence.nfs.haDataMount }}"
readOnly: false
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: {{ template "artifactory-ha.fullname" . }}-data-pvc
labels:
app: {{ template "artifactory-ha.name" . }}
chart: {{ template "artifactory-ha.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
type: nfs-volume
spec:
accessModes:
- ReadWriteOnce
storageClassName: ""
resources:
requests:
storage: {{ .Values.artifactory.persistence.nfs.capacity }}
selector:
matchLabels:
id: {{ template "artifactory-ha.name" . }}-data-pv
app: {{ template "artifactory-ha.name" . }}
release: {{ .Release.Name }}
---
### Artifactory HA backup
apiVersion: v1
kind: PersistentVolume
metadata:
name: {{ template "artifactory-ha.fullname" . }}-backup-pv
labels:
app: {{ template "artifactory-ha.name" . }}
chart: {{ template "artifactory-ha.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
id: {{ template "artifactory-ha.name" . }}-backup-pv
type: nfs-volume
spec:
capacity:
storage: {{ .Values.artifactory.persistence.nfs.capacity }}
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
nfs:
server: {{ .Values.artifactory.persistence.nfs.ip }}
path: "{{ .Values.artifactory.persistence.nfs.haBackupMount }}"
readOnly: false
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: {{ template "artifactory-ha.fullname" . }}-backup-pvc
labels:
app: {{ template "artifactory-ha.name" . }}
chart: {{ template "artifactory-ha.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
type: nfs-volume
spec:
accessModes:
- ReadWriteOnce
storageClassName: ""
resources:
requests:
storage: {{ .Values.artifactory.persistence.nfs.capacity }}
selector:
matchLabels:
id: {{ template "artifactory-ha.name" . }}-backup-pv
app: {{ template "artifactory-ha.name" . }}
release: {{ .Release.Name }}
{{- end }}
\ No newline at end of file
apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
name: {{ template "artifactory-ha.fullname" . }}-node
labels:
app: {{ template "artifactory-ha.name" . }}
chart: {{ template "artifactory-ha.chart" . }}
component: {{ .Values.artifactory.name }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
spec:
selector:
matchLabels:
app: {{ template "artifactory-ha.name" . }}
{{- if eq .Values.artifactory.service.pool "members" }}
role: {{ template "artifactory-ha.node.name" . }}
{{- end }}
release: {{ .Release.Name }}
minAvailable: {{ .Values.artifactory.node.minAvailable }}
{{- if .Values.rbac.create }}
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
labels:
app: {{ template "artifactory-ha.name" . }}
chart: {{ template "artifactory-ha.chart" . }}
component: {{ .Values.artifactory.name }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
name: {{ template "artifactory-ha.fullname" . }}
rules:
{{ toYaml .Values.rbac.role.rules }}
{{- end }}
{{- if .Values.rbac.create }}
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
app: {{ template "artifactory-ha.name" . }}
chart: {{ template "artifactory-ha.chart" . }}
component: {{ .Values.artifactory.name }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
name: {{ template "artifactory-ha.fullname" . }}
subjects:
- kind: ServiceAccount
name: {{ template "artifactory-ha.serviceAccountName" . }}
roleRef:
kind: Role
apiGroup: rbac.authorization.k8s.io
name: {{ template "artifactory-ha.fullname" . }}
{{- end }}
apiVersion: v1
kind: Secret
metadata:
name: {{ template "artifactory-ha.fullname" . }}
labels:
app: {{ template "artifactory-ha.name" . }}
chart: {{ template "artifactory-ha.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
type: Opaque
data:
{{- if not .Values.artifactory.masterKeySecretName }}
master-key: {{ .Values.artifactory.masterKey | b64enc | quote }}
{{- end }}
{{- if .Values.database.password }}
db-password: {{ .Values.database.password | b64enc | quote }}
{{- end }}
# Service for all Artifactory cluster nodes.
apiVersion: v1
kind: Service
metadata:
name: {{ template "artifactory-ha.fullname" . }}
labels:
app: {{ template "artifactory-ha.name" . }}
chart: {{ template "artifactory-ha.chart" . }}
component: {{ .Values.artifactory.name }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
spec:
type: {{ .Values.artifactory.service.type }}
{{- if and (eq .Values.artifactory.service.type "ClusterIP") .Values.artifactory.service.clusterIP }}
clusterIP: {{ .Values.artifactory.service.clusterIP }}
{{- end }}
ports:
- port: {{ .Values.artifactory.externalPort }}
targetPort: {{ .Values.artifactory.internalPort }}
protocol: TCP
name: http
{{- with .Values.artifactory.node.javaOpts.jmx }}
{{- if .enabled }}
- port: {{ .port }}
targetPort: {{ .port }}
protocol: TCP
name: jmx
{{- end }}
{{- end }}
selector:
{{- if eq .Values.artifactory.service.pool "members" }}
role: {{ template "artifactory-ha.node.name" . }}
{{- end }}
app: {{ template "artifactory-ha.name" . }}
component: "{{ .Values.artifactory.name }}"
release: {{ .Release.Name }}
---
# Internal service for Artifactory primary node only!
# Used by member nodes to check readiness of primary node before starting up
apiVersion: v1
kind: Service
metadata:
name: {{ template "artifactory-ha.primary.name" . }}
labels:
app: {{ template "artifactory-ha.name" . }}
chart: {{ template "artifactory-ha.chart" . }}
component: {{ .Values.artifactory.name }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
spec:
type: {{ .Values.artifactory.service.type }}
{{- if and (eq .Values.artifactory.service.type "ClusterIP") .Values.artifactory.service.clusterIP }}
clusterIP: {{ .Values.artifactory.service.clusterIP }}
{{- end }}
ports:
- port: {{ .Values.artifactory.externalPort }}
targetPort: {{ .Values.artifactory.internalPort }}
protocol: TCP
name: http
{{- if .Values.artifactory.replicator.enabled }}
- port: {{ .Values.artifactory.externalPortReplicator }}
targetPort: {{ .Values.artifactory.internalPortReplicator }}
protocol: TCP
name: replicator
{{- end}}
{{- with .Values.artifactory.primary.javaOpts.jmx }}
{{- if .enabled }}
- port: {{ .port }}
targetPort: {{ .port }}
protocol: TCP
name: jmx
{{- end }}
{{- end }}
selector:
role: {{ template "artifactory-ha.primary.name" . }}
app: {{ template "artifactory-ha.name" . }}
component: "{{ .Values.artifactory.name }}"
release: {{ .Release.Name }}
{{- if .Values.serviceAccount.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
app: {{ template "artifactory-ha.name" . }}
chart: {{ template "artifactory-ha.chart" . }}
component: {{ .Values.artifactory.name }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
name: {{ template "artifactory-ha.serviceAccountName" . }}
{{- end }}
{{- if .Values.artifactory.catalinaLoggers }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ template "artifactory-ha.fullname" . }}-catalina-logger
labels:
app: {{ template "artifactory-ha.name" . }}
chart: {{ template "artifactory-ha.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
data:
tail-log.sh: |
#!/bin/sh
LOG_DIR=$1
LOG_NAME=$2
PID=
# Wait for log dir to appear
while [ ! -d ${LOG_DIR} ]; do
sleep 1
done
sleep 5
cd ${LOG_DIR}
LOG_PREFIX=$(echo ${LOG_NAME} | awk -F\. '{print $1}')
# Find the log to tail
LOG_FILE=$(ls -1t ./${LOG_PREFIX}.*.log | head -1)
# echo "Tailing ${LOG_FILE}"
tail -F ${LOG_FILE} &
PID=$!
# Loop forever to see if a new log was created
while true; do
# Find the latest log
NEW_LOG_FILE=$(ls -1t ./${LOG_PREFIX}.*.log | head -1)
# If a new log file is found, kill old tail and switch to tailing it
if [ "${LOG_FILE}" != "${NEW_LOG_FILE}" ]; then
kill -9 ${PID}
wait $! 2>/dev/null
LOG_FILE=${NEW_LOG_FILE}
# echo "Tailing ${LOG_FILE}"
tail -F ${LOG_FILE} &
PID=$!
fi
sleep 2
done
{{- end }}
{{- if .Values.ingress.enabled -}}
{{- $serviceName := include "artifactory-ha.fullname" . -}}
{{- $servicePort := .Values.artifactory.externalPort -}}
{{- if semverCompare ">=v1.14.0" .Capabilities.KubeVersion.GitVersion }}
apiVersion: networking.k8s.io/v1beta1
{{- else }}
apiVersion: extensions/v1beta1
{{- end }}
kind: Ingress
metadata:
name: {{ template "artifactory-ha.fullname" . }}
labels:
app: {{ template "artifactory-ha.name" . }}
chart: {{ template "artifactory-ha.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
{{- if .Values.ingress.labels }}
{{ .Values.ingress.labels | toYaml | trimSuffix "\n"| indent 4 -}}
{{- end}}
{{- if .Values.ingress.annotations }}
annotations:
{{ .Values.ingress.annotations | toYaml | trimSuffix "\n" | indent 4 -}}
{{- end }}
spec:
{{- if .Values.ingress.defaultBackend.enabled }}
backend:
serviceName: {{ $serviceName }}
servicePort: {{ $servicePort }}
{{- end }}
rules:
{{- if .Values.ingress.hosts }}
{{- range $host := .Values.ingress.hosts }}
- host: {{ $host | quote }}
http:
paths:
- path: {{ $.Values.ingress.path }}
backend:
serviceName: {{ $serviceName }}
servicePort: {{ $servicePort }}
{{- end -}}
{{- end -}}
{{- with .Values.ingress.additionalRules }}
{{ tpl . $ | indent 2 }}
{{- end }}
{{- if .Values.ingress.tls }}
tls:
{{ toYaml .Values.ingress.tls | indent 4 }}
{{- end -}}
{{- end -}}
{{- if and (not .Values.nginx.customArtifactoryConfigMap) .Values.nginx.enabled }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ template "artifactory-ha.fullname" . }}-nginx-artifactory-conf
labels:
app: {{ template "artifactory-ha.name" . }}
chart: {{ template "artifactory-ha.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
data:
artifactory.conf: |
{{ tpl .Values.nginx.artifactoryConf . | indent 4 }}
{{- end }}
\ No newline at end of file
{{- if and (not .Values.nginx.tlsSecretName) .Values.nginx.enabled }}
apiVersion: v1
kind: Secret
type: kubernetes.io/tls
metadata:
name: {{ template "artifactory-ha.fullname" . }}-nginx-certificate
labels:
app: {{ template "artifactory-ha.name" . }}
chart: {{ template "artifactory-ha.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
data:
{{ ( include "artifactory-ha.gen-certs" . ) | indent 2 }}
{{- end }}
{{- if and (not .Values.nginx.customConfigMap) .Values.nginx.enabled }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ template "artifactory-ha.fullname" . }}-nginx-conf
labels:
app: {{ template "artifactory-ha.name" . }}
chart: {{ template "artifactory-ha.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
data:
nginx.conf: |
{{ tpl .Values.nginx.mainConf . | indent 4 }}
{{- end }}
{{- if .Values.nginx.enabled -}}
{{- $serviceName := include "artifactory-ha.fullname" . -}}
{{- $servicePort := .Values.artifactory.externalPort -}}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ template "artifactory-ha.nginx.fullname" . }}
labels:
app: {{ template "artifactory-ha.name" . }}
chart: {{ template "artifactory-ha.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: {{ .Values.nginx.name }}
{{- if .Values.nginx.labels }}
{{ toYaml .Values.nginx.labels | indent 4 }}
{{- end }}
spec:
replicas: {{ .Values.nginx.replicaCount }}
selector:
matchLabels:
app: {{ template "artifactory-ha.name" . }}
release: {{ .Release.Name }}
component: {{ .Values.nginx.name }}
template:
metadata:
annotations:
checksum/nginx-conf: {{ include (print $.Template.BasePath "/nginx-conf.yaml") . | sha256sum }}
checksum/nginx-artifactory-conf: {{ include (print $.Template.BasePath "/nginx-artifactory-conf.yaml") . | sha256sum }}
checksum/replicator-conf: {{ include (print $.Template.BasePath "/replicator-configmap.yaml") . | sha256sum }}
labels:
app: {{ template "artifactory-ha.name" . }}
chart: {{ template "artifactory-ha.chart" . }}
component: {{ .Values.nginx.name }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
spec:
serviceAccountName: {{ template "artifactory-ha.serviceAccountName" . }}
{{- if .Values.imagePullSecrets }}
imagePullSecrets:
- name: {{ .Values.imagePullSecrets }}
{{- end }}
initContainers:
- name: "setup"
image: "{{ .Values.initContainerImage }}"
imagePullPolicy: {{ .Values.nginx.image.pullPolicy }}
command:
- '/bin/sh'
- '-c'
- >
rm -rfv {{ .Values.nginx.persistence.mountPath }}/lost+found;
mkdir -p {{ .Values.nginx.persistence.mountPath }}/logs;
volumeMounts:
- mountPath: {{ .Values.nginx.persistence.mountPath | quote }}
name: nginx-volume
securityContext:
runAsUser: {{ .Values.nginx.uid }}
fsGroup: {{ .Values.nginx.gid }}
containers:
- name: {{ .Values.nginx.name }}
image: '{{ .Values.nginx.image.repository }}:{{ default .Chart.AppVersion .Values.nginx.image.version }}'
imagePullPolicy: {{ .Values.nginx.image.pullPolicy }}
command:
- 'nginx'
- '-g'
- 'daemon off;'
ports:
- containerPort: {{ .Values.nginx.internalPortHttp }}
- containerPort: {{ .Values.nginx.internalPortHttps }}
{{- if .Values.artifactory.replicator.enabled }}
- containerPort: {{ .Values.nginx.internalPortReplicator }}
{{- end }}
volumeMounts:
- name: nginx-conf
mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf
- name: nginx-artifactory-conf
mountPath: "{{ .Values.nginx.persistence.mountPath }}/conf.d/"
{{- if .Values.artifactory.replicator.enabled }}
- name: nginx-replicator-conf
mountPath: "{{ .Values.nginx.persistence.mountPath }}/conf.d/replicator/"
{{- end }}
- name: nginx-volume
mountPath: {{ .Values.nginx.persistence.mountPath | quote }}
- name: ssl-certificates
mountPath: "{{ .Values.nginx.persistence.mountPath }}/ssl"
resources:
{{ toYaml .Values.nginx.resources | indent 10 }}
{{- if .Values.nginx.readinessProbe.enabled }}
readinessProbe:
httpGet:
path: {{ .Values.nginx.readinessProbe.path }}
port: 80
initialDelaySeconds: {{ .Values.nginx.readinessProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.nginx.readinessProbe.periodSeconds }}
timeoutSeconds: {{ .Values.nginx.readinessProbe.timeoutSeconds }}
failureThreshold: {{ .Values.nginx.readinessProbe.failureThreshold }}
successThreshold: {{ .Values.nginx.readinessProbe.successThreshold }}
{{- end }}
{{- if .Values.nginx.livenessProbe.enabled }}
livenessProbe:
httpGet:
path: {{ .Values.nginx.livenessProbe.path }}
port: 80
initialDelaySeconds: {{ .Values.nginx.livenessProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.nginx.livenessProbe.periodSeconds }}
timeoutSeconds: {{ .Values.nginx.livenessProbe.timeoutSeconds }}
failureThreshold: {{ .Values.nginx.livenessProbe.failureThreshold }}
successThreshold: {{ .Values.nginx.livenessProbe.successThreshold }}
{{- end }}
{{- $image := .Values.logger.image.repository }}
{{- $tag := .Values.logger.image.tag }}
{{- $mountPath := .Values.nginx.persistence.mountPath }}
{{- range .Values.nginx.loggers }}
- name: {{ . | replace "_" "-" | replace "." "-" }}
image: '{{ $image }}:{{ $tag }}'
command:
- tail
args:
- '-F'
- '{{ $mountPath }}/logs/{{ . }}'
volumeMounts:
- name: nginx-volume
mountPath: {{ $mountPath }}
{{- end }}
{{- with .Values.nginx.nodeSelector }}
nodeSelector:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.nginx.affinity }}
affinity:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.nginx.tolerations }}
tolerations:
{{ toYaml . | indent 8 }}
{{- end }}
volumes:
- name: nginx-conf
configMap:
{{- if .Values.nginx.customConfigMap }}
name: {{ .Values.nginx.customConfigMap }}
{{- else }}
name: {{ template "artifactory-ha.fullname" . }}-nginx-conf
{{- end }}
- name: nginx-artifactory-conf
configMap:
{{- if .Values.nginx.customArtifactoryConfigMap }}
name: {{ .Values.nginx.customArtifactoryConfigMap }}
{{- else }}
name: {{ template "artifactory-ha.fullname" . }}-nginx-artifactory-conf
{{- end }}
{{- if .Values.artifactory.replicator.enabled }}
- name: nginx-replicator-conf
configMap:
name: {{ template "artifactory-ha.fullname" . }}-replicator-config
{{- end }}
- name: nginx-volume
{{- if .Values.nginx.persistence.enabled }}
persistentVolumeClaim:
claimName: {{ .Values.nginx.persistence.existingClaim | default (include "artifactory-ha.nginx.fullname" .) }}
{{- else }}
emptyDir: {}
{{- end }}
- name: ssl-certificates
secret:
{{- if .Values.nginx.tlsSecretName }}
secretName: {{ .Values.nginx.tlsSecretName }}
{{- else }}
secretName: {{ template "artifactory-ha.fullname" . }}-nginx-certificate
{{- end }}
{{- end }}
{{- if and .Values.nginx.persistence.enabled (.Values.nginx.enabled) (eq (int .Values.nginx.replicaCount) 1) }}
{{- if (not .Values.nginx.persistence.existingClaim) }}
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: {{ template "artifactory-ha.nginx.fullname" . }}
labels:
app: {{ template "artifactory-ha.name" . }}
chart: {{ template "artifactory-ha.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
spec:
accessModes:
- {{ .Values.nginx.persistence.accessMode | quote }}
resources:
requests:
storage: {{ .Values.nginx.persistence.size | quote }}
{{- if .Values.nginx.persistence.storageClass }}
{{- if (eq "-" .Values.nginx.persistence.storageClass) }}
storageClassName: ""
{{- else }}
storageClassName: "{{ .Values.nginx.persistence.storageClass }}"
{{- end }}
{{- end }}
{{- end }}
{{- end }}
{{- if .Values.nginx.enabled -}}
apiVersion: v1
kind: Service
metadata:
name: {{ template "artifactory-ha.nginx.fullname" . }}
labels:
app: {{ template "artifactory-ha.name" . }}
chart: {{ template "artifactory-ha.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: {{ .Values.nginx.name }}
{{- if .Values.nginx.service.labels }}
{{ toYaml .Values.nginx.service.labels | indent 4 }}
{{- end }}
{{- if .Values.nginx.service.annotations }}
annotations:
{{ toYaml .Values.nginx.service.annotations | indent 4 }}
{{- end }}
spec:
type: {{ .Values.nginx.service.type }}
{{- if and (eq .Values.nginx.service.type "ClusterIP") .Values.nginx.service.clusterIP }}
clusterIP: {{ .Values.nginx.service.clusterIP }}
{{- end }}
{{- if eq .Values.nginx.service.type "LoadBalancer" }}
{{ if .Values.nginx.service.loadBalancerIP -}}
loadBalancerIP: {{ .Values.nginx.service.loadBalancerIP }}
{{ end -}}
{{- if .Values.nginx.service.externalTrafficPolicy }}
externalTrafficPolicy: {{ .Values.nginx.service.externalTrafficPolicy }}
{{- end }}
{{- end }}
{{- if .Values.nginx.service.loadBalancerSourceRanges }}
loadBalancerSourceRanges:
{{ toYaml .Values.nginx.service.loadBalancerSourceRanges | indent 4 }}
{{- end }}
ports:
{{- if .Values.artifactory.replicator.enabled }}
- port: {{ .Values.nginx.externalPortReplicator }}
targetPort: {{ .Values.nginx.internalPortReplicator }}
protocol: TCP
name: replicator
{{- end }}
- port: {{ .Values.nginx.externalPortHttp }}
targetPort: {{ .Values.nginx.internalPortHttp }}
protocol: TCP
name: http
- port: {{ .Values.nginx.externalPortHttps }}
targetPort: {{ .Values.nginx.internalPortHttps }}
protocol: TCP
name: https
selector:
app: {{ template "artifactory-ha.name" . }}
component: {{ .Values.nginx.name }}
release: {{ .Release.Name }}
{{- end }}
{{- if .Values.artifactory.replicator.enabled }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ template "artifactory-ha.fullname" . }}-replicator-config
labels:
app: {{ template "artifactory-ha.name" . }}
chart: {{ template "artifactory-ha.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
data:
replicator.yaml: |-
externalUrl: {{ required "artifactory.replicator.publicUrl is required when artifactory.replicator.enabled is true" .Values.artifactory.replicator.publicUrl }}
internalUrl: http://localhost:{{ .Values.nginx.internalPortReplicator }}
listenPort: {{ .Values.nginx.internalPortReplicator }}
replicator-nginx.conf: |
## Artifactory replicator
server {
listen {{ .Values.nginx.externalPortReplicator }};
server_name {{ include "artifactory-ha.fullname" . }};
client_max_body_size 0;
location / {
proxy_read_timeout 900;
proxy_pass_header Server;
proxy_pass http://{{ include "artifactory-ha.primary.name" . }}:{{ .Values.nginx.internalPortReplicator }};
proxy_http_version 1.1;
}
}
{{- end }}
artifactory:
primary:
resources:
requests:
memory: "6Gi"
cpu: "4"
limits:
memory: "10Gi"
cpu: "8"
javaOpts:
xms: "6g"
xmx: "8g"
node:
replicaCount: 3
resources:
requests:
memory: "6Gi"
cpu: "4"
limits:
memory: "10Gi"
cpu: "8"
javaOpts:
xms: "6g"
xmx: "8g"
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