diff --git a/ansible/roles/harbor/files/etc/confd/templates/harbor.sh/03.chartserver.env.tmpl b/ansible/roles/harbor/files/etc/confd/templates/harbor.sh/03.chartserver.env.tmpl index 62911ce..00bb810 100644 --- a/ansible/roles/harbor/files/etc/confd/templates/harbor.sh/03.chartserver.env.tmpl +++ b/ansible/roles/harbor/files/etc/confd/templates/harbor.sh/03.chartserver.env.tmpl @@ -27,6 +27,7 @@ DEPTH=1 STORAGE=local STORAGE_LOCAL_ROOTDIR=/chart_storage {{- else }} +AWS_SDK_LOAD_CONFIG=1 STORAGE=amazon STORAGE_AMAZON_BUCKET={{ getv "/env/QS_BUCKET" }} STORAGE_AMAZON_PREFIX={{ getv "/env/QS_ROOT_DIRECTORY" "" }} diff --git a/ansible/roles/harbor/files/etc/confd/templates/harbor.sh/04.core.env.tmpl b/ansible/roles/harbor/files/etc/confd/templates/harbor.sh/04.core.env.tmpl index aa5dc0a..e8c3108 100644 --- a/ansible/roles/harbor/files/etc/confd/templates/harbor.sh/04.core.env.tmpl +++ b/ansible/roles/harbor/files/etc/confd/templates/harbor.sh/04.core.env.tmpl @@ -13,10 +13,10 @@ xsrfKey=${encrypted:0:32} flush > /opt/app/current/conf/core/env << CORE_ENV_FILE CONFIG_PATH=/etc/core/app.conf UAA_CA_ROOT=/etc/core/certificates/uaa_ca.pem -_REDIS_URL_CORE=redis://redis:$redisPassword@redis:6379?idle_timeout_seconds=30 +_REDIS_URL_CORE=redis://:$redisPassword@redis:6379?idle_timeout_seconds=30 SYNC_QUOTA=true CHART_CACHE_DRIVER=redis -_REDIS_URL_REG=redis://redis:$redisPassword@redis:6379/1?idle_timeout_seconds=30 +_REDIS_URL_REG=redis://:$redisPassword@redis:6379/1?idle_timeout_seconds=30 LOG_LEVEL=info EXT_ENDPOINT={{ getv "/env/HARBOR_HOST" }} @@ -64,4 +64,10 @@ NO_PROXY=log,127.0.0.1,core,exporter,postgresql,.internal,db,portal,.local,regis PORT=8080 CORE_ENV_FILE + +METRIC_ENABLE=true +METRIC_PATH=/metrics +METRIC_PORT=9090 +METRIC_NAMESPACE=harbor +METRIC_SUBSYSTEM=core {{- end }} diff --git a/ansible/roles/harbor/files/etc/confd/templates/harbor.sh/06.jobservice.env.tmpl b/ansible/roles/harbor/files/etc/confd/templates/harbor.sh/06.jobservice.env.tmpl index b95e5c8..5e9f61f 100644 --- a/ansible/roles/harbor/files/etc/confd/templates/harbor.sh/06.jobservice.env.tmpl +++ b/ansible/roles/harbor/files/etc/confd/templates/harbor.sh/06.jobservice.env.tmpl @@ -22,6 +22,7 @@ NO_PROXY=log,127.0.0.1,core,exporter,postgresql,.internal,db,portal,.local,regis REGISTRY_CREDENTIAL_USERNAME=harbor_registry_user REGISTRY_CREDENTIAL_PASSWORD=$registryPassword JOBSERVICE_ENV_FILE - +METRIC_NAMESPACE=harbor +METRIC_SUBSYSTEM=jobservice chown 10000:10000 /opt/app/current/conf/jobservice/env {{- end }} diff --git a/ansible/roles/harbor/files/etc/confd/templates/harbor.sh/13.docker-compose.yml.tmpl b/ansible/roles/harbor/files/etc/confd/templates/harbor.sh/13.docker-compose.yml.tmpl index e3753bb..fc83f71 100644 --- a/ansible/roles/harbor/files/etc/confd/templates/harbor.sh/13.docker-compose.yml.tmpl +++ b/ansible/roles/harbor/files/etc/confd/templates/harbor.sh/13.docker-compose.yml.tmpl @@ -34,7 +34,7 @@ $tmpstr logging: driver: "syslog" options: - tag: "harbor.log" + tag: "harborLogSelf.log" {{- end }} {{- if eq $nodeRole "cache" }} redis: @@ -94,6 +94,7 @@ $tmpstr options: syslog-address: "tcp://log:1514" tag: "db.postgresql" + shm_size: '1gb' {{- end }} {{- range getvs "/host/role" | filter "web|job" }} registry: @@ -281,6 +282,33 @@ $tmpstr env_file: ./trivy-adapter/env {{- end }} + exporter: + image: goharbor/harbor-exporter:\$HARBOR_VERSION + container_name: harbor-exporter + env_file: + - ./exporter/env + restart: always + networks: + - harbor + depends_on: + - core + volumes: + - type: bind + source: ./shared/trust-certificates + target: /harbor_cust_cert + ports: + - 9090:9090 + dns_search: . + dns: +$tmpstr + logging: + driver: "syslog" + options: + syslog-address: "tcp://log:1514" + tag: "exporter" + extra_hosts: + - "postgresql:{{ range getvs "/hosts/db_node/*/ip" }}{{ . }}{{ end }}" + - "redis:{{ range getvs "/hosts/cache_node/*/ip" }}{{ . }}{{ end }}" jobservice: image: goharbor/harbor-jobservice:\$HARBOR_VERSION container_name: harbor-jobservice @@ -303,6 +331,8 @@ $tmpstr target: /harbor_cust_cert networks: - harbor + depends_on: + - core ports: - 8080:8080 dns_search: . @@ -311,8 +341,6 @@ $tmpstr extra_hosts: - "redis:{{ range getvs "/hosts/cache_node/*/ip" }}{{ . }}{{ end }}" - "postgresql:{{ range getvs "/hosts/db_node/*/ip" }}{{ . }}{{ end }}" - depends_on: - - core logging: driver: "syslog" options: @@ -368,6 +396,7 @@ $tmpstr $tmpstr ports: - 80:8080 + - 9090:9090 depends_on: - registry - core @@ -377,6 +406,9 @@ $tmpstr options: syslog-address: "tcp://log:1514" tag: "web.proxy" + extra_hosts: + - "jobservice:{{ range getvs "/hosts/job_node/*/ip" }}{{ . }}{{ end }}" + - "exporter:{{ range getvs "/hosts/job_node/*/ip" }}{{ . }}{{ end }}" {{- end }} networks: harbor: diff --git a/ansible/roles/harbor/files/etc/confd/templates/harbor.sh/14.redis.tmpl b/ansible/roles/harbor/files/etc/confd/templates/harbor.sh/14.redis.tmpl index 54af968..7698f45 100644 --- a/ansible/roles/harbor/files/etc/confd/templates/harbor.sh/14.redis.tmpl +++ b/ansible/roles/harbor/files/etc/confd/templates/harbor.sh/14.redis.tmpl @@ -18,7 +18,7 @@ worker_pool: #Additional config if use 'redis' backend redis_pool: #redis://[arbitrary_username:password@]ipaddress:port/database_index - redis_url: redis://redis:$redisPassword@redis:6379/2?idle_timeout_seconds=30 + redis_url: redis://:$redisPassword@redis:6379/2?idle_timeout_seconds=30 namespace: "harbor_job_service_namespace" idle_timeout_second: 3600 #Loggers for the running job @@ -48,10 +48,10 @@ redisPassword=${encrypted:0:16} flush > /opt/app/current/conf/trivy-adapter/env << ENV_FILE SCANNER_LOG_LEVEL=info SCANNER_API_SERVER_ADDR=:8081 -SCANNER_REDIS_URL=redis://redis:$redisPassword@redis:6379/5?idle_timeout_seconds=30 -SCANNER_STORE_REDIS_URL=redis://redis:$redisPassword@redis:6379/5?idle_timeout_seconds=30 +SCANNER_REDIS_URL=redis://:$redisPassword@redis:6379/5?idle_timeout_seconds=30 +SCANNER_STORE_REDIS_URL=redis://:$redisPassword@redis:6379/5?idle_timeout_seconds=30 SCANNER_STORE_REDIS_NAMESPACE=harbor.scanner.trivy:store -SCANNER_JOB_QUEUE_REDIS_URL=redis://redis:$redisPassword@redis:6379/5?idle_timeout_seconds=30 +SCANNER_JOB_QUEUE_REDIS_URL=redis://:$redisPassword@redis:6379/5?idle_timeout_seconds=30 SCANNER_JOB_QUEUE_REDIS_NAMESPACE=harbor.scanner.trivy:job-queue SCANNER_TRIVY_CACHE_DIR=/home/scanner/.cache/trivy SCANNER_TRIVY_REPORTS_DIR=/home/scanner/.cache/reports diff --git a/ansible/roles/harbor/files/etc/confd/templates/harbor.sh/16.exporter.env.tmpl b/ansible/roles/harbor/files/etc/confd/templates/harbor.sh/16.exporter.env.tmpl new file mode 100644 index 0000000..806ac9d --- /dev/null +++ b/ansible/roles/harbor/files/etc/confd/templates/harbor.sh/16.exporter.env.tmpl @@ -0,0 +1,35 @@ +{{- range getvs "/host/role" | filter "job" }} +encrypted=$(echo -n {{ getv "/cluster/cluster_id" }}{{ getv "/cluster/global_uuid" }} | sha256sum | base64) +coreSecret=${encrypted:0:16} +jobSecret=${encrypted:16:16} +encrypted=$(echo -n {{ getv "/cluster/user_id" }}{{ getv "/cluster/global_uuid" }} | sha256sum | base64) +redisPassword=${encrypted:0:16} +dbPassword=${encrypted:16:16} +registryPassword=${encrypted:32:16} + +flush > /opt/app/current/conf/exporter/env << CORE_ENV_FILE +LOG_LEVEL=info +HARBOR_EXPORTER_PORT=8080 +HARBOR_EXPORTER_METRICS_PATH=/metrics +HARBOR_EXPORTER_METRICS_ENABLED=true +HARBOR_EXPORTER_MAX_REQUESTS=30 +HARBOR_EXPORTER_CACHE_TIME=23 +HARBOR_EXPORTER_CACHE_CLEAN_INTERVAL=14400 +HARBOR_METRIC_NAMESPACE=harbor +HARBOR_METRIC_SUBSYSTEM=exporter +HARBOR_SERVICE_HOST=core +HARBOR_REDIS_URL=redis://:$redisPassword@redis:6379?idle_timeout_seconds=30 +HARBOR_REDIS_NAMESPACE=harbor_job_service_namespace +HARBOR_REDIS_TIMEOUT=3600 +HARBOR_SERVICE_PORT=8080 +HARBOR_SERVICE_SCHEME=http +HARBOR_DATABASE_HOST=postgresql +HARBOR_DATABASE_PORT=5432 +HARBOR_DATABASE_USERNAME=postgres +HARBOR_DATABASE_PASSWORD=$dbPassword +HARBOR_DATABASE_DBNAME=registry +HARBOR_DATABASE_SSLMODE=disable +HARBOR_DATABASE_MAX_IDLE_CONNS=100 +HARBOR_DATABASE_MAX_OPEN_CONNS=900 +CORE_ENV_FILE +{{- end }} \ No newline at end of file diff --git a/ansible/roles/harbor/files/opt/app/conf/jobservice/config.yml b/ansible/roles/harbor/files/etc/confd/templates/harbor.sh/17.jobservice.config.tmpl similarity index 63% rename from ansible/roles/harbor/files/opt/app/conf/jobservice/config.yml rename to ansible/roles/harbor/files/etc/confd/templates/harbor.sh/17.jobservice.config.tmpl index 82d5be9..2efef6f 100644 --- a/ansible/roles/harbor/files/opt/app/conf/jobservice/config.yml +++ b/ansible/roles/harbor/files/etc/confd/templates/harbor.sh/17.jobservice.config.tmpl @@ -1,3 +1,9 @@ +{{- if eq $nodeRole "job" }} + +encrypted=$(echo -n {{ getv "/cluster/user_id" }}{{ getv "/cluster/global_uuid" }} | sha256sum | base64) +redisPassword=${encrypted:0:16} + +flush > /opt/app/current/conf/jobservice/config.yml << JOBSERVICE_ENV_FILE --- #Protocol used to serve protocol: "http" @@ -13,7 +19,7 @@ worker_pool: #Additional config if use 'redis' backend redis_pool: #redis://[arbitrary_username:password@]ipaddress:port/database_index - redis_url: redis://redis:6379/2?idle_timeout_seconds=30 + redis_url: redis://:$redisPassword@redis:6379?idle_timeout_seconds=30 namespace: "harbor_job_service_namespace" idle_timeout_second: 3600 #Loggers for the running job @@ -32,4 +38,14 @@ job_loggers: #Loggers for the job service loggers: - name: "STD_OUTPUT" # Same with above - level: "INFO" \ No newline at end of file + level: "INFO" + +metric: + enabled: true + path: /metrics + port: 9090 + +JOBSERVICE_ENV_FILE +chown 10000:10000 /opt/app/current/conf/jobservice/config.yml + +{{- end }} \ No newline at end of file diff --git a/ansible/roles/harbor/files/opt/app/bin/node/all.sh b/ansible/roles/harbor/files/opt/app/bin/node/all.sh index f68f589..f26267d 100755 --- a/ansible/roles/harbor/files/opt/app/bin/node/all.sh +++ b/ansible/roles/harbor/files/opt/app/bin/node/all.sh @@ -7,7 +7,7 @@ EC_CHECK_HEALTH=6 EC_RETRY_FAILED=5 # retry: failed several times EC_UPGRADE_DB_NO_MOUNT=10 # upgrade failure: no DB data directory mount EC_UPGRADE_DISK_SPACE=11 # upgrade failure: no enough disk space (>33%) -EC_UPGRADE_DB_DIR_EXISTS=12 # upgrade failure: DB data directory is not empty +EC_UPGRADE_DB_DIR_NOT_EXISTS=12 # upgrade failure: DB data directory is not empty EC_UPGRADE_DB_NO_DIR=13 # upgrade failure: no DB data directory mount EC_UPGRADE_TO_130=20 # upgrade failure: DB migration to Harbor v1.3.0 EC_UPGRADE_TO_160=21 # upgrade failure: DB migration to Harbor v1.6.0 @@ -26,6 +26,7 @@ dockerCompose() { docker-compose --env-file /opt/app/current/bin/envs/harbor.env -f /opt/app/current/conf/docker-compose.yml $@ } +oldVersion=harbor-v2.2.1 serverMountPath=/data/registry dbMountDir=/data/database dbDataDir=$dbMountDir/harbor-$HARBOR_VERSION @@ -107,38 +108,24 @@ checkContainerHealthy() { } duplicateDb() { - [ -d "$dbDataDir" ] && return $EC_UPGRADE_DB_DIR_EXISTS || echo Duplicating DB data directory. rm -rf $dbMountDir/lost+found - local files=$(ls $dbMountDir) - mkdir -p $dbDataDir - for file in $files; do - cp -r "$dbMountDir/$file" "$dbDataDir/$file" - done + mkdir -p $dbMountDir/harbor-v2.4.3 + mkdir -p $dbMountDir/back_up + cp -r $dbMountDir/$oldVersion/* $dbMountDir/back_up/ + cp -r $dbMountDir/$oldVersion/* $dbMountDir/harbor-v2.4.3/ + chmod 700 $dbMountDir/harbor-v2.4.3/ + chown -R 999.999 $dbMountDir/harbor-v2.4.3/ } revertDb() { rm -rf $dbDataDir } -migrateDb() { - # Migrating to v1.3.0 ... - echo -n "y" | docker run -i --rm -e DB_USR=root -e DB_PWD=root123 -v $dbDataDir:/var/lib/mysql vmware/harbor-db-migrator:1.3 up head || return $EC_UPGRADE_TO_130 - - # Migrating to v1.6.0 ... - echo -n "y" | docker run -i --rm -e DB_USR=root -e DB_PWD=root123 -v $dbDataDir:/var/lib/mysql goharbor/harbor-migrator:v1.6.0 --db up || return $EC_UPGRADE_TO_160 - - # Replace default password with the generated stronger one for super user - docker run --rm -di --name update-passwd --env-file=/opt/app/conf/db/env -v $dbDataDir:/var/lib/postgresql/data goharbor/harbor-db:$HARBOR_VERSION || return $EC_UPDATE_DB_PWD_INIT - retry 30 2 0 checkContainerHealthy update-passwd || return $EC_UPDATE_DB_PWD_START - docker exec -i update-passwd sh -c "psql -U postgres -c \"alter user postgres with password '\$POSTGRES_PASSWORD'\"" || return $EC_UPDATE_DB_PWD_RUN - docker stop update-passwd || return $EC_UPDATE_DB_PWD_STOP -} - upgrade() { if [ "$MY_ROLE" = "db" ]; then [ -d $dbMountDir ] || return $EC_UPGRADE_DB_NO_DIR - if [ -f "$dbMountDir/ibdata1" ]; then + if [ -d "$dbMountDir/$oldVersion" ]; then echo About to upgrade. Checking volume usage ... used=$(df --output=pcent $dbMountDir | tail -1 | tr -d '%') [ $used -lt 33 ] || { @@ -149,18 +136,6 @@ upgrade() { echo Duplicating DB data ... duplicateDb - echo Migrating DB data ... - migrateDb || { - retcode=$? - revertDb - return $retcode - } - - local oldFiles=`realpath $dbMountDir/*` - for oldFile in $oldFiles; do - [ "$oldFile" = "$dbDataDir" ] || rm -rf "$oldFile" - done - else [ -d "$dbDataDir" ] || return $EC_UPGRADE_DB_NO_DIR fi diff --git a/ansible/roles/harbor/files/opt/app/conf/core/certificates/.gitkeep b/ansible/roles/harbor/files/opt/app/conf/core/certificates/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/ansible/roles/harbor/files/opt/app/conf/exporter/.gitkeep b/ansible/roles/harbor/files/opt/app/conf/exporter/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/ansible/roles/harbor/files/opt/app/conf/jobservice/.gitkeep b/ansible/roles/harbor/files/opt/app/conf/jobservice/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/ansible/roles/harbor/files/opt/app/conf/nginx/nginx.conf b/ansible/roles/harbor/files/opt/app/conf/nginx/nginx.conf index c44ae16..c098772 100644 --- a/ansible/roles/harbor/files/opt/app/conf/nginx/nginx.conf +++ b/ansible/roles/harbor/files/opt/app/conf/nginx/nginx.conf @@ -2,7 +2,7 @@ worker_processes auto; pid /tmp/nginx.pid; events { - worker_connections 1024; + worker_connections 3096; use epoll; multi_accept on; } @@ -33,6 +33,11 @@ http { access_log /dev/stdout timed_combined; + map $http_x_forwarded_proto $x_forwarded_proto { + default $http_x_forwarded_proto; + "" $scheme; + } + server { listen 8080; server_tokens off; @@ -43,7 +48,7 @@ http { add_header X-Frame-Options DENY; add_header Content-Security-Policy "frame-ancestors 'none'"; - # costumized location config file can place to /etc/nginx/etc with prefix harbor.http. and suffix .conf + # customized location config file can place to /etc/nginx/etc with prefix harbor.http. and suffix .conf include /etc/nginx/conf.d/harbor.http.*.conf; location / { @@ -51,10 +56,8 @@ http { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $x_forwarded_proto; - # 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; } @@ -64,10 +67,8 @@ http { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $x_forwarded_proto; - # 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; } @@ -77,10 +78,8 @@ http { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $x_forwarded_proto; - # 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; } @@ -90,10 +89,8 @@ http { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $x_forwarded_proto; - # 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; } @@ -107,9 +104,7 @@ http { 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_set_header X-Forwarded-Proto $x_forwarded_proto; proxy_buffering off; proxy_request_buffering off; @@ -122,9 +117,7 @@ http { 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_set_header X-Forwarded-Proto $x_forwarded_proto; proxy_buffering off; proxy_request_buffering off; @@ -134,4 +127,29 @@ http { return 404; } } + upstream core_metrics { + server core:9090; + } + + upstream js_metrics { + server jobservice:9090; + } + + upstream registry_metrics { + server registry:9090; + } + + upstream harbor_exporter { + server exporter:8080; + } + + server { + listen 9090; + location = /metrics { + if ($arg_comp = core) { proxy_pass http://core_metrics; } + if ($arg_comp = jobservice) { proxy_pass http://js_metrics; } + if ($arg_comp = registry) { proxy_pass http://registry_metrics; } + proxy_pass http://harbor_exporter; + } + } } \ No newline at end of file diff --git a/ansible/roles/harbor/tasks/main.yml b/ansible/roles/harbor/tasks/main.yml index 86df745..bf64095 100644 --- a/ansible/roles/harbor/tasks/main.yml +++ b/ansible/roles/harbor/tasks/main.yml @@ -1,10 +1,10 @@ --- - name: set vars set_fact: - harbor_version: v2.2.1 - containerd_version: 1.4.4-1 - docker_version: 20.10.6~3 - docker_compose_version: 1.29.2 + harbor_version: v2.4.3 + containerd_version: 1.4.6-1 + docker_version: 20.10.7~3 + docker_compose_version: 2.1.1 - name: install app-agent include_role: diff --git a/patches/patch001/harbor.sh.tmpl b/patches/patch001/harbor.sh.tmpl index 67176ac..8661bde 100644 --- a/patches/patch001/harbor.sh.tmpl +++ b/patches/patch001/harbor.sh.tmpl @@ -167,10 +167,10 @@ xsrfKey=${encrypted:0:32} flush > /opt/app/current/conf/core/env << CORE_ENV_FILE CONFIG_PATH=/etc/core/app.conf UAA_CA_ROOT=/etc/core/certificates/uaa_ca.pem -_REDIS_URL_CORE=redis://redis:$redisPassword@redis:6379?idle_timeout_seconds=30 +_REDIS_URL_CORE=redis://:$redisPassword@redis:6379?idle_timeout_seconds=30 SYNC_QUOTA=true CHART_CACHE_DRIVER=redis -_REDIS_URL_REG=redis://redis:$redisPassword@redis:6379?idle_timeout_seconds=30 +_REDIS_URL_REG=redis://:$redisPassword@redis:6379?idle_timeout_seconds=30 LOG_LEVEL=info EXT_ENDPOINT={{ getv "/env/HARBOR_HOST" }}